From 51be79b5c580a794760cf1baf4e040c55443adc6 Mon Sep 17 00:00:00 2001
From: Dilip Kumar <dilip.kumar@enterprisedb.com>
Date: Thu, 2 Nov 2023 11:40:08 +0530
Subject: [PATCH v4 5/5] Ensure slru buffer slots are in multiple of numbe of
 partitions

---
 src/backend/access/transam/clog.c      | 10 ++++++++++
 src/backend/access/transam/commit_ts.c | 10 ++++++++++
 src/backend/access/transam/multixact.c | 19 +++++++++++++++++++
 src/backend/access/transam/slru.c      | 18 ++++++++++++++++++
 src/backend/access/transam/subtrans.c  | 10 ++++++++++
 src/backend/commands/async.c           | 10 ++++++++++
 src/backend/storage/lmgr/predicate.c   | 10 ++++++++++
 src/backend/utils/misc/guc_tables.c    | 14 +++++++-------
 src/include/access/slru.h              |  1 +
 src/include/utils/guc_hooks.h          | 11 +++++++++++
 10 files changed, 106 insertions(+), 7 deletions(-)

diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index ab453cd171..17e08792d4 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -43,6 +43,7 @@
 #include "pgstat.h"
 #include "storage/proc.h"
 #include "storage/sync.h"
+#include "utils/guc_hooks.h"
 
 /*
  * Defines for CLOG page sizes.  A page is the same BLCKSZ as is used
@@ -1056,3 +1057,12 @@ clogsyncfiletag(const FileTag *ftag, char *path)
 {
 	return SlruSyncFileTag(XactCtl, ftag, path);
 }
+
+/*
+ * GUC check_hook for xact_buffers
+ */
+bool
+check_xact_buffers(int *newval, void **extra, GucSource source)
+{
+	return check_slru_buffers("xact_buffers", newval);
+}
diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c
index 58314e3885..4fd01c5ce8 100644
--- a/src/backend/access/transam/commit_ts.c
+++ b/src/backend/access/transam/commit_ts.c
@@ -33,6 +33,7 @@
 #include "pg_trace.h"
 #include "storage/shmem.h"
 #include "utils/builtins.h"
+#include "utils/guc_hooks.h"
 #include "utils/snapmgr.h"
 #include "utils/timestamp.h"
 
@@ -1022,3 +1023,12 @@ committssyncfiletag(const FileTag *ftag, char *path)
 {
 	return SlruSyncFileTag(CommitTsCtl, ftag, path);
 }
+
+/*
+ * GUC check_hook for commit_ts_buffers
+ */
+bool
+check_commit_ts_buffers(int *newval, void **extra, GucSource source)
+{
+	return check_slru_buffers("commit_ts_buffers", newval);
+}
\ No newline at end of file
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index aa4f11fd3b..d0ce4e28d2 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -88,6 +88,7 @@
 #include "storage/proc.h"
 #include "storage/procarray.h"
 #include "utils/builtins.h"
+#include "utils/guc_hooks.h"
 #include "utils/memutils.h"
 #include "utils/snapmgr.h"
 
@@ -3494,3 +3495,21 @@ multixactmemberssyncfiletag(const FileTag *ftag, char *path)
 {
 	return SlruSyncFileTag(MultiXactMemberCtl, ftag, path);
 }
+
+/*
+ * GUC check_hook for multixact_offsets_buffers
+ */
+bool
+check_multixact_offsets_buffers(int *newval, void **extra, GucSource source)
+{
+	return check_slru_buffers("multixact_offsets_buffers", newval);
+}
+
+/*
+ * GUC check_hook for multixact_members_buffers
+ */
+bool
+check_multixact_members_buffers(int *newval, void **extra, GucSource source)
+{
+	return check_slru_buffers("multixact_members_buffers", newval);
+}
\ No newline at end of file
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index 8b89a86a10..bac6bf1d42 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -59,6 +59,7 @@
 #include "pgstat.h"
 #include "storage/fd.h"
 #include "storage/shmem.h"
+#include "utils/guc.h"
 #include "utils/hsearch.h"
 
 #define SlruFileName(ctl, path, seg) \
@@ -1850,3 +1851,20 @@ SimpleLruUnLockAllPartitions(SlruCtl ctl)
 	for (partno = 0; partno < SLRU_NUM_PARTITIONS; partno++)
 		LWLockRelease(&shared->locks[nslots + partno].lock);
 }
+
+/*
+ * Helper function for GUC check_hook to check whether slru buffers are in
+ * multiples of SLRU_NUM_PARTITIONS.
+ */
+bool
+check_slru_buffers(const char *name, int *newval)
+{
+	/* Value upper and lower hard limits are inclusive */
+	if (*newval % SLRU_NUM_PARTITIONS == 0)
+		return true;
+
+	/* Value does not fall within any allowable range */
+	GUC_check_errdetail("\"%s\" must be in multiple of %d", name,
+						SLRU_NUM_PARTITIONS);
+	return false;
+}
diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c
index e4da6e28ae..16a26a2ca5 100644
--- a/src/backend/access/transam/subtrans.c
+++ b/src/backend/access/transam/subtrans.c
@@ -33,6 +33,7 @@
 #include "access/transam.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "utils/guc_hooks.h"
 #include "utils/snapmgr.h"
 
 
@@ -406,3 +407,12 @@ SubTransPagePrecedes(int page1, int page2)
 	return (TransactionIdPrecedes(xid1, xid2) &&
 			TransactionIdPrecedes(xid1, xid2 + SUBTRANS_XACTS_PER_PAGE - 1));
 }
