From 6bd0809b5f5c83a464566eb0438b44fe5d1d2576 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 28 Oct 2024 18:11:23 -0400
Subject: [PATCH v2 13/15] bufmgr: Detect some missing
 BufferPrepareToSetHintBits() calls

Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/storage/buffer/bufmgr.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 6f39cc14596..a91e4a7eff5 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -4993,6 +4993,24 @@ MarkBufferDirtyHintImpl(Buffer buffer, bool buffer_std, bool single_hint_write)
 	/* here, either share or exclusive lock is OK */
 	Assert(LWLockHeldByMe(BufferDescriptorGetContentLock(bufHdr)));
 
+	/*
+	 * A share-locked buffer may only be marked dirty for hints after having
+	 * gotten the permission to do so with BufferPrepareToSetHintBits(). It'd
+	 * perhaps be cheap enough to test this even outside of assert enabled
+	 * builds, but LWLockHeldByMeInMode() says "debug support only".
+	 */
+#ifdef USE_ASSERT_CHECKING
+	if (!single_hint_write)
+	{
+		uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
+
+		if (!LWLockHeldByMeInMode(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE))
+		{
+			Assert(buf_state & BM_SETTING_HINTS);
+		}
+	}
+#endif
+
 	/*
 	 * This routine might get called many times on the same page, if we are
 	 * making the first scan after commit of an xact that added/deleted many
-- 
2.45.2.746.g06e570c0df.dirty

