From: Andres Freund Date: Wed, 26 Mar 2025 20:06:54 +0000 (-0400) Subject: aio: Pass result of local callbacks to ->report_return X-Git-Tag: REL_18_BETA1~424 X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=f321ec237a54912b28d81acc4bfc4e434d9339c7;p=postgresql.git aio: Pass result of local callbacks to ->report_return 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 Discussion: https://postgr.es/m/20250326001915.bc.nmisch@google.com --- diff --git a/src/backend/storage/aio/aio.c b/src/backend/storage/aio/aio.c index 29f57f9cd1c..1fd82842718 100644 --- a/src/backend/storage/aio/aio.c +++ b/src/backend/storage/aio/aio.c @@ -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); diff --git a/src/backend/storage/aio/aio_callback.c b/src/backend/storage/aio/aio_callback.c index 09f03f296f5..d6b53165ccf 100644 --- a/src/backend/storage/aio/aio_callback.c +++ b/src/backend/storage/aio/aio_callback.c @@ -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; } diff --git a/src/include/storage/aio_internal.h b/src/include/storage/aio_internal.h index 108fe61c7b4..d5f64416870 100644 --- a/src/include/storage/aio_internal.h +++ b/src/include/storage/aio_internal.h @@ -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);