From ff275f0d2fbc8ee9de79c516a21591e229ddc073 Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <byavuz81@gmail.com>
Date: Thu, 20 Aug 2026 12:25:29 +0300
Subject: [PATCH v2] aio: Don't silently drop wait_event_info

FileStartReadV() accepts a wait_event_info argument but never passes it.
Instead pgaio_io_perform_synchronously() hardcodes
WAIT_EVENT_DATA_FILE_READ and WAIT_EVENT_DATA_FILE_WRITE, so a wait
event supplied by the caller is silently ignored.

This is not a live bug today: the only caller of FileStartReadV() is
md.c, which passes exactly the wait event that is hardcoded, and
pgaio_io_start_writev() has no callers at all. It would become one as
soon as AIO is used for files other than relation data files.

Fix this by storing the wait event in PgAioHandle and reporting it.
---
 src/backend/storage/aio/aio.c      |  1 +
 src/backend/storage/aio/aio_io.c   | 26 ++++++++++++++++++++++----
 src/backend/storage/file/fd.c      |  2 +-
 src/include/storage/aio.h          |  6 ++++--
 src/include/storage/aio_internal.h |  3 +++
 5 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/src/backend/storage/aio/aio.c b/src/backend/storage/aio/aio.c
index 8f7e26607b9..ed2ed1ae4f6 100644
--- a/src/backend/storage/aio/aio.c
+++ b/src/backend/storage/aio/aio.c
@@ -739,6 +739,7 @@ pgaio_io_reclaim(PgAioHandle *ioh)
 	ioh->flags = 0;
 	ioh->num_callbacks = 0;
 	ioh->handle_data_len = 0;
+	ioh->wait_event_info = 0;
 	ioh->report_return = NULL;
 	ioh->result = 0;
 	ioh->distilled_result.status = PGAIO_RS_UNKNOWN;
diff --git a/src/backend/storage/aio/aio_io.c b/src/backend/storage/aio/aio_io.c
index 132868130e7..97c281e2a6a 100644
--- a/src/backend/storage/aio/aio_io.c
+++ b/src/backend/storage/aio/aio_io.c
@@ -26,6 +26,7 @@
 
 
 static void pgaio_io_before_start(PgAioHandle *ioh);
+static void pgaio_io_set_wait_event(PgAioHandle *ioh, uint32 wait_event_info);
 
 
 
@@ -76,26 +77,30 @@ pgaio_io_get_op_data(PgAioHandle *ioh)
 
 void
 pgaio_io_start_readv(PgAioHandle *ioh,
-					 int fd, int iovcnt, uint64 offset)
+					 int fd, int iovcnt, uint64 offset,
+					 uint32 wait_event_info)
 {
 	pgaio_io_before_start(ioh);
 
 	ioh->op_data.read.fd = fd;
 	ioh->op_data.read.offset = offset;
 	ioh->op_data.read.iov_length = iovcnt;
+	pgaio_io_set_wait_event(ioh, wait_event_info);
 
 	pgaio_io_stage(ioh, PGAIO_OP_READV);
 }
 
 void
 pgaio_io_start_writev(PgAioHandle *ioh,
-					  int fd, int iovcnt, uint64 offset)
+					  int fd, int iovcnt, uint64 offset,
+					  uint32 wait_event_info)
 {
 	pgaio_io_before_start(ioh);
 
 	ioh->op_data.write.fd = fd;
 	ioh->op_data.write.offset = offset;
 	ioh->op_data.write.iov_length = iovcnt;
+	pgaio_io_set_wait_event(ioh, wait_event_info);
 
 	pgaio_io_stage(ioh, PGAIO_OP_WRITEV);
 }
@@ -124,14 +129,14 @@ pgaio_io_perform_synchronously(PgAioHandle *ioh)
 	switch ((PgAioOp) ioh->op)
 	{
 		case PGAIO_OP_READV:
-			pgstat_report_wait_start(WAIT_EVENT_DATA_FILE_READ);
+			pgstat_report_wait_start(ioh->wait_event_info);
 			result = pg_preadv(ioh->op_data.read.fd, iov,
 							   ioh->op_data.read.iov_length,
 							   ioh->op_data.read.offset);
 			pgstat_report_wait_end();
 			break;
 		case PGAIO_OP_WRITEV:
-			pgstat_report_wait_start(WAIT_EVENT_DATA_FILE_WRITE);
+			pgstat_report_wait_start(ioh->wait_event_info);
 			result = pg_pwritev(ioh->op_data.write.fd, iov,
 								ioh->op_data.write.iov_length,
 								ioh->op_data.write.offset);
@@ -172,6 +177,19 @@ pgaio_io_before_start(PgAioHandle *ioh)
 	Assert(!INTERRUPTS_CAN_BE_PROCESSED());
 }
 
+/*
+ * Helper function to be called by IO operation preparation functions, to
+ * specify the wait event to report while the IO is executed.
+ */
+static void
+pgaio_io_set_wait_event(PgAioHandle *ioh, uint32 wait_event_info)
+{
+	/* every IO needs a wait event to report while it is being executed */
+	Assert(wait_event_info != 0);
+
+	ioh->wait_event_info = wait_event_info;
+}
+
 /*
  * Could be made part of the public interface, but it's not clear there's
  * really a use case for that.
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 190c9974494..9044d01a674 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -2222,7 +2222,7 @@ FileStartReadV(PgAioHandle *ioh, File file,
 
 	vfdP = &VfdCache[file];
 
-	pgaio_io_start_readv(ioh, vfdP->fd, iovcnt, offset);
+	pgaio_io_start_readv(ioh, vfdP->fd, iovcnt, offset, wait_event_info);
 
 	return 0;
 }
diff --git a/src/include/storage/aio.h b/src/include/storage/aio.h
index ec543b78409..7a0eb5167a3 100644
--- a/src/include/storage/aio.h
+++ b/src/include/storage/aio.h
@@ -297,9 +297,11 @@ extern PgAioOp pgaio_io_get_op(PgAioHandle *ioh);
 extern PgAioOpData *pgaio_io_get_op_data(PgAioHandle *ioh);
 
 extern void pgaio_io_start_readv(PgAioHandle *ioh,
-								 int fd, int iovcnt, uint64 offset);
+								 int fd, int iovcnt, uint64 offset,
+								 uint32 wait_event_info);
 extern void pgaio_io_start_writev(PgAioHandle *ioh,
-								  int fd, int iovcnt, uint64 offset);
+								  int fd, int iovcnt, uint64 offset,
+								  uint32 wait_event_info);
 
 /* functions in aio_target.c */
 extern void pgaio_io_set_target(PgAioHandle *ioh, PgAioTargetID targetid);
diff --git a/src/include/storage/aio_internal.h b/src/include/storage/aio_internal.h
index 9ca4087aa7f..d14c8c9c56c 100644
--- a/src/include/storage/aio_internal.h
+++ b/src/include/storage/aio_internal.h
@@ -129,6 +129,9 @@ struct PgAioHandle
 	 */
 	uint8		handle_data_len;
 
+	/* wait event to report while the IO is executed */
+	uint32		wait_event_info;
+
 	/* XXX: could be optimized out with some pointer math */
 	int32		owner_procno;
 
-- 
2.47.3

