From f7fbe490b03eef984d454f204e28e86a7d982a74 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 20 Mar 2025 14:21:59 -0400 Subject: [PATCH] MT#55283 request aligned addresses from mmap Or rather, request double the amount, then use the contained aligned block. Change-Id: Iaf1da4b3df243a1d4391fc2ff46eba1fec3d738c --- daemon/kernel.c | 33 +++++++++++++++++++++++++++++---- lib/bufferpool.h | 1 + 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/daemon/kernel.c b/daemon/kernel.c index fdc834981..112bbb400 100644 --- a/daemon/kernel.c +++ b/daemon/kernel.c @@ -58,12 +58,37 @@ static bool kernel_delete_table(unsigned int id) { } static void *kernel_alloc(void) { - void *b = mmap(NULL, BUFFERPOOL_SHARD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, kernel.fd, 0); - assert(b != NULL && b != MAP_FAILED); - return b; + // Since we can't really request memory at a specific location that we know + // will be correctly aligned, request twice as much, which we know must be + // enough to contain at least one correctly aligned block. This may seem like + // a waste, but the extra pages won't ever be used, and so usually won't even + // be mapped. + void *b = mmap(NULL, BUFFERPOOL_SHARD_SIZE * 2, PROT_READ | PROT_WRITE, MAP_SHARED, kernel.fd, 0); + + if (b == NULL || b == MAP_FAILED) { + ilog(LOG_CRIT, "Failed to allocate shared kernel memory: %s", strerror(errno)); + abort(); + } + + // find the aligned block + void *aligned = (void *) (((size_t) b + BUFFERPOOL_SHARD_SIZE - 1) & BUFFERPOOL_TOP_MASK); + + // place a pointer to the real beginning of the block just past the end, so we + // know what to free + void **back_ptr = aligned + BUFFERPOOL_SHARD_SIZE; + // make sure there is enough extra space to store our back pointer (there should be, unless + // our page size is really tiny) + assert((void *) back_ptr + sizeof(void *) < b + BUFFERPOOL_SHARD_SIZE * 2); + + *back_ptr = b; + + return aligned; } static void kernel_free(void *p) { - munmap(p, BUFFERPOOL_SHARD_SIZE); + // restore saved pointer to read beginning of the block + void **back_ptr = p + BUFFERPOOL_SHARD_SIZE; + p = *back_ptr; + munmap(p, BUFFERPOOL_SHARD_SIZE * 2); } static int kernel_open_table(unsigned int id) { diff --git a/lib/bufferpool.h b/lib/bufferpool.h index 9123a5c4d..4b7251039 100644 --- a/lib/bufferpool.h +++ b/lib/bufferpool.h @@ -10,6 +10,7 @@ #define BUFFERPOOL_OVERHEAD (0) // storage space not available #define BUFFERPOOL_BOTTOM_MASK (BUFFERPOOL_SHARD_SIZE - 1) +#define BUFFERPOOL_TOP_MASK (~BUFFERPOOL_BOTTOM_MASK) struct bufferpool; struct bpool_shard;