+
+/*
+ * GUC check_hook for subtrans_buffers
+ */
+bool
+check_subtrans_buffers(int *newval, void **extra, GucSource source)
+{
+	return check_slru_buffers("subtrans_buffers", newval);
+}
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 81fdca410b..0ea6880764 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -149,6 +149,7 @@
 #include "storage/sinval.h"
 #include "tcop/tcopprot.h"
 #include "utils/builtins.h"
+#include "utils/guc_hooks.h"
 #include "utils/memutils.h"
 #include "utils/ps_status.h"
 #include "utils/snapmgr.h"
@@ -2462,3 +2463,12 @@ ClearPendingActionsAndNotifies(void)
 	pendingActions = NULL;
 	pendingNotifies = NULL;
 }
+
+/*
+ * GUC check_hook for notify_buffers
+ */
+bool
+check_notify_buffers(int *newval, void **extra, GucSource source)
+{
+	return check_slru_buffers("notify_buffers", newval);
+}
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index 6b7c1aa00e..40089a606d 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -208,6 +208,7 @@
 #include "storage/predicate_internals.h"
 #include "storage/proc.h"
 #include "storage/procarray.h"
+#include "utils/guc_hooks.h"
 #include "utils/rel.h"
 #include "utils/snapmgr.h"
 
@@ -5014,3 +5015,12 @@ AttachSerializableXact(SerializableXactHandle handle)
 	if (MySerializableXact != InvalidSerializableXact)
 		CreateLocalPredicateLockHash();
 }
+
+/*
+ * GUC check_hook for serial_buffers
+ */
+bool
+check_serial_buffers(int *newval, void **extra, GucSource source)
+{
+	return check_slru_buffers("serial_buffers", newval);
+}
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index c82635943b..7c85d2126e 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -2296,7 +2296,7 @@ struct config_int ConfigureNamesInt[] =
 		},
 		&multixact_offsets_buffers,
 		64, 16, SLRU_MAX_ALLOWED_BUFFERS,
-		NULL, NULL, NULL
+		check_multixact_offsets_buffers, NULL, NULL
 	},
 
 	{
@@ -2307,7 +2307,7 @@ struct config_int ConfigureNamesInt[] =
 		},
 		&multixact_members_buffers,
 		64, 16, SLRU_MAX_ALLOWED_BUFFERS,
-		NULL, NULL, NULL
+		check_multixact_members_buffers, NULL, NULL
 	},
 
 	{
@@ -2318,7 +2318,7 @@ struct config_int ConfigureNamesInt[] =
 		},
 		&subtrans_buffers,
 		64, 16, SLRU_MAX_ALLOWED_BUFFERS,
-		NULL, NULL, NULL
+		check_subtrans_buffers, NULL, NULL
 	},
 	{
 		{"notify_buffers", PGC_POSTMASTER, RESOURCES_MEM,
@@ -2328,7 +2328,7 @@ struct config_int ConfigureNamesInt[] =
 		},
 		&notify_buffers,
 		64, 16, SLRU_MAX_ALLOWED_BUFFERS,
-		NULL, NULL, NULL
+		check_notify_buffers, NULL, NULL
 	},
 
 	{
@@ -2339,7 +2339,7 @@ struct config_int ConfigureNamesInt[] =
 		},
 		&serial_buffers,
 		64, 16, SLRU_MAX_ALLOWED_BUFFERS,
-		NULL, NULL, NULL
+		check_serial_buffers, NULL, NULL
 	},
 
 	{
@@ -2350,7 +2350,7 @@ struct config_int ConfigureNamesInt[] =
 		},
 		&xact_buffers,
 		64, 0, CLOG_MAX_ALLOWED_BUFFERS,
-		NULL, NULL, show_xact_buffers
+		check_xact_buffers, NULL, show_xact_buffers
 	},
 
 	{
@@ -2361,7 +2361,7 @@ struct config_int ConfigureNamesInt[] =
 		},
 		&commit_ts_buffers,
 		64, 0, SLRU_MAX_ALLOWED_BUFFERS,
-		NULL, NULL, show_commit_ts_buffers
+		check_commit_ts_buffers, NULL, show_commit_ts_buffers
 	},
 
 	{
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index ac1227f29f..fef23d30f5 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -198,4 +198,5 @@ extern LWLock *SimpleLruGetPartitionLock(SlruCtl ctl, int pageno);
 extern void SimpleLruLockAllPartitions(SlruCtl ctl, LWLockMode mode);
 extern void SimpleLruUnLockAllPartitions(SlruCtl ctl);
 extern LWLock *SimpleLruGetPartitionLock(SlruCtl ctl, int pageno);
+extern bool check_slru_buffers(const char *name, int *newval);
 #endif							/* SLRU_H */
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 8597e430de..7dd96a2059 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -128,6 +128,17 @@ extern bool check_ssl(bool *newval, void **extra, GucSource source);
 extern bool check_stage_log_stats(bool *newval, void **extra, GucSource source);
 extern bool check_synchronous_standby_names(char **newval, void **extra,
 											GucSource source);
+extern bool check_multixact_offsets_buffers(int *newval, void **extra,
+											GucSource source);
+extern bool check_multixact_members_buffers(int *newval, void **extra,
+											GucSource source);
+extern bool check_subtrans_buffers(int *newval, void **extra,
+								   GucSource source);
+extern bool check_notify_buffers(int *newval, void **extra, GucSource source);
+extern bool check_serial_buffers(int *newval, void **extra, GucSource source);
+extern bool check_xact_buffers(int *newval, void **extra, GucSource source);
+extern bool check_commit_ts_buffers(int *newval, void **extra,
+									GucSource source);
 extern void assign_synchronous_standby_names(const char *newval, void *extra);
 extern void assign_synchronous_commit(int newval, void *extra);
 extern void assign_syslog_facility(int newval, void *extra);
-- 
2.39.2 (Apple Git-143)

