From 2c285bf3967d10644361fef5d1e9a3111b35691e Mon Sep 17 00:00:00 2001 From: Fujii Masao Date: Thu, 5 Nov 2026 16:58:26 +0900 Subject: [PATCH v1] Use postmaster-local metadata for io_uring cleanup Commit 953c6dabdb5 added cleanup of io_uring resources during a restart after a backend crash. However, the cleanup used ring descriptors stored in shared memory, which a crashing backend might have corrupted. Passing these descriptors to io_uring_queue_exit() could cause the postmaster to close unrelated file descriptors, including listening sockets, or unmap unrelated memory, preventing successful crash recovery. Keep postmaster-local copies of the ring descriptors and the metadata needed for cleanup, and pass these copies to io_uring_queue_exit() so that resource release does not depend on the contents of shared memory. Backpatch to v18, where io_method=io_uring was introduced. --- src/backend/storage/aio/method_io_uring.c | 40 +++++++++++++++++++++-- src/tools/pgindent/typedefs.list | 1 + 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/backend/storage/aio/method_io_uring.c b/src/backend/storage/aio/method_io_uring.c index d788ad18547..b7dcfebe374 100644 --- a/src/backend/storage/aio/method_io_uring.c +++ b/src/backend/storage/aio/method_io_uring.c @@ -102,6 +102,13 @@ typedef struct PgAioUringContext struct io_uring io_uring_ring; } PgAioUringContext; +/* Postmaster-local metadata needed to release a ring */ +typedef struct PgAioUringCleanup +{ + struct io_uring ring; + unsigned sq_entries; +} PgAioUringCleanup; + /* * Information about the capabilities that io_uring has. * @@ -120,6 +127,12 @@ typedef struct PgAioUringCaps /* PgAioUringContexts for all backends */ static PgAioUringContext *pgaio_uring_contexts; +/* + * Postmaster-local cleanup metadata for all rings. Keep this separate from + * shared memory, which a crashing backend might corrupt. + */ +static PgAioUringCleanup *pgaio_uring_cleanup_rings; + /* the current backend's context */ static PgAioUringContext *pgaio_my_uring_context; @@ -300,11 +313,13 @@ pgaio_uring_cleanup(int code, Datum arg) int TotalProcs = pgaio_uring_procs(); Assert(!IsUnderPostmaster); - Assert(pgaio_uring_contexts != NULL); + Assert(pgaio_uring_cleanup_rings != NULL); for (int i = 0; i < TotalProcs; i++) - io_uring_queue_exit(&pgaio_uring_contexts[i].io_uring_ring); + io_uring_queue_exit(&pgaio_uring_cleanup_rings[i].ring); + free(pgaio_uring_cleanup_rings); + pgaio_uring_cleanup_rings = NULL; pgaio_uring_contexts = NULL; } @@ -316,6 +331,14 @@ pgaio_uring_shmem_init(void *arg) size_t ring_mem_remain = 0; char *ring_mem_next = 0; + Assert(!IsUnderPostmaster); + Assert(pgaio_uring_cleanup_rings == NULL); + + pgaio_uring_cleanup_rings = + malloc(mul_size(TotalProcs, sizeof(PgAioUringCleanup))); + if (pgaio_uring_cleanup_rings == NULL) + elog(PANIC, "out of memory"); + /* * We allocate memory for all PgAioUringContext instances and, if * supported, the memory required for each of the io_uring instances, in @@ -345,6 +368,7 @@ pgaio_uring_shmem_init(void *arg) for (int contextno = 0; contextno < TotalProcs; contextno++) { PgAioUringContext *context = &pgaio_uring_contexts[contextno]; + PgAioUringCleanup *cleanup = &pgaio_uring_cleanup_rings[contextno]; int ret; /* @@ -419,6 +443,18 @@ pgaio_uring_shmem_init(void *arg) hint != NULL ? errhint("%s", hint) : 0); } + /* + * Save the cleanup metadata before any backend can modify it. + * + * Some liburing versions dereference sq.kring_entries to determine + * the size of the SQE mapping to unmap. Save that value locally too, + * and point the cleanup copy at it to avoid reading shared memory + * during cleanup. + */ + cleanup->ring = context->io_uring_ring; + cleanup->sq_entries = *context->io_uring_ring.sq.kring_entries; + cleanup->ring.sq.kring_entries = &cleanup->sq_entries; + LWLockInitialize(&context->completion_lock, LWTRANCHE_AIO_URING_COMPLETION); } diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 553162c0810..f29d84bbd55 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -2261,6 +2261,7 @@ PgAioTargetData PgAioTargetID PgAioTargetInfo PgAioUringCaps +PgAioUringCleanup PgAioUringContext PgAioWaitRef PgAioWorkerControl -- 2.56.0