Elimination of the repetitive code at the SLRU bootstrap functions.

Started by Evgeny Voropaev11 months ago20 messages
#1Evgeny Voropaev
evgeny.voropaev@tantorlabs.com
1 attachment(s)

Hello hackers!

The functions, bootstrapping SLRU pages, such as BootStrapMultiXact,
BootStrapCLOG, ActivateCommitTs, multixact_redo and others, have a lot
of repetitive code.

A new proposed function BootStrapSlruPage moves a duplicating code into
the single place. Additionally, a new member ZeroFunc is implemented in
the SlruCtlData structure. The ZeroFunc keeps a pointer to a function
proper for nullifying SLRU pages of a type defined by a corresponding
SlruCtlData object.

Applying proposed modifications can simplify maintenance and future
development of Postgres code in the realm of bootstrapping SLRU.

Best regards,
Evgeny Voropaev,
Tantor Labs LLC.

Attachments:

v1-0001-Elimination-of-the-repetitive-code-at-SLRU-bootst.patchtext/x-patch; charset=UTF-8; name=v1-0001-Elimination-of-the-repetitive-code-at-SLRU-bootst.patchDownload
From 62762bf4a86af76d845755e41f46714d2b41bbe4 Mon Sep 17 00:00:00 2001
From: Evgeny Voropaev <evorop@gmail.com>
Date: Thu, 13 Feb 2025 12:43:20 +0800
Subject: [PATCH v1] Elimination of the repetitive code at the SLRU bootstrap
 functions.

The functions bootstrapping SLRU pages had a lot of repetitive code. A new
realized function BootStrapSlruPage has moved a duplicating code into the
single place. Additionally, a new member ZeroFunc has been implemented in the
SlruCtlData structure. The ZeroFunc keeps a pointer to a function proper
for nullifying SLRU pages of a type defined by a corresponding SlruCtlData
object.

Author: Evgeny Voropaev <evgeny.voropaev@tantorlabs.com> <evorop@gmail.com>
---
 src/backend/access/transam/clog.c      | 43 ++++------------
 src/backend/access/transam/commit_ts.c | 38 ++++----------
 src/backend/access/transam/multixact.c | 71 +++++---------------------
 src/backend/access/transam/slru.c      | 34 ++++++++++++
 src/backend/access/transam/subtrans.c  | 35 +++++--------
 src/include/access/slru.h              |  8 +++
 6 files changed, 87 insertions(+), 142 deletions(-)

diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 0d556c00b8c..d02a80378a1 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -102,14 +102,6 @@ TransactionIdToPage(TransactionId xid)
  */
 #define THRESHOLD_SUBTRANS_CLOG_OPT	5
 
-/*
- * Link to shared-memory data structures for CLOG control
- */
-static SlruCtlData XactCtlData;
-
-#define XactCtl (&XactCtlData)
-
-
 static int	ZeroCLOGPage(int64 pageno, bool writeXlog);
 static bool CLOGPagePrecedes(int64 page1, int64 page2);
 static void WriteZeroPageXlogRec(int64 pageno);
@@ -130,6 +122,14 @@ static void TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids,
 											   XLogRecPtr lsn, int64 pageno);
 
 
+/*
+ * Link to shared-memory data structures for CLOG control
+ */
+static SlruCtlData XactCtlData = { .ZeroPage = ZeroCLOGPage };
+
+#define XactCtl (&XactCtlData)
+
+
 /*
  * TransactionIdSetTreeStatus
  *
@@ -832,19 +832,7 @@ check_transaction_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapCLOG(void)
 {
-	int			slotno;
-	LWLock	   *lock = SimpleLruGetBankLock(XactCtl, 0);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the commit log */
-	slotno = ZeroCLOGPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(XactCtl, slotno);
-	Assert(!XactCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
+	BootStrapSlruPage(XactCtl, 0);
 }
 
 /*
@@ -1114,19 +1102,8 @@ clog_redo(XLogReaderState *record)
 	if (info == CLOG_ZEROPAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(XactCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroCLOGPage(pageno, false);
-		SimpleLruWritePage(XactCtl, slotno);
-		Assert(!XactCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		BootStrapSlruPage(XactCtl, pageno);
 	}
 	else if (info == CLOG_TRUNCATE)
 	{
diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c
index 95049acd0b5..33ef6716535 100644
--- a/src/backend/access/transam/commit_ts.c
+++ b/src/backend/access/transam/commit_ts.c
@@ -77,13 +77,6 @@ TransactionIdToCTsPage(TransactionId xid)
 #define TransactionIdToCTsEntry(xid)	\
 	((xid) % (TransactionId) COMMIT_TS_XACTS_PER_PAGE)
 
-/*
- * Link to shared-memory data structures for CommitTs control
- */
-static SlruCtlData CommitTsCtlData;
-
-#define CommitTsCtl (&CommitTsCtlData)
-
 /*
  * We keep a cache of the last value set in shared memory.
  *
@@ -121,6 +114,13 @@ static void DeactivateCommitTs(void);
 static void WriteZeroPageXlogRec(int64 pageno);
 static void WriteTruncateXlogRec(int64 pageno, TransactionId oldestXid);
 
+/*
+ * Link to shared-memory data structures for CommitTs control
+ */
+static SlruCtlData CommitTsCtlData = { .ZeroPage = ZeroCommitTsPage };
+
+#define CommitTsCtl (&CommitTsCtlData)
+
 /*
  * TransactionTreeSetCommitTsData
  *
@@ -747,16 +747,7 @@ ActivateCommitTs(void)
 
 	/* Create the current segment file, if necessary */
 	if (!SimpleLruDoesPhysicalPageExist(CommitTsCtl, pageno))
-	{
-		LWLock	   *lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-		int			slotno;
-
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-		slotno = ZeroCommitTsPage(pageno, false);
-		SimpleLruWritePage(CommitTsCtl, slotno);
-		Assert(!CommitTsCtl->shared->page_dirty[slotno]);
-		LWLockRelease(lock);
-	}
+		BootStrapSlruPage(CommitTsCtl, pageno);
 
 	/* Change the activation status in shared memory. */
 	LWLockAcquire(CommitTsLock, LW_EXCLUSIVE);
@@ -1023,19 +1014,8 @@ commit_ts_redo(XLogReaderState *record)
 	if (info == COMMIT_TS_ZEROPAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroCommitTsPage(pageno, false);
-		SimpleLruWritePage(CommitTsCtl, slotno);
-		Assert(!CommitTsCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		BootStrapSlruPage(CommitTsCtl, pageno);
 	}
 	else if (info == COMMIT_TS_TRUNCATE)
 	{
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 27ccdf9500f..5fb688d19a1 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -223,15 +223,6 @@ PreviousMultiXactId(MultiXactId multi)
 	return multi == FirstMultiXactId ? MaxMultiXactId : multi - 1;
 }
 
-/*
- * Links to shared-memory data structures for MultiXact control
- */
-static SlruCtlData MultiXactOffsetCtlData;
-static SlruCtlData MultiXactMemberCtlData;
-
-#define MultiXactOffsetCtl	(&MultiXactOffsetCtlData)
-#define MultiXactMemberCtl	(&MultiXactMemberCtlData)
-
 /*
  * MultiXact state shared across all backends.  All this state is protected
  * by MultiXactGenLock.  (We also use SLRU bank's lock of MultiXactOffset and
@@ -420,6 +411,14 @@ static void WriteMTruncateXlogRec(Oid oldestMultiDB,
 								  MultiXactOffset startTruncMemb,
 								  MultiXactOffset endTruncMemb);
 
+/*
+ * Links to shared-memory data structures for MultiXact control
+ */
+static SlruCtlData MultiXactOffsetCtlData = { .ZeroPage = &ZeroMultiXactOffsetPage };
+static SlruCtlData MultiXactMemberCtlData = { .ZeroPage = &ZeroMultiXactMemberPage };
+
+#define MultiXactOffsetCtl	(&MultiXactOffsetCtlData)
+#define MultiXactMemberCtl	(&MultiXactMemberCtlData)
 
 /*
  * MultiXactIdCreate
@@ -2033,32 +2032,8 @@ check_multixact_member_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapMultiXact(void)
 {
-	int			slotno;
-	LWLock	   *lock;
-
-	lock = SimpleLruGetBankLock(MultiXactOffsetCtl, 0);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the offsets log */
-	slotno = ZeroMultiXactOffsetPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(MultiXactOffsetCtl, slotno);
-	Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-
-	lock = SimpleLruGetBankLock(MultiXactMemberCtl, 0);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the members log */
-	slotno = ZeroMultiXactMemberPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(MultiXactMemberCtl, slotno);
-	Assert(!MultiXactMemberCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
+	BootStrapSlruPage(MultiXactOffsetCtl, 0);
+	BootStrapSlruPage(MultiXactMemberCtl, 0);
 }
 
 /*
@@ -3401,36 +3376,14 @@ multixact_redo(XLogReaderState *record)
 	if (info == XLOG_MULTIXACT_ZERO_OFF_PAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroMultiXactOffsetPage(pageno, false);
-		SimpleLruWritePage(MultiXactOffsetCtl, slotno);
-		Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		BootStrapSlruPage(MultiXactOffsetCtl, pageno);
 	}
 	else if (info == XLOG_MULTIXACT_ZERO_MEM_PAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(MultiXactMemberCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroMultiXactMemberPage(pageno, false);
-		SimpleLruWritePage(MultiXactMemberCtl, slotno);
-		Assert(!MultiXactMemberCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		BootStrapSlruPage(MultiXactMemberCtl, pageno);
 	}
 	else if (info == XLOG_MULTIXACT_CREATE_ID)
 	{
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index 9ce628e62a5..b73bea16972 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -1850,3 +1850,37 @@ SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path)
 	errno = save_errno;
 	return result;
 }
+
+/*
+ * BootStrapSlruPage is a workhorse for functions bootstraping
+ *  SLRU pages, including:
+ *		BootStrapMultiXact,
+ *		BootStrapCLOG,
+ *		ActivateCommitTs,
+ *		multixact_redo,
+ *		commit_ts_redo.
+ *
+ * It performs all of the rut such as acquiring a lock, zeroing,
+ * ensuring that bootstrapped page is written out, and releasing the lock.
+ *
+ * A caller has to provide a proper ZeroFunc in the ctl structure.
+ *
+ */
+void
+BootStrapSlruPage(SlruCtl ctl, int64 pageno)
+{
+	int			slotno;
+	LWLock	   *lock;
+
+	lock = SimpleLruGetBankLock(ctl, pageno);
+	LWLockAcquire(lock, LW_EXCLUSIVE);
+
+	/* Create and zero the page in SLRU */
+	slotno = ctl->ZeroPage(pageno, false);
+
+	/* Make sure it's written out */
+	SimpleLruWritePage(ctl, slotno);
+	Assert(!ctl->shared->page_dirty[slotno]);
+
+	LWLockRelease(lock);
+}
diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c
index 15153618fad..bad2c15951b 100644
--- a/src/backend/access/transam/subtrans.c
+++ b/src/backend/access/transam/subtrans.c
@@ -66,18 +66,18 @@ TransactionIdToPage(TransactionId xid)
 #define TransactionIdToEntry(xid) ((xid) % (TransactionId) SUBTRANS_XACTS_PER_PAGE)
 
 
+static int	ZeroSUBTRANSPage(int64 pageno, bool unused);
+static bool SubTransPagePrecedes(int64 page1, int64 page2);
+
+
 /*
  * Link to shared-memory data structures for SUBTRANS control
  */
-static SlruCtlData SubTransCtlData;
+static SlruCtlData SubTransCtlData = { .ZeroPage = ZeroSUBTRANSPage };
 
 #define SubTransCtl  (&SubTransCtlData)
 
 
-static int	ZeroSUBTRANSPage(int64 pageno);
-static bool SubTransPagePrecedes(int64 page1, int64 page2);
-
-
 /*
  * Record the parent of a subtransaction in the subtrans log.
  */
@@ -269,19 +269,7 @@ check_subtrans_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapSUBTRANS(void)
 {
-	int			slotno;
-	LWLock	   *lock = SimpleLruGetBankLock(SubTransCtl, 0);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the subtrans log */
-	slotno = ZeroSUBTRANSPage(0);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(SubTransCtl, slotno);
-	Assert(!SubTransCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
+	BootStrapSlruPage(SubTransCtl, 0);
 }
 
 /*
@@ -291,10 +279,15 @@ BootStrapSUBTRANS(void)
  * The slot number of the new page is returned.
  *
  * Control lock must be held at entry, and will be held at exit.
+ * 
+ * bool unused is a parameter required to provide matching of the 
+ * ZeroSUBTRANSPage function to the SlruCtlData.ZeroPage function type.
  */
 static int
-ZeroSUBTRANSPage(int64 pageno)
+ZeroSUBTRANSPage(int64 pageno, bool unused)
 {
+	(void)unused; /* Supress compiler warning*/
+
 	return SimpleLruZeroPage(SubTransCtl, pageno);
 }
 
@@ -335,7 +328,7 @@ StartupSUBTRANS(TransactionId oldestActiveXID)
 			prevlock = lock;
 		}
 
-		(void) ZeroSUBTRANSPage(startPage);
+		(void) ZeroSUBTRANSPage(startPage, false);
 		if (startPage == endPage)
 			break;
 
@@ -395,7 +388,7 @@ ExtendSUBTRANS(TransactionId newestXact)
 	LWLockAcquire(lock, LW_EXCLUSIVE);
 
 	/* Zero the page */
-	ZeroSUBTRANSPage(pageno);
+	ZeroSUBTRANSPage(pageno, false);
 
 	LWLockRelease(lock);
 }
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index e142800aab2..ec48355ac74 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -161,6 +161,13 @@ typedef struct SlruCtlData
 	 * it's always the same, it doesn't need to be in shared memory.
 	 */
 	char		Dir[64];
+
+	/*
+	 * Function for nulifying a page pointed by this SlruCtlData object
+	 * Signature: 
+	 * 				int ZeroPage(int64 pageno, bool writeXlog);
+	*/
+	int			(*ZeroPage) (int64, bool);
 } SlruCtlData;
 
 typedef SlruCtlData *SlruCtl;
