memory: large aligned allocations can return under-aligned pointers
Summary
The Seastar allocator's large aligned allocation path computes the requested alignment in pages, but the lower-level allocator ignores that value. As a result, valid aligned allocation requests whose alignment is larger than the requested size can return a pointer that is only aligned to the allocated buddy span size, not to the requested alignment.
For example, on the default 4 KiB allocator page size, a reactor-thread call like:
void* p = nullptr;
int rc = posix_memalign(&p, 2 << 20, 4096);can succeed with p only 4 KiB-aligned instead of 2 MiB-aligned. That violates the posix_memalign() alignment contract.
Code path
Current origin/master has this flow:
posix_memalign()callsallocate_aligned(align, size).allocate_aligned()routes requests withalign > page_sizethroughallocate_large_aligned(align, size), even whensize <= max_small_allocation.allocate_large_aligned(size_t align, size_t size, ...)computesalign_in_pagesand passes it down.cpu_pages::allocate_large_aligned(unsigned align_pages, unsigned n_pages, ...)ignoresalign_pagesand delegates directly toallocate_large_and_trim(n_pages, ...)with the comment// buddy allocation is always aligned.allocate_large_and_trim()selects a suitable buddy span, trims it down to the requestedn_pages, and returnsmem() + span_idx * page_size.
Buddy allocation only guarantees natural alignment to the span size that is actually allocated. If n_pages == 1, the returned pointer is only guaranteed to be one allocator page aligned. It is not guaranteed to satisfy a larger requested alignment such as 512 pages / 2 MiB.
Why this matters
This is reachable through public aligned allocation entry points on reactor threads, including:
posix_memalign()memalign()aligned_alloc()- aligned C++
operator new(size_t, std::align_val_t)
Existing allocator tests cover cases where size >= align up to 64 KiB, but they do not cover the valid case where align > size, such as posix_memalign(&p, 2 MiB, 4 KiB).
Expected behavior
Large aligned allocations should either return a pointer aligned to the requested alignment or fail. For requests where align_pages > n_pages, the allocator likely needs to allocate/search a span large enough to contain an aligned subspan, return the aligned portion, and free the unused prefix/suffix appropriately.
Related: #3467 also touches allocate_large_aligned(), but it is about page-count overflow/truncation. This issue is about the requested alignment being ignored after conversion to pages.
Source: scylladb/seastar