From 1ef36366ca19e12615b19bdc993c25f3987f21e1 Mon Sep 17 00:00:00 2001 From: Minshen Cai Date: Mon, 2 Mar 2026 13:50:57 +0000 Subject: [PATCH 1/2] Release the mapped memory at the end of PrepareHugePages() --- src/backend/port/sysv_shmem.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c index a2a7dad7d8a4c..267df8db6b4b1 100644 --- a/src/backend/port/sysv_shmem.c +++ b/src/backend/port/sysv_shmem.c @@ -913,6 +913,7 @@ void PrepareHugePages() { void *ptr = MAP_FAILED; + Size total_size = 0; MemoryMappingSizes mapping_sizes[NUM_MEMORY_MAPPINGS]; int mmap_flags = (MAP_SHARED | MAP_HASSEMAPHORE); @@ -927,8 +928,7 @@ PrepareHugePages() #else if (huge_pages == HUGE_PAGES_ON || huge_pages == HUGE_PAGES_TRY) { - Size hugepagesize, - total_size = 0; + Size hugepagesize; int huge_mmap_flags; GetHugePageSize(&hugepagesize, &huge_mmap_flags, NULL); @@ -964,6 +964,13 @@ PrepareHugePages() SetConfigOption("huge_pages_status", (ptr == MAP_FAILED) ? "off" : "on", PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT); huge_pages_on = ptr != MAP_FAILED; + + /* Release the mapped memory if huge pages are in use */ + if (ptr != MAP_FAILED) + { + if (munmap(ptr, total_size) < 0) + elog(LOG, "munmap(%p, %zu) failed: %m", ptr, total_size); + } } /* From 2e1dcd09e6561b1fc88f1d0603d2be97ed72350d Mon Sep 17 00:00:00 2001 From: Minshen Cai Date: Wed, 11 Mar 2026 12:25:35 +0000 Subject: [PATCH 2/2] Optimize the Shared Buffers Resizing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Key changes: - Refactor ShmemResizeStructInSegment() to verify internally: Instead of returning the shared memory location pointer for the caller to verify, the function now validates pointer consistency internally via a new helper VerifyAfterShmemUpdateInSegment(), which fatals on mismatch. - Align buffer block pointer before verification in ShmemResizeStructInSegment(): When the target segment is BUFFERS_SHMEM_SEGMENT, align the stored shared memory location pointer to PG_IO_ALIGN_SIZE (via TYPEALIGN) before passing it to the verification helper, matching the alignment applied during initial allocation. - Unify round_off_mapping_sizes() and round_off_mapping_sizes_for_hugepages() into a single round_off_mapping_sizes(): The merged function takes a pagesize parameter (rounds up both shmem_req_size and shmem_reserved to multiples of pagesize, no-op when pagesize is 0). After this change, round_off_mapping_sizes() is only invoked by BufferManagerShmemSize() (for non-main segments) and CalculateShmemSize() (for the main segment). - Refine BufferManagerShmemSize(): Introduce a padsize (header + spinlock aligned to PG_IO_ALIGN_SIZE) as the base offset for each segment's size calculation. For every segment except MAIN_SHMEM_SEGMENT, compute both shmem_req_size and shmem_reserved, then round off to both BLCKSZ and huge page size via round_off_mapping_sizes(). After this change, BufferManagerShmemSize() is only called from CalculateShmemSize() — the previous direct call in pg_resize_shared_buffers() is replaced with a CalculateShmemSize() call. - Refine CalculateShmemSize(): Round off MAIN_SHMEM_SEGMENT sizes to both BLCKSZ and huge page size via round_off_mapping_sizes(). - Parameterize PrepareHugePages(): Remove its internal CalculateShmemSize() call and local mapping_sizes array. The caller now passes pre-computed sizes. - Extract a new method UpdateShmemGUCs(Size size_b): It updates all internal configurations related with Shared Memory. This allows pg_resize_shared_buffers() to call it after a live shared memory resize. - Downgrade ftruncate failure in AnonymousShmemResize(): Change from ereport(ERROR) to elog(WARNING) + return false, making the failure non-fatal so the caller can handle it gracefully. --- src/backend/port/sysv_shmem.c | 38 ++-------- src/backend/storage/buffer/buf_init.c | 98 ++++++++++++------------- src/backend/storage/buffer/buf_resize.c | 14 +--- src/backend/storage/buffer/bufmgr.c | 11 ++- src/backend/storage/ipc/ipci.c | 24 ++++-- src/backend/storage/ipc/shmem.c | 51 ++++++++----- src/include/storage/ipc.h | 1 + src/include/storage/pg_shmem.h | 18 ++++- src/include/storage/shmem.h | 6 +- 9 files changed, 132 insertions(+), 129 deletions(-) diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c index 267df8db6b4b1..f34156b84ca0b 100644 --- a/src/backend/port/sysv_shmem.c +++ b/src/backend/port/sysv_shmem.c @@ -748,25 +748,6 @@ shmem_fallocate(int fd, const char *mapping_name, Size size, int elevel) #endif } -/* - * Round up the required amount of memory and the amount of required reserved - * address space to the nearest huge page size. - */ -static inline void -round_off_mapping_sizes_for_hugepages(MemoryMappingSizes *mapping, int hugepagesize) -{ - if (hugepagesize == 0) - return; - - if (mapping->shmem_req_size % hugepagesize != 0) - mapping->shmem_req_size = add_size(mapping->shmem_req_size, - hugepagesize - (mapping->shmem_req_size % hugepagesize)); - - if (mapping->shmem_reserved % hugepagesize != 0) - mapping->shmem_reserved = add_size(mapping->shmem_reserved, - hugepagesize - (mapping->shmem_reserved % hugepagesize)); -} - /* * Creates an anonymous mmap()ed shared memory segment. * @@ -803,9 +784,7 @@ CreateAnonymousSegment(int segment_id, MemoryMappingSizes *mapping) /* Make sure nothing is messed up */ Assert(huge_pages == HUGE_PAGES_ON || huge_pages == HUGE_PAGES_TRY); - /* Round up the request size to a suitable large value */ GetHugePageSize(&hugepagesize, &huge_mmap_flags, &huge_memfd_flags); - round_off_mapping_sizes_for_hugepages(mapping, hugepagesize); /* Verify that the new size is withing the reserved boundaries */ Assert(mapping->shmem_reserved >= mapping->shmem_req_size); @@ -910,15 +889,12 @@ CreateAnonymousSegment(int segment_id, MemoryMappingSizes *mapping) * we go with a simple solution. */ void -PrepareHugePages() +PrepareHugePages(MemoryMappingSizes *mapping_sizes) { void *ptr = MAP_FAILED; Size total_size = 0; - MemoryMappingSizes mapping_sizes[NUM_MEMORY_MAPPINGS]; int mmap_flags = (MAP_SHARED | MAP_HASSEMAPHORE); - CalculateShmemSize(mapping_sizes); - /* Complain if hugepages demanded but we can't possibly support them */ #if !defined(MAP_HUGETLB) if (huge_pages == HUGE_PAGES_ON) @@ -1016,7 +992,6 @@ AnonymousShmemDetach(int status, Datum arg) static bool AnonymousShmemResize(int segment_id, MemoryMappingSizes *mapping, bool expanding) { - Size hugepagesize; AnonShmemSegment *anonseg = &AnonShmemSegs[segment_id]; Assert(!pg_atomic_unlocked_test_flag(&ShmemCtrl->resize_in_progress)); @@ -1036,8 +1011,6 @@ AnonymousShmemResize(int segment_id, MemoryMappingSizes *mapping, bool expanding if (huge_pages_on) { Assert(huge_pages == HUGE_PAGES_ON || huge_pages == HUGE_PAGES_TRY); - GetHugePageSize(&hugepagesize, NULL, NULL); - round_off_mapping_sizes_for_hugepages(mapping, hugepagesize); } #endif Assert(anonseg->addr); @@ -1053,10 +1026,11 @@ AnonymousShmemResize(int segment_id, MemoryMappingSizes *mapping, bool expanding * more memory on supported platforms if required. */ if (ftruncate(anonseg->fd, mapping->shmem_req_size) == -1) - ereport(ERROR, - (errcode(ERRCODE_SYSTEM_ERROR), - errmsg("could not truncate anonymous file segment for \"%s\": %m", - MappingName(segment_id)))); + { + elog(WARNING, "segment[%s]: could not resize anonymous file to size %zu: %m", + MappingName(segment_id), mapping->shmem_req_size); + return false; + } if (expanding) shmem_fallocate(anonseg->fd, MappingName(segment_id), mapping->shmem_req_size, ERROR); diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index a11717b6709b9..575e12b7b32e4 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -176,41 +176,60 @@ Size BufferManagerShmemSize(MemoryMappingSizes *mapping_sizes) { size_t size; + Size hugepagesize = 0; + size_t padsize = 0; + + padsize = add_size(sizeof(PGShmemHeader), sizeof(slock_t)); + padsize = TYPEALIGN(PG_IO_ALIGN_SIZE, padsize); /* size of buffer descriptors, plus alignment padding */ - size = add_size(0, mul_size(NBuffersPending, sizeof(BufferDescPadded))); - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_size(padsize, mul_size(NBuffersPending, sizeof(BufferDescPadded))); mapping_sizes[BUFFER_DESCRIPTORS_SHMEM_SEGMENT].shmem_req_size = size; - size = add_size(0, mul_size(MaxNBuffers, sizeof(BufferDescPadded))); - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_size(padsize, mul_size(MaxNBuffers, sizeof(BufferDescPadded))); mapping_sizes[BUFFER_DESCRIPTORS_SHMEM_SEGMENT].shmem_reserved = size; /* size of data pages, plus alignment padding */ - size = add_size(0, PG_IO_ALIGN_SIZE); - size = add_size(size, mul_size(NBuffersPending, BLCKSZ)); + size = add_size(padsize, mul_size(NBuffersPending, BLCKSZ)); + size = add_size(size, PG_IO_ALIGN_SIZE); mapping_sizes[BUFFERS_SHMEM_SEGMENT].shmem_req_size = size; - size = add_size(0, PG_IO_ALIGN_SIZE); - size = add_size(size, mul_size(MaxNBuffers, BLCKSZ)); + size = add_size(padsize, mul_size(MaxNBuffers, BLCKSZ)); + size = add_size(size, PG_IO_ALIGN_SIZE); mapping_sizes[BUFFERS_SHMEM_SEGMENT].shmem_reserved = size; /* size of I/O condition variables, plus alignment padding */ - size = add_size(0, mul_size(NBuffersPending, - sizeof(ConditionVariableMinimallyPadded))); - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_size(padsize, mul_size(NBuffersPending, + sizeof(ConditionVariableMinimallyPadded))); mapping_sizes[BUFFER_IOCV_SHMEM_SEGMENT].shmem_req_size = size; - size = add_size(0, mul_size(MaxNBuffers, - sizeof(ConditionVariableMinimallyPadded))); - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_size(padsize, mul_size(MaxNBuffers, + sizeof(ConditionVariableMinimallyPadded))); mapping_sizes[BUFFER_IOCV_SHMEM_SEGMENT].shmem_reserved = size; /* size of checkpoint sort array in bufmgr.c */ - mapping_sizes[CHECKPOINT_BUFFERS_SHMEM_SEGMENT].shmem_req_size = mul_size(NBuffersPending, sizeof(CkptSortItem)); - mapping_sizes[CHECKPOINT_BUFFERS_SHMEM_SEGMENT].shmem_reserved = mul_size(MaxNBuffers, sizeof(CkptSortItem)); + mapping_sizes[CHECKPOINT_BUFFERS_SHMEM_SEGMENT].shmem_req_size = add_size(padsize, mul_size(NBuffersPending, sizeof(CkptSortItem))); + mapping_sizes[CHECKPOINT_BUFFERS_SHMEM_SEGMENT].shmem_reserved = add_size(padsize, mul_size(MaxNBuffers, sizeof(CkptSortItem))); + + if (huge_pages == HUGE_PAGES_ON || huge_pages == HUGE_PAGES_TRY) + { + GetHugePageSize(&hugepagesize, NULL, NULL); + } + + for (int segment = 0; segment < NUM_MEMORY_MAPPINGS; segment++) + { + MemoryMappingSizes *mapping; + + // We don't calculate main segment size here. + if (segment == MAIN_SHMEM_SEGMENT) + continue; + + mapping = &mapping_sizes[segment]; + round_off_mapping_sizes(mapping, BLCKSZ); + round_off_mapping_sizes(mapping, hugepagesize); + } /* Allocations in the main memory segment, at the end. */ /* size of stuff controlled by freelist.c */ - size = add_size(0, StrategyShmemSize()); + size = add_size(padsize, StrategyShmemSize()); return size; } @@ -229,40 +248,19 @@ BufferManagerShmemResize(int currentNBuffers, int targetNBuffers) { bool found; int i; - void *tmpPtr; - - tmpPtr = (BufferDescPadded *) - ShmemResizeStructInSegment("Buffer Descriptors", - targetNBuffers * sizeof(BufferDescPadded), - &found, BUFFER_DESCRIPTORS_SHMEM_SEGMENT); - if (BufferDescriptors != tmpPtr || !found) - elog(FATAL, "resizing buffer descriptors failed: expected pointer %p, got %p, found=%d", - BufferDescriptors, tmpPtr, found); - - tmpPtr = (ConditionVariableMinimallyPadded *) - ShmemResizeStructInSegment("Buffer IO Condition Variables", - targetNBuffers * sizeof(ConditionVariableMinimallyPadded), - &found, BUFFER_IOCV_SHMEM_SEGMENT); - if (BufferIOCVArray != tmpPtr || !found) - elog(FATAL, "resizing buffer IO condition variables failed: expected pointer %p, got %p, found=%d", - BufferIOCVArray, tmpPtr, found); - tmpPtr = (CkptSortItem *) - ShmemResizeStructInSegment("Checkpoint BufferIds", - targetNBuffers * sizeof(CkptSortItem), &found, - CHECKPOINT_BUFFERS_SHMEM_SEGMENT); - if (CkptBufferIds != tmpPtr || !found) - elog(FATAL, "resizing checkpoint buffer IDs failed: expected pointer %p, got %p, found=%d", - CkptBufferIds, tmpPtr, found); - - tmpPtr = (char *) - TYPEALIGN(PG_IO_ALIGN_SIZE, - ShmemResizeStructInSegment("Buffer Blocks", - targetNBuffers * (Size) BLCKSZ + PG_IO_ALIGN_SIZE, - &found, BUFFERS_SHMEM_SEGMENT)); - if (BufferBlocks != tmpPtr || !found) - elog(FATAL, "resizing buffer blocks failed: expected pointer %p, got %p, found=%d", - BufferBlocks, tmpPtr, found); + ShmemResizeStructInSegment("Buffer Descriptors", + targetNBuffers * sizeof(BufferDescPadded), + &found, BUFFER_DESCRIPTORS_SHMEM_SEGMENT, BufferDescriptors); + ShmemResizeStructInSegment("Buffer IO Condition Variables", + targetNBuffers * sizeof(ConditionVariableMinimallyPadded), + &found, BUFFER_IOCV_SHMEM_SEGMENT, BufferIOCVArray); + ShmemResizeStructInSegment("Checkpoint BufferIds", + targetNBuffers * sizeof(CkptSortItem), &found, + CHECKPOINT_BUFFERS_SHMEM_SEGMENT, CkptBufferIds); + ShmemResizeStructInSegment("Buffer Blocks", + targetNBuffers * (Size) BLCKSZ + PG_IO_ALIGN_SIZE, + &found, BUFFERS_SHMEM_SEGMENT, BufferBlocks); /* * Initialize the headers for new buffers. If we are shrinking the diff --git a/src/backend/storage/buffer/buf_resize.c b/src/backend/storage/buffer/buf_resize.c index 836811356725b..7f1f9eebff0b5 100644 --- a/src/backend/storage/buffer/buf_resize.c +++ b/src/backend/storage/buffer/buf_resize.c @@ -167,6 +167,7 @@ pg_resize_shared_buffers(PG_FUNCTION_ARGS) bool result = true; int currentNBuffers = pg_atomic_read_u32(&ShmemCtrl->currentNBuffers); int targetNBuffers = NBuffersPending; + Size size_b; MemoryMappingSizes mapping_sizes[NUM_MEMORY_MAPPINGS]; if (currentNBuffers == targetNBuffers) @@ -186,16 +187,7 @@ pg_resize_shared_buffers(PG_FUNCTION_ARGS) * leading to wrong memory size estimates. Find a way to pass * targetNBuffers value to BufferManagerShmemSize(). */ - BufferManagerShmemSize(mapping_sizes); - /* Round it off to a multiple of a typical page size */ - for (int i = 0; i < NUM_MEMORY_MAPPINGS; i++) - { - /* Structures in main memory segment are never resized. */ - if (i == MAIN_SHMEM_SEGMENT) - continue; - - round_off_mapping_sizes(&mapping_sizes[i]); - } + size_b = CalculateShmemSize(mapping_sizes); /* * TODO: What if the NBuffersPending value seen here is not the desired @@ -282,6 +274,8 @@ pg_resize_shared_buffers(PG_FUNCTION_ARGS) SharedBufferResizeBarrier(PROCSIGNAL_BARRIER_SHBUF_EXPAND, CppAsString(PROCSIGNAL_BARRIER_SHBUF_EXPAND)); } + UpdateShmemGUCs(size_b); + /* * Reset buffer resize control area. */ diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index d39e65ef811d0..94161cf2623fa 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -8626,12 +8626,15 @@ EvictExtraBuffers(int targetNBuffers, int currentNBuffers) continue; /* - * XXX: Looks like CurrentResourceOwner can be NULL here, find another - * one in that case? + * Ensure we have a valid resource owner. If CurrentResourceOwner is + * NULL, we cannot proceed with pinning. */ - if (CurrentResourceOwner) - ResourceOwnerEnlarge(CurrentResourceOwner); + if (CurrentResourceOwner == NULL) + { + elog(ERROR, "CurrentResourceOwner is NULL, cannot evict buffers"); + } + ResourceOwnerEnlarge(CurrentResourceOwner); ReservePrivateRefCountEntry(); LockBufHdr(desc); diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index 1e92b0bcc5e9c..a3fb6e6e62d57 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -173,12 +173,18 @@ CalculateShmemSize(MemoryMappingSizes *mapping_sizes) */ mapping_sizes[MAIN_SHMEM_SEGMENT].shmem_req_size = size; mapping_sizes[MAIN_SHMEM_SEGMENT].shmem_reserved = size; + round_off_mapping_sizes(&mapping_sizes[MAIN_SHMEM_SEGMENT], BLCKSZ); + if (huge_pages == HUGE_PAGES_ON || huge_pages == HUGE_PAGES_TRY) + { + Size hugepagesize = 0; + GetHugePageSize(&hugepagesize, NULL, NULL); + round_off_mapping_sizes(&mapping_sizes[MAIN_SHMEM_SEGMENT], hugepagesize); + } size = 0; /* might as well round it off to a multiple of a typical page size */ for (int segment = 0; segment < NUM_MEMORY_MAPPINGS; segment++) { - round_off_mapping_sizes(&mapping_sizes[segment]); /* Compute the total size of all segments */ size = size + mapping_sizes[segment].shmem_req_size; } @@ -234,7 +240,7 @@ CreateSharedMemoryAndSemaphores(void) CalculateShmemSize(mapping_sizes); /* Decide if we use huge pages or regular size pages */ - PrepareHugePages(); + PrepareHugePages(mapping_sizes); /* * Make sure that huge pages are never reported as "unknown" while the @@ -404,17 +410,23 @@ CreateOrAttachShmemStructs(void) void InitializeShmemGUCs(void) { - char buf[64]; Size size_b; - Size size_mb; - Size hp_size; MemoryMappingSizes mapping_sizes[NUM_MEMORY_MAPPINGS]; - /* * Calculate the shared memory size and round up to the nearest megabyte. */ size_b = CalculateShmemSize(mapping_sizes); + UpdateShmemGUCs(size_b); +} + + +void +UpdateShmemGUCs(Size size_b) +{ + char buf[64]; + Size size_mb; + Size hp_size; size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024); sprintf(buf, "%zu", size_mb); SetConfigOption("shared_memory_size", buf, diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index 5a8ea67b3114f..8e284d42f0ea0 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -96,6 +96,8 @@ #include "utils/injection_point.h" #include "utils/wait_event.h" +static void VerifyAfterShmemUpdateInSegment(const char *name, const void * originalPtr, void * targetPtr); + /* Structure managing one shared memory segment. */ typedef struct ShmemSegment { @@ -550,6 +552,7 @@ ShmemInitStructInSegment(const char *name, Size size, bool *foundPtr, int segmen /* * Structure is in the shmem index so someone else has allocated it * already. The size better be the same as the size we are trying to + * initialize to, or there is a name conflict (or worse). */ if (result->size != size) { @@ -594,18 +597,25 @@ ShmemInitStructInSegment(const char *name, Size size, bool *foundPtr, int segmen return structPtr; } +void +VerifyAfterShmemUpdateInSegment(const char *name, const void *originalPtr, + void *targetPtr) +{ + if (originalPtr != targetPtr) + elog(FATAL, "validating %s failed: expected pointer %p, got %p", + name, originalPtr, targetPtr); +} + /* * ShmemResizeStructInSegment -- Resize the given structure in shared memory. * * This function resizes an existing shared memory structure while preserving * the existing memory location. * - * Returns: pointer to the existing structure location, if the resize is - * successful, otherwise NULL. */ -void * +void ShmemResizeStructInSegment(const char *name, Size size, bool *foundPtr, - int segment_id) + int segment_id, const void *originalPtr) { ShmemIndexEnt *result; void *structPtr; @@ -619,6 +629,7 @@ ShmemResizeStructInSegment(const char *name, Size size, bool *foundPtr, * resizable */ Assert(ShmemIndex); Assert(size > 0); + Assert(originalPtr != NULL); segment = &Segments[segment_id]; shmhdr = segment->ShmemSegHdr; Assert(shmhdr != NULL); @@ -634,6 +645,11 @@ ShmemResizeStructInSegment(const char *name, Size size, bool *foundPtr, /* Save the existing structure pointer to be returned. */ structPtr = result->location; + if (segment_id == BUFFERS_SHMEM_SEGMENT) + { + /* For buffer blocks, its pointer aligns buffer pool on IO page size boundary */ + structPtr = (char *) TYPEALIGN(PG_IO_ALIGN_SIZE, structPtr); + } /* Cachealign new size */ allocated_size = CACHELINEALIGN(size); @@ -641,9 +657,11 @@ ShmemResizeStructInSegment(const char *name, Size size, bool *foundPtr, if (allocated_size == result->allocated_size) { result->size = size; + /* No need to resize if the existing allocated size is sufficient */ LWLockRelease(ShmemIndexLock); - return structPtr; + VerifyAfterShmemUpdateInSegment(name, originalPtr, structPtr); + return; } SpinLockAcquire(segment->ShmemLock); @@ -654,17 +672,12 @@ ShmemResizeStructInSegment(const char *name, Size size, bool *foundPtr, * same as the start of free memory in that segment. */ Assert((char *) segment->ShmemBase + shmhdr->freeoffset == (char *) result->location + result->allocated_size); - newFree = shmhdr->freeoffset + (allocated_size - result->allocated_size); - if (newFree > shmhdr->totalsize) - { - structPtr = NULL; - } - else - { - shmhdr->freeoffset = newFree; - result->size = size; - result->allocated_size = allocated_size; - } + newFree = shmhdr->freeoffset + allocated_size - result->allocated_size; + + Assert(newFree <= shmhdr->totalsize); + shmhdr->freeoffset = newFree; + result->size = size; + result->allocated_size = allocated_size; /* * End of the structure should still be same as the start of free memory @@ -677,12 +690,10 @@ ShmemResizeStructInSegment(const char *name, Size size, bool *foundPtr, /* note this assert is okay with structPtr == NULL */ Assert(structPtr == (void *) CACHELINEALIGN(structPtr)); - - return structPtr; + VerifyAfterShmemUpdateInSegment(name, originalPtr, structPtr); + return; } - - /* * Add two Size values, checking for overflow */ diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h index 23003412c9a31..d6c8a80af4121 100644 --- a/src/include/storage/ipc.h +++ b/src/include/storage/ipc.h @@ -86,5 +86,6 @@ extern void CreateSharedMemoryAndSemaphores(void); extern void AttachSharedMemoryStructs(void); #endif extern void InitializeShmemGUCs(void); +extern void UpdateShmemGUCs(Size size_b); #endif /* IPC_H */ diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h index ac679259787e0..4ca0dc8f83085 100644 --- a/src/include/storage/pg_shmem.h +++ b/src/include/storage/pg_shmem.h @@ -187,10 +187,20 @@ extern void PGSharedMemoryNoReAttach(void); * round off mapping size to a multiple of a typical page size. */ static inline void -round_off_mapping_sizes(MemoryMappingSizes *mapping_sizes) +round_off_mapping_sizes(MemoryMappingSizes *mapping_sizes, int pagesize) { - mapping_sizes->shmem_req_size = add_size(mapping_sizes->shmem_req_size, 8192 - (mapping_sizes->shmem_req_size % 8192)); - mapping_sizes->shmem_reserved = add_size(mapping_sizes->shmem_reserved, 8192 - (mapping_sizes->shmem_reserved % 8192)); + if (pagesize == 0) + return; + + if (mapping_sizes->shmem_req_size % pagesize != 0) + mapping_sizes->shmem_req_size = add_size(mapping_sizes->shmem_req_size, + pagesize - (mapping_sizes->shmem_req_size % pagesize)); + + if (mapping_sizes->shmem_reserved % pagesize != 0) + mapping_sizes->shmem_reserved = add_size(mapping_sizes->shmem_reserved, + pagesize - (mapping_sizes->shmem_reserved % pagesize)); + + Assert(mapping_sizes->shmem_reserved >= mapping_sizes->shmem_req_size); } static inline const char * @@ -223,7 +233,7 @@ extern void GetHugePageSize(Size *hugepagesize, int *mmap_flags, int *memfd_flags); extern bool PGSharedMemoryResize(int segment_id, MemoryMappingSizes *mapping_sizes); -extern void PrepareHugePages(void); +extern void PrepareHugePages(MemoryMappingSizes *mapping_sizes); extern const char *show_shared_buffers(void); extern bool check_shared_buffers(int *newval, void **extra, GucSource source); extern void ShmemControlInit(void); diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index da55034e5ccfb..c37e9a521a987 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -39,9 +39,9 @@ extern HTAB *ShmemInitHash(const char *name, int64 init_size, int64 max_size, HASHCTL *infoP, int hash_flags); extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern void *ShmemInitStructInSegment(const char *name, Size size, - bool *foundPtr, int segment_id); -extern void *ShmemResizeStructInSegment(const char *name, Size size, - bool *foundPtr, int segment_id); + bool *foundPtr, int segment_id); +extern void ShmemResizeStructInSegment(const char *name, Size size, + bool *foundPtr, int segment_id, const void * originalPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2);