Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 15 additions & 34 deletions src/backend/port/sysv_shmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -910,14 +889,12 @@ CreateAnonymousSegment(int segment_id, MemoryMappingSizes *mapping)
* we go with a simple solution.
*/
void
PrepareHugePages()
PrepareHugePages(MemoryMappingSizes *mapping_sizes)
{
void *ptr = MAP_FAILED;
MemoryMappingSizes mapping_sizes[NUM_MEMORY_MAPPINGS];
Size total_size = 0;
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)
Expand All @@ -927,8 +904,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);
Expand Down Expand Up @@ -964,6 +940,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);
}
}

/*
Expand Down Expand Up @@ -1009,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));
Expand All @@ -1029,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);
Expand All @@ -1046,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);

Expand Down
98 changes: 48 additions & 50 deletions src/backend/storage/buffer/buf_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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
Expand Down
14 changes: 4 additions & 10 deletions src/backend/storage/buffer/buf_resize.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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.
*/
Expand Down
11 changes: 7 additions & 4 deletions src/backend/storage/buffer/bufmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
24 changes: 18 additions & 6 deletions src/backend/storage/ipc/ipci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
Loading