@@ -214,5 +221,6 @@ extern bool SlruScanDirCbReportPresence(SlruCtl ctl, char *filename,
 extern bool SlruScanDirCbDeleteAll(SlruCtl ctl, char *filename, int64 segpage,
 								   void *data);
 extern bool check_slru_buffers(const char *name, int *newval);
+extern void BootStrapSlruPage(SlruCtl ctl, int64 pageno);
 
 #endif							/* SLRU_H */
-- 
2.47.1

#2Aleksander Alekseev
aleksander@timescale.com
In reply to: Evgeny Voropaev (#1)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

Hi Evgeny,

The functions, bootstrapping SLRU pages, such as BootStrapMultiXact,
BootStrapCLOG, ActivateCommitTs, multixact_redo and others, have a lot
of repetitive code.

A new proposed function BootStrapSlruPage moves a duplicating code into
the single place. Additionally, a new member ZeroFunc is implemented in
the SlruCtlData structure. The ZeroFunc keeps a pointer to a function
proper for nullifying SLRU pages of a type defined by a corresponding
SlruCtlData object.

Applying proposed modifications can simplify maintenance and future
development of Postgres code in the realm of bootstrapping SLRU.

Thanks for the patch.

```
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -102,14 +102,6 @@ TransactionIdToPage(TransactionId xid)
  */
 #define THRESHOLD_SUBTRANS_CLOG_OPT    5
-/*
- * Link to shared-memory data structures for CLOG control
- */
-static SlruCtlData XactCtlData;
-
-#define XactCtl (&XactCtlData)
-
-
 static int    ZeroCLOGPage(int64 pageno, bool writeXlog);
 static bool CLOGPagePrecedes(int64 page1, int64 page2);
 static void WriteZeroPageXlogRec(int64 pageno);
@@ -130,6 +122,14 @@ static void
TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids,
                                                XLogRecPtr lsn, int64 pageno);
+/*
+ * Link to shared-memory data structures for CLOG control
+ */
+static SlruCtlData XactCtlData = { .ZeroPage = ZeroCLOGPage };
+
+#define XactCtl (&XactCtlData)
+
+
```

Since BootStrapSlruPage() is the only caller of ZeroPage() it seems to
me that it merely wastes space in SlruCtlData. On top of that I'm not
100% sure if all the supported platforms have C99 compilers with
designated initializers support. Wouldn't it be simpler to pass the
callback straight to BootStrapSlruPage()?

After changing the patch accordingly it shouldn't move XactCtl and
others. This is just an irrelevant change.

--
Best regards,
Aleksander Alekseev

#3Álvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Aleksander Alekseev (#2)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

On 2025-Feb-13, Aleksander Alekseev wrote:

Since BootStrapSlruPage() is the only caller of ZeroPage() it seems to
me that it merely wastes space in SlruCtlData. On top of that I'm not
100% sure if all the supported platforms have C99 compilers with
designated initializers support.

They do -- we use them quite extensively nowadays.

Wouldn't it be simpler to pass the callback straight to
BootStrapSlruPage()?

Yeah, maybe this would be easier.

--
Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/
"Just treat us the way you want to be treated + some extra allowance
for ignorance." (Michael Brusser)

#4Aleksander Alekseev
aleksander@timescale.com
In reply to: Álvaro Herrera (#3)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

Hi Alvaro,

Since BootStrapSlruPage() is the only caller of ZeroPage() it seems to
me that it merely wastes space in SlruCtlData. On top of that I'm not
100% sure if all the supported platforms have C99 compilers with
designated initializers support.

They do -- we use them quite extensively nowadays.

Got it, thanks. I was a bit worried about Visual Studio in particular.

--
Best regards,
Aleksander Alekseev

#5Evgeny Voropaev
evgeny.voropaev@tantorlabs.com
In reply to: Aleksander Alekseev (#4)
1 attachment(s)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

Hello Aleksander!
Hello Álvaro!
Thank you for your attention to the patch.

Since BootStrapSlruPage() is the only caller of ZeroPage() it seems to
me that it merely wastes space in SlruCtlData. On top of that I'm not
100% sure if all the supported platforms have C99 compilers with
designated initializers support.

Wouldn't it be simpler to pass the callback straight to
BootStrapSlruPage()?

I agree with your proposals. Moreover, similar solution is also implemented and exploited at
Tantor's versions of the xid64 patch (/messages/by-id/5ca56aed-dc69-4c3e-968f-a822ae0937b5@gmail.com).

The corrected patch version implementing these proposals is attached.

Best regards,
Evgeny Voropaev,
Tantor Labs LLC.

Attachments:

v2-0001-Elimination-of-the-repetitive-code-at-the-SLRU-bo.patchtext/x-patch; charset=UTF-8; name=v2-0001-Elimination-of-the-repetitive-code-at-the-SLRU-bo.patchDownload
From a5a29cdbb37834bfcd23cd22db90a78a7db43d18 Mon Sep 17 00:00:00 2001
From: Evgeny Voropaev <evorop@gmail.com>
Date: Fri, 14 Feb 2025 14:03:01 +0800
Subject: [PATCH v2] Elimination of the repetitive code at the SLRU bootstrap
 functions.

The functions bootstrapping SLRU pages used to have a lot of repetitive code. The new
realized function BootStrapSlruPage has moved duplicating code into the
single place and eliminated code repetitions.

Author: Evgeny Voropaev <evgeny.voropaev@tantorlabs.com> <evorop@gmail.com>
---
 src/backend/access/transam/clog.c      | 27 +------------
 src/backend/access/transam/commit_ts.c | 24 +-----------
 src/backend/access/transam/multixact.c | 54 ++------------------------
 src/backend/access/transam/slru.c      | 35 +++++++++++++++++
 src/backend/access/transam/subtrans.c  | 28 ++++++-------
 src/include/access/slru.h              |  1 +
 6 files changed, 55 insertions(+), 114 deletions(-)

diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 0d556c00b8c..5ae684da6af 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -832,19 +832,7 @@ check_transaction_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapCLOG(void)
 {
-	int			slotno;
-	LWLock	   *lock = SimpleLruGetBankLock(XactCtl, 0);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the commit log */
-	slotno = ZeroCLOGPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(XactCtl, slotno);
-	Assert(!XactCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
+	BootStrapSlruPage(XactCtl, 0, ZeroCLOGPage);
 }
 
 /*
@@ -1114,19 +1102,8 @@ clog_redo(XLogReaderState *record)
 	if (info == CLOG_ZEROPAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(XactCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroCLOGPage(pageno, false);
-		SimpleLruWritePage(XactCtl, slotno);
-		Assert(!XactCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		BootStrapSlruPage(XactCtl, pageno, ZeroCLOGPage);
 	}
 	else if (info == CLOG_TRUNCATE)
 	{
diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c
index 95049acd0b5..54600f1b69c 100644
--- a/src/backend/access/transam/commit_ts.c
+++ b/src/backend/access/transam/commit_ts.c
@@ -747,16 +747,7 @@ ActivateCommitTs(void)
 
 	/* Create the current segment file, if necessary */
 	if (!SimpleLruDoesPhysicalPageExist(CommitTsCtl, pageno))
-	{
-		LWLock	   *lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-		int			slotno;
-
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-		slotno = ZeroCommitTsPage(pageno, false);
-		SimpleLruWritePage(CommitTsCtl, slotno);
-		Assert(!CommitTsCtl->shared->page_dirty[slotno]);
-		LWLockRelease(lock);
-	}
+		BootStrapSlruPage(CommitTsCtl, pageno, ZeroCommitTsPage);
 
 	/* Change the activation status in shared memory. */
 	LWLockAcquire(CommitTsLock, LW_EXCLUSIVE);
@@ -1023,19 +1014,8 @@ commit_ts_redo(XLogReaderState *record)
 	if (info == COMMIT_TS_ZEROPAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroCommitTsPage(pageno, false);
-		SimpleLruWritePage(CommitTsCtl, slotno);
-		Assert(!CommitTsCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		BootStrapSlruPage(CommitTsCtl, pageno, ZeroCommitTsPage);
 	}
 	else if (info == COMMIT_TS_TRUNCATE)
 	{
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 27ccdf9500f..30cc47021f7 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -2033,32 +2033,8 @@ check_multixact_member_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapMultiXact(void)
 {
-	int			slotno;
-	LWLock	   *lock;
-
-	lock = SimpleLruGetBankLock(MultiXactOffsetCtl, 0);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the offsets log */
-	slotno = ZeroMultiXactOffsetPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(MultiXactOffsetCtl, slotno);
-	Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-
-	lock = SimpleLruGetBankLock(MultiXactMemberCtl, 0);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the members log */
-	slotno = ZeroMultiXactMemberPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(MultiXactMemberCtl, slotno);
-	Assert(!MultiXactMemberCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
+	BootStrapSlruPage(MultiXactOffsetCtl, 0, ZeroMultiXactOffsetPage);
+	BootStrapSlruPage(MultiXactMemberCtl, 0, ZeroMultiXactMemberPage);
 }
 
 /*
@@ -3401,36 +3377,14 @@ multixact_redo(XLogReaderState *record)
 	if (info == XLOG_MULTIXACT_ZERO_OFF_PAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroMultiXactOffsetPage(pageno, false);
-		SimpleLruWritePage(MultiXactOffsetCtl, slotno);
-		Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		BootStrapSlruPage(MultiXactOffsetCtl, pageno, ZeroMultiXactOffsetPage);
 	}
 	else if (info == XLOG_MULTIXACT_ZERO_MEM_PAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(MultiXactMemberCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroMultiXactMemberPage(pageno, false);
-		SimpleLruWritePage(MultiXactMemberCtl, slotno);
-		Assert(!MultiXactMemberCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		BootStrapSlruPage(MultiXactMemberCtl, pageno, ZeroMultiXactMemberPage);
 	}
 	else if (info == XLOG_MULTIXACT_CREATE_ID)
 	{
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index 9ce628e62a5..fd332fd4c64 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -1850,3 +1850,38 @@ SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path)
 	errno = save_errno;
 	return result;
 }
+
+/*
+ * BootStrapSlruPage is a workhorse for functions bootstraping
+ *  SLRU pages, including:
+ *		BootStrapMultiXact,
+ *		BootStrapCLOG,
+ *		ActivateCommitTs,
+ *		multixact_redo,
+ *		commit_ts_redo.
+ *
+ * It performs all of the rut such as acquiring a lock, zeroing,
+ * ensuring that a bootstrapped page is written out, and releasing the lock.
+ *
+ * A caller has to provide a proper zerofunc appropriate for the type of 
+ * the page.
+ *
+ */
+void
+BootStrapSlruPage(SlruCtl ctl, int64 pageno, int(*zerofunc)(int64, bool) )
+{
+	int			slotno;
+	LWLock	   *lock;
+
+	lock = SimpleLruGetBankLock(ctl, pageno);
+	LWLockAcquire(lock, LW_EXCLUSIVE);
+
+	/* Create and zero the page*/
+	slotno = (*zerofunc)(pageno, false);
+
+	/* Make sure it's written out */
+	SimpleLruWritePage(ctl, slotno);
+	Assert(!ctl->shared->page_dirty[slotno]);
+
+	LWLockRelease(lock);
+}
diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c
index 15153618fad..ec63c823d66 100644
--- a/src/backend/access/transam/subtrans.c
+++ b/src/backend/access/transam/subtrans.c
@@ -74,7 +74,7 @@ static SlruCtlData SubTransCtlData;
 #define SubTransCtl  (&SubTransCtlData)
 
 
-static int	ZeroSUBTRANSPage(int64 pageno);
+static int	ZeroSUBTRANSPage(int64 pageno, bool unused);
 static bool SubTransPagePrecedes(int64 page1, int64 page2);
 
 
@@ -269,19 +269,7 @@ check_subtrans_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapSUBTRANS(void)
 {
-	int			slotno;
-	LWLock	   *lock = SimpleLruGetBankLock(SubTransCtl, 0);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the subtrans log */
-	slotno = ZeroSUBTRANSPage(0);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(SubTransCtl, slotno);
-	Assert(!SubTransCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
+	BootStrapSlruPage(SubTransCtl, 0, ZeroSUBTRANSPage);
 }
 
 /*
@@ -291,10 +279,16 @@ BootStrapSUBTRANS(void)
  * The slot number of the new page is returned.
  *
  * Control lock must be held at entry, and will be held at exit.
+ *
+ * "bool unused" is a parameter required to provide matching of the
+ * ZeroSUBTRANSPage function to the zerofunc function prototype
+ * used by BootStrapSlruPage.
  */
 static int
-ZeroSUBTRANSPage(int64 pageno)
+ZeroSUBTRANSPage(int64 pageno, bool unused)
 {
+	(void)unused; /* Supress compiler warning */
+
 	return SimpleLruZeroPage(SubTransCtl, pageno);
 }
 
@@ -335,7 +329,7 @@ StartupSUBTRANS(TransactionId oldestActiveXID)
 			prevlock = lock;
 		}
 
-		(void) ZeroSUBTRANSPage(startPage);
+		(void) ZeroSUBTRANSPage(startPage, false);
 		if (startPage == endPage)
 			break;
 
@@ -395,7 +389,7 @@ ExtendSUBTRANS(TransactionId newestXact)
 	LWLockAcquire(lock, LW_EXCLUSIVE);
 
 	/* Zero the page */
-	ZeroSUBTRANSPage(pageno);
+	ZeroSUBTRANSPage(pageno, false);
 
 	LWLockRelease(lock);
 }
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index e142800aab2..515986b4506 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -214,5 +214,6 @@ extern bool SlruScanDirCbReportPresence(SlruCtl ctl, char *filename,
 extern bool SlruScanDirCbDeleteAll(SlruCtl ctl, char *filename, int64 segpage,
 								   void *data);
 extern bool check_slru_buffers(const char *name, int *newval);
+extern void BootStrapSlruPage( SlruCtl ctl, int64 pageno, int(*zerofunc)(int64, bool) );
 
 #endif							/* SLRU_H */
-- 
2.47.1

#6Andrey Borodin
x4mmm@yandex-team.ru
In reply to: Evgeny Voropaev (#5)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

On 14 Feb 2025, at 11:54, Evgeny Voropaev <evgeny.voropaev@tantorlabs.com> wrote:

<v2-0001-Elimination-of-the-repetitive-code-at-the-SLRU-bo.patch>

Hi! Nice patch!

BootStrapSlruPage() always calls zerofunc(pageno, false) with second argument false.
In case of every possible argument (ZeroCLOGPage, ZeroCommitTsPage, ZeroMultiXactOffsetPage, ZeroMultiXactMemberPage, ZeroSUBTRANSPage) it means just a call to SimpleLruZeroPage().
I think we can safely replace

+ slotno = (*zerofunc)(pageno, false);

with

+ slotno = SimpleLruZeroPage(pageno);

Thus we will not need zerofunc argument at all.

Thanks!

Best regards, Andrey Borodin.

#7Álvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Andrey Borodin (#6)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

On 2025-Feb-17, Andrey Borodin wrote:

BootStrapSlruPage() always calls zerofunc(pageno, false) with second argument false.
In case of every possible argument (ZeroCLOGPage, ZeroCommitTsPage,
ZeroMultiXactOffsetPage, ZeroMultiXactMemberPage, ZeroSUBTRANSPage) it
means just a call to SimpleLruZeroPage().
I think we can safely replace

+ slotno = (*zerofunc)(pageno, false);

with

+ slotno = SimpleLruZeroPage(pageno);

Thus we will not need zerofunc argument at all.

Good observation. This also suggests another change: because this new
function is used not only for bootstrapping but also during WAL replay,
we can call the new function SimpleLruUnloggedZeroPage() and place it
immediately after SimpleLruZeroPage, instead of at the end of the file.

--
Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/
"La persona que no quería pecar / estaba obligada a sentarse
en duras y empinadas sillas / desprovistas, por cierto
de blandos atenuantes" (Patricio Vogel)

#8Evgeny Voropaev
evgeny.voropaev@tantorlabs.com
In reply to: Álvaro Herrera (#7)
1 attachment(s)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

On 17.02.2025 21:00, Álvaro Herrera wrote:

On 2025-Feb-17, Andrey Borodin wrote:

BootStrapSlruPage() always calls zerofunc(pageno, false) with second argument false.
In case of every possible argument (ZeroCLOGPage, ZeroCommitTsPage,
ZeroMultiXactOffsetPage, ZeroMultiXactMemberPage, ZeroSUBTRANSPage) it
means just a call to SimpleLruZeroPage().
I think we can safely replace

+ slotno = (*zerofunc)(pageno, false);

with

+ slotno = SimpleLruZeroPage(pageno);

Thus we will not need zerofunc argument at all.

Good observation. This also suggests another change: because this new
function is used not only for bootstrapping but also during WAL replay,
we can call the new function SimpleLruUnloggedZeroPage() and place it
immediately after SimpleLruZeroPage, instead of at the end of the file.

Created functions BootStrapSlruPage,SimpleLruZeroAndLogPage,
WriteSlruZeroPageXlogRec. Using of these functions allows to delete
ZeroXYZPage functions, WriteXYZZeroPageXlogRec functions and eliminate
code repetitions.

The conception is:
/*
* BootStrapSlruPage,
* SimpleLruZeroAndLogPage,
* SimpleLruZeroPage
* - functions nullifying SLRU pages.
*
* BootStrapSlruPage is the most holistic. It performs:
* 1. locking,
* 2. nullifying,
* 3. logging (when writeXlog is true),
* 4. writing out,
* 5. releasing the lock.
*
* SimpleLruZeroAndLogPage performs:
* 2. nullifying,
* 3. logging (when writeXlog is true),
* 4. writing out.
*
* If the writeXlog is true, BootStrapSlruPage and SimpleLruZeroAndLogPage
* emit an XLOG record saying we did this.
* If the writeXlog is false, the rmid and info parameters are unused.
*
* SimpleLruZeroPage performs:
* 2. nullifying.
*/

Attachments:

v3-0001-Elimination-of-the-repetitive-code-at-the-SLRU-bo.patchtext/x-patch; charset=UTF-8; name=v3-0001-Elimination-of-the-repetitive-code-at-the-SLRU-bo.patchDownload
From de4621460b1b63fb3cbc78095af31e1e6b565dd2 Mon Sep 17 00:00:00 2001
From: Evgeny Voropaev <evorop@gmail.com>
Date: Tue, 18 Feb 2025 15:48:12 +0800
Subject: [PATCH v3] Elimination of the repetitive code at the SLRU
 bootstrapping and nullifying functions.

The functions bootstrapping and nullifying SLRU pages used to have a lot of
repetitive code. New functions realized by this commit (BootStrapSlruPage,
SimpleLruZeroAndLogPage, WriteSlruZeroPageXlogRec) have moved duplicating code
into the single place and eliminated code repetitions.

Author: Evgeny Voropaev <evgeny.voropaev@tantorlabs.com> <evorop@gmail.com>
---
 src/backend/access/transam/clog.c      |  65 +-------------
 src/backend/access/transam/commit_ts.c |  65 ++------------
 src/backend/access/transam/multixact.c | 117 +++----------------------
 src/backend/access/transam/slru.c      |  73 ++++++++++++++-
 src/backend/access/transam/subtrans.c  |  35 +-------
 src/include/access/slru.h              |   5 ++
 6 files changed, 105 insertions(+), 255 deletions(-)

diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 48f10bec91e..a78b8bde628 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -110,9 +110,7 @@ static SlruCtlData XactCtlData;
 #define XactCtl (&XactCtlData)
 
 
-static int	ZeroCLOGPage(int64 pageno, bool writeXlog);
 static bool CLOGPagePrecedes(int64 page1, int64 page2);
-static void WriteZeroPageXlogRec(int64 pageno);
 static void WriteTruncateXlogRec(int64 pageno, TransactionId oldestXact,
 								 Oid oldestXactDb);
 static void TransactionIdSetPageStatus(TransactionId xid, int nsubxids,
@@ -832,41 +830,7 @@ check_transaction_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapCLOG(void)
 {
-	int			slotno;
-	LWLock	   *lock = SimpleLruGetBankLock(XactCtl, 0);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the commit log */
-	slotno = ZeroCLOGPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(XactCtl, slotno);
-	Assert(!XactCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of CLOG to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroCLOGPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(XactCtl, pageno);
-
-	if (writeXlog)
-		WriteZeroPageXlogRec(pageno);
-
-	return slotno;
+	BootStrapSlruPage(XactCtl, 0, false, RM_CLOG_ID, CLOG_ZEROPAGE);
 }
 
 /*
@@ -975,8 +939,7 @@ ExtendCLOG(TransactionId newestXact)
 	LWLockAcquire(lock, LW_EXCLUSIVE);
 
 	/* Zero the page and make an XLOG entry about it */
-	ZeroCLOGPage(pageno, true);
-
+	SimpleLruZeroAndLogPage(XactCtl, pageno, true, RM_CLOG_ID, CLOG_ZEROPAGE);
 	LWLockRelease(lock);
 }
 
@@ -1067,17 +1030,6 @@ CLOGPagePrecedes(int64 page1, int64 page2)
 }
 
 
-/*
- * Write a ZEROPAGE xlog record
- */
-static void
-WriteZeroPageXlogRec(int64 pageno)
-{
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE);
-}
-
 /*
  * Write a TRUNCATE xlog record
  *
@@ -1114,19 +1066,8 @@ clog_redo(XLogReaderState *record)
 	if (info == CLOG_ZEROPAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(XactCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroCLOGPage(pageno, false);
-		SimpleLruWritePage(XactCtl, slotno);
-		Assert(!XactCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		BootStrapSlruPage(XactCtl, pageno, false, RM_CLOG_ID, CLOG_ZEROPAGE);
 	}
 	else if (info == CLOG_TRUNCATE)
 	{
diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c
index 113fae1437a..766e8b7bf0a 100644
--- a/src/backend/access/transam/commit_ts.c
+++ b/src/backend/access/transam/commit_ts.c
@@ -114,11 +114,9 @@ static void SetXidCommitTsInPage(TransactionId xid, int nsubxids,
 static void TransactionIdSetCommitTs(TransactionId xid, TimestampTz ts,
 									 RepOriginId nodeid, int slotno);
 static void error_commit_ts_disabled(void);
-static int	ZeroCommitTsPage(int64 pageno, bool writeXlog);
 static bool CommitTsPagePrecedes(int64 page1, int64 page2);
 static void ActivateCommitTs(void);
 static void DeactivateCommitTs(void);
-static void WriteZeroPageXlogRec(int64 pageno);
 static void WriteTruncateXlogRec(int64 pageno, TransactionId oldestXid);
 
 /*
@@ -602,28 +600,6 @@ BootStrapCommitTs(void)
 	 */
 }
 
-/*
- * Initialize (or reinitialize) a page of CommitTs to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroCommitTsPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(CommitTsCtl, pageno);
-
-	if (writeXlog)
-		WriteZeroPageXlogRec(pageno);
-
-	return slotno;
-}
-
 /*
  * This must be called ONCE during postmaster or standalone-backend startup,
  * after StartupXLOG has initialized TransamVariables->nextXid.
@@ -747,16 +723,8 @@ ActivateCommitTs(void)
 
 	/* Create the current segment file, if necessary */
 	if (!SimpleLruDoesPhysicalPageExist(CommitTsCtl, pageno))
-	{
-		LWLock	   *lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-		int			slotno;
-
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-		slotno = ZeroCommitTsPage(pageno, false);
-		SimpleLruWritePage(CommitTsCtl, slotno);
-		Assert(!CommitTsCtl->shared->page_dirty[slotno]);
-		LWLockRelease(lock);
-	}
+		BootStrapSlruPage(CommitTsCtl, pageno, 
+						  false, RM_COMMIT_TS_ID, COMMIT_TS_ZEROPAGE);
 
 	/* Change the activation status in shared memory. */
 	LWLockAcquire(CommitTsLock, LW_EXCLUSIVE);
@@ -868,7 +836,8 @@ ExtendCommitTs(TransactionId newestXact)
 	LWLockAcquire(lock, LW_EXCLUSIVE);
 
 	/* Zero the page and make an XLOG entry about it */
-	ZeroCommitTsPage(pageno, !InRecovery);
+	SimpleLruZeroAndLogPage(CommitTsCtl, pageno, 
+							!InRecovery, RM_COMMIT_TS_ID, COMMIT_TS_ZEROPAGE);
 
 	LWLockRelease(lock);
 }
@@ -982,17 +951,6 @@ CommitTsPagePrecedes(int64 page1, int64 page2)
 }
 
 
-/*
- * Write a ZEROPAGE xlog record
- */
-static void
-WriteZeroPageXlogRec(int64 pageno)
-{
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_COMMIT_TS_ID, COMMIT_TS_ZEROPAGE);
-}
-
 /*
  * Write a TRUNCATE xlog record
  */
@@ -1023,19 +981,10 @@ commit_ts_redo(XLogReaderState *record)
 	if (info == COMMIT_TS_ZEROPAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroCommitTsPage(pageno, false);
-		SimpleLruWritePage(CommitTsCtl, slotno);
-		Assert(!CommitTsCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		
+		BootStrapSlruPage(CommitTsCtl, pageno, 
+						  false, RM_COMMIT_TS_ID, COMMIT_TS_ZEROPAGE);
 	}
 	else if (info == COMMIT_TS_TRUNCATE)
 	{
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index c1e2c42e1bb..6961c354306 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -401,8 +401,6 @@ static void mXactCachePut(MultiXactId multi, int nmembers,
 static char *mxstatus_to_string(MultiXactStatus status);
 
 /* management of SLRU infrastructure */
-static int	ZeroMultiXactOffsetPage(int64 pageno, bool writeXlog);
-static int	ZeroMultiXactMemberPage(int64 pageno, bool writeXlog);
 static bool MultiXactOffsetPagePrecedes(int64 page1, int64 page2);
 static bool MultiXactMemberPagePrecedes(int64 page1, int64 page2);
 static bool MultiXactOffsetPrecedes(MultiXactOffset offset1,
@@ -413,7 +411,6 @@ static bool MultiXactOffsetWouldWrap(MultiXactOffset boundary,
 									 MultiXactOffset start, uint32 distance);
 static bool SetOffsetVacuumLimit(bool is_startup);
 static bool find_multixact_start(MultiXactId multi, MultiXactOffset *result);
-static void WriteMZeroPageXlogRec(int64 pageno, uint8 info);
 static void WriteMTruncateXlogRec(Oid oldestMultiDB,
 								  MultiXactId startTruncOff,
 								  MultiXactId endTruncOff,
@@ -2033,70 +2030,11 @@ check_multixact_member_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapMultiXact(void)
 {
-	int			slotno;
-	LWLock	   *lock;
-
-	lock = SimpleLruGetBankLock(MultiXactOffsetCtl, 0);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the offsets log */
-	slotno = ZeroMultiXactOffsetPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(MultiXactOffsetCtl, slotno);
-	Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-
-	lock = SimpleLruGetBankLock(MultiXactMemberCtl, 0);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the members log */
-	slotno = ZeroMultiXactMemberPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(MultiXactMemberCtl, slotno);
-	Assert(!MultiXactMemberCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of MultiXactOffset to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroMultiXactOffsetPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(MultiXactOffsetCtl, pageno);
-
-	if (writeXlog)
-		WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_OFF_PAGE);
-
-	return slotno;
-}
-
-/*
- * Ditto, for MultiXactMember
- */
-static int
-ZeroMultiXactMemberPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(MultiXactMemberCtl, pageno);
-
-	if (writeXlog)
-		WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_MEM_PAGE);
+	BootStrapSlruPage(MultiXactOffsetCtl, 0,
+					  false, RM_MULTIXACT_ID, XLOG_MULTIXACT_ZERO_OFF_PAGE);
 
-	return slotno;
+	BootStrapSlruPage(MultiXactMemberCtl, 0,
+					  false, RM_MULTIXACT_ID, XLOG_MULTIXACT_ZERO_MEM_PAGE);
 }
 
 /*
@@ -2134,7 +2072,7 @@ MaybeExtendOffsetSlru(void)
 		 * with creating a new segment file even if the page we're writing is
 		 * not the first in it, so this is enough.
 		 */
-		slotno = ZeroMultiXactOffsetPage(pageno, false);
+		slotno = SimpleLruZeroPage(MultiXactOffsetCtl, pageno);
 		SimpleLruWritePage(MultiXactOffsetCtl, slotno);
 	}
 
@@ -2569,7 +2507,8 @@ ExtendMultiXactOffset(MultiXactId multi)
 	LWLockAcquire(lock, LW_EXCLUSIVE);
 
 	/* Zero the page and make an XLOG entry about it */
-	ZeroMultiXactOffsetPage(pageno, true);
+	SimpleLruZeroAndLogPage(MultiXactOffsetCtl, pageno,
+					  		true, RM_MULTIXACT_ID, XLOG_MULTIXACT_ZERO_OFF_PAGE);
 
 	LWLockRelease(lock);
 }
@@ -2612,7 +2551,9 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
 			LWLockAcquire(lock, LW_EXCLUSIVE);
 
 			/* Zero the page and make an XLOG entry about it */
-			ZeroMultiXactMemberPage(pageno, true);
+			SimpleLruZeroAndLogPage(MultiXactMemberCtl, pageno,
+						true, RM_MULTIXACT_ID, XLOG_MULTIXACT_ZERO_MEM_PAGE);
+
 
 			LWLockRelease(lock);
 		}
@@ -3347,18 +3288,6 @@ MultiXactOffsetPrecedes(MultiXactOffset offset1, MultiXactOffset offset2)
 	return (diff < 0);
 }
 
-/*
- * Write an xlog record reflecting the zeroing of either a MEMBERs or
- * OFFSETs page (info shows which)
- */
-static void
-WriteMZeroPageXlogRec(int64 pageno, uint8 info)
-{
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_MULTIXACT_ID, info);
-}
-
 /*
  * Write a TRUNCATE xlog record
  *
@@ -3401,36 +3330,18 @@ multixact_redo(XLogReaderState *record)
 	if (info == XLOG_MULTIXACT_ZERO_OFF_PAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
 
-		lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroMultiXactOffsetPage(pageno, false);
-		SimpleLruWritePage(MultiXactOffsetCtl, slotno);
-		Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		BootStrapSlruPage(MultiXactOffsetCtl, pageno,
+						  false, RM_MULTIXACT_ID, XLOG_MULTIXACT_ZERO_OFF_PAGE);
 	}
 	else if (info == XLOG_MULTIXACT_ZERO_MEM_PAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
 
-		lock = SimpleLruGetBankLock(MultiXactMemberCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroMultiXactMemberPage(pageno, false);
-		SimpleLruWritePage(MultiXactMemberCtl, slotno);
-		Assert(!MultiXactMemberCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		BootStrapSlruPage(MultiXactMemberCtl, pageno,
+						  false, RM_MULTIXACT_ID, XLOG_MULTIXACT_ZERO_MEM_PAGE);
 	}
 	else if (info == XLOG_MULTIXACT_CREATE_ID)
 	{
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index 9ce628e62a5..cc069da19c6 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -65,6 +65,7 @@
 #include "access/slru.h"
 #include "access/transam.h"
 #include "access/xlog.h"
+#include "access/xloginsert.h"
 #include "access/xlogutils.h"
 #include "miscadmin.h"
 #include "pgstat.h"
@@ -189,7 +190,7 @@ static bool SlruScanDirCbDeleteCutoff(SlruCtl ctl, char *filename,
 									  int64 segpage, void *data);
 static void SlruInternalDeleteSegment(SlruCtl ctl, int64 segno);
 static inline void SlruRecentlyUsed(SlruShared shared, int slotno);
-
+static inline void WriteSlruZeroPageXlogRec(int64 pageno, RmgrId rmid, uint8 info);
 
 /*
  * Initialization of shared memory
@@ -363,6 +364,65 @@ check_slru_buffers(const char *name, int *newval)
 	return false;
 }
 
+/*
+ * BootStrapSlruPage, 
+ * SimpleLruZeroAndLogPage, 
+ * SimpleLruZeroPage
+ * 		- functions nullifying SLRU pages.
+ *
+ * BootStrapSlruPage is the most holistic. It performs:
+ * 		1. locking,
+ * 		2. nullifying,
+ * 		3. logging (when writeXlog is true),
+ * 		4. writing out,
+ * 		5. releasing the lock.
+ *
+ * SimpleLruZeroAndLogPage performs:
+ * 		2. nullifying,
+ * 		3. logging (when writeXlog is true),
+ * 		4. writing out.
+ * 		
+ * If the writeXlog is true, BootStrapSlruPage and SimpleLruZeroAndLogPage 
+ * emit an XLOG record saying we did this.
+ * If the writeXlog is false, the rmid and info parameters are unused.
+ * 
+ * SimpleLruZeroPage performs:
+ * 		2. nullifying.
+ */
+void
+BootStrapSlruPage(SlruCtl ctl, int64 pageno,
+				  bool writeXlog, RmgrId rmid, uint8 info)
+{
+	int			slotno;
+	LWLock	   *lock;
+
+	lock = SimpleLruGetBankLock(ctl, pageno);
+	LWLockAcquire(lock, LW_EXCLUSIVE);
+
+	/* Create and zero the page*/
+	slotno = SimpleLruZeroAndLogPage(ctl, pageno, writeXlog, rmid, info);
+
+	/* Make sure it's written out */
+	SimpleLruWritePage(ctl, slotno);
+	Assert(!ctl->shared->page_dirty[slotno]);
+
+	LWLockRelease(lock);
+}
+
+int
+SimpleLruZeroAndLogPage(SlruCtl ctl, int64 pageno, 
+						bool writeXlog, RmgrId rmid, uint8 info)
+{
+	int			slotno;
+
+	slotno = SimpleLruZeroPage(ctl, pageno);
+
+	if (writeXlog)
+		WriteSlruZeroPageXlogRec(pageno, rmid, info);
+
+	return slotno;
+}
+
 /*
  * Initialize (or reinitialize) a page to zeroes.
  *
@@ -1850,3 +1910,14 @@ SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path)
 	errno = save_errno;
 	return result;
 }
+
+/*
+ * Write a SLRU ZEROPAGE xlog record
+ */
+static inline void
+WriteSlruZeroPageXlogRec(int64 pageno, RmgrId rmid, uint8 info)
+{
+	XLogBeginInsert();
+	XLogRegisterData(&pageno, sizeof(pageno));
+	(void) XLogInsert(rmid, info);
+}
diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c
index 15153618fad..6b013801825 100644
--- a/src/backend/access/transam/subtrans.c
+++ b/src/backend/access/transam/subtrans.c
@@ -74,7 +74,6 @@ static SlruCtlData SubTransCtlData;
 #define SubTransCtl  (&SubTransCtlData)
 
 
-static int	ZeroSUBTRANSPage(int64 pageno);
 static bool SubTransPagePrecedes(int64 page1, int64 page2);
 
 
@@ -269,33 +268,7 @@ check_subtrans_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapSUBTRANS(void)
 {
-	int			slotno;
-	LWLock	   *lock = SimpleLruGetBankLock(SubTransCtl, 0);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the subtrans log */
-	slotno = ZeroSUBTRANSPage(0);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(SubTransCtl, slotno);
-	Assert(!SubTransCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of SUBTRANS to zeroes.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroSUBTRANSPage(int64 pageno)
-{
-	return SimpleLruZeroPage(SubTransCtl, pageno);
+	BootStrapSlruPage(SubTransCtl, 0, false, 0, 0);
 }
 
 /*
@@ -334,8 +307,8 @@ StartupSUBTRANS(TransactionId oldestActiveXID)
 			LWLockAcquire(lock, LW_EXCLUSIVE);
 			prevlock = lock;
 		}
-
-		(void) ZeroSUBTRANSPage(startPage);
+		
+		(void) SimpleLruZeroPage(SubTransCtl, startPage);
 		if (startPage == endPage)
 			break;
 
@@ -395,7 +368,7 @@ ExtendSUBTRANS(TransactionId newestXact)
 	LWLockAcquire(lock, LW_EXCLUSIVE);
 
 	/* Zero the page */
-	ZeroSUBTRANSPage(pageno);
+	SimpleLruZeroPage(SubTransCtl, pageno);
 
 	LWLockRelease(lock);
 }
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index e142800aab2..3826ab5088c 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -13,6 +13,7 @@
 #ifndef SLRU_H
 #define SLRU_H
 
+#include "access/rmgr.h"
 #include "access/xlogdefs.h"
 #include "storage/lwlock.h"
 #include "storage/sync.h"
@@ -186,6 +187,10 @@ extern void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
 						  const char *subdir, int buffer_tranche_id,
 						  int bank_tranche_id, SyncRequestHandler sync_handler,
 						  bool long_segment_names);
+extern void BootStrapSlruPage(SlruCtl ctl, int64 pageno,
+				  bool writeXlog, RmgrId rmid, uint8 info);
+extern int  SimpleLruZeroAndLogPage(SlruCtl ctl, int64 pageno, 
+						bool writeXlog, RmgrId rmid, uint8 info);
 extern int	SimpleLruZeroPage(SlruCtl ctl, int64 pageno);
 extern int	SimpleLruReadPage(SlruCtl ctl, int64 pageno, bool write_ok,
 							  TransactionId xid);
-- 
2.47.1

#9Álvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Evgeny Voropaev (#8)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

On 2025-Feb-18, Evgeny Voropaev wrote:

Created functions BootStrapSlruPage,SimpleLruZeroAndLogPage,
WriteSlruZeroPageXlogRec. Using of these functions allows to delete
ZeroXYZPage functions, WriteXYZZeroPageXlogRec functions and eliminate code
repetitions.

I think the overall idea here is good, but I didn't like the new
WriteSlruZeroPageXlogRec helper function; it looks too much like a
modularity violation (same for the fact that you have to pass the rmid
and info from each caller into slru.c). I would not do that in slru.c
but instead in every individual caller, and have this helper function in
xloginsert.c where it can be caller XLogSimpleInsert or something like
that.

Also, please do not document a bunch of functions together in a single
comment. Instead, have one comment for each function. I mean this
here:

diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index 9ce628e62a5..cc069da19c6 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -363,6 +364,65 @@ check_slru_buffers(const char *name, int *newval)
return false;
}
+/*
+ * BootStrapSlruPage, 
+ * SimpleLruZeroAndLogPage, 
+ * SimpleLruZeroPage
+ * 		- functions nullifying SLRU pages.
+ *
+ * BootStrapSlruPage is the most holistic. It performs:
+ * 		1. locking,
+ * 		2. nullifying,
+ * 		3. logging (when writeXlog is true),
+ * 		4. writing out,
+ * 		5. releasing the lock.
+ *
+ * SimpleLruZeroAndLogPage performs:
+ * 		2. nullifying,
+ * 		3. logging (when writeXlog is true),
+ * 		4. writing out.
+ * 		
+ * If the writeXlog is true, BootStrapSlruPage and SimpleLruZeroAndLogPage 
+ * emit an XLOG record saying we did this.
+ * If the writeXlog is false, the rmid and info parameters are unused.
+ * 
+ * SimpleLruZeroPage performs:
+ * 		2. nullifying.
+ */
+void
+BootStrapSlruPage(SlruCtl ctl, int64 pageno,
+				  bool writeXlog, RmgrId rmid, uint8 info)
+{

This is not our style, and I don't think it's very ergonomical. Most
people don't read source files from top to bottom normally (heck,
sometimes I read source from bottom to top), so somebody looking at
SimpleLruZeroAndLogPage (the second function) might just not realize
that it's documented a few pagefuls above itself.

--
Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/
Thou shalt study thy libraries and strive not to reinvent them without
cause, that thy code may be short and readable and thy days pleasant
and productive. (7th Commandment for C Programmers)

#10Evgeny
evorop@gmail.com
In reply to: Álvaro Herrera (#9)
1 attachment(s)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

Hello hackers!

I think the overall idea here is good, but I didn't like the new
WriteSlruZeroPageXlogRec helper function; it looks too much like a
modularity violation (same for the fact that you have to pass the rmid
and info from each caller into slru.c). I would not do that in slru.c
but instead in every individual caller, and have this helper function in
xloginsert.c where it can be caller XLogSimpleInsert or something like
that.

Thank you Alvaro! I got your ideas and have tried to implement them.

In the v4 patch version:
1) WriteSlruZeroPageXlogRec has been renamed into XLogSimpleInsert and
moved to the xloginset.c.

2) With the purpose of excluding passing any resource manager’s
information into the slru.c module I propose to pass into the
BootStrapSlruPage the XLogInsertFunc parameter pointing to a function
accomplishing insertion of an XLog record. Implementations of these
functions are enclosed in a corresponding slru-page module (commit_ts.c,
multixaxt.c and so on). It preserves original modularity - the
BootStrapSlruPage and the slru.c still do not know anything about
resource managers. If the XLogInsertFunc parameter equals zero,
BootStrapSlruPage will not try to perform XLog recording.

3) In addition, let’s also implement in the BootStrapSlruPage a new
parameter writePage. It commands whether to write a page onto a disk or
not. As a result, the BootStrapSlruPage become apt to be used in a
larger number of places of code.

