Move SLRU_PAGES_PER_SEGMENT to pg_config_manual.h
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 10 Nov 2025 14:11:41 +0000 (16:11 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 10 Nov 2025 14:11:41 +0000 (16:11 +0200)
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.

Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de>
Discussion: https://www.postgresql.org/message-id/c7a4ea90-9f7b-4953-81be-b3fcb47db057@iki.fi

src/backend/access/transam/xlog.c
src/include/access/slru.h
src/include/catalog/catversion.h
src/include/catalog/pg_control.h
src/include/pg_config_manual.h

index 101b616b028b600dd9b93f1373f6ab949ec2f665..22d0a2e8c3a6ac465b2f2628efd19cfd174608e3 100644 (file)
@@ -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),
index 8d57753ed01bdb7469c49454e2585d4603c0318f..8576649b15e3ac3a34557740f5147dc0887beacd 100644 (file)
  */
 #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;
index 60e7fd047d1a33482fa950c0dad07fe8a4956c84..7eefca1ae42922aa103ec173d409ad894ad5f53b 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 202511071
+#define CATALOG_VERSION_NO 202511101
 
 #endif
index 63e834a6ce4771a38d6ca98c3d8ab454e4fca8da..1ac0d5126fc3b1cc507273aa859938a89948ac97 100644 (file)
@@ -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 */
 
index 7e1aa4223326e4acd9372fce8894f155c1b40073..c61a9faf87097af5101b4f233367d91e4c2efdbb 100644 (file)
  */
 #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,