v1_PGMASTER-0007-xlog-Verify-all-block-references-are-use.patch
text/x-patch
Filename: v1_PGMASTER-0007-xlog-Verify-all-block-references-are-use.patch
Type: text/x-patch
Part: 6
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v1-0007
Subject: xlog: Verify all block references are used during replay
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlog.c | 10 | 0 |
| src/backend/access/transam/xlogreader.c | 4 | 0 |
| src/backend/access/transam/xlogrecovery.c | 9 | 0 |
| src/backend/access/transam/xlogutils.c | 6 | 0 |
| src/include/access/xlogreader.h | 4 | 0 |
From a8e41a30b323447b023f0cf5a3f26a3f51a9c80f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 29 Apr 2026 12:08:26 -0400
Subject: [PATCH v1_PGMASTER 7/7] xlog: Verify all block references are used
during replay
It's unclear if this makes sense to actually commit. It requires that
blocks read during recovery go through XLogReadBufferForRedoExtended()
and has a special case for handling XLOG_FPI_FOR_HINT when full page
writes are disabled.
Author: Andres Freund <andres@anarazel.de>
Co-authored-by: Melanie Plageman <melanieplageman@gmail.com>
---
src/backend/access/transam/xlog.c | 10 ++++++++++
src/backend/access/transam/xlogreader.c | 4 ++++
src/backend/access/transam/xlogrecovery.c | 9 +++++++++
src/backend/access/transam/xlogutils.c | 6 ++++++
src/include/access/xlogreader.h | 4 ++++
5 files changed, 33 insertions(+)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 18d5dee06e0..0731439df90 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -9085,6 +9085,16 @@ xlog_redo(XLogReaderState *record)
{
if (info == XLOG_FPI)
elog(ERROR, "XLOG_FPI record did not contain a full-page image");
+
+#ifdef USE_ASSERT_CHECKING
+
+ /*
+ * If full_page_writes are disabled, we don't want to error
+ * out because we didn't read the block.
+ */
+ if (info == XLOG_FPI_FOR_HINT)
+ record->record->blocks[block_id].used_read = true;
+#endif
continue;
}
diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c
index 8849610db00..63747aec566 100644
--- a/src/backend/access/transam/xlogreader.c
+++ b/src/backend/access/transam/xlogreader.c
@@ -1794,6 +1794,10 @@ DecodeXLogRecord(XLogReaderState *state,
blk = &decoded->blocks[block_id];
blk->in_use = true;
+#ifdef USE_ASSERT_CHECKING
+ blk->used_read = false;
+#endif
+
blk->apply_image = false;
COPY_HEADER_FIELD(&fork_flags, sizeof(uint8));
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index c236e2b7969..4e1d50f642d 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -1962,6 +1962,15 @@ ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *repl
/* Now apply the WAL record itself */
GetRmgr(record->xl_rmid).rm_redo(xlogreader);
+#ifdef USE_ASSERT_CHECKING
+ for (int block_id = 0; block_id <= xlogreader->record->max_block_id; block_id++)
+ {
+ DecodedBkpBlock *blk = &xlogreader->record->blocks[block_id];
+
+ Assert(!blk->in_use || blk->used_read);
+ }
+#endif
+
/*
* After redo, check whether the backup pages associated with the WAL
* record are consistent with the existing pages. This check is done only
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..979d6465159 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -359,6 +359,12 @@ XLogReadBufferForRedoExtended(XLogReaderState *record,
block_id);
}
+#ifdef USE_ASSERT_CHECKING
+ /* Shouldn't have multiple read references to block */
+ Assert(!record->record->blocks[block_id].used_read);
+ record->record->blocks[block_id].used_read = true;
+#endif
+
/*
* Make sure that if the block is marked with WILL_INIT, the caller is
* going to initialize it. And vice versa.
diff --git a/src/include/access/xlogreader.h b/src/include/access/xlogreader.h
index 97eae2c1dab..fd2119005e8 100644
--- a/src/include/access/xlogreader.h
+++ b/src/include/access/xlogreader.h
@@ -145,6 +145,10 @@ typedef struct
bool has_data;
char *data;
uint16 data_len;
+
+#ifdef USE_ASSERT_CHECKING
+ bool used_read;
+#endif
} DecodedBkpBlock;
/*
--
2.43.0