Also, please do not document a bunch of functions together in a single
comment. Instead, have one comment for each function.
This is not our style, and I don't think it's very ergonomical.

I got it. And since
4) The SimpleLruZeroAndLogPage is subject to deletion now.
comments are formatted as well.

sometimes I read source from bottom to top

Probably, we all should profess this approach!

Best regards,
Evgeny Voropaev,
Tantor Labs LLC.

Attachments:

v4-0001-Elimination-of-the-repetitive-code-at-the-SLRU-bo.patchtext/x-patch; charset=UTF-8; name=v4-0001-Elimination-of-the-repetitive-code-at-the-SLRU-bo.patchDownload
From 885c15ba379da4fd5f0dd71ee4dc9b5e31108d6f Mon Sep 17 00:00:00 2001
From: Evgeny Voropaev <evorop@gmail.com>
Date: Sun, 23 Feb 2025 23:19:19 +0800
Subject: [PATCH v4] Elimination of the repetitive code at the SLRU
 bootstrapping and nullifying functions.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The functions bootstrapping and nullifying SLRU pages used to have a lot of
repetitive code. New functions realized by this commit (BootStrapSlruPage,
XLogSimpleInsert) have allowed to remove these repetitions.

Author: Evgeny Voropaev <evgeny.voropaev@tantorlabs.com> <evorop@gmail.com>
Reviewed by: Álvaro Herrera <alvherre@alvh.no-ip.org>
Reviewed by: Andrey Borodin <x4mmm@yandex-team.ru>
Reviewed by: Aleksander Alekseev <aleksander@timescale.com>
Discussion: https://www.postgresql.org/message-id/flat/97820ce8-a1cd-407f-a02b-47368fadb14b%40tantorlabs.com
---
 src/backend/access/transam/clog.c       |  72 ++---------
 src/backend/access/transam/commit_ts.c  |  70 ++---------
 src/backend/access/transam/multixact.c  | 155 ++++++------------------
 src/backend/access/transam/slru.c       |  45 ++++++-
 src/backend/access/transam/subtrans.c   |  48 ++------
 src/backend/access/transam/xloginsert.c |  14 +++
 src/include/access/slru.h               |   2 +
 src/include/access/xloginsert.h         |   1 +
 8 files changed, 138 insertions(+), 269 deletions(-)

diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 48f10bec91e..c86129282fa 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -110,7 +110,6 @@ static SlruCtlData XactCtlData;
 #define XactCtl (&XactCtlData)
 
 
-static int	ZeroCLOGPage(int64 pageno, bool writeXlog);
 static bool CLOGPagePrecedes(int64 page1, int64 page2);
 static void WriteZeroPageXlogRec(int64 pageno);
 static void WriteTruncateXlogRec(int64 pageno, TransactionId oldestXact,
@@ -832,41 +831,11 @@ check_transaction_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapCLOG(void)
 {
-	int			slotno;
-	LWLock	   *lock = SimpleLruGetBankLock(XactCtl, 0);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the commit log */
-	slotno = ZeroCLOGPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(XactCtl, slotno);
-	Assert(!XactCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of CLOG to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroCLOGPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(XactCtl, pageno);
-
-	if (writeXlog)
-		WriteZeroPageXlogRec(pageno);
-
-	return slotno;
+	/*
+	 * Nullify the page (pageno = 0), don't insert an XLog record, 
+	 * save the page on a disk
+	 */
+	BootStrapSlruPage(XactCtl, 0, 0, true);
 }
 
 /*
@@ -959,7 +928,6 @@ void
 ExtendCLOG(TransactionId newestXact)
 {
 	int64		pageno;
-	LWLock	   *lock;
 
 	/*
 	 * No work except at first XID of a page.  But beware: just after
@@ -970,14 +938,12 @@ ExtendCLOG(TransactionId newestXact)
 		return;
 
 	pageno = TransactionIdToPage(newestXact);
-	lock = SimpleLruGetBankLock(XactCtl, pageno);
 
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Zero the page and make an XLOG entry about it */
-	ZeroCLOGPage(pageno, true);
-
-	LWLockRelease(lock);
+	/*
+	 * Zero the page, make an XLOG entry about it,
+	 * don't write the page on a disk
+	 */
+	BootStrapSlruPage(XactCtl, pageno, WriteZeroPageXlogRec, false);
 }
 
 
@@ -1073,9 +1039,7 @@ CLOGPagePrecedes(int64 page1, int64 page2)
 static void
 WriteZeroPageXlogRec(int64 pageno)
 {
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE);
+	XLogSimpleInsert(pageno, RM_CLOG_ID, CLOG_ZEROPAGE);
 }
 
 /*
@@ -1114,19 +1078,9 @@ clog_redo(XLogReaderState *record)
 	if (info == CLOG_ZEROPAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(XactCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroCLOGPage(pageno, false);
-		SimpleLruWritePage(XactCtl, slotno);
-		Assert(!XactCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		/* Zero the page, don't make an XLOG entry about it, write the page on a disk */
+		BootStrapSlruPage(XactCtl, pageno, 0, true);
 	}
 	else if (info == CLOG_TRUNCATE)
 	{
diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c
index 113fae1437a..6c479133350 100644
--- a/src/backend/access/transam/commit_ts.c
+++ b/src/backend/access/transam/commit_ts.c
@@ -114,7 +114,6 @@ static void SetXidCommitTsInPage(TransactionId xid, int nsubxids,
 static void TransactionIdSetCommitTs(TransactionId xid, TimestampTz ts,
 									 RepOriginId nodeid, int slotno);
 static void error_commit_ts_disabled(void);
-static int	ZeroCommitTsPage(int64 pageno, bool writeXlog);
 static bool CommitTsPagePrecedes(int64 page1, int64 page2);
 static void ActivateCommitTs(void);
 static void DeactivateCommitTs(void);
@@ -602,28 +601,6 @@ BootStrapCommitTs(void)
 	 */
 }
 
-/*
- * Initialize (or reinitialize) a page of CommitTs to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroCommitTsPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(CommitTsCtl, pageno);
-
-	if (writeXlog)
-		WriteZeroPageXlogRec(pageno);
-
-	return slotno;
-}
-
 /*
  * This must be called ONCE during postmaster or standalone-backend startup,
  * after StartupXLOG has initialized TransamVariables->nextXid.
@@ -747,16 +724,8 @@ ActivateCommitTs(void)
 
 	/* Create the current segment file, if necessary */
 	if (!SimpleLruDoesPhysicalPageExist(CommitTsCtl, pageno))
-	{
-		LWLock	   *lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-		int			slotno;
-
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-		slotno = ZeroCommitTsPage(pageno, false);
-		SimpleLruWritePage(CommitTsCtl, slotno);
-		Assert(!CommitTsCtl->shared->page_dirty[slotno]);
-		LWLockRelease(lock);
-	}
+		/* Zero the page, don't make an XLOG entry about it, write the page on a disk */
+		BootStrapSlruPage(CommitTsCtl, pageno, 0, true);
 
 	/* Change the activation status in shared memory. */
 	LWLockAcquire(CommitTsLock, LW_EXCLUSIVE);
@@ -842,7 +811,6 @@ void
 ExtendCommitTs(TransactionId newestXact)
 {
 	int64		pageno;
-	LWLock	   *lock;
 
 	/*
 	 * Nothing to do if module not enabled.  Note we do an unlocked read of
@@ -863,14 +831,13 @@ ExtendCommitTs(TransactionId newestXact)
 
 	pageno = TransactionIdToCTsPage(newestXact);
 
-	lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Zero the page and make an XLOG entry about it */
-	ZeroCommitTsPage(pageno, !InRecovery);
-
-	LWLockRelease(lock);
+	/* 
+	 * Zero the page; 
+	 * if we are not doing recovery from XLOG, make an XLOG entry about it;
+	 * don't write the page on a disk.
+	 */
+	BootStrapSlruPage(CommitTsCtl, pageno,
+					  InRecovery ? 0 : WriteZeroPageXlogRec, false);
 }
 
 /*
@@ -988,9 +955,7 @@ CommitTsPagePrecedes(int64 page1, int64 page2)
 static void
 WriteZeroPageXlogRec(int64 pageno)
 {
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_COMMIT_TS_ID, COMMIT_TS_ZEROPAGE);
+	XLogSimpleInsert(pageno, RM_COMMIT_TS_ID, COMMIT_TS_ZEROPAGE);
 }
 
 /*
@@ -1023,19 +988,10 @@ commit_ts_redo(XLogReaderState *record)
 	if (info == COMMIT_TS_ZEROPAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroCommitTsPage(pageno, false);
-		SimpleLruWritePage(CommitTsCtl, slotno);
-		Assert(!CommitTsCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		
+		/* Zero the page, don't make an XLOG entry about it, write the page on a disk */
+		BootStrapSlruPage(CommitTsCtl, pageno, 0, true);
 	}
 	else if (info == COMMIT_TS_TRUNCATE)
 	{
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index c1e2c42e1bb..c559447f3d9 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -401,8 +401,6 @@ static void mXactCachePut(MultiXactId multi, int nmembers,
 static char *mxstatus_to_string(MultiXactStatus status);
 
 /* management of SLRU infrastructure */
-static int	ZeroMultiXactOffsetPage(int64 pageno, bool writeXlog);
-static int	ZeroMultiXactMemberPage(int64 pageno, bool writeXlog);
 static bool MultiXactOffsetPagePrecedes(int64 page1, int64 page2);
 static bool MultiXactMemberPagePrecedes(int64 page1, int64 page2);
 static bool MultiXactOffsetPrecedes(MultiXactOffset offset1,
@@ -413,7 +411,9 @@ static bool MultiXactOffsetWouldWrap(MultiXactOffset boundary,
 									 MultiXactOffset start, uint32 distance);
 static bool SetOffsetVacuumLimit(bool is_startup);
 static bool find_multixact_start(MultiXactId multi, MultiXactOffset *result);
-static void WriteMZeroPageXlogRec(int64 pageno, uint8 info);
+static inline void WriteMZeroPageXlogRec(int64 pageno, uint8 info);
+static void WriteMMembersZeroPageXlogRec(int64 pageno);
+static void WriteMOffserZeroPageXlogRec(int64 pageno);
 static void WriteMTruncateXlogRec(Oid oldestMultiDB,
 								  MultiXactId startTruncOff,
 								  MultiXactId endTruncOff,
@@ -2033,70 +2033,12 @@ check_multixact_member_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapMultiXact(void)
 {
-	int			slotno;
-	LWLock	   *lock;
-
-	lock = SimpleLruGetBankLock(MultiXactOffsetCtl, 0);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the offsets log */
-	slotno = ZeroMultiXactOffsetPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(MultiXactOffsetCtl, slotno);
-	Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-
-	lock = SimpleLruGetBankLock(MultiXactMemberCtl, 0);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the members log */
-	slotno = ZeroMultiXactMemberPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(MultiXactMemberCtl, slotno);
-	Assert(!MultiXactMemberCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of MultiXactOffset to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroMultiXactOffsetPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(MultiXactOffsetCtl, pageno);
-
-	if (writeXlog)
-		WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_OFF_PAGE);
-
-	return slotno;
-}
-
-/*
- * Ditto, for MultiXactMember
- */
-static int
-ZeroMultiXactMemberPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(MultiXactMemberCtl, pageno);
-
-	if (writeXlog)
-		WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_MEM_PAGE);
-
-	return slotno;
+	/*
+	 * Nullify the page (pageno = 0), don't insert an XLog record, 
+	 * save the page on a disk
+	 */
+	BootStrapSlruPage(MultiXactOffsetCtl, 0, 0, true);
+	BootStrapSlruPage(MultiXactMemberCtl, 0, 0, true);
 }
 
 /*
@@ -2134,7 +2076,7 @@ MaybeExtendOffsetSlru(void)
 		 * with creating a new segment file even if the page we're writing is
 		 * not the first in it, so this is enough.
 		 */
-		slotno = ZeroMultiXactOffsetPage(pageno, false);
+		slotno = SimpleLruZeroPage(MultiXactOffsetCtl, pageno);
 		SimpleLruWritePage(MultiXactOffsetCtl, slotno);
 	}
 
@@ -2553,7 +2495,6 @@ static void
 ExtendMultiXactOffset(MultiXactId multi)
 {
 	int64		pageno;
-	LWLock	   *lock;
 
 	/*
 	 * No work except at first MultiXactId of a page.  But beware: just after
@@ -2564,14 +2505,8 @@ ExtendMultiXactOffset(MultiXactId multi)
 		return;
 
 	pageno = MultiXactIdToOffsetPage(multi);
-	lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Zero the page and make an XLOG entry about it */
-	ZeroMultiXactOffsetPage(pageno, true);
-
-	LWLockRelease(lock);
+	/* Zero the page, make an XLOG entry about it, don't write the page on a disk */
+	BootStrapSlruPage(MultiXactOffsetCtl, pageno, WriteMOffserZeroPageXlogRec, false);
 }
 
 /*
@@ -2604,17 +2539,9 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
 		if (flagsoff == 0 && flagsbit == 0)
 		{
 			int64		pageno;
-			LWLock	   *lock;
-
 			pageno = MXOffsetToMemberPage(offset);
-			lock = SimpleLruGetBankLock(MultiXactMemberCtl, pageno);
-
-			LWLockAcquire(lock, LW_EXCLUSIVE);
-
-			/* Zero the page and make an XLOG entry about it */
-			ZeroMultiXactMemberPage(pageno, true);
-
-			LWLockRelease(lock);
+			/* Zero the page, make an XLOG entry about it, don't write the page on a disk */
+			BootStrapSlruPage(MultiXactMemberCtl, pageno, WriteMMembersZeroPageXlogRec, false);
 		}
 
 		/*
@@ -3351,12 +3278,28 @@ MultiXactOffsetPrecedes(MultiXactOffset offset1, MultiXactOffset offset2)
  * Write an xlog record reflecting the zeroing of either a MEMBERs or
  * OFFSETs page (info shows which)
  */
