aio: Pass result of local callbacks to ->report_return
authorAndres Freund <[email protected]>
Wed, 26 Mar 2025 20:06:54 +0000 (16:06 -0400)
committerAndres Freund <[email protected]>
Wed, 26 Mar 2025 20:06:54 +0000 (16:06 -0400)
Otherwise the results of e.g. temp table buffer verification errors will not
reach bufmgr.c. Obviously that's not right. Found while expanding the tests
for invalid buffer contents.

Reviewed-by: Noah Misch <[email protected]>
Discussion: https://postgr.es/m/20250326001915[email protected]

src/backend/storage/aio/aio.c
src/backend/storage/aio/aio_callback.c
src/include/storage/aio_internal.h

index 29f57f9cd1c2d512dac8ffc5223e8e455893fff5..1fd82842718b59194d24ad67ded996c105146de1 100644 (file)
@@ -626,13 +626,21 @@ pgaio_io_reclaim(PgAioHandle *ioh)
 
    /*
     * It's a bit ugly, but right now the easiest place to put the execution
-    * of shared completion callbacks is this function, as we need to execute
+    * of local completion callbacks is this function, as we need to execute
     * local callbacks just before reclaiming at multiple callsites.
     */
    if (ioh->state == PGAIO_HS_COMPLETED_SHARED)
    {
-       pgaio_io_call_complete_local(ioh);
+       PgAioResult local_result;
+
+       local_result = pgaio_io_call_complete_local(ioh);
        pgaio_io_update_state(ioh, PGAIO_HS_COMPLETED_LOCAL);
+
+       if (ioh->report_return)
+       {
+           ioh->report_return->result = local_result;
+           ioh->report_return->target_data = ioh->target_data;
+       }
    }
 
    pgaio_debug_io(DEBUG4, ioh,
@@ -642,18 +650,10 @@ pgaio_io_reclaim(PgAioHandle *ioh)
                   ioh->distilled_result.error_data,
                   ioh->result);
 
-   /* if the IO has been defined, we might need to do more work */
+   /* if the IO has been defined, it's on the in-flight list, remove */
    if (ioh->state != PGAIO_HS_HANDED_OUT)
-   {
        dclist_delete_from(&pgaio_my_backend->in_flight_ios, &ioh->node);
 
-       if (ioh->report_return)
-       {
-           ioh->report_return->result = ioh->distilled_result;
-           ioh->report_return->target_data = ioh->target_data;
-       }
-   }
-
    if (ioh->resowner)
    {
        ResourceOwnerForgetAioHandle(ioh->resowner, &ioh->resowner_node);
index 09f03f296f58f7c7b3c3f3800a3d14a7527db742..d6b53165ccfe10952f09e217dab73db469b0c7b1 100644 (file)
@@ -262,9 +262,12 @@ pgaio_io_call_complete_shared(PgAioHandle *ioh)
  * Internal function which invokes ->complete_local for all the registered
  * callbacks.
  *
+ * Returns ioh->distilled_result after, possibly, being modified by local
+ * callbacks.
+ *
  * XXX: It'd be nice to deduplicate with pgaio_io_call_complete_shared().
  */
-void
+PgAioResult
 pgaio_io_call_complete_local(PgAioHandle *ioh)
 {
    PgAioResult result;
@@ -296,13 +299,17 @@ pgaio_io_call_complete_local(PgAioHandle *ioh)
 
    /*
     * Note that we don't save the result in ioh->distilled_result, the local
-    * callback's result should not ever matter to other waiters.
+    * callback's result should not ever matter to other waiters. However, the
+    * local backend does care, so we return the result as modified by local
+    * callbacks, which then can be passed to ioh->report_return->result.
     */
    pgaio_debug_io(DEBUG3, ioh,
-                  "after local completion: distilled result: (status %s, id %u, error_data %d, result %d), raw_result: %d",
+                  "after local completion: result: (status %s, id %u, error_data %d, result %d), raw_result: %d",
                   pgaio_result_status_string(result.status),
                   result.id, result.error_data, result.result,
                   ioh->result);
 
    END_CRIT_SECTION();
+
+   return result;
 }
index 108fe61c7b4483507f8b0542756d8986a3aa3a93..d5f6441687098338774577b73c438ee97f61ce25 100644 (file)
@@ -309,7 +309,7 @@ extern void pgaio_shutdown(int code, Datum arg);
 /* aio_callback.c */
 extern void pgaio_io_call_stage(PgAioHandle *ioh);
 extern void pgaio_io_call_complete_shared(PgAioHandle *ioh);
-extern void pgaio_io_call_complete_local(PgAioHandle *ioh);
+extern PgAioResult pgaio_io_call_complete_local(PgAioHandle *ioh);
 
 /* aio_io.c */
 extern void pgaio_io_perform_synchronously(PgAioHandle *ioh);