0010-WIP-Reinitialize-buffer-sync-strategy-20250228.patch

text/x-patch

Filename: 0010-WIP-Reinitialize-buffer-sync-strategy-20250228.patch
Type: text/x-patch
Part: 6
Message: Re: Changing shared_buffers without restart

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch 0010
Subject: WIP: Reinitialize buffer sync strategy
File+
src/backend/port/sysv_shmem.c 6 0
src/backend/postmaster/bgwriter.c 1 1
src/backend/storage/buffer/buf_init.c 1 1
src/backend/storage/buffer/bufmgr.c 18 2
src/backend/storage/buffer/freelist.c 32 0
src/include/storage/buf_internals.h 1 0
src/include/storage/bufmgr.h 1 1
From 67ab7fe07bd0bd9f6a1f7ebbeaa7f27e32cf0cf3 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Date: Mon, 27 Jan 2025 15:46:23 +0530
Subject: [PATCH 10/11] WIP: Reinitialize buffer sync strategy

Resizing the shared buffers renders the saved state of BgBufferSync() invalid.
Hence reinitialize it. The state is saved in static variables inside the
function and thus can not be accessed from outside the function. Hence we add an
argument to BgBufferSync() to request the function to reset the state.

TODO: Ideally we should save this state in some global structure and add a
function to reset it.

TODO: StrategyInitialize() initializes buffer lookup table but
StrategyReInitialize() doesn't.  Where should we reinitialize the buffer
lookup table?

Ashutosh Bapat
---
 src/backend/port/sysv_shmem.c         |  6 +++++
 src/backend/postmaster/bgwriter.c     |  2 +-
 src/backend/storage/buffer/buf_init.c |  2 +-
 src/backend/storage/buffer/bufmgr.c   | 20 +++++++++++++++--
 src/backend/storage/buffer/freelist.c | 32 +++++++++++++++++++++++++++
 src/include/storage/buf_internals.h   |  1 +
 src/include/storage/bufmgr.h          |  2 +-
 7 files changed, 60 insertions(+), 5 deletions(-)

diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index f084a0747ff..66d6d4b4333 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -1007,7 +1007,13 @@ AnonymousShmemResize(void)
 		 * backend who can not lock the LWLock conditionally won't resize the
 		 * buffers.
 		 */
+
+		if (MyBackendType == B_BG_WRITER)
+		{
+			/* If we are bgwriter wipe out the previous state and start anew. */
+			BgBufferSync(NULL, true);
 		}
+	}
 
 	return true;
 }
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index 3eff5dc6f0e..3cd421b23c0 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -231,7 +231,7 @@ BackgroundWriterMain(char *startup_data, size_t startup_data_len)
 		/*
 		 * Do one cycle of dirty-buffer writing.
 		 */
-		can_hibernate = BgBufferSync(&wb_context);
+		can_hibernate = BgBufferSync(&wb_context, false);
 
 		/* Report pending statistics to the cumulative stats system */
 		pgstat_report_bgwriter();
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c
index d8139a899bb..6b6f6e6ae08 100644
--- a/src/backend/storage/buffer/buf_init.c
+++ b/src/backend/storage/buffer/buf_init.c
@@ -305,7 +305,7 @@ ResizeBufferPool(int NBuffersOld, bool initNew)
 	GetBufferDescriptor(NBuffers - 1)->freeNext = FREENEXT_END_OF_LIST;
 
 	/* Init other shared buffer-management stuff */
-	StrategyInitialize(!foundDescs);
+	StrategyReInitialize();
 
 	/* Initialize per-backend file flush context */
 	WritebackContextInit(&BackendWritebackContext,
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index b6bec73e6b7..a7948e75e76 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -3179,7 +3179,10 @@ BufferSync(int flags)
  * BgBufferSync -- Write out some dirty buffers in the pool.
  *
  * This is called periodically by the background writer process.
- *
+ * 
+ * If `reset` = true, the function discards any saved information and starts
+ * anew.
+ * 
  * Returns true if it's appropriate for the bgwriter process to go into
  * low-power hibernation mode.  (This happens if the strategy clock sweep
  * has been "lapped" and no buffer allocations have occurred recently,
@@ -3187,7 +3190,7 @@ BufferSync(int flags)
  * bgwriter_lru_maxpages to 0.)
  */
 bool
-BgBufferSync(WritebackContext *wb_context)
+BgBufferSync(WritebackContext *wb_context, bool reset)
 {
 	/* info obtained from freelist.c */
 	int			strategy_buf_id;
@@ -3230,6 +3233,19 @@ BgBufferSync(WritebackContext *wb_context)
 	long		new_strategy_delta;
 	uint32		new_recent_alloc;
 
+	if (reset)
+	{
+		saved_info_valid = false;
+
+		/*
+		 * Return from here, if we don't have a valid WritebackContext. Next time
+		 * this function will be executed with a valid WritebackContext, it will
+		 * start over again.
+		 */
+		if (!wb_context)
+			return false;
+	}
+
 	/*
 	 * Find out where the freelist clock sweep currently is, and how many
 	 * buffer allocations have happened since our last call.
diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c
index 45a6e768332..4bb000f36e1 100644
--- a/src/backend/storage/buffer/freelist.c
+++ b/src/backend/storage/buffer/freelist.c
@@ -528,6 +528,38 @@ StrategyInitialize(bool init)
 		Assert(!init);
 }
 
+/*
+ * StrategyReInitialize -- re-initialize the buffer cache replacement
+ *		strategy.
+ *
+ * To be called when resizing buffer manager and only from the coordinator.
+ */
+void
+StrategyReInitialize(void)
+{
+	bool		found;
+
+	/*
+	 * Get or create the shared strategy control block. This is mostly not
+	 * required since we are not moving the starting pointer anyway.
+	 */
+	StrategyControl = (BufferStrategyControl *)
+		ShmemInitStructInSegment("Buffer Strategy Status",
+						sizeof(BufferStrategyControl),
+						&found, STRATEGY_SHMEM_SEGMENT);
+
+	SpinLockInit(&StrategyControl->buffer_strategy_lock);
+
+	/* Initialize the clock sweep pointer */
+	pg_atomic_init_u32(&StrategyControl->nextVictimBuffer, 0);
+
+	/* Clear statistics */
+	StrategyControl->completePasses = 0;
+	pg_atomic_init_u32(&StrategyControl->numBufferAllocs, 0);
+
+	/* No pending notification */
+	StrategyControl->bgwprocno = -1;
+}
 
 /* ----------------------------------------------------------------
  *				Backend-private buffer ring management
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index 416c405fe4e..77bcaf1b43c 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -437,6 +437,7 @@ extern void StrategyNotifyBgWriter(int bgwprocno);
 
 extern Size StrategyShmemSize(void);
 extern void StrategyInitialize(bool init);
+extern void StrategyReInitialize(void);
 extern bool have_free_buffer(void);
 
 /* buf_table.c */
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index fff80214822..02db81fa416 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -288,7 +288,7 @@ extern bool ConditionalLockBufferForCleanup(Buffer buffer);
 extern bool IsBufferCleanupOK(Buffer buffer);
 extern bool HoldingBufferPinThatDelaysRecovery(void);
 
-extern bool BgBufferSync(struct WritebackContext *wb_context);
+extern bool BgBufferSync(struct WritebackContext *wb_context, bool reset);
 
 extern void LimitAdditionalPins(uint32 *additional_pins);
 extern void LimitAdditionalLocalPins(uint32 *additional_pins);
-- 
2.34.1