-static void
+static inline void
 WriteMZeroPageXlogRec(int64 pageno, uint8 info)
 {
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_MULTIXACT_ID, info);
+	XLogSimpleInsert(pageno, RM_MULTIXACT_ID, info);
+}
+
+/*
+ * Write a ZEROPAGE xlog record of MEMBERs page
+ */
+static void
+WriteMMembersZeroPageXlogRec(int64 pageno)
+{
+	WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_MEM_PAGE);
+}
+
+/*
+ * Write a ZEROPAGE xlog record of OFFSETs page
+ */
+static void
+WriteMOffserZeroPageXlogRec(int64 pageno)
+{
+	WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_OFF_PAGE);
 }
 
 /*
@@ -3401,36 +3344,18 @@ multixact_redo(XLogReaderState *record)
 	if (info == XLOG_MULTIXACT_ZERO_OFF_PAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroMultiXactOffsetPage(pageno, false);
-		SimpleLruWritePage(MultiXactOffsetCtl, slotno);
-		Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		/* Zero the page, don't make an XLOG entry about it, 
+		 * write the page on a disk */
+		BootStrapSlruPage(MultiXactOffsetCtl, pageno, 0, true);
 	}
 	else if (info == XLOG_MULTIXACT_ZERO_MEM_PAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(MultiXactMemberCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroMultiXactMemberPage(pageno, false);
-		SimpleLruWritePage(MultiXactMemberCtl, slotno);
-		Assert(!MultiXactMemberCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		/* Zero the page, don't make an XLOG entry about it, 
+		 * write the page on a disk */
+		BootStrapSlruPage(MultiXactMemberCtl, pageno, 0, true);
 	}
 	else if (info == XLOG_MULTIXACT_CREATE_ID)
 	{
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index 9ce628e62a5..e6c701121f3 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -190,7 +190,6 @@ static bool SlruScanDirCbDeleteCutoff(SlruCtl ctl, char *filename,
 static void SlruInternalDeleteSegment(SlruCtl ctl, int64 segno);
 static inline void SlruRecentlyUsed(SlruShared shared, int slotno);
 
-
 /*
  * Initialization of shared memory
  */
@@ -363,6 +362,50 @@ check_slru_buffers(const char *name, int *newval)
 	return false;
 }
 
+/*
+ * BootStrapSlruPage is one of the functions nullifying a SLRU page. 
+ * It performs:
+ * 		1. locking,
+ * 		2. nullifying,
+ * 		3. logging (optionally),
+ * 		4. writing out (optionally),
+ * 		5. releasing the lock.
+ *
+ * XLogInsertFunc is a parameter pointing to a function emitting an XLog
+ * record. The implementation of this function usually enclosed in 
+ * a corresponding SLRU-page module (commit_ts.c, multixaxt.c and others).
+ * If XLogInsertFunc equals to zero, XLog record emition is not going to 
+ * be accomplished. Caller must provide a correct XLogInsertFunc pointer
+ * or provide its equality to zero.  
+ * 
+ * The writePage parameter commands whether to write a page on a disk or not.
+ */
+void
+BootStrapSlruPage(SlruCtl ctl, int64 pageno,
+				  void (*XLogInsertFunc)(int64 pageno), bool writePage)
+{
+	int			slotno;
+	LWLock	   *lock;
+
+	lock = SimpleLruGetBankLock(ctl, pageno);
+	LWLockAcquire(lock, LW_EXCLUSIVE);
+
+	/* Create and zero the page*/
+	slotno = SimpleLruZeroPage(ctl, pageno);
+	
+	if (XLogInsertFunc)
+		XLogInsertFunc(pageno);
+
+	if (writePage != 0)
+	{
+		/* Make sure it's written out */
+		SimpleLruWritePage(ctl, slotno);
+		Assert(!ctl->shared->page_dirty[slotno]);
+	}
+
+	LWLockRelease(lock);
+}
+
 /*
  * Initialize (or reinitialize) a page to zeroes.
  *
diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c
index 15153618fad..66f8301ef3d 100644
--- a/src/backend/access/transam/subtrans.c
+++ b/src/backend/access/transam/subtrans.c
@@ -74,7 +74,6 @@ static SlruCtlData SubTransCtlData;
 #define SubTransCtl  (&SubTransCtlData)
 
 
-static int	ZeroSUBTRANSPage(int64 pageno);
 static bool SubTransPagePrecedes(int64 page1, int64 page2);
 
 
@@ -269,33 +268,11 @@ check_subtrans_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapSUBTRANS(void)
 {
-	int			slotno;
-	LWLock	   *lock = SimpleLruGetBankLock(SubTransCtl, 0);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the subtrans log */
-	slotno = ZeroSUBTRANSPage(0);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(SubTransCtl, slotno);
-	Assert(!SubTransCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of SUBTRANS to zeroes.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroSUBTRANSPage(int64 pageno)
-{
-	return SimpleLruZeroPage(SubTransCtl, pageno);
+	/*
+	 * Nullify the page (pageno = 0), don't insert an XLog record, 
+	 * save the page on a disk
+	 */
+	BootStrapSlruPage(SubTransCtl, 0, 0, true);
 }
 
 /*
@@ -335,7 +312,7 @@ StartupSUBTRANS(TransactionId oldestActiveXID)
 			prevlock = lock;
 		}
 
-		(void) ZeroSUBTRANSPage(startPage);
+		(void) SimpleLruZeroPage(SubTransCtl, startPage);
 		if (startPage == endPage)
 			break;
 
@@ -379,7 +356,6 @@ void
 ExtendSUBTRANS(TransactionId newestXact)
 {
 	int64		pageno;
-	LWLock	   *lock;
 
 	/*
 	 * No work except at first XID of a page.  But beware: just after
@@ -391,13 +367,11 @@ ExtendSUBTRANS(TransactionId newestXact)
 
 	pageno = TransactionIdToPage(newestXact);
 
-	lock = SimpleLruGetBankLock(SubTransCtl, pageno);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Zero the page */
-	ZeroSUBTRANSPage(pageno);
-
-	LWLockRelease(lock);
+	/*
+	 * Zero the page, don't make an XLOG entry about it,
+	 * don't write the page on a disk
+	 */
+	BootStrapSlruPage(SubTransCtl, pageno, 0, false);
 }
 
 
diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c
index 14d583ae7ae..4a62e63cf92 100644
--- a/src/backend/access/transam/xloginsert.c
+++ b/src/backend/access/transam/xloginsert.c
@@ -1390,3 +1390,17 @@ InitXLogInsert(void)
 		hdr_scratch = MemoryContextAllocZero(xloginsert_cxt,
 											 HEADER_SCRATCH_SIZE);
 }
+
+/*
+ * Write a simple xlog record.
+ *
+ * Useful for SLRU zeropages. In this case the simpledata is usually the number of 
+ * a nullified SLRU page.
+ */
+void
+XLogSimpleInsert(int64 simpledata, RmgrId rmid, uint8 info)
+{
+	XLogBeginInsert();
+	XLogRegisterData(&simpledata, sizeof(simpledata));
+	(void) XLogInsert(rmid, info);
+}
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index e142800aab2..275c99b6131 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -186,6 +186,8 @@ extern void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
 						  const char *subdir, int buffer_tranche_id,
 						  int bank_tranche_id, SyncRequestHandler sync_handler,
 						  bool long_segment_names);
+extern void BootStrapSlruPage(SlruCtl ctl, int64 pageno,
+					void (*XLogInsertFunc)(int64 pageno), bool writePage);
 extern int	SimpleLruZeroPage(SlruCtl ctl, int64 pageno);
 extern int	SimpleLruReadPage(SlruCtl ctl, int64 pageno, bool write_ok,
 							  TransactionId xid);
diff --git a/src/include/access/xloginsert.h b/src/include/access/xloginsert.h
index cf057f033a2..249092e27d5 100644
--- a/src/include/access/xloginsert.h
+++ b/src/include/access/xloginsert.h
@@ -64,5 +64,6 @@ extern void log_newpage_range(Relation rel, ForkNumber forknum,
 extern XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std);
 
 extern void InitXLogInsert(void);
+extern void XLogSimpleInsert(int64 simpledata, RmgrId rmid, uint8 info);
 
 #endif							/* XLOGINSERT_H */
-- 
2.48.1

#11Evgeny
evorop@gmail.com
In reply to: Evgeny (#10)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

Hello Hackers!

Álvaro, Andrey, Aleksander! We have not been discussing anything in the
thread for the past ten days. Can we mark this thread as "Ready for
Merge" or should I improve something in the patch. If I should, I am
ready to do it.

Looking forward to your feedback.
Evgeny Voropaev.

#12Evgeny
evorop@gmail.com
In reply to: Evgeny (#11)
1 attachment(s)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

Hello Hackers!

On 11 March 2025, the CI job failed
(https://cirrus-ci.com/task/5453963400577024).

The issue occurred in the test ‘pg_amcheck/t/002_nonesuch.pl .

Log:

https://api.cirrus-ci.com/v1/artifact/task/5453963400577024/testrun/build/testrun/pg_amcheck/002_nonesuch/log/regress_log_002_nonesuch

Log output:
--------------------------------------------------------------------------------------
[11:40:20.527](0.000s) not ok 18 - checking with a non-existent user
stderr /(?^:role "no_such_user" does not exist)/
[11:40:20.527](0.000s) # Failed test 'checking with a non-existent
user stderr /(?^:role "no_such_user" does not exist)/'
# at C:/cirrus/src/bin/pg_amcheck/t/002_nonesuch.pl line 86.
[11:40:20.527](0.000s) # 'pg_amcheck: error:
connection to server on socket
"C:/Windows/TEMP/AtJUArHHFu/.s.PGSQL.17536" failed: server closed the
connection unexpectedly
# This probably means the server terminated abnormally
# before or while processing the request.
# '
# doesn't match '(?^:role "no_such_user" does not exist)'
# Running: pg_amcheck template1
----------------------------------------------------------------------------------

It appears to be a flickering issue that regularly occurs on the Windows
platform and is not related to the patch.

For the purpose of restarting the CI job, I have attached the 5th
version of the patch. It is identical to v4, except for the version
number increment, which helps prevent duplicate attachment names in this
thread.

Best regards,
Evgeny Voropaev.

Attachments:

v5-0001-Elimination-of-the-repetitive-code-at-the-SLRU-bo.patchtext/x-patch; charset=UTF-8; name=v5-0001-Elimination-of-the-repetitive-code-at-the-SLRU-bo.patchDownload
From 885c15ba379da4fd5f0dd71ee4dc9b5e31108d6f Mon Sep 17 00:00:00 2001
From: Evgeny Voropaev <evorop@gmail.com>
Date: Sun, 23 Feb 2025 23:19:19 +0800
Subject: [PATCH v5] Elimination of the repetitive code at the SLRU
 bootstrapping and nullifying functions.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The functions bootstrapping and nullifying SLRU pages used to have a lot of
repetitive code. New functions realized by this commit (BootStrapSlruPage,
XLogSimpleInsert) have allowed to remove these repetitions.

Author: Evgeny Voropaev <evgeny.voropaev@tantorlabs.com> <evorop@gmail.com>
Reviewed by: Álvaro Herrera <alvherre@alvh.no-ip.org>
Reviewed by: Andrey Borodin <x4mmm@yandex-team.ru>
Reviewed by: Aleksander Alekseev <aleksander@timescale.com>
Discussion: https://www.postgresql.org/message-id/flat/97820ce8-a1cd-407f-a02b-47368fadb14b%40tantorlabs.com
---
 src/backend/access/transam/clog.c       |  72 ++---------
 src/backend/access/transam/commit_ts.c  |  70 ++---------
 src/backend/access/transam/multixact.c  | 155 ++++++------------------
 src/backend/access/transam/slru.c       |  45 ++++++-
 src/backend/access/transam/subtrans.c   |  48 ++------
 src/backend/access/transam/xloginsert.c |  14 +++
 src/include/access/slru.h               |   2 +
 src/include/access/xloginsert.h         |   1 +
 8 files changed, 138 insertions(+), 269 deletions(-)

diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 48f10bec91e..c86129282fa 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -110,7 +110,6 @@ static SlruCtlData XactCtlData;
 #define XactCtl (&XactCtlData)
 
 
-static int	ZeroCLOGPage(int64 pageno, bool writeXlog);
 static bool CLOGPagePrecedes(int64 page1, int64 page2);
 static void WriteZeroPageXlogRec(int64 pageno);
 static void WriteTruncateXlogRec(int64 pageno, TransactionId oldestXact,
@@ -832,41 +831,11 @@ check_transaction_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapCLOG(void)
 {
-	int			slotno;
-	LWLock	   *lock = SimpleLruGetBankLock(XactCtl, 0);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the commit log */
-	slotno = ZeroCLOGPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(XactCtl, slotno);
-	Assert(!XactCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of CLOG to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroCLOGPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(XactCtl, pageno);
-
-	if (writeXlog)
-		WriteZeroPageXlogRec(pageno);
-
-	return slotno;
+	/*
+	 * Nullify the page (pageno = 0), don't insert an XLog record, 
+	 * save the page on a disk
+	 */
+	BootStrapSlruPage(XactCtl, 0, 0, true);
 }
 
 /*
@@ -959,7 +928,6 @@ void
 ExtendCLOG(TransactionId newestXact)
 {
 	int64		pageno;
-	LWLock	   *lock;
 
 	/*
 	 * No work except at first XID of a page.  But beware: just after
@@ -970,14 +938,12 @@ ExtendCLOG(TransactionId newestXact)
 		return;
 
 	pageno = TransactionIdToPage(newestXact);
-	lock = SimpleLruGetBankLock(XactCtl, pageno);
 
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Zero the page and make an XLOG entry about it */
-	ZeroCLOGPage(pageno, true);
-
-	LWLockRelease(lock);
+	/*
+	 * Zero the page, make an XLOG entry about it,
+	 * don't write the page on a disk
+	 */
+	BootStrapSlruPage(XactCtl, pageno, WriteZeroPageXlogRec, false);
 }
 
 
@@ -1073,9 +1039,7 @@ CLOGPagePrecedes(int64 page1, int64 page2)
 static void
 WriteZeroPageXlogRec(int64 pageno)
 {
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE);
+	XLogSimpleInsert(pageno, RM_CLOG_ID, CLOG_ZEROPAGE);
 }
 
 /*
@@ -1114,19 +1078,9 @@ clog_redo(XLogReaderState *record)
 	if (info == CLOG_ZEROPAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(XactCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroCLOGPage(pageno, false);
-		SimpleLruWritePage(XactCtl, slotno);
-		Assert(!XactCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		/* Zero the page, don't make an XLOG entry about it, write the page on a disk */
+		BootStrapSlruPage(XactCtl, pageno, 0, true);
 	}
 	else if (info == CLOG_TRUNCATE)
 	{
diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c
index 113fae1437a..6c479133350 100644
--- a/src/backend/access/transam/commit_ts.c
+++ b/src/backend/access/transam/commit_ts.c
@@ -114,7 +114,6 @@ static void SetXidCommitTsInPage(TransactionId xid, int nsubxids,
 static void TransactionIdSetCommitTs(TransactionId xid, TimestampTz ts,
 									 RepOriginId nodeid, int slotno);
 static void error_commit_ts_disabled(void);
-static int	ZeroCommitTsPage(int64 pageno, bool writeXlog);
 static bool CommitTsPagePrecedes(int64 page1, int64 page2);
 static void ActivateCommitTs(void);
 static void DeactivateCommitTs(void);
@@ -602,28 +601,6 @@ BootStrapCommitTs(void)
 	 */
 }
 
-/*
- * Initialize (or reinitialize) a page of CommitTs to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroCommitTsPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(CommitTsCtl, pageno);
-
-	if (writeXlog)
-		WriteZeroPageXlogRec(pageno);
-
-	return slotno;
-}
-
 /*
  * This must be called ONCE during postmaster or standalone-backend startup,
  * after StartupXLOG has initialized TransamVariables->nextXid.
@@ -747,16 +724,8 @@ ActivateCommitTs(void)
 
 	/* Create the current segment file, if necessary */
 	if (!SimpleLruDoesPhysicalPageExist(CommitTsCtl, pageno))
-	{
-		LWLock	   *lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-		int			slotno;
-
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-		slotno = ZeroCommitTsPage(pageno, false);
-		SimpleLruWritePage(CommitTsCtl, slotno);
-		Assert(!CommitTsCtl->shared->page_dirty[slotno]);
-		LWLockRelease(lock);
-	}
+		/* Zero the page, don't make an XLOG entry about it, write the page on a disk */
+		BootStrapSlruPage(CommitTsCtl, pageno, 0, true);
 
 	/* Change the activation status in shared memory. */
 	LWLockAcquire(CommitTsLock, LW_EXCLUSIVE);
@@ -842,7 +811,6 @@ void
 ExtendCommitTs(TransactionId newestXact)
 {
 	int64		pageno;
-	LWLock	   *lock;
 
 	/*
 	 * Nothing to do if module not enabled.  Note we do an unlocked read of
@@ -863,14 +831,13 @@ ExtendCommitTs(TransactionId newestXact)
 
 	pageno = TransactionIdToCTsPage(newestXact);
 
-	lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Zero the page and make an XLOG entry about it */
-	ZeroCommitTsPage(pageno, !InRecovery);
-
-	LWLockRelease(lock);
+	/* 
+	 * Zero the page; 
+	 * if we are not doing recovery from XLOG, make an XLOG entry about it;
+	 * don't write the page on a disk.
+	 */
+	BootStrapSlruPage(CommitTsCtl, pageno,
+					  InRecovery ? 0 : WriteZeroPageXlogRec, false);
 }
 
 /*
@@ -988,9 +955,7 @@ CommitTsPagePrecedes(int64 page1, int64 page2)
 static void
 WriteZeroPageXlogRec(int64 pageno)
 {
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_COMMIT_TS_ID, COMMIT_TS_ZEROPAGE);
+	XLogSimpleInsert(pageno, RM_COMMIT_TS_ID, COMMIT_TS_ZEROPAGE);
 }
 
 /*
@@ -1023,19 +988,10 @@ commit_ts_redo(XLogReaderState *record)
 	if (info == COMMIT_TS_ZEROPAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroCommitTsPage(pageno, false);
-		SimpleLruWritePage(CommitTsCtl, slotno);
-		Assert(!CommitTsCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		
+		/* Zero the page, don't make an XLOG entry about it, write the page on a disk */
+		BootStrapSlruPage(CommitTsCtl, pageno, 0, true);
 	}
 	else if (info == COMMIT_TS_TRUNCATE)
 	{
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index c1e2c42e1bb..c559447f3d9 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -401,8 +401,6 @@ static void mXactCachePut(MultiXactId multi, int nmembers,
 static char *mxstatus_to_string(MultiXactStatus status);
 
 /* management of SLRU infrastructure */
-static int	ZeroMultiXactOffsetPage(int64 pageno, bool writeXlog);
-static int	ZeroMultiXactMemberPage(int64 pageno, bool writeXlog);
 static bool MultiXactOffsetPagePrecedes(int64 page1, int64 page2);
 static bool MultiXactMemberPagePrecedes(int64 page1, int64 page2);
 static bool MultiXactOffsetPrecedes(MultiXactOffset offset1,
@@ -413,7 +411,9 @@ static bool MultiXactOffsetWouldWrap(MultiXactOffset boundary,
 									 MultiXactOffset start, uint32 distance);
 static bool SetOffsetVacuumLimit(bool is_startup);
 static bool find_multixact_start(MultiXactId multi, MultiXactOffset *result);
-static void WriteMZeroPageXlogRec(int64 pageno, uint8 info);
+static inline void WriteMZeroPageXlogRec(int64 pageno, uint8 info);
+static void WriteMMembersZeroPageXlogRec(int64 pageno);
+static void WriteMOffserZeroPageXlogRec(int64 pageno);
 static void WriteMTruncateXlogRec(Oid oldestMultiDB,
 								  MultiXactId startTruncOff,
 								  MultiXactId endTruncOff,
@@ -2033,70 +2033,12 @@ check_multixact_member_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapMultiXact(void)
 {
-	int			slotno;
-	LWLock	   *lock;
-
-	lock = SimpleLruGetBankLock(MultiXactOffsetCtl, 0);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the offsets log */
-	slotno = ZeroMultiXactOffsetPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(MultiXactOffsetCtl, slotno);
-	Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-
-	lock = SimpleLruGetBankLock(MultiXactMemberCtl, 0);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the members log */
-	slotno = ZeroMultiXactMemberPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(MultiXactMemberCtl, slotno);
-	Assert(!MultiXactMemberCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of MultiXactOffset to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroMultiXactOffsetPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(MultiXactOffsetCtl, pageno);
-
-	if (writeXlog)
-		WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_OFF_PAGE);
-
-	return slotno;
-}
-
-/*
- * Ditto, for MultiXactMember
- */
-static int
-ZeroMultiXactMemberPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(MultiXactMemberCtl, pageno);
-
-	if (writeXlog)
-		WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_MEM_PAGE);
-
-	return slotno;
+	/*
+	 * Nullify the page (pageno = 0), don't insert an XLog record, 
+	 * save the page on a disk
+	 */
+	BootStrapSlruPage(MultiXactOffsetCtl, 0, 0, true);
+	BootStrapSlruPage(MultiXactMemberCtl, 0, 0, true);
 }
 
 /*
@@ -2134,7 +2076,7 @@ MaybeExtendOffsetSlru(void)
 		 * with creating a new segment file even if the page we're writing is
 		 * not the first in it, so this is enough.
 		 */
-		slotno = ZeroMultiXactOffsetPage(pageno, false);
+		slotno = SimpleLruZeroPage(MultiXactOffsetCtl, pageno);
 		SimpleLruWritePage(MultiXactOffsetCtl, slotno);
 	}
 
@@ -2553,7 +2495,6 @@ static void
 ExtendMultiXactOffset(MultiXactId multi)
 {
 	int64		pageno;
-	LWLock	   *lock;
 
 	/*
 	 * No work except at first MultiXactId of a page.  But beware: just after
@@ -2564,14 +2505,8 @@ ExtendMultiXactOffset(MultiXactId multi)
 		return;
 
 	pageno = MultiXactIdToOffsetPage(multi);
-	lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Zero the page and make an XLOG entry about it */
-	ZeroMultiXactOffsetPage(pageno, true);
-
-	LWLockRelease(lock);
+	/* Zero the page, make an XLOG entry about it, don't write the page on a disk */
+	BootStrapSlruPage(MultiXactOffsetCtl, pageno, WriteMOffserZeroPageXlogRec, false);
 }
 
 /*
@@ -2604,17 +2539,9 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
 		if (flagsoff == 0 && flagsbit == 0)
 		{
 			int64		pageno;
-			LWLock	   *lock;
-
 			pageno = MXOffsetToMemberPage(offset);
-			lock = SimpleLruGetBankLock(MultiXactMemberCtl, pageno);
-
-			LWLockAcquire(lock, LW_EXCLUSIVE);
-
-			/* Zero the page and make an XLOG entry about it */
-			ZeroMultiXactMemberPage(pageno, true);
-
-			LWLockRelease(lock);
+			/* Zero the page, make an XLOG entry about it, don't write the page on a disk */
+			BootStrapSlruPage(MultiXactMemberCtl, pageno, WriteMMembersZeroPageXlogRec, false);
 		}
 
 		/*
@@ -3351,12 +3278,28 @@ MultiXactOffsetPrecedes(MultiXactOffset offset1, MultiXactOffset offset2)
  * Write an xlog record reflecting the zeroing of either a MEMBERs or
  * OFFSETs page (info shows which)
  */
-static void
+static inline void
 WriteMZeroPageXlogRec(int64 pageno, uint8 info)
 {
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_MULTIXACT_ID, info);
+	XLogSimpleInsert(pageno, RM_MULTIXACT_ID, info);
+}
+
+/*
+ * Write a ZEROPAGE xlog record of MEMBERs page
+ */
+static void
+WriteMMembersZeroPageXlogRec(int64 pageno)
+{
+	WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_MEM_PAGE);
+}
+
+/*
+ * Write a ZEROPAGE xlog record of OFFSETs page
+ */
+static void
+WriteMOffserZeroPageXlogRec(int64 pageno)
+{
+	WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_OFF_PAGE);
 }
 
 /*
@@ -3401,36 +3344,18 @@ multixact_redo(XLogReaderState *record)
 	if (info == XLOG_MULTIXACT_ZERO_OFF_PAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroMultiXactOffsetPage(pageno, false);
-		SimpleLruWritePage(MultiXactOffsetCtl, slotno);
-		Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		/* Zero the page, don't make an XLOG entry about it, 
+		 * write the page on a disk */
+		BootStrapSlruPage(MultiXactOffsetCtl, pageno, 0, true);
 	}
 	else if (info == XLOG_MULTIXACT_ZERO_MEM_PAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(MultiXactMemberCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroMultiXactMemberPage(pageno, false);
-		SimpleLruWritePage(MultiXactMemberCtl, slotno);
-		Assert(!MultiXactMemberCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		/* Zero the page, don't make an XLOG entry about it, 
+		 * write the page on a disk */
+		BootStrapSlruPage(MultiXactMemberCtl, pageno, 0, true);
 	}
 	else if (info == XLOG_MULTIXACT_CREATE_ID)
 	{
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index 9ce628e62a5..e6c701121f3 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -190,7 +190,6 @@ static bool SlruScanDirCbDeleteCutoff(SlruCtl ctl, char *filename,
 static void SlruInternalDeleteSegment(SlruCtl ctl, int64 segno);
 static inline void SlruRecentlyUsed(SlruShared shared, int slotno);
 
-
 /*
  * Initialization of shared memory
  */
@@ -363,6 +362,50 @@ check_slru_buffers(const char *name, int *newval)
 	return false;
 }
 
+/*
+ * BootStrapSlruPage is one of the functions nullifying a SLRU page. 
+ * It performs:
+ * 		1. locking,
+ * 		2. nullifying,
+ * 		3. logging (optionally),
+ * 		4. writing out (optionally),
+ * 		5. releasing the lock.
+ *
+ * XLogInsertFunc is a parameter pointing to a function emitting an XLog
+ * record. The implementation of this function usually enclosed in 
+ * a corresponding SLRU-page module (commit_ts.c, multixaxt.c and others).
+ * If XLogInsertFunc equals to zero, XLog record emition is not going to 
+ * be accomplished. Caller must provide a correct XLogInsertFunc pointer
+ * or provide its equality to zero.  
+ * 
+ * The writePage parameter commands whether to write a page on a disk or not.
+ */
+void
+BootStrapSlruPage(SlruCtl ctl, int64 pageno,
+				  void (*XLogInsertFunc)(int64 pageno), bool writePage)
+{
+	int			slotno;
+	LWLock	   *lock;
+
+	lock = SimpleLruGetBankLock(ctl, pageno);
+	LWLockAcquire(lock, LW_EXCLUSIVE);
+
+	/* Create and zero the page*/
+	slotno = SimpleLruZeroPage(ctl, pageno);
+	
+	if (XLogInsertFunc)
+		XLogInsertFunc(pageno);
+
+	if (writePage != 0)
+	{
+		/* Make sure it's written out */
+		SimpleLruWritePage(ctl, slotno);
+		Assert(!ctl->shared->page_dirty[slotno]);
+	}
+
+	LWLockRelease(lock);
+}
+
 /*
  * Initialize (or reinitialize) a page to zeroes.
  *
diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c
index 15153618fad..66f8301ef3d 100644
--- a/src/backend/access/transam/subtrans.c
+++ b/src/backend/access/transam/subtrans.c
@@ -74,7 +74,6 @@ static SlruCtlData SubTransCtlData;
 #define SubTransCtl  (&SubTransCtlData)
 
 
-static int	ZeroSUBTRANSPage(int64 pageno);
 static bool SubTransPagePrecedes(int64 page1, int64 page2);
 
 
@@ -269,33 +268,11 @@ check_subtrans_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapSUBTRANS(void)
 {
-	int			slotno;
-	LWLock	   *lock = SimpleLruGetBankLock(SubTransCtl, 0);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the subtrans log */
-	slotno = ZeroSUBTRANSPage(0);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(SubTransCtl, slotno);
-	Assert(!SubTransCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of SUBTRANS to zeroes.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroSUBTRANSPage(int64 pageno)
-{
-	return SimpleLruZeroPage(SubTransCtl, pageno);
+	/*
+	 * Nullify the page (pageno = 0), don't insert an XLog record, 
+	 * save the page on a disk
+	 */
+	BootStrapSlruPage(SubTransCtl, 0, 0, true);
 }
 
 /*
@@ -335,7 +312,7 @@ StartupSUBTRANS(TransactionId oldestActiveXID)
 			prevlock = lock;
 		}
 
-		(void) ZeroSUBTRANSPage(startPage);
+		(void) SimpleLruZeroPage(SubTransCtl, startPage);
 		if (startPage == endPage)
 			break;
 
@@ -379,7 +356,6 @@ void
 ExtendSUBTRANS(TransactionId newestXact)
 {
 	int64		pageno;
-	LWLock	   *lock;
 
 	/*
 	 * No work except at first XID of a page.  But beware: just after
@@ -391,13 +367,11 @@ ExtendSUBTRANS(TransactionId newestXact)
 
 	pageno = TransactionIdToPage(newestXact);
 
-	lock = SimpleLruGetBankLock(SubTransCtl, pageno);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Zero the page */
-	ZeroSUBTRANSPage(pageno);
-
-	LWLockRelease(lock);
+	/*
+	 * Zero the page, don't make an XLOG entry about it,
+	 * don't write the page on a disk
+	 */
+	BootStrapSlruPage(SubTransCtl, pageno, 0, false);
 }
 
 
diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c
index 14d583ae7ae..4a62e63cf92 100644
--- a/src/backend/access/transam/xloginsert.c
+++ b/src/backend/access/transam/xloginsert.c
@@ -1390,3 +1390,17 @@ InitXLogInsert(void)
 		hdr_scratch = MemoryContextAllocZero(xloginsert_cxt,
 											 HEADER_SCRATCH_SIZE);
 }
+
+/*
+ * Write a simple xlog record.
+ *
+ * Useful for SLRU zeropages. In this case the simpledata is usually the number of 
+ * a nullified SLRU page.
+ */
+void
+XLogSimpleInsert(int64 simpledata, RmgrId rmid, uint8 info)
+{
+	XLogBeginInsert();
+	XLogRegisterData(&simpledata, sizeof(simpledata));
+	(void) XLogInsert(rmid, info);
+}
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index e142800aab2..275c99b6131 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -186,6 +186,8 @@ extern void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
 						  const char *subdir, int buffer_tranche_id,
 						  int bank_tranche_id, SyncRequestHandler sync_handler,
 						  bool long_segment_names);
+extern void BootStrapSlruPage(SlruCtl ctl, int64 pageno,
+					void (*XLogInsertFunc)(int64 pageno), bool writePage);
 extern int	SimpleLruZeroPage(SlruCtl ctl, int64 pageno);
 extern int	SimpleLruReadPage(SlruCtl ctl, int64 pageno, bool write_ok,
 							  TransactionId xid);
diff --git a/src/include/access/xloginsert.h b/src/include/access/xloginsert.h
index cf057f033a2..249092e27d5 100644
--- a/src/include/access/xloginsert.h
+++ b/src/include/access/xloginsert.h
@@ -64,5 +64,6 @@ extern void log_newpage_range(Relation rel, ForkNumber forknum,
 extern XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std);
 
 extern void InitXLogInsert(void);
+extern void XLogSimpleInsert(int64 simpledata, RmgrId rmid, uint8 info);
 
 #endif							/* XLOGINSERT_H */
-- 
2.48.1

#13Andrey Borodin
x4mmm@yandex-team.ru
In reply to: Evgeny (#12)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

On 11 Mar 2025, at 14:12, Evgeny <evorop@gmail.com> wrote:

Hi!

Some nits:

Patch adds whitespace errors
.git/rebase-apply/patch:64: trailing whitespace.
* Nullify the page (pageno = 0), don't insert an XLog record, .git/rebase-apply/patch:212: trailing whitespace.
/* .git/rebase-apply/patch:213: trailing whitespace.
* Zero the page; .git/rebase-apply/patch:250: trailing whitespace.
.git/rebase-apply/patch:349: trailing whitespace.
* Nullify the page (pageno = 0), don't insert an XLog record, warning: squelched 10 whitespace errors
warning: 15 lines add whitespace errors.

if (writePage != 0) should be if (writePage)

XLogSimpleInsert(int64 simpledata, RmgrId rmid, uint8 info)
I’d rename function XLogSimpleInsert() to something more descriptive and changed arguments order from generic to specific. Probably, committer has broader view on XLog routines and can decide if this function would better belong to SLRU than common XLog stuff.

Besides this patch seems ready to me.

Thanks!

Best regards, Andrey Borodin.

#14Evgeny Voropaev
evorop.wiki@gmail.com
In reply to: Andrey Borodin (#13)
1 attachment(s)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

Hello Hackers!

Andrey, thank you for your review and remarks.

Patch adds whitespace errors

Cleaned.

if (writePage != 0) should be if (writePage)

Done.

XLogSimpleInsert(int64 simpledata, RmgrId rmid, uint8 info)
I’d rename function XLogSimpleInsert() to something more descriptive
and changed arguments order from generic to specific.

The function has been renamed and the parameters have been reordered.
Now we have:
XLogInsertInt64(RmgrId rmid, uint8 info, int64 simpledata)

Probably, committer has broader view on XLog routines and can decide
if this function would better belong to SLRU than common XLog stuff.

In accordance with Álvaro's proposal, we want to enclose this function
in the "xloginsert.c" module.

Best regards,
Evgeny Voropaev.

Attachments:

v6-0001-Elimination-of-the-repetitive-code-at-the-SLRU-bo.patchtext/x-patch; charset=UTF-8; name=v6-0001-Elimination-of-the-repetitive-code-at-the-SLRU-bo.patchDownload
From 8c9aa484dc96cdf23c7fa524d88d67ce3c4cc6fc Mon Sep 17 00:00:00 2001
From: Evgeny Voropaev <evorop@gmail.com>
Date: Wed, 12 Mar 2025 22:35:19 +0800
Subject: [PATCH v6] Elimination of the repetitive code at the SLRU
 bootstrapping and nullifying functions.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The functions bootstrapping and nullifying SLRU pages used to have a lot of
repetitive code. New functions realized by this commit (BootStrapSlruPage,
XLogInsertInt64) have allowed to remove these repetitions.

Author: Evgeny Voropaev <evgeny.voropaev@tantorlabs.com> <evorop@gmail.com>
Reviewed by: Álvaro Herrera <alvherre@alvh.no-ip.org>
Reviewed by: Andrey Borodin <x4mmm@yandex-team.ru>
Reviewed by: Aleksander Alekseev <aleksander@timescale.com>
Discussion: https://www.postgresql.org/message-id/flat/97820ce8-a1cd-407f-a02b-47368fadb14b%40tantorlabs.com
---
 src/backend/access/transam/clog.c       |  72 ++---------
 src/backend/access/transam/commit_ts.c  |  68 ++---------
 src/backend/access/transam/multixact.c  | 155 ++++++------------------
 src/backend/access/transam/slru.c       |  45 ++++++-
 src/backend/access/transam/subtrans.c   |  48 ++------
 src/backend/access/transam/xloginsert.c |  14 +++
 src/include/access/slru.h               |   2 +
 src/include/access/xloginsert.h         |   1 +
 8 files changed, 137 insertions(+), 268 deletions(-)

diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 48f10bec91e..aca8c31d680 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -110,7 +110,6 @@ static SlruCtlData XactCtlData;
 #define XactCtl (&XactCtlData)
 
 
-static int	ZeroCLOGPage(int64 pageno, bool writeXlog);
 static bool CLOGPagePrecedes(int64 page1, int64 page2);
 static void WriteZeroPageXlogRec(int64 pageno);
 static void WriteTruncateXlogRec(int64 pageno, TransactionId oldestXact,
@@ -832,41 +831,11 @@ check_transaction_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapCLOG(void)
 {
-	int			slotno;
-	LWLock	   *lock = SimpleLruGetBankLock(XactCtl, 0);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the commit log */
-	slotno = ZeroCLOGPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(XactCtl, slotno);
-	Assert(!XactCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of CLOG to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroCLOGPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(XactCtl, pageno);
-
-	if (writeXlog)
-		WriteZeroPageXlogRec(pageno);
-
-	return slotno;
+	/*
+	 * Nullify the page (pageno = 0), don't insert an XLog record,
+	 * save the page on a disk
+	 */
+	BootStrapSlruPage(XactCtl, 0, 0, true);
 }
 
 /*
@@ -959,7 +928,6 @@ void
 ExtendCLOG(TransactionId newestXact)
 {
 	int64		pageno;
-	LWLock	   *lock;
 
 	/*
 	 * No work except at first XID of a page.  But beware: just after
@@ -970,14 +938,12 @@ ExtendCLOG(TransactionId newestXact)
 		return;
 
 	pageno = TransactionIdToPage(newestXact);
-	lock = SimpleLruGetBankLock(XactCtl, pageno);
 
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Zero the page and make an XLOG entry about it */
-	ZeroCLOGPage(pageno, true);
-
-	LWLockRelease(lock);
+	/*
+	 * Zero the page, make an XLOG entry about it,
+	 * don't write the page on a disk
+	 */
+	BootStrapSlruPage(XactCtl, pageno, WriteZeroPageXlogRec, false);
 }
 
 
@@ -1073,9 +1039,7 @@ CLOGPagePrecedes(int64 page1, int64 page2)
 static void
 WriteZeroPageXlogRec(int64 pageno)
 {
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE);
+	XLogInsertInt64(RM_CLOG_ID, CLOG_ZEROPAGE, pageno);
 }
 
 /*
@@ -1114,19 +1078,9 @@ clog_redo(XLogReaderState *record)
 	if (info == CLOG_ZEROPAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(XactCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroCLOGPage(pageno, false);
-		SimpleLruWritePage(XactCtl, slotno);
-		Assert(!XactCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		/* Zero the page, don't make an XLOG entry about it, write the page on a disk */
+		BootStrapSlruPage(XactCtl, pageno, 0, true);
 	}
 	else if (info == CLOG_TRUNCATE)
 	{
diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c
index 113fae1437a..b3a7d483e02 100644
--- a/src/backend/access/transam/commit_ts.c
+++ b/src/backend/access/transam/commit_ts.c
@@ -114,7 +114,6 @@ static void SetXidCommitTsInPage(TransactionId xid, int nsubxids,
 static void TransactionIdSetCommitTs(TransactionId xid, TimestampTz ts,
 									 RepOriginId nodeid, int slotno);
 static void error_commit_ts_disabled(void);
-static int	ZeroCommitTsPage(int64 pageno, bool writeXlog);
 static bool CommitTsPagePrecedes(int64 page1, int64 page2);
 static void ActivateCommitTs(void);
 static void DeactivateCommitTs(void);
@@ -602,28 +601,6 @@ BootStrapCommitTs(void)
 	 */
 }
 
-/*
- * Initialize (or reinitialize) a page of CommitTs to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroCommitTsPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(CommitTsCtl, pageno);
-
-	if (writeXlog)
-		WriteZeroPageXlogRec(pageno);
-
-	return slotno;
-}
-
 /*
  * This must be called ONCE during postmaster or standalone-backend startup,
  * after StartupXLOG has initialized TransamVariables->nextXid.
@@ -747,16 +724,8 @@ ActivateCommitTs(void)
 
 	/* Create the current segment file, if necessary */
 	if (!SimpleLruDoesPhysicalPageExist(CommitTsCtl, pageno))
-	{
-		LWLock	   *lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-		int			slotno;
-
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-		slotno = ZeroCommitTsPage(pageno, false);
-		SimpleLruWritePage(CommitTsCtl, slotno);
-		Assert(!CommitTsCtl->shared->page_dirty[slotno]);
-		LWLockRelease(lock);
-	}
+		/* Zero the page, don't make an XLOG entry about it, write the page on a disk */
+		BootStrapSlruPage(CommitTsCtl, pageno, 0, true);
 
 	/* Change the activation status in shared memory. */
 	LWLockAcquire(CommitTsLock, LW_EXCLUSIVE);
@@ -842,7 +811,6 @@ void
 ExtendCommitTs(TransactionId newestXact)
 {
 	int64		pageno;
-	LWLock	   *lock;
 
 	/*
 	 * Nothing to do if module not enabled.  Note we do an unlocked read of
@@ -863,14 +831,13 @@ ExtendCommitTs(TransactionId newestXact)
 
 	pageno = TransactionIdToCTsPage(newestXact);
 
-	lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Zero the page and make an XLOG entry about it */
-	ZeroCommitTsPage(pageno, !InRecovery);
-
-	LWLockRelease(lock);
+	/*
+	 * Zero the page;
+	 * if we are not doing recovery from XLOG, make an XLOG entry about it;
+	 * don't write the page on a disk.
+	 */
+	BootStrapSlruPage(CommitTsCtl, pageno,
+					  InRecovery ? 0 : WriteZeroPageXlogRec, false);
 }
 
 /*
@@ -988,9 +955,7 @@ CommitTsPagePrecedes(int64 page1, int64 page2)
 static void
 WriteZeroPageXlogRec(int64 pageno)
 {
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_COMMIT_TS_ID, COMMIT_TS_ZEROPAGE);
+	XLogInsertInt64(RM_COMMIT_TS_ID, COMMIT_TS_ZEROPAGE, pageno);
 }
 
 /*
@@ -1023,19 +988,10 @@ commit_ts_redo(XLogReaderState *record)
 	if (info == COMMIT_TS_ZEROPAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
 
-		lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroCommitTsPage(pageno, false);
-		SimpleLruWritePage(CommitTsCtl, slotno);
-		Assert(!CommitTsCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		/* Zero the page, don't make an XLOG entry about it, write the page on a disk */
+		BootStrapSlruPage(CommitTsCtl, pageno, 0, true);
 	}
 	else if (info == COMMIT_TS_TRUNCATE)
 	{
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index c1e2c42e1bb..b2a7fb09b52 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -401,8 +401,6 @@ static void mXactCachePut(MultiXactId multi, int nmembers,
 static char *mxstatus_to_string(MultiXactStatus status);
 
 /* management of SLRU infrastructure */
-static int	ZeroMultiXactOffsetPage(int64 pageno, bool writeXlog);
-static int	ZeroMultiXactMemberPage(int64 pageno, bool writeXlog);
 static bool MultiXactOffsetPagePrecedes(int64 page1, int64 page2);
 static bool MultiXactMemberPagePrecedes(int64 page1, int64 page2);
 static bool MultiXactOffsetPrecedes(MultiXactOffset offset1,
@@ -413,7 +411,9 @@ static bool MultiXactOffsetWouldWrap(MultiXactOffset boundary,
 									 MultiXactOffset start, uint32 distance);
 static bool SetOffsetVacuumLimit(bool is_startup);
 static bool find_multixact_start(MultiXactId multi, MultiXactOffset *result);
-static void WriteMZeroPageXlogRec(int64 pageno, uint8 info);
+static inline void WriteMZeroPageXlogRec(int64 pageno, uint8 info);
+static void WriteMMembersZeroPageXlogRec(int64 pageno);
+static void WriteMOffserZeroPageXlogRec(int64 pageno);
 static void WriteMTruncateXlogRec(Oid oldestMultiDB,
 								  MultiXactId startTruncOff,
 								  MultiXactId endTruncOff,
@@ -2033,70 +2033,12 @@ check_multixact_member_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapMultiXact(void)
 {
-	int			slotno;
-	LWLock	   *lock;
-
-	lock = SimpleLruGetBankLock(MultiXactOffsetCtl, 0);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the offsets log */
-	slotno = ZeroMultiXactOffsetPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(MultiXactOffsetCtl, slotno);
-	Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-
-	lock = SimpleLruGetBankLock(MultiXactMemberCtl, 0);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the members log */
-	slotno = ZeroMultiXactMemberPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(MultiXactMemberCtl, slotno);
-	Assert(!MultiXactMemberCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of MultiXactOffset to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroMultiXactOffsetPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(MultiXactOffsetCtl, pageno);
-
-	if (writeXlog)
-		WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_OFF_PAGE);
-
-	return slotno;
-}
-
-/*
- * Ditto, for MultiXactMember
- */
-static int
-ZeroMultiXactMemberPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(MultiXactMemberCtl, pageno);
-
-	if (writeXlog)
-		WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_MEM_PAGE);
-
-	return slotno;
+	/*
+	 * Nullify the page (pageno = 0), don't insert an XLog record,
+	 * save the page on a disk
+	 */
+	BootStrapSlruPage(MultiXactOffsetCtl, 0, 0, true);
+	BootStrapSlruPage(MultiXactMemberCtl, 0, 0, true);
 }
 
 /*
@@ -2134,7 +2076,7 @@ MaybeExtendOffsetSlru(void)
 		 * with creating a new segment file even if the page we're writing is
 		 * not the first in it, so this is enough.
 		 */
-		slotno = ZeroMultiXactOffsetPage(pageno, false);
+		slotno = SimpleLruZeroPage(MultiXactOffsetCtl, pageno);
 		SimpleLruWritePage(MultiXactOffsetCtl, slotno);
 	}
 
@@ -2553,7 +2495,6 @@ static void
 ExtendMultiXactOffset(MultiXactId multi)
 {
 	int64		pageno;
-	LWLock	   *lock;
 
 	/*
 	 * No work except at first MultiXactId of a page.  But beware: just after
@@ -2564,14 +2505,8 @@ ExtendMultiXactOffset(MultiXactId multi)
 		return;
 
 	pageno = MultiXactIdToOffsetPage(multi);
-	lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Zero the page and make an XLOG entry about it */
-	ZeroMultiXactOffsetPage(pageno, true);
-
-	LWLockRelease(lock);
+	/* Zero the page, make an XLOG entry about it, don't write the page on a disk */
+	BootStrapSlruPage(MultiXactOffsetCtl, pageno, WriteMOffserZeroPageXlogRec, false);
 }
 
 /*
@@ -2604,17 +2539,9 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
 		if (flagsoff == 0 && flagsbit == 0)
 		{
 			int64		pageno;
-			LWLock	   *lock;
-
 			pageno = MXOffsetToMemberPage(offset);
-			lock = SimpleLruGetBankLock(MultiXactMemberCtl, pageno);
-
-			LWLockAcquire(lock, LW_EXCLUSIVE);
-
-			/* Zero the page and make an XLOG entry about it */
-			ZeroMultiXactMemberPage(pageno, true);
-
-			LWLockRelease(lock);
+			/* Zero the page, make an XLOG entry about it, don't write the page on a disk */
+			BootStrapSlruPage(MultiXactMemberCtl, pageno, WriteMMembersZeroPageXlogRec, false);
 		}
 
 		/*
@@ -3351,12 +3278,28 @@ MultiXactOffsetPrecedes(MultiXactOffset offset1, MultiXactOffset offset2)
  * Write an xlog record reflecting the zeroing of either a MEMBERs or
  * OFFSETs page (info shows which)
  */
