From 0d52ad50c8c5d96d87c7e9ee37e9e4122b6196eb Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Thu, 2 Apr 2026 00:44:02 +0300 Subject: [PATCH v20260405 13/15] Convert buffer manager to the new API --- src/backend/storage/buffer/buf_init.c | 149 ++++++++++--------------- src/backend/storage/buffer/buf_table.c | 54 +++++---- src/backend/storage/buffer/freelist.c | 93 +++++---------- src/backend/storage/ipc/ipci.c | 3 - src/include/storage/buf_internals.h | 5 - src/include/storage/bufmgr.h | 4 - src/include/storage/subsystemlist.h | 3 + 7 files changed, 124 insertions(+), 187 deletions(-) diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index c0c223b2e32..1407c930c56 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -18,6 +18,8 @@ #include "storage/buf_internals.h" #include "storage/bufmgr.h" #include "storage/proclist.h" +#include "storage/shmem.h" +#include "storage/subsystems.h" BufferDescPadded *BufferDescriptors; char *BufferBlocks; @@ -25,6 +27,15 @@ ConditionVariableMinimallyPadded *BufferIOCVArray; WritebackContext BackendWritebackContext; CkptSortItem *CkptBufferIds; +static void BufferManagerShmemRequest(void *arg); +static void BufferManagerShmemInit(void *arg); +static void BufferManagerShmemAttach(void *arg); + +const ShmemCallbacks BufferManagerShmemCallbacks = { + .request_fn = BufferManagerShmemRequest, + .init_fn = BufferManagerShmemInit, + .attach_fn = BufferManagerShmemAttach, +}; /* * Data Structures: @@ -60,37 +71,31 @@ CkptSortItem *CkptBufferIds; /* - * Initialize shared buffer pool - * - * This is called once during shared-memory initialization (either in the - * postmaster, or in a standalone backend). + * Register shared memory area for the buffer pool. */ -void -BufferManagerShmemInit(void) +static void +BufferManagerShmemRequest(void *arg) { - bool foundBufs, - foundDescs, - foundIOCV, - foundBufCkpt; - + ShmemRequestStruct(.name = "Buffer Descriptors", + .size = NBuffers * sizeof(BufferDescPadded), /* Align descriptors to a cacheline boundary. */ - BufferDescriptors = (BufferDescPadded *) - ShmemInitStruct("Buffer Descriptors", - NBuffers * sizeof(BufferDescPadded), - &foundDescs); + .alignment = PG_CACHE_LINE_SIZE, + .ptr = (void **) &BufferDescriptors, + ); + ShmemRequestStruct(.name = "Buffer Blocks", + .size = NBuffers * (Size) BLCKSZ, /* Align buffer pool on IO page size boundary. */ - BufferBlocks = (char *) - TYPEALIGN(PG_IO_ALIGN_SIZE, - ShmemInitStruct("Buffer Blocks", - NBuffers * (Size) BLCKSZ + PG_IO_ALIGN_SIZE, - &foundBufs)); - - /* Align condition variables to cacheline boundary. */ - BufferIOCVArray = (ConditionVariableMinimallyPadded *) - ShmemInitStruct("Buffer IO Condition Variables", - NBuffers * sizeof(ConditionVariableMinimallyPadded), - &foundIOCV); + .alignment = PG_IO_ALIGN_SIZE, + .ptr = (void **) &BufferBlocks, + ); + + ShmemRequestStruct(.name = "Buffer IO Condition Variables", + .size = NBuffers * sizeof(ConditionVariableMinimallyPadded), + /* Align descriptors to a cacheline boundary. */ + .alignment = PG_CACHE_LINE_SIZE, + .ptr = (void **) &BufferIOCVArray, + ); /* * The array used to sort to-be-checkpointed buffer ids is located in @@ -99,80 +104,50 @@ BufferManagerShmemInit(void) * the checkpointer is restarted, memory allocation failures would be * painful. */ - CkptBufferIds = (CkptSortItem *) - ShmemInitStruct("Checkpoint BufferIds", - NBuffers * sizeof(CkptSortItem), &foundBufCkpt); + ShmemRequestStruct(.name = "Checkpoint BufferIds", + .size = NBuffers * sizeof(CkptSortItem), + .ptr = (void **) &CkptBufferIds, + ); +} - if (foundDescs || foundBufs || foundIOCV || foundBufCkpt) - { - /* should find all of these, or none of them */ - Assert(foundDescs && foundBufs && foundIOCV && foundBufCkpt); - /* note: this path is only taken in EXEC_BACKEND case */ - } - else +/* + * Initialize shared buffer pool + * + * This is called once during shared-memory initialization (either in the + * postmaster, or in a standalone backend). + */ +static void +BufferManagerShmemInit(void *arg) +{ + /* + * Initialize all the buffer headers. + */ + for (int i = 0; i < NBuffers; i++) { - int i; + BufferDesc *buf = GetBufferDescriptor(i); - /* - * Initialize all the buffer headers. - */ - for (i = 0; i < NBuffers; i++) - { - BufferDesc *buf = GetBufferDescriptor(i); + ClearBufferTag(&buf->tag); - ClearBufferTag(&buf->tag); + pg_atomic_init_u64(&buf->state, 0); + buf->wait_backend_pgprocno = INVALID_PROC_NUMBER; - pg_atomic_init_u64(&buf->state, 0); - buf->wait_backend_pgprocno = INVALID_PROC_NUMBER; + buf->buf_id = i; - buf->buf_id = i; + pgaio_wref_clear(&buf->io_wref); - pgaio_wref_clear(&buf->io_wref); - - proclist_init(&buf->lock_waiters); - ConditionVariableInit(BufferDescriptorGetIOCV(buf)); - } + proclist_init(&buf->lock_waiters); + ConditionVariableInit(BufferDescriptorGetIOCV(buf)); } - /* Init other shared buffer-management stuff */ - StrategyInitialize(!foundDescs); - /* Initialize per-backend file flush context */ WritebackContextInit(&BackendWritebackContext, &backend_flush_after); } -/* - * BufferManagerShmemSize - * - * compute the size of shared memory for the buffer pool including - * data pages, buffer descriptors, hash tables, etc. - */ -Size -BufferManagerShmemSize(void) +static void +BufferManagerShmemAttach(void *arg) { - Size size = 0; - - /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); - - /* size of data pages, plus alignment padding */ - size = add_size(size, PG_IO_ALIGN_SIZE); - size = add_size(size, mul_size(NBuffers, BLCKSZ)); - - /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); - - /* size of I/O condition variables */ - size = add_size(size, mul_size(NBuffers, - sizeof(ConditionVariableMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); - - /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); - - return size; + /* Initialize per-backend file flush context */ + WritebackContextInit(&BackendWritebackContext, + &backend_flush_after); } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index d04ef74b850..347bf267d73 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -22,6 +22,7 @@ #include "postgres.h" #include "storage/buf_internals.h" +#include "storage/subsystems.h" /* entry for buffer lookup hashtable */ typedef struct @@ -32,37 +33,42 @@ typedef struct static HTAB *SharedBufHash; +static void BufTableShmemRequest(void *arg); -/* - * Estimate space needed for mapping hashtable - * size is the desired hash table size (possibly more than NBuffers) - */ -Size -BufTableShmemSize(int size) -{ - return hash_estimate_size(size, sizeof(BufferLookupEnt)); -} +const ShmemCallbacks BufTableShmemCallbacks = { + .request_fn = BufTableShmemRequest, + /* no special initialization needed, the hash table will start empty */ +}; /* - * Initialize shmem hash table for mapping buffers + * Register shmem hash table for mapping buffers. * size is the desired hash table size (possibly more than NBuffers) */ void -InitBufTable(int size) +BufTableShmemRequest(void *arg) { - HASHCTL info; - - /* assume no locking is needed yet */ - - /* BufferTag maps to Buffer */ - info.keysize = sizeof(BufferTag); - info.entrysize = sizeof(BufferLookupEnt); - info.num_partitions = NUM_BUFFER_PARTITIONS; - - SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table", - size, - &info, - HASH_ELEM | HASH_BLOBS | HASH_PARTITION | HASH_FIXED_SIZE); + int size; + + /* + * Request the shared buffer lookup hashtable. + * + * Since we can't tolerate running out of lookup table entries, we must be + * sure to specify an adequate table size here. The maximum steady-state + * usage is of course NBuffers entries, but BufferAlloc() tries to insert + * a new entry before deleting the old. In principle this could be + * happening in each partition concurrently, so we could need as many as + * NBuffers + NUM_BUFFER_PARTITIONS entries. + */ + size = NBuffers + NUM_BUFFER_PARTITIONS; + + ShmemRequestHash(.name = "Shared Buffer Lookup Table", + .nelems = size, + .ptr = &SharedBufHash, + .hash_info.keysize = sizeof(BufferTag), + .hash_info.entrysize = sizeof(BufferLookupEnt), + .hash_info.num_partitions = NUM_BUFFER_PARTITIONS, + .hash_flags = HASH_ELEM | HASH_BLOBS | HASH_PARTITION | HASH_FIXED_SIZE, + ); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index b7687836188..fdb5bad7910 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -20,6 +20,8 @@ #include "storage/buf_internals.h" #include "storage/bufmgr.h" #include "storage/proc.h" +#include "storage/shmem.h" +#include "storage/subsystems.h" #define INT_ACCESS_ONCE(var) ((int)(*((volatile int *)&(var)))) @@ -56,6 +58,14 @@ typedef struct /* Pointers to shared state */ static BufferStrategyControl *StrategyControl = NULL; +static void StrategyCtlShmemRequest(void *arg); +static void StrategyCtlShmemInit(void *arg); + +const ShmemCallbacks StrategyCtlShmemCallbacks = { + .request_fn = StrategyCtlShmemRequest, + .init_fn = StrategyCtlShmemInit, +}; + /* * Private (non-shared) state for managing a ring of shared buffers to re-use. * This is currently the only kind of BufferAccessStrategy object, but someday @@ -369,80 +379,35 @@ StrategyNotifyBgWriter(int bgwprocno) /* - * StrategyShmemSize - * - * estimate the size of shared memory used by the freelist-related structures. - * - * Note: for somewhat historical reasons, the buffer lookup hashtable size - * is also determined here. + * StrategyCtlShmemRequest -- request shared memory for the buffer + * cache replacement strategy. */ -Size -StrategyShmemSize(void) +static void +StrategyCtlShmemRequest(void *arg) { - Size size = 0; - - /* size of lookup hash table ... see comment in StrategyInitialize */ - size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); - - /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); - - return size; + ShmemRequestStruct(.name = "Buffer Strategy Status", + .size = sizeof(BufferStrategyControl), + .ptr = (void **) &StrategyControl + ); } /* - * StrategyInitialize -- initialize the buffer cache replacement - * strategy. - * - * Assumes: All of the buffers are already built into a linked list. - * Only called by postmaster and only during initialization. + * StrategyCtlShmemInit -- initialize the buffer cache replacement strategy. */ -void -StrategyInitialize(bool init) +static void +StrategyCtlShmemInit(void *arg) { - bool found; + SpinLockInit(&StrategyControl->buffer_strategy_lock); - /* - * Initialize the shared buffer lookup hashtable. - * - * Since we can't tolerate running out of lookup table entries, we must be - * sure to specify an adequate table size here. The maximum steady-state - * usage is of course NBuffers entries, but BufferAlloc() tries to insert - * a new entry before deleting the old. In principle this could be - * happening in each partition concurrently, so we could need as many as - * NBuffers + NUM_BUFFER_PARTITIONS entries. - */ - InitBufTable(NBuffers + NUM_BUFFER_PARTITIONS); - - /* - * Get or create the shared strategy control block - */ - StrategyControl = (BufferStrategyControl *) - ShmemInitStruct("Buffer Strategy Status", - sizeof(BufferStrategyControl), - &found); - - if (!found) - { - /* - * Only done once, usually in postmaster - */ - Assert(init); - - SpinLockInit(&StrategyControl->buffer_strategy_lock); + /* Initialize the clock-sweep pointer */ + pg_atomic_init_u32(&StrategyControl->nextVictimBuffer, 0); - /* Initialize the clock-sweep pointer */ - pg_atomic_init_u32(&StrategyControl->nextVictimBuffer, 0); + /* Clear statistics */ + StrategyControl->completePasses = 0; + pg_atomic_init_u32(&StrategyControl->numBufferAllocs, 0); - /* Clear statistics */ - StrategyControl->completePasses = 0; - pg_atomic_init_u32(&StrategyControl->numBufferAllocs, 0); - - /* No pending notification */ - StrategyControl->bgwprocno = -1; - } - else - Assert(!init); + /* No pending notification */ + StrategyControl->bgwprocno = -1; } diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index a510c928daa..f64c1d59fa3 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -39,7 +39,6 @@ #include "replication/walreceiver.h" #include "replication/walsender.h" #include "storage/aio_subsys.h" -#include "storage/bufmgr.h" #include "storage/dsm.h" #include "storage/ipc.h" #include "storage/pg_shmem.h" @@ -99,7 +98,6 @@ CalculateShmemSize(void) size = add_size(size, ShmemGetRequestedSize()); /* legacy subsystems */ - size = add_size(size, BufferManagerShmemSize()); size = add_size(size, LockManagerShmemSize()); size = add_size(size, XLogPrefetchShmemSize()); size = add_size(size, XLOGShmemSize()); @@ -263,7 +261,6 @@ CreateOrAttachShmemStructs(void) XLOGShmemInit(); XLogPrefetchShmemInit(); XLogRecoveryShmemInit(); - BufferManagerShmemInit(); /* * Set up lock manager diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h index ad1b7b2216a..89615a254a3 100644 --- a/src/include/storage/buf_internals.h +++ b/src/include/storage/buf_internals.h @@ -587,12 +587,7 @@ extern bool StrategyRejectBuffer(BufferAccessStrategy strategy, extern int StrategySyncStart(uint32 *complete_passes, uint32 *num_buf_alloc); extern void StrategyNotifyBgWriter(int bgwprocno); -extern Size StrategyShmemSize(void); -extern void StrategyInitialize(bool init); - /* buf_table.c */ -extern Size BufTableShmemSize(int size); -extern void InitBufTable(int size); extern uint32 BufTableHashCode(BufferTag *tagPtr); extern int BufTableLookup(BufferTag *tagPtr, uint32 hashcode); extern int BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id); diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h index aa61a39d9e6..6837b35fc6d 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -371,10 +371,6 @@ extern void MarkDirtyAllUnpinnedBuffers(int32 *buffers_dirtied, int32 *buffers_already_dirty, int32 *buffers_skipped); -/* in buf_init.c */ -extern void BufferManagerShmemInit(void); -extern Size BufferManagerShmemSize(void); - /* in localbuf.c */ extern void AtProcExit_LocalBuffers(void); diff --git a/src/include/storage/subsystemlist.h b/src/include/storage/subsystemlist.h index b438794d46d..d8e11756a61 100644 --- a/src/include/storage/subsystemlist.h +++ b/src/include/storage/subsystemlist.h @@ -36,6 +36,9 @@ PG_SHMEM_SUBSYSTEM(CLOGShmemCallbacks) PG_SHMEM_SUBSYSTEM(CommitTsShmemCallbacks) PG_SHMEM_SUBSYSTEM(SUBTRANSShmemCallbacks) PG_SHMEM_SUBSYSTEM(MultiXactShmemCallbacks) +PG_SHMEM_SUBSYSTEM(BufferManagerShmemCallbacks) +PG_SHMEM_SUBSYSTEM(StrategyCtlShmemCallbacks) +PG_SHMEM_SUBSYSTEM(BufTableShmemCallbacks) /* predicate lock manager */ PG_SHMEM_SUBSYSTEM(PredicateLockShmemCallbacks) -- 2.34.1