]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
bufmgr: Return whether WaitReadBuffers() needed to wait
authorAndres Freund <andres@anarazel.de>
Wed, 1 Apr 2026 13:26:43 +0000 (09:26 -0400)
committerAndres Freund <andres@anarazel.de>
Wed, 1 Apr 2026 13:26:43 +0000 (09:26 -0400)
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 <melanieplageman@gmail.com>
Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com>
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
src/include/storage/bufmgr.h

index 17499451ad2e7c9ec3c18311e520377a76c89a61..5c64570020d4895f5c54c477026427c4ba15c6ae 100644 (file)
@@ -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;
 }
 
 /*
index dd41b92f9444dca3345047f9669c29f13a06131d..aa61a39d9e65ba19c38ad01434da19d46b0c50ce 100644 (file)
@@ -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);