-static void
+static inline void
 WriteMZeroPageXlogRec(int64 pageno, uint8 info)
 {
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_MULTIXACT_ID, info);
+	XLogInsertInt64(RM_MULTIXACT_ID, info, pageno);
+}
+
+/*
+ * Write a ZEROPAGE xlog record of a MULTIXACT MEMBERs page
+ */
+static void
+WriteMMembersZeroPageXlogRec(int64 pageno)
+{
+	WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_MEM_PAGE);
+}
+
+/*
+ * Write a ZEROPAGE xlog record of a MULTIXACT OFFSETs page
+ */
+static void
+WriteMOffserZeroPageXlogRec(int64 pageno)
+{
+	WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_OFF_PAGE);
 }
 
 /*
@@ -3401,36 +3344,18 @@ multixact_redo(XLogReaderState *record)
 	if (info == XLOG_MULTIXACT_ZERO_OFF_PAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroMultiXactOffsetPage(pageno, false);
-		SimpleLruWritePage(MultiXactOffsetCtl, slotno);
-		Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		/* Zero the page, don't make an XLOG entry about it,
+		 * write the page on a disk */
+		BootStrapSlruPage(MultiXactOffsetCtl, pageno, 0, true);
 	}
 	else if (info == XLOG_MULTIXACT_ZERO_MEM_PAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(MultiXactMemberCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroMultiXactMemberPage(pageno, false);
-		SimpleLruWritePage(MultiXactMemberCtl, slotno);
-		Assert(!MultiXactMemberCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		/* Zero the page, don't make an XLOG entry about it,
+		 * write the page on a disk */
+		BootStrapSlruPage(MultiXactMemberCtl, pageno, 0, true);
 	}
 	else if (info == XLOG_MULTIXACT_CREATE_ID)
 	{
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index 9ce628e62a5..4964ffafe8f 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -190,7 +190,6 @@ static bool SlruScanDirCbDeleteCutoff(SlruCtl ctl, char *filename,
 static void SlruInternalDeleteSegment(SlruCtl ctl, int64 segno);
 static inline void SlruRecentlyUsed(SlruShared shared, int slotno);
 
-
 /*
  * Initialization of shared memory
  */
@@ -363,6 +362,50 @@ check_slru_buffers(const char *name, int *newval)
 	return false;
 }
 
+/*
+ * BootStrapSlruPage is one of the functions that nullify an SLRU page.
+ * It performs:
+ * 		1. locking the page,
+ * 		2. nullifying the page,
+ * 		3. logging (optionally),
+ * 		4. writing out (optionally),
+ * 		5. releasing the lock.
+ *
+ * XLogInsertFunc is a parameter pointing to a function emitting an XLog
+ * record. The implementation of this function usually enclosed in
+ * a corresponding SLRU-page module (commit_ts.c, multixaxt.c and others).
+ * If XLogInsertFunc equals to zero, XLog record emition is not going to
+ * be accomplished. Caller must provide a correct XLogInsertFunc pointer
+ * or provide its equality to zero.
+ *
+ * The writePage parameter commands whether to write a page on a disk or not.
+ */
+void
+BootStrapSlruPage(SlruCtl ctl, int64 pageno,
+				  void (*XLogInsertFunc)(int64 pageno), bool writePage)
+{
+	int			slotno;
+	LWLock	   *lock;
+
+	lock = SimpleLruGetBankLock(ctl, pageno);
+	LWLockAcquire(lock, LW_EXCLUSIVE);
+
+	/* Create and zero the page*/
+	slotno = SimpleLruZeroPage(ctl, pageno);
+
+	if (XLogInsertFunc)
+		XLogInsertFunc(pageno);
+
+	if (writePage)
+	{
+		/* Make sure it's written out */
+		SimpleLruWritePage(ctl, slotno);
+		Assert(!ctl->shared->page_dirty[slotno]);
+	}
+
+	LWLockRelease(lock);
+}
+
 /*
  * Initialize (or reinitialize) a page to zeroes.
  *
diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c
index 15153618fad..07c1e4db163 100644
--- a/src/backend/access/transam/subtrans.c
+++ b/src/backend/access/transam/subtrans.c
@@ -74,7 +74,6 @@ static SlruCtlData SubTransCtlData;
 #define SubTransCtl  (&SubTransCtlData)
 
 
-static int	ZeroSUBTRANSPage(int64 pageno);
 static bool SubTransPagePrecedes(int64 page1, int64 page2);
 
 
@@ -269,33 +268,11 @@ check_subtrans_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapSUBTRANS(void)
 {
-	int			slotno;
-	LWLock	   *lock = SimpleLruGetBankLock(SubTransCtl, 0);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the subtrans log */
-	slotno = ZeroSUBTRANSPage(0);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(SubTransCtl, slotno);
-	Assert(!SubTransCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of SUBTRANS to zeroes.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroSUBTRANSPage(int64 pageno)
-{
-	return SimpleLruZeroPage(SubTransCtl, pageno);
+	/*
+	 * Nullify the page (pageno = 0), don't insert an XLog record,
+	 * save the page on a disk
+	 */
+	BootStrapSlruPage(SubTransCtl, 0, 0, true);
 }
 
 /*
@@ -335,7 +312,7 @@ StartupSUBTRANS(TransactionId oldestActiveXID)
 			prevlock = lock;
 		}
 
-		(void) ZeroSUBTRANSPage(startPage);
+		(void) SimpleLruZeroPage(SubTransCtl, startPage);
 		if (startPage == endPage)
 			break;
 
@@ -379,7 +356,6 @@ void
 ExtendSUBTRANS(TransactionId newestXact)
 {
 	int64		pageno;
-	LWLock	   *lock;
 
 	/*
 	 * No work except at first XID of a page.  But beware: just after
@@ -391,13 +367,11 @@ ExtendSUBTRANS(TransactionId newestXact)
 
 	pageno = TransactionIdToPage(newestXact);
 
-	lock = SimpleLruGetBankLock(SubTransCtl, pageno);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Zero the page */
-	ZeroSUBTRANSPage(pageno);
-
-	LWLockRelease(lock);
+	/*
+	 * Zero the page, don't make an XLOG entry about it,
+	 * don't write the page on a disk
+	 */
+	BootStrapSlruPage(SubTransCtl, pageno, 0, false);
 }
 
 
diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c
index 14d583ae7ae..35a1b7a02ae 100644
--- a/src/backend/access/transam/xloginsert.c
+++ b/src/backend/access/transam/xloginsert.c
@@ -1390,3 +1390,17 @@ InitXLogInsert(void)
 		hdr_scratch = MemoryContextAllocZero(xloginsert_cxt,
 											 HEADER_SCRATCH_SIZE);
 }
+
+/*
+ * Write an xlog record comprising simple int64 data.
+ *
+ * Useful for SLRU zeropages. In this case the simpledata is usually the number of
+ * a nullified SLRU page.
+ */
+void
+XLogInsertInt64(RmgrId rmid, uint8 info, int64 simpledata)
+{
+	XLogBeginInsert();
+	XLogRegisterData(&simpledata, sizeof(simpledata));
+	(void) XLogInsert(rmid, info);
+}
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index e142800aab2..275c99b6131 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -186,6 +186,8 @@ extern void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
 						  const char *subdir, int buffer_tranche_id,
 						  int bank_tranche_id, SyncRequestHandler sync_handler,
 						  bool long_segment_names);
+extern void BootStrapSlruPage(SlruCtl ctl, int64 pageno,
+					void (*XLogInsertFunc)(int64 pageno), bool writePage);
 extern int	SimpleLruZeroPage(SlruCtl ctl, int64 pageno);
 extern int	SimpleLruReadPage(SlruCtl ctl, int64 pageno, bool write_ok,
 							  TransactionId xid);
diff --git a/src/include/access/xloginsert.h b/src/include/access/xloginsert.h
index cf057f033a2..384252c75fe 100644
--- a/src/include/access/xloginsert.h
+++ b/src/include/access/xloginsert.h
@@ -64,5 +64,6 @@ extern void log_newpage_range(Relation rel, ForkNumber forknum,
 extern XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std);
 
 extern void InitXLogInsert(void);
+extern void XLogInsertInt64(RmgrId rmid, uint8 info, int64 simpledata);
 
 #endif							/* XLOGINSERT_H */
-- 
2.48.1

#15Andrey Borodin
x4mmm@yandex-team.ru
In reply to: Evgeny Voropaev (#14)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

On 12 Mar 2025, at 20:02, Evgeny Voropaev <evorop.wiki@gmail.com> wrote:

v6 looks good to me. I'll flip the CF entry.

Thanks!

Best regards, Andrey Borodin.

#16Álvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Evgeny Voropaev (#14)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

Hello

I think this is going too far. The new function BootStrapSlruPage() now
is being used for things other than bootstrapping, and that doesn't seem
appropriate to me. I think we should leave the things that aren't
bootstrap out of this patch. For instance, ExtendCLOG was more
understandable before this patch than after. Same with
ExtendMultiXact{Offset,Member}, ExtendSUBTRANS, etc.

By removing these changes, you can remove the third argument to
BootStrapSlruPage (the function pointer), since you don't need it.

I'm also very suspicious of the use of the new function in the redo
routines also, because those are not bootstrapping anything. I'd rather
have another routine, say SimpleLruRedoZeroPage() which only handles the
zeroing of a page from a WAL record. It would be very similar to
BootstrapSlruPage, and maybe they can share an internal "workhorse"
function for the bits that are common.

I don't have faith in the function name XLogInsertInt64(). The datatype
has no role there. I liked my proposal better.

--
Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/

#17Evgeny
evorop@gmail.com
In reply to: Álvaro Herrera (#16)
1 attachment(s)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

Hello Hackers!

I think this is going too far. The new function BootStrapSlruPage() now
is being used for things other than bootstrapping, and that doesn't seem
appropriate to me. I think we should leave the things that aren't
bootstrap out of this patch. For instance, ExtendCLOG was more
understandable before this patch than after. Same with
ExtendMultiXact{Offset,Member}, ExtendSUBTRANS, etc.

I have excluded the uses of BootStrapSlruPage in Extend* functions. The
code of these functions is remaining still modified a bit on account of
Zero* functions having been deleted. It now includes such fragments:

/* Zero the page and make an XLOG entry about it */
SimpleLruZeroPage(MultiXactMemberCtl, pageno);
XLogSimpleInsert(RM_MULTIXACT_ID, XLOG_MULTIXACT_ZERO_MEM_PAGE, pageno);

as a substitution of:
/* Zero the page and make an XLOG entry about it */
ZeroMultiXactOffsetPage(pageno, true);

But, probably, it even makes a code more readable showing both actions
clearly.

By removing these changes, you can remove the third argument to
BootStrapSlruPage (the function pointer), since you don't need it.

Indeed, it has helped to remove an input parameter from the
BootStrapSlruPage function. Honestly, even two arguments are removed,
since code has not opted whether to write a page on a disk or not. It
saves a page every time.

I'm also very suspicious of the use of the new function in the redo
routines also, because those are not bootstrapping anything. I'd rather
have another routine, say SimpleLruRedoZeroPage() which only handles the
zeroing of a page from a WAL record. It would be very similar to
BootstrapSlruPage, and maybe they can share an internal "workhorse"
function for the bits that are common.

Now the logic zeroing page on the "do" side is fully equal to one on the
"redo" side. As a result, creation of a new distinct function for "redo"
is not needed. In order for the function to conform to the both sides
("do" and "redo") I have renamed it into SimpleLruZeroPageExt. If this
name looks not appropriate, we can change it, please, propose new one.

I don't have faith in the function name XLogInsertInt64(). The datatype
has no role there. I liked my proposal better.

The name has been reverted to one Álvaro has proposed at first
(XLogSimpleInsert).

Patch looks even better - it reduce code by 180 lines.

Best regards,
Evgeny Voropaev.

Attachments:

v7-0001-Elimination-of-the-repetitive-code-at-the-SLRU-bo.patchtext/x-patch; charset=UTF-8; name=v7-0001-Elimination-of-the-repetitive-code-at-the-SLRU-bo.patchDownload
From a324f639627e2128ec64156453e97a7b1b8b420a Mon Sep 17 00:00:00 2001
From: Evgeny Voropaev <evorop@gmail.com>
Date: Wed, 12 Mar 2025 22:35:19 +0800
Subject: [PATCH v7] Elimination of the repetitive code at the SLRU
 bootstrapping and nullifying functions.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The functions bootstrapping and nullifying SLRU pages used to have a lot of
repetitive code. New functions, realized by this commit (SimpleLruZeroPageExt,
XLogSimpleInsert), have removed these repetitions.

Author: Evgeny Voropaev <evgeny.voropaev@tantorlabs.com> <evorop@gmail.com>
Reviewed by: Álvaro Herrera <alvherre@alvh.no-ip.org>
Reviewed by: Andrey Borodin <x4mmm@yandex-team.ru>
Reviewed by: Aleksander Alekseev <aleksander@timescale.com>
Discussion: https://www.postgresql.org/message-id/flat/97820ce8-a1cd-407f-a02b-47368fadb14b%40tantorlabs.com
---
 src/backend/access/transam/clog.c       |  69 ++------------
 src/backend/access/transam/commit_ts.c  |  65 ++-----------
 src/backend/access/transam/multixact.c  | 120 +++---------------------
 src/backend/access/transam/slru.c       |  27 +++++-
 src/backend/access/transam/subtrans.c   |  36 ++-----
 src/backend/access/transam/xloginsert.c |  14 +++
 src/include/access/slru.h               |   1 +
 src/include/access/xloginsert.h         |   1 +
 8 files changed, 78 insertions(+), 255 deletions(-)

diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 48f10bec91e..e9ac93be9fa 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -110,9 +110,7 @@ static SlruCtlData XactCtlData;
 #define XactCtl (&XactCtlData)
 
 
-static int	ZeroCLOGPage(int64 pageno, bool writeXlog);
 static bool CLOGPagePrecedes(int64 page1, int64 page2);
-static void WriteZeroPageXlogRec(int64 pageno);
 static void WriteTruncateXlogRec(int64 pageno, TransactionId oldestXact,
 								 Oid oldestXactDb);
 static void TransactionIdSetPageStatus(TransactionId xid, int nsubxids,
@@ -832,41 +830,10 @@ check_transaction_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapCLOG(void)
 {
-	int			slotno;
-	LWLock	   *lock = SimpleLruGetBankLock(XactCtl, 0);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the commit log */
-	slotno = ZeroCLOGPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(XactCtl, slotno);
-	Assert(!XactCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of CLOG to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroCLOGPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(XactCtl, pageno);
-
-	if (writeXlog)
-		WriteZeroPageXlogRec(pageno);
-
-	return slotno;
+	/*
+	 * Nullify the page (pageno = 0) and save the page on a disk
+	 */
+	SimpleLruZeroPageExt(XactCtl, 0);
 }
 
 /*
@@ -975,7 +942,8 @@ ExtendCLOG(TransactionId newestXact)
 	LWLockAcquire(lock, LW_EXCLUSIVE);
 
 	/* Zero the page and make an XLOG entry about it */
-	ZeroCLOGPage(pageno, true);
+	SimpleLruZeroPage(XactCtl, pageno);
+	XLogSimpleInsert(RM_CLOG_ID, CLOG_ZEROPAGE, pageno);
 
 	LWLockRelease(lock);
 }
@@ -1067,17 +1035,6 @@ CLOGPagePrecedes(int64 page1, int64 page2)
 }
 
 
-/*
- * Write a ZEROPAGE xlog record
- */
-static void
-WriteZeroPageXlogRec(int64 pageno)
-{
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE);
-}
-
 /*
  * Write a TRUNCATE xlog record
  *
@@ -1114,19 +1071,9 @@ clog_redo(XLogReaderState *record)
 	if (info == CLOG_ZEROPAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(XactCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroCLOGPage(pageno, false);
-		SimpleLruWritePage(XactCtl, slotno);
-		Assert(!XactCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		/* Zero the page, write the page on a disk */
+		SimpleLruZeroPageExt(XactCtl, pageno);
 	}
 	else if (info == CLOG_TRUNCATE)
 	{
diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c
index 113fae1437a..d8c04a0ff63 100644
--- a/src/backend/access/transam/commit_ts.c
+++ b/src/backend/access/transam/commit_ts.c
@@ -114,11 +114,9 @@ static void SetXidCommitTsInPage(TransactionId xid, int nsubxids,
 static void TransactionIdSetCommitTs(TransactionId xid, TimestampTz ts,
 									 RepOriginId nodeid, int slotno);
 static void error_commit_ts_disabled(void);
-static int	ZeroCommitTsPage(int64 pageno, bool writeXlog);
 static bool CommitTsPagePrecedes(int64 page1, int64 page2);
 static void ActivateCommitTs(void);
 static void DeactivateCommitTs(void);
-static void WriteZeroPageXlogRec(int64 pageno);
 static void WriteTruncateXlogRec(int64 pageno, TransactionId oldestXid);
 
 /*
@@ -602,28 +600,6 @@ BootStrapCommitTs(void)
 	 */
 }
 
-/*
- * Initialize (or reinitialize) a page of CommitTs to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroCommitTsPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(CommitTsCtl, pageno);
-
-	if (writeXlog)
-		WriteZeroPageXlogRec(pageno);
-
-	return slotno;
-}
-
 /*
  * This must be called ONCE during postmaster or standalone-backend startup,
  * after StartupXLOG has initialized TransamVariables->nextXid.
@@ -747,16 +723,8 @@ ActivateCommitTs(void)
 
 	/* Create the current segment file, if necessary */
 	if (!SimpleLruDoesPhysicalPageExist(CommitTsCtl, pageno))
-	{
-		LWLock	   *lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-		int			slotno;
-
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-		slotno = ZeroCommitTsPage(pageno, false);
-		SimpleLruWritePage(CommitTsCtl, slotno);
-		Assert(!CommitTsCtl->shared->page_dirty[slotno]);
-		LWLockRelease(lock);
-	}
+		/* Zero the page, write the page on a disk */
+		SimpleLruZeroPageExt(CommitTsCtl, pageno);
 
 	/* Change the activation status in shared memory. */
 	LWLockAcquire(CommitTsLock, LW_EXCLUSIVE);
@@ -868,7 +836,10 @@ ExtendCommitTs(TransactionId newestXact)
 	LWLockAcquire(lock, LW_EXCLUSIVE);
 
 	/* Zero the page and make an XLOG entry about it */
-	ZeroCommitTsPage(pageno, !InRecovery);
+	SimpleLruZeroPage(CommitTsCtl, pageno);
+
+	if (!InRecovery)
+		XLogSimpleInsert(RM_COMMIT_TS_ID, COMMIT_TS_ZEROPAGE, pageno);
 
 	LWLockRelease(lock);
 }
@@ -982,17 +953,6 @@ CommitTsPagePrecedes(int64 page1, int64 page2)
 }
 
 
