diff options
author | Dave Airlie <airlied@redhat.com> | 2025-08-23 06:45:22 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2025-08-23 06:45:53 +1000 |
commit | f9915c391cf72789ec5b6d5966ba82c2bca5daa7 (patch) | |
tree | 42f9e1d38a2c1c340dd9fcf3207a6f404ae1963a /rust/kernel/alloc/allocator.rs | |
parent | dbb2c3adc4a641d9f136005285bcbba15227249c (diff) | |
parent | 1a2cf179e2973f6801c67397ecc987391b084bcf (diff) |
Merge tag 'drm-misc-fixes-2025-08-21' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes
A bunch of fixes for 6.17:
- analogix_dp: devm_drm_bridge_alloc() error handling fix
- gaudi: Memory deallocation fix
- gpuvm: Documentation warning fix
- hibmc: Various misc fixes
- nouveau: Memory leak fixes, typos
- panic: u64 division handling on 32 bits architecture fix
- rockchip: Kconfig fix, register caching fix
- rust: memory layout and safety fixes
- tests: Endianness fixes
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maxime Ripard <mripard@redhat.com>
Link: https://lore.kernel.org/r/20250821-economic-dandelion-rooster-c57fa9@houat
Diffstat (limited to 'rust/kernel/alloc/allocator.rs')
-rw-r--r-- | rust/kernel/alloc/allocator.rs | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index aa2dfa9dca4c..2692cf90c948 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -43,17 +43,6 @@ pub struct Vmalloc; /// For more details see [self]. pub struct KVmalloc; -/// Returns a proper size to alloc a new object aligned to `new_layout`'s alignment. -fn aligned_size(new_layout: Layout) -> usize { - // Customized layouts from `Layout::from_size_align()` can have size < align, so pad first. - let layout = new_layout.pad_to_align(); - - // Note that `layout.size()` (after padding) is guaranteed to be a multiple of `layout.align()` - // which together with the slab guarantees means the `krealloc` will return a properly aligned - // object (see comments in `kmalloc()` for more information). - layout.size() -} - /// # Invariants /// /// One of the following: `krealloc`, `vrealloc`, `kvrealloc`. @@ -88,7 +77,7 @@ impl ReallocFunc { old_layout: Layout, flags: Flags, ) -> Result<NonNull<[u8]>, AllocError> { - let size = aligned_size(layout); + let size = layout.size(); let ptr = match ptr { Some(ptr) => { if old_layout.size() == 0 { @@ -123,6 +112,17 @@ impl ReallocFunc { } } +impl Kmalloc { + /// Returns a [`Layout`] that makes [`Kmalloc`] fulfill the requested size and alignment of + /// `layout`. + pub fn aligned_layout(layout: Layout) -> Layout { + // Note that `layout.size()` (after padding) is guaranteed to be a multiple of + // `layout.align()` which together with the slab guarantees means that `Kmalloc` will return + // a properly aligned object (see comments in `kmalloc()` for more information). + layout.pad_to_align() + } +} + // SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees that // - memory remains valid until it is explicitly freed, // - passing a pointer to a valid memory allocation is OK, @@ -135,6 +135,8 @@ unsafe impl Allocator for Kmalloc { old_layout: Layout, flags: Flags, ) -> Result<NonNull<[u8]>, AllocError> { + let layout = Kmalloc::aligned_layout(layout); + // SAFETY: `ReallocFunc::call` has the same safety requirements as `Allocator::realloc`. unsafe { ReallocFunc::KREALLOC.call(ptr, layout, old_layout, flags) } } @@ -176,6 +178,10 @@ unsafe impl Allocator for KVmalloc { old_layout: Layout, flags: Flags, ) -> Result<NonNull<[u8]>, AllocError> { + // `KVmalloc` may use the `Kmalloc` backend, hence we have to enforce a `Kmalloc` + // compatible layout. + let layout = Kmalloc::aligned_layout(layout); + // TODO: Support alignments larger than PAGE_SIZE. if layout.align() > bindings::PAGE_SIZE { pr_warn!("KVmalloc does not support alignments larger than PAGE_SIZE yet.\n"); |