From c83d29130375d256b20027fef7e4a75ce51ccfe9 Mon Sep 17 00:00:00 2001
From: Greg Burd <greg@burd.me>
Date: Sun, 11 Oct 2026 17:34:51 +0000
Subject: [PATCH v20261011 05/12] clock-sweep: admit demand-loaded pages on
 probation

A page read in from disk is admitted with its second chance already granted,
so the clock hand must pass it twice before it can be reclaimed.  For a page
that is about to be read again that is the right call, but for a page touched
once -- every page of a sequential scan -- it means the scan's own pages are
protected for a full revolution of the hand, and the pages they displace are
the ones being re-read.

Admit demand-loaded pages without the chance instead.  The next pass of the
hand can reclaim such a page, and a second access promotes it, so a page earns
its place in the working set by being used twice rather than once.  A
one-touch scan now fills and drains the pool without evicting pages that are
being re-read: scan resistance as a property of the replacement rule, with no
ring, no hint and no caller cooperation.

This does not replace BufferAccessStrategy.  The rings still bound how much of
the pool one backend can occupy and still provide the write pacing that
bulk-write callers depend on; what changes is that a page which escapes a ring
no longer starts out protected.

Pages faulted in by the buffer manager's own read-ahead are admitted the same
way, so prefetching cannot promote a page the query never looks at.
---
 src/backend/storage/buffer/bufmgr.c   | 9 +++++++--
 src/backend/storage/buffer/localbuf.c | 4 ++--
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index ea3220e43db..6aecbd7094a 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -2335,7 +2335,11 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 	 * checkpoints, except for their "init" forks, which need to be treated
 	 * just like permanent relations.
 	 */
-	set_bits |= BM_TAG_VALID | BM_SECOND_CHANCE;
+	/*
+	 * Admit the page on probation: no second chance yet, so the next pass of
+	 * the hand may reclaim it.  A further access promotes it (see PinBuffer).
+	 */
+	set_bits |= BM_TAG_VALID;
 	if (relpersistence == RELPERSISTENCE_PERMANENT || forkNum == INIT_FORKNUM)
 		set_bits |= BM_PERMANENT;
 
@@ -3004,7 +3008,8 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 
 			victim_buf_hdr->tag = tag;
 
-			set_bits |= BM_TAG_VALID | BM_SECOND_CHANCE;
+			/* Admit on probation; see the comment at the other admission site. */
+			set_bits |= BM_TAG_VALID;
 			if (bmr.relpersistence == RELPERSISTENCE_PERMANENT || fork == INIT_FORKNUM)
 				set_bits |= BM_PERMANENT;
 
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 9c6035a62d4..3daf63e8e08 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -167,7 +167,7 @@ LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
 
 		buf_state = pg_atomic_read_u64(&bufHdr->state);
 		buf_state &= ~BUF_FLAG_MASK;
-		buf_state |= BM_TAG_VALID | BM_SECOND_CHANCE;
+		buf_state |= BM_TAG_VALID;	/* admit on probation */
 		pg_atomic_unlocked_write_u64(&bufHdr->state, buf_state);
 
 		*foundPtr = false;
@@ -454,7 +454,7 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr,
 
 			victim_buf_hdr->tag = tag;
 
-			buf_state |= BM_TAG_VALID | BM_SECOND_CHANCE;
+			buf_state |= BM_TAG_VALID;	/* admit on probation */
 
 			pg_atomic_unlocked_write_u64(&victim_buf_hdr->state, buf_state);
 
-- 
2.56.0

