From 709c222f2c13e62646ca53947dff6d9a6c3d1693 Mon Sep 17 00:00:00 2001
From: Greg Burd <greg@burd.me>
Date: Fri, 30 Oct 2026 10:17:46 -0400
Subject: [PATCH v6 4/4] Remove REGBUF_NO_CHANGE

With the previous commits, the hash index AM no longer registers any
pin-only or otherwise-unchanged buffer, so REGBUF_NO_CHANGE has no users
left.  Remove the flag and restore the invariant that every registered
buffer is content-locked and dirty: XLogRegisterBuffer() asserts it
unconditionally again.

This also reverts the defensive measures added in 27caf4ca5ae5, which
let a REGBUF_NO_CHANGE buffer skip the full-page image forced by
wal_consistency_checking: XLogRecordAssemble() no longer special-cases
the flag, and verifyBackupPageConsistency() again asserts that a
registered block carries an image.  27caf4ca5ae5 remains in the back
branches, where this hash rework is not applied.

Discussion: https://postgr.es/m/055bb33c-bccc-bc1d-c2f8-8598534448ac@gmail.com
---
 src/backend/access/transam/README         |  5 ----
 src/backend/access/transam/xloginsert.c   | 28 ++++++-----------------
 src/backend/access/transam/xlogrecovery.c |  7 +-----
 src/include/access/xloginsert.h           |  3 ---
 4 files changed, 8 insertions(+), 35 deletions(-)

diff --git a/src/backend/access/transam/README b/src/backend/access/transam/README
index 595afa01fa7..231106270fd 100644
--- a/src/backend/access/transam/README
+++ b/src/backend/access/transam/README
@@ -586,11 +586,6 @@ void XLogRegisterBuffer(uint8 block_id, Buffer buf, uint8 flags);
     XLogRegisterBufData() is included in the WAL record even if a full-page
     image is taken.
 
-    The REGBUF_NO_CHANGE flag indicates that the buffer is registered without
-    being modified by this record, and possibly without an exclusive content
-    lock.  wal_consistency_checking does not force a full-page image for such
-    a buffer.
-
 void XLogRegisterData(const void *data, int len);
 
     XLogRegisterData is used to include arbitrary data in the WAL record.  If
diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c
index cd3359434e1..2d031e38594 100644
--- a/src/backend/access/transam/xloginsert.c
+++ b/src/backend/access/transam/xloginsert.c
@@ -257,22 +257,13 @@ XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
 	Assert(begininsert_called);
 
 	/*
-	 * Ordinarily, the buffer should be exclusive-locked (or share-exclusive
-	 * in case of hint bits) and marked dirty before we get here, otherwise we
-	 * could end up violating one of the rules in access/transam/README.
-	 *
-	 * Some callers intentionally register a clean page and never update that
-	 * page's LSN; in that case they can pass the flag REGBUF_NO_CHANGE to
-	 * bypass these checks.
+	 * The buffer should be exclusive-locked (or share-exclusive in case of
+	 * hint bits) and marked dirty before we get here, otherwise we could end
+	 * up violating one of the rules in access/transam/README.
 	 */
-#ifdef USE_ASSERT_CHECKING
-	if (!(flags & REGBUF_NO_CHANGE))
-	{
-		Assert(BufferIsDirty(buffer));
-		Assert(BufferIsLockedByMeInMode(buffer, BUFFER_LOCK_EXCLUSIVE) ||
-			   BufferIsLockedByMeInMode(buffer, BUFFER_LOCK_SHARE_EXCLUSIVE));
-	}
-#endif
+	Assert(BufferIsDirty(buffer));
+	Assert(BufferIsLockedByMeInMode(buffer, BUFFER_LOCK_EXCLUSIVE) ||
+		   BufferIsLockedByMeInMode(buffer, BUFFER_LOCK_SHARE_EXCLUSIVE));
 
 	if (block_id >= max_registered_block_id)
 	{
@@ -722,13 +713,8 @@ XLogRecordAssemble(RmgrId rmid, uint8 info,
 		/*
 		 * If needs_backup is true or WAL checking is enabled for current
 		 * resource manager, log a full-page write for the current block.
-		 *
-		 * Do not force an image for a REGBUF_NO_CHANGE buffer.
 		 */
-		if (regbuf->flags & REGBUF_NO_CHANGE)
-			include_image = needs_backup;
-		else
-			include_image = needs_backup || (info & XLR_CHECK_CONSISTENCY) != 0;
+		include_image = needs_backup || (info & XLR_CHECK_CONSISTENCY) != 0;
 
 		if (include_image)
 		{
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index 52ac6d58423..7a1de0567a8 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -2488,12 +2488,7 @@ verifyBackupPageConsistency(XLogReaderState *record)
 			continue;
 		}
 
-		/*
-		 * Blocks registered with REGBUF_NO_CHANGE may have no image, see
-		 * XLogRecordAssemble().  Nothing to compare for these.
-		 */
-		if (!XLogRecHasBlockImage(record, block_id))
-			continue;
+		Assert(XLogRecHasBlockImage(record, block_id));
 
 		if (XLogRecBlockImageApply(record, block_id))
 		{
diff --git a/src/include/access/xloginsert.h b/src/include/access/xloginsert.h
index 86264564ebb..ddb1a85db59 100644
--- a/src/include/access/xloginsert.h
+++ b/src/include/access/xloginsert.h
@@ -38,9 +38,6 @@
 									 * will be skipped) */
 #define REGBUF_KEEP_DATA	0x10	/* include data even if a full-page image
 									 * is taken */
-#define REGBUF_NO_CHANGE	0x20	/* intentionally register clean buffer; no
-									 * image is forced for WAL consistency
-									 * checking */
 
 /* prototypes for public functions in xloginsert.c: */
 extern void XLogBeginInsert(void);
-- 
2.47.3

