From 513374a47a71d64ff5c4790b7f962d3a80e8cc7c Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Wed, 1 Apr 2026 09:26:43 -0400 Subject: [PATCH] bufmgr: Return whether WaitReadBuffers() needed to wait Thanks to the previous commit, pgaio_wref_check_done() will now detect whether IO has completed even if userspace has not yet consumed the kernel completion. This knowledge can be useful for callers of WaitReadBuffers() to know whether it needed to wait or not, e.g. for adjusting read-ahead aggressiveness or for instrumentation. Reviewed-by: Melanie Plageman Reviewed-by: Nazir Bilal Yavuz Discussion: https://postgr.es/m/f3xxfrkafjxpyqxywcxricxgyizjirfceychyxsgn7bwjp5eda@kwbduhy7tfmu Discussion: https://postgr.es/m/CAH2-Wz%3DkMg3PNay96cHMT0LFwtxP-cQSRZTZzh1Cixxf8G%3Dzrw%40mail.gmail.com Discussion: https://postgr.es/m/a177a6dd-240b-455a-8f25-aca0b1c08c6e@vondra.me --- src/backend/storage/buffer/bufmgr.c | 17 ++++++++++++++++- src/include/storage/bufmgr.h | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 17499451ad2..5c64570020d 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -1740,12 +1740,19 @@ ProcessReadBuffersResult(ReadBuffersOperation *operation) Assert(operation->nblocks_done <= operation->nblocks); } -void +/* + * Wait for the IO operation initiated by StartReadBuffers() et al to + * complete. + * + * Returns true if we needed to wait for the IO operation, false otherwise. + */ +bool WaitReadBuffers(ReadBuffersOperation *operation) { PgAioReturn *aio_ret = &operation->io_return; IOContext io_context; IOObject io_object; + bool needed_wait = false; if (operation->persistence == RELPERSISTENCE_TEMP) { @@ -1810,6 +1817,7 @@ WaitReadBuffers(ReadBuffersOperation *operation) instr_time io_start = pgstat_prepare_io_time(track_io_timing); pgaio_wref_wait(&operation->io_wref); + needed_wait = true; /* * The IO operation itself was already counted earlier, in @@ -1874,6 +1882,12 @@ WaitReadBuffers(ReadBuffersOperation *operation) CHECK_FOR_INTERRUPTS(); + /* + * If the IO completed only partially, we need to perform additional + * work, consider that a form of having had to wait. + */ + needed_wait = true; + /* * This may only complete the IO partially, either because some * buffers were already valid, or because of a partial read. @@ -1890,6 +1904,7 @@ WaitReadBuffers(ReadBuffersOperation *operation) CheckReadBuffersOperation(operation, true); /* NB: READ_DONE tracepoint was already executed in completion callback */ + return needed_wait; } /* diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h index dd41b92f944..aa61a39d9e6 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -251,7 +251,7 @@ extern bool StartReadBuffers(ReadBuffersOperation *operation, BlockNumber blockNum, int *nblocks, int flags); -extern void WaitReadBuffers(ReadBuffersOperation *operation); +extern bool WaitReadBuffers(ReadBuffersOperation *operation); extern void ReleaseBuffer(Buffer buffer); extern void UnlockReleaseBuffer(Buffer buffer);