At the "make mxidoff 64 bits" thread [1], we're discussing moving SLRU_PAGES_PER_SEGMENT to pg_config_manual.h, to make it accessible from pg_upgrade code. It's currently defined in slru.h, which cannot be included in frontend code. There are many ways we could fix that, but moving SLRU_PAGES_PER_SEGMENT to pg_config_manual.h seems best to me. Patch attached.

There was a suggestion earlier to make SLRU_PAGES_PER_SEGMENT a configure option [2]. I don't want to go that far; pg_config_manual.h seems like the right level of configurability to me.

I'm raising this in a new thread for visibility, in case someone who hasn't been following the other threads have objections or better suggestions.

The patch does not move over this comment from slru.h:

- * Note: because TransactionIds are 32 bits and wrap around at 0xFFFFFFFF,
- * page numbering also wraps around at 0xFFFFFFFF/xxxx_XACTS_PER_PAGE (where
- * xxxx is CLOG or SUBTRANS, respectively), and segment numbering at
- * 0xFFFFFFFF/xxxx_XACTS_PER_PAGE/SLRU_PAGES_PER_SEGMENT.  We need
- * take no explicit notice of that fact in slru.c, except when comparing
- * segment and page numbers in SimpleLruTruncate (see PagePrecedes()).

I left it out because there's already a copy of the same comment next to CLOG_XACTS_PER_PAGE and SUBTRANS_XACTS_PER_PAGE. That seems enough.

[1] https://www.postgresql.org/message-id/CACG%3DezbZo_3_fnx%3DS5BfepwRftzrpJ%2B7WET4EkTU6wnjDTsnjg%40mail.gmail.com

[2] https://www.postgresql.org/message-id/CAJDiXgiSVjsMj7pCKrXjwoVb2UCo28Fifd2VndNgybfbAhjbpg%40mail.gmail.com

- Heikki
From 0915d845a720c68252d61395c48ed908dd18dafd Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <[email protected]>
Date: Mon, 10 Nov 2025 13:14:54 +0200
Subject: [PATCH 1/1] Move SLRU_PAGES_PER_SEGMENT to pg_config_manual.h

It seems plausible that someone might want to experiment with
different values. The pressing reason though is that I'm reviewing a
patch that requires pg_upgrade to manipulate SLRU files. That patch
needs to access SLRU_PAGES_PER_SEGMENT from pg_upgrade code, and
slru.h, where SLRU_PAGES_PER_SEGMENT is currently defined, cannot be
included from frontend code. Moving it to pg_config_manual.h makes it
accessible.

Now that it's a little more likely that someone might change
SLRU_PAGES_PER_SEGMENT, add a cluster compatibility check for it.

Bump catalog version because of the new field in the control file.

Discussion: https://www.postgresql.org/message-id/cacg%3dezbzo_3_fnx%3ds5bfepwrftzrpj%[email protected]
---
 src/backend/access/transam/xlog.c | 11 +++++++++++
 src/include/access/slru.h         | 15 ---------------
 src/include/catalog/catversion.h  |  3 ++-
 src/include/catalog/pg_control.h  |  2 ++
 src/include/pg_config_manual.h    | 10 ++++++++++
 5 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 101b616b028..22d0a2e8c3a 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4271,6 +4271,7 @@ WriteControlFile(void)
 
 	ControlFile->blcksz = BLCKSZ;
 	ControlFile->relseg_size = RELSEG_SIZE;
+	ControlFile->slru_pages_per_segment = SLRU_PAGES_PER_SEGMENT;
 	ControlFile->xlog_blcksz = XLOG_BLCKSZ;
 	ControlFile->xlog_seg_size = wal_segment_size;
 
@@ -4490,6 +4491,16 @@ ReadControlFile(void)
 						   "RELSEG_SIZE", ControlFile->relseg_size,
 						   "RELSEG_SIZE", RELSEG_SIZE),
 				 errhint("It looks like you need to recompile or initdb.")));
+	if (ControlFile->slru_pages_per_segment != SLRU_PAGES_PER_SEGMENT)
+		ereport(FATAL,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("database files are incompatible with server"),
+		/* translator: %s is a variable name and %d is its value */
+				 errdetail("The database cluster was initialized with %s %d,"
+						   " but the server was compiled with %s %d.",
+						   "SLRU_PAGES_PER_SEGMENT", ControlFile->slru_pages_per_segment,
+						   "SLRU_PAGES_PER_SEGMENT", SLRU_PAGES_PER_SEGMENT),
+				 errhint("It looks like you need to recompile or initdb.")));
 	if (ControlFile->xlog_blcksz != XLOG_BLCKSZ)
 		ereport(FATAL,
 				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index 8d57753ed01..8576649b15e 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -23,21 +23,6 @@
  */
 #define SLRU_MAX_ALLOWED_BUFFERS ((1024 * 1024 * 1024) / BLCKSZ)
 
-/*
- * Define SLRU segment size.  A page is the same BLCKSZ as is used everywhere
- * else in Postgres.  The segment size can be chosen somewhat arbitrarily;
- * we make it 32 pages by default, or 256Kb, i.e. 1M transactions for CLOG
- * or 64K transactions for SUBTRANS.
- *
- * Note: because TransactionIds are 32 bits and wrap around at 0xFFFFFFFF,
- * page numbering also wraps around at 0xFFFFFFFF/xxxx_XACTS_PER_PAGE (where
- * xxxx is CLOG or SUBTRANS, respectively), and segment numbering at
- * 0xFFFFFFFF/xxxx_XACTS_PER_PAGE/SLRU_PAGES_PER_SEGMENT.  We need
- * take no explicit notice of that fact in slru.c, except when comparing
- * segment and page numbers in SimpleLruTruncate (see PagePrecedes()).
- */
-#define SLRU_PAGES_PER_SEGMENT	32
-
 /*
  * Page status codes.  Note that these do not include the "dirty" bit.
  * page_dirty can be true only in the VALID or WRITE_IN_PROGRESS states;
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 60e7fd047d1..ef796602c53 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -57,6 +57,7 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	202511071
+/*  FIXME: bump it */
+#define CATALOG_VERSION_NO	999999999
 
 #endif
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
index 63e834a6ce4..1ac0d5126fc 100644
--- a/src/include/catalog/pg_control.h
+++ b/src/include/catalog/pg_control.h
@@ -207,6 +207,8 @@ typedef struct ControlFileData
 	uint32		blcksz;			/* data block size for this DB */
 	uint32		relseg_size;	/* blocks per segment of large relation */
 
+	uint32		slru_pages_per_segment; /* size of each SLRU segment */
+
 	uint32		xlog_blcksz;	/* block size within WAL files */
 	uint32		xlog_seg_size;	/* size of each WAL segment */
 
diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h
index 7e1aa422332..c61a9faf870 100644
--- a/src/include/pg_config_manual.h
+++ b/src/include/pg_config_manual.h
@@ -19,6 +19,16 @@
  */
 #define DEFAULT_XLOG_SEG_SIZE	(16*1024*1024)
 
+/*
+ * SLRU segment size.  A page is the same BLCKSZ as is used everywhere else in
+ * Postgres.  The segment size can be chosen somewhat arbitrarily; we make it
+ * 32 pages by default, or 256Kb, i.e. 1M transactions for CLOG or 64K
+ * transactions for SUBTRANS.
+ *
+ * Changing this requires an initdb.
+ */
+#define SLRU_PAGES_PER_SEGMENT	32
+
 /*
  * Maximum length for identifiers (e.g. table names, column names,
  * function names).  Names actually are limited to one fewer byte than this,
-- 
2.47.3

Reply via email to