aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/aio/aio.c21
-rw-r--r--src/backend/storage/aio/aio_target.c12
2 files changed, 24 insertions, 9 deletions
diff --git a/src/backend/storage/aio/aio.c b/src/backend/storage/aio/aio.c
index 64e8e81e184..e2a133cfac6 100644
--- a/src/backend/storage/aio/aio.c
+++ b/src/backend/storage/aio/aio.c
@@ -670,6 +670,21 @@ pgaio_io_reclaim(PgAioHandle *ioh)
Assert(!ioh->resowner);
+ /*
+ * Update generation & state first, before resetting the IO's fields,
+ * otherwise a concurrent "viewer" could think the fields are valid, even
+ * though they are being reset. Increment the generation first, so that
+ * we can assert elsewhere that we never wait for an IDLE IO. While it's
+ * a bit weird for the state to go backwards for a generation, it's OK
+ * here, as there cannot be references to the "reborn" IO yet. Can't
+ * update both at once, so something has to give.
+ */
+ ioh->generation++;
+ pgaio_io_update_state(ioh, PGAIO_HS_IDLE);
+
+ /* ensure the state update is visible before we reset fields */
+ pg_write_barrier();
+
ioh->op = PGAIO_OP_INVALID;
ioh->target = PGAIO_TID_INVALID;
ioh->flags = 0;
@@ -679,12 +694,6 @@ pgaio_io_reclaim(PgAioHandle *ioh)
ioh->result = 0;
ioh->distilled_result.status = PGAIO_RS_UNKNOWN;
- /* XXX: the barrier is probably superfluous */
- pg_write_barrier();
- ioh->generation++;
-
- pgaio_io_update_state(ioh, PGAIO_HS_IDLE);
-
/*
* We push the IO to the head of the idle IO list, that seems more cache
* efficient in cases where only a few IOs are used.
diff --git a/src/backend/storage/aio/aio_target.c b/src/backend/storage/aio/aio_target.c
index ac6c74f4ff2..161f0f1edf6 100644
--- a/src/backend/storage/aio/aio_target.c
+++ b/src/backend/storage/aio/aio_target.c
@@ -49,7 +49,8 @@ pgaio_io_has_target(PgAioHandle *ioh)
const char *
pgaio_io_get_target_name(PgAioHandle *ioh)
{
- Assert(ioh->target >= 0 && ioh->target < PGAIO_TID_COUNT);
+ /* explicitly allow INVALID here, function used by debug messages */
+ Assert(ioh->target >= PGAIO_TID_INVALID && ioh->target < PGAIO_TID_COUNT);
return pgaio_target_info[ioh->target]->name;
}
@@ -82,6 +83,9 @@ pgaio_io_get_target_data(PgAioHandle *ioh)
char *
pgaio_io_get_target_description(PgAioHandle *ioh)
{
+ /* disallow INVALID, there wouldn't be a description */
+ Assert(ioh->target > PGAIO_TID_INVALID && ioh->target < PGAIO_TID_COUNT);
+
return pgaio_target_info[ioh->target]->describe_identity(&ioh->target_data);
}
@@ -98,6 +102,8 @@ pgaio_io_get_target_description(PgAioHandle *ioh)
bool
pgaio_io_can_reopen(PgAioHandle *ioh)
{
+ Assert(ioh->target > PGAIO_TID_INVALID && ioh->target < PGAIO_TID_COUNT);
+
return pgaio_target_info[ioh->target]->reopen != NULL;
}
@@ -109,8 +115,8 @@ pgaio_io_can_reopen(PgAioHandle *ioh)
void
pgaio_io_reopen(PgAioHandle *ioh)
{
- Assert(ioh->target >= 0 && ioh->target < PGAIO_TID_COUNT);
- Assert(ioh->op >= 0 && ioh->op < PGAIO_OP_COUNT);
+ Assert(ioh->target > PGAIO_TID_INVALID && ioh->target < PGAIO_TID_COUNT);
+ Assert(ioh->op > PGAIO_OP_INVALID && ioh->op < PGAIO_OP_COUNT);
pgaio_target_info[ioh->target]->reopen(ioh);
}