-/*
- * Write a ZEROPAGE xlog record
- */
-static void
-WriteZeroPageXlogRec(int64 pageno)
-{
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_COMMIT_TS_ID, COMMIT_TS_ZEROPAGE);
-}
-
 /*
  * Write a TRUNCATE xlog record
  */
@@ -1023,19 +983,10 @@ commit_ts_redo(XLogReaderState *record)
 	if (info == COMMIT_TS_ZEROPAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
 
-		lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroCommitTsPage(pageno, false);
-		SimpleLruWritePage(CommitTsCtl, slotno);
-		Assert(!CommitTsCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		/* Zero the page, write the page on a disk */
+		SimpleLruZeroPageExt(CommitTsCtl, pageno);
 	}
 	else if (info == COMMIT_TS_TRUNCATE)
 	{
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index c1e2c42e1bb..9839037d3d3 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -401,8 +401,6 @@ static void mXactCachePut(MultiXactId multi, int nmembers,
 static char *mxstatus_to_string(MultiXactStatus status);
 
 /* management of SLRU infrastructure */
-static int	ZeroMultiXactOffsetPage(int64 pageno, bool writeXlog);
-static int	ZeroMultiXactMemberPage(int64 pageno, bool writeXlog);
 static bool MultiXactOffsetPagePrecedes(int64 page1, int64 page2);
 static bool MultiXactMemberPagePrecedes(int64 page1, int64 page2);
 static bool MultiXactOffsetPrecedes(MultiXactOffset offset1,
@@ -413,7 +411,6 @@ static bool MultiXactOffsetWouldWrap(MultiXactOffset boundary,
 									 MultiXactOffset start, uint32 distance);
 static bool SetOffsetVacuumLimit(bool is_startup);
 static bool find_multixact_start(MultiXactId multi, MultiXactOffset *result);
-static void WriteMZeroPageXlogRec(int64 pageno, uint8 info);
 static void WriteMTruncateXlogRec(Oid oldestMultiDB,
 								  MultiXactId startTruncOff,
 								  MultiXactId endTruncOff,
@@ -2033,70 +2030,11 @@ check_multixact_member_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapMultiXact(void)
 {
-	int			slotno;
-	LWLock	   *lock;
-
-	lock = SimpleLruGetBankLock(MultiXactOffsetCtl, 0);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the offsets log */
-	slotno = ZeroMultiXactOffsetPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(MultiXactOffsetCtl, slotno);
-	Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-
-	lock = SimpleLruGetBankLock(MultiXactMemberCtl, 0);
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the members log */
-	slotno = ZeroMultiXactMemberPage(0, false);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(MultiXactMemberCtl, slotno);
-	Assert(!MultiXactMemberCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of MultiXactOffset to zeroes.
- * If writeXlog is true, also emit an XLOG record saying we did this.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroMultiXactOffsetPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(MultiXactOffsetCtl, pageno);
-
-	if (writeXlog)
-		WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_OFF_PAGE);
-
-	return slotno;
-}
-
-/*
- * Ditto, for MultiXactMember
- */
-static int
-ZeroMultiXactMemberPage(int64 pageno, bool writeXlog)
-{
-	int			slotno;
-
-	slotno = SimpleLruZeroPage(MultiXactMemberCtl, pageno);
-
-	if (writeXlog)
-		WriteMZeroPageXlogRec(pageno, XLOG_MULTIXACT_ZERO_MEM_PAGE);
-
-	return slotno;
+	/*
+	 * Nullify the page (pageno = 0), save the page on a disk
+	 */
+	SimpleLruZeroPageExt(MultiXactOffsetCtl, 0);
+	SimpleLruZeroPageExt(MultiXactMemberCtl, 0);
 }
 
 /*
@@ -2134,7 +2072,7 @@ MaybeExtendOffsetSlru(void)
 		 * with creating a new segment file even if the page we're writing is
 		 * not the first in it, so this is enough.
 		 */
-		slotno = ZeroMultiXactOffsetPage(pageno, false);
+		slotno = SimpleLruZeroPage(MultiXactOffsetCtl, pageno);
 		SimpleLruWritePage(MultiXactOffsetCtl, slotno);
 	}
 
@@ -2569,7 +2507,8 @@ ExtendMultiXactOffset(MultiXactId multi)
 	LWLockAcquire(lock, LW_EXCLUSIVE);
 
 	/* Zero the page and make an XLOG entry about it */
-	ZeroMultiXactOffsetPage(pageno, true);
+	SimpleLruZeroPage(MultiXactOffsetCtl, pageno);
+	XLogSimpleInsert(RM_MULTIXACT_ID, XLOG_MULTIXACT_ZERO_OFF_PAGE, pageno);
 
 	LWLockRelease(lock);
 }
@@ -2612,7 +2551,8 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
 			LWLockAcquire(lock, LW_EXCLUSIVE);
 
 			/* Zero the page and make an XLOG entry about it */
-			ZeroMultiXactMemberPage(pageno, true);
+			SimpleLruZeroPage(MultiXactMemberCtl, pageno);
+			XLogSimpleInsert(RM_MULTIXACT_ID, XLOG_MULTIXACT_ZERO_MEM_PAGE, pageno);
 
 			LWLockRelease(lock);
 		}
@@ -3347,18 +3287,6 @@ MultiXactOffsetPrecedes(MultiXactOffset offset1, MultiXactOffset offset2)
 	return (diff < 0);
 }
 
-/*
- * Write an xlog record reflecting the zeroing of either a MEMBERs or
- * OFFSETs page (info shows which)
- */
-static void
-WriteMZeroPageXlogRec(int64 pageno, uint8 info)
-{
-	XLogBeginInsert();
-	XLogRegisterData(&pageno, sizeof(pageno));
-	(void) XLogInsert(RM_MULTIXACT_ID, info);
-}
-
 /*
  * Write a TRUNCATE xlog record
  *
@@ -3401,36 +3329,16 @@ multixact_redo(XLogReaderState *record)
 	if (info == XLOG_MULTIXACT_ZERO_OFF_PAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroMultiXactOffsetPage(pageno, false);
-		SimpleLruWritePage(MultiXactOffsetCtl, slotno);
-		Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		/* Zero the page, write the page on a disk */
+		SimpleLruZeroPageExt(MultiXactOffsetCtl, pageno);
 	}
 	else if (info == XLOG_MULTIXACT_ZERO_MEM_PAGE)
 	{
 		int64		pageno;
-		int			slotno;
-		LWLock	   *lock;
-
 		memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
-
-		lock = SimpleLruGetBankLock(MultiXactMemberCtl, pageno);
-		LWLockAcquire(lock, LW_EXCLUSIVE);
-
-		slotno = ZeroMultiXactMemberPage(pageno, false);
-		SimpleLruWritePage(MultiXactMemberCtl, slotno);
-		Assert(!MultiXactMemberCtl->shared->page_dirty[slotno]);
-
-		LWLockRelease(lock);
+		/* Zero the page, write the page on a disk */
+		SimpleLruZeroPageExt(MultiXactMemberCtl, pageno);
 	}
 	else if (info == XLOG_MULTIXACT_CREATE_ID)
 	{
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index 9ce628e62a5..5032f1cf126 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -190,7 +190,6 @@ static bool SlruScanDirCbDeleteCutoff(SlruCtl ctl, char *filename,
 static void SlruInternalDeleteSegment(SlruCtl ctl, int64 segno);
 static inline void SlruRecentlyUsed(SlruShared shared, int slotno);
 
-
 /*
  * Initialization of shared memory
  */
@@ -363,6 +362,32 @@ check_slru_buffers(const char *name, int *newval)
 	return false;
 }
 
+/*
+ * SimpleLruZeroPageExt performs:
+ * 		1. locking the page,
+ * 		2. nullifying the page,
+ * 		3. writing the page out,
+ * 		4. releasing the lock.
+ */
+void
+SimpleLruZeroPageExt(SlruCtl ctl, int64 pageno)
+{
+	int			slotno;
+	LWLock	   *lock;
+
+	lock = SimpleLruGetBankLock(ctl, pageno);
+	LWLockAcquire(lock, LW_EXCLUSIVE);
+
+	/* Create and zero the page*/
+	slotno = SimpleLruZeroPage(ctl, pageno);
+
+	/* Make sure it's written out */
+	SimpleLruWritePage(ctl, slotno);
+	Assert(!ctl->shared->page_dirty[slotno]);
+
+	LWLockRelease(lock);
+}
+
 /*
  * Initialize (or reinitialize) a page to zeroes.
  *
diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c
index 15153618fad..e597f54fb1e 100644
--- a/src/backend/access/transam/subtrans.c
+++ b/src/backend/access/transam/subtrans.c
@@ -74,7 +74,6 @@ static SlruCtlData SubTransCtlData;
 #define SubTransCtl  (&SubTransCtlData)
 
 
-static int	ZeroSUBTRANSPage(int64 pageno);
 static bool SubTransPagePrecedes(int64 page1, int64 page2);
 
 
@@ -269,33 +268,10 @@ check_subtrans_buffers(int *newval, void **extra, GucSource source)
 void
 BootStrapSUBTRANS(void)
 {
-	int			slotno;
-	LWLock	   *lock = SimpleLruGetBankLock(SubTransCtl, 0);
-
-	LWLockAcquire(lock, LW_EXCLUSIVE);
-
-	/* Create and zero the first page of the subtrans log */
-	slotno = ZeroSUBTRANSPage(0);
-
-	/* Make sure it's written out */
-	SimpleLruWritePage(SubTransCtl, slotno);
-	Assert(!SubTransCtl->shared->page_dirty[slotno]);
-
-	LWLockRelease(lock);
-}
-
-/*
- * Initialize (or reinitialize) a page of SUBTRANS to zeroes.
- *
- * The page is not actually written, just set up in shared memory.
- * The slot number of the new page is returned.
- *
- * Control lock must be held at entry, and will be held at exit.
- */
-static int
-ZeroSUBTRANSPage(int64 pageno)
-{
-	return SimpleLruZeroPage(SubTransCtl, pageno);
+	/*
+	 * Nullify the page (pageno = 0), save the page on a disk
+	 */
+	SimpleLruZeroPageExt(SubTransCtl, 0);
 }
 
 /*
@@ -335,7 +311,7 @@ StartupSUBTRANS(TransactionId oldestActiveXID)
 			prevlock = lock;
 		}
 
-		(void) ZeroSUBTRANSPage(startPage);
+		(void) SimpleLruZeroPage(SubTransCtl, startPage);
 		if (startPage == endPage)
 			break;
 
@@ -395,7 +371,7 @@ ExtendSUBTRANS(TransactionId newestXact)
 	LWLockAcquire(lock, LW_EXCLUSIVE);
 
 	/* Zero the page */
-	ZeroSUBTRANSPage(pageno);
+	SimpleLruZeroPage(SubTransCtl, pageno);
 
 	LWLockRelease(lock);
 }
diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c
index 14d583ae7ae..468e7cf60b1 100644
--- a/src/backend/access/transam/xloginsert.c
+++ b/src/backend/access/transam/xloginsert.c
@@ -1390,3 +1390,17 @@ InitXLogInsert(void)
 		hdr_scratch = MemoryContextAllocZero(xloginsert_cxt,
 											 HEADER_SCRATCH_SIZE);
 }
+
+/*
+ * Write an xlog record comprising simple int64 data.
+ *
+ * Useful for SLRU zeropages. In this case the simpledata is usually the number of
+ * a nullified SLRU page.
+ */
+void
+XLogSimpleInsert(RmgrId rmid, uint8 info, int64 simpledata)
+{
+	XLogBeginInsert();
+	XLogRegisterData(&simpledata, sizeof(simpledata));
+	(void) XLogInsert(rmid, info);
+}
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index e142800aab2..eb728df3055 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -186,6 +186,7 @@ extern void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
 						  const char *subdir, int buffer_tranche_id,
 						  int bank_tranche_id, SyncRequestHandler sync_handler,
 						  bool long_segment_names);
+extern void	SimpleLruZeroPageExt(SlruCtl ctl, int64 pageno);
 extern int	SimpleLruZeroPage(SlruCtl ctl, int64 pageno);
 extern int	SimpleLruReadPage(SlruCtl ctl, int64 pageno, bool write_ok,
 							  TransactionId xid);
diff --git a/src/include/access/xloginsert.h b/src/include/access/xloginsert.h
index cf057f033a2..befd4250655 100644
--- a/src/include/access/xloginsert.h
+++ b/src/include/access/xloginsert.h
@@ -64,5 +64,6 @@ extern void log_newpage_range(Relation rel, ForkNumber forknum,
 extern XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std);
 
 extern void InitXLogInsert(void);
+extern void XLogSimpleInsert(RmgrId rmid, uint8 info, int64 simpledata);
 
 #endif							/* XLOGINSERT_H */
-- 
2.48.1

#18Evgeny
evorop@gmail.com
In reply to: Evgeny (#17)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

Álvaro, Andrey, Alexander, hello!

Since the master branch became the PG19dev and PG18 is now stable, I
have directed this patch into PG19. Could we continue with it now?

Álvaro, should I rename the SimpleLruZeroPageExt function?

Best regards,
Evgeny Voropaev.

Show quoted text

On 14.03.2025 21:43, Evgeny wrote:

Hello Hackers!

I think this is going too far.  The new function BootStrapSlruPage() now
is being used for things other than bootstrapping, and that doesn't seem
appropriate to me.  I think we should leave the things that aren't
bootstrap out of this patch.  For instance, ExtendCLOG was more
understandable before this patch than after.  Same with
ExtendMultiXact{Offset,Member}, ExtendSUBTRANS, etc.

I have excluded the uses of BootStrapSlruPage in Extend* functions. The
code of these functions is remaining still modified a bit on account of
Zero* functions having been deleted. It now includes such fragments:

/* Zero the page and make an XLOG entry about it */
SimpleLruZeroPage(MultiXactMemberCtl, pageno);
XLogSimpleInsert(RM_MULTIXACT_ID, XLOG_MULTIXACT_ZERO_MEM_PAGE, pageno);

as a substitution of:
/* Zero the page and make an XLOG entry about it */
ZeroMultiXactOffsetPage(pageno, true);

But, probably, it even makes a code more readable showing both actions
clearly.

By removing these changes, you can remove the third argument to
BootStrapSlruPage (the function pointer), since you don't need it.

Indeed, it has helped to remove an input parameter from the
BootStrapSlruPage function. Honestly, even two arguments are removed,
since code has not opted whether to write a page on a disk or not. It
saves a page every time.

I'm also very suspicious of the use of the new function in the redo
routines also, because those are not bootstrapping anything.  I'd rather
have another routine, say SimpleLruRedoZeroPage() which only handles the
zeroing of a page from a WAL record.  It would be very similar to
BootstrapSlruPage, and maybe they can share an internal "workhorse"
function for the bits that are common.

Now the logic zeroing page on the "do" side is fully equal to one on the
"redo" side. As a result, creation of a new distinct function for "redo"
is not needed. In order for the function to conform to the both sides
("do" and "redo") I have renamed it into SimpleLruZeroPageExt. If this
name looks not appropriate, we can change it, please, propose new one.

I don't have faith in the function name XLogInsertInt64().  The datatype
has no role there.  I liked my proposal better.

The name has been reverted to one Álvaro has proposed at first
(XLogSimpleInsert).

Patch looks even better - it reduce code by 180 lines.

Best regards,
Evgeny Voropaev.

#19Álvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Evgeny (#18)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

On 2025-Jul-02, Evgeny wrote:

Álvaro, Andrey, Alexander, hello!

Since the master branch became the PG19dev and PG18 is now stable, I have
directed this patch into PG19. Could we continue with it now?

Sure, I pushed your patch now.

Álvaro, should I rename the SimpleLruZeroPageExt function?

Well, I didn't like that name -- normally, names ending in Ext represent
a version of the routine named without the "Ext" that has some additions
to its argument list, so the Ext is an extended version or something
like that. That pattern does not fit this case. I used the name
"SimpleLruZeroAndWritePage" instead, and rewrote the comment to explain
that it's a simple wrapper that does exactly what the name says.
Because of this I also removed some comments in the callsites, because
those would have been redundant with the new name. So, no you don't
need to do anything, because I already did it.

I also went back and accepted Andrey's suggestion to have Int64 in the
name of the XLogSimpleInsert routine, because it's not totally
unthinkable that we'll have some other simple wrapper in the future.
I made it return the LSN, because while no current caller needs it, some
external caller might want to have that.

I also moved each routine to a more natural place, namely just below the
function they wrap. The pattern of adding stuff at the end of the file
just results in messy code, so don't do that.

--
Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/
"Tiene valor aquel que admite que es un cobarde" (Fernandel)

#20Evgeny
evorop@gmail.com
In reply to: Álvaro Herrera (#19)
Re: Elimination of the repetitive code at the SLRU bootstrap functions.

Álvaro, thank you for pushing, attention and final editing of the patch!
I got your recommendations and requirements. I will take them into
account at a next patch.

Andrey, Alexander thank you for your proposals, attention, advice, and
review!

Best regards,
Evgeny Voropaev,
Tantor Labs, LLC.