Messages in this thread Patch in this message | | | Date | Fri, 23 Jun 2023 10:35:00 -0700 | From | Boqun Feng <> | Subject | Re: [PATCH] rust: alloc: Add realloc and alloc_zeroed to the GlobalAlloc impl |
| |
On Thu, Jun 22, 2023 at 09:24:40PM +0200, Björn Roy Baron via B4 Relay wrote: > From: Björn Roy Baron <bjorn3_gh@protonmail.com> > > While there are default impls for these methods, using the respective C > api's is faster. Currently neither the existing nor these new > GlobalAlloc method implementations are actually called. Instead the > __rust_* function defined below the GlobalAlloc impl are used. With > rustc 1.71 these functions will be gone and all allocation calls will go > through the GlobalAlloc implementation. > > Link: https://github.com/Rust-for-Linux/linux/issues/68
Nice! Although I think we need to do the simialr size adjustment as:
https://lore.kernel.org/rust-for-linux/20230613164258.3831917-1-boqun.feng@gmail.com/
so I applied your patch onto my patch and came up with the following:
--------------------------------->8 diff --git a/rust/kernel/allocator.rs b/rust/kernel/allocator.rs index ce7a06bf7589..af723c2924dc 100644 --- a/rust/kernel/allocator.rs +++ b/rust/kernel/allocator.rs @@ -9,8 +9,17 @@ struct KernelAllocator; -unsafe impl GlobalAlloc for KernelAllocator { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { +impl KernelAllocator { + /// # Safety + /// + /// * `ptr` can be either null or a pointer which has been allocated by this allocator. + /// * `layout` must have a non-zero size. + unsafe fn krealloc_with_flags( + &self, + ptr: *mut u8, + layout: Layout, + flags: bindings::gfp_t, + ) -> *mut u8 { // Customized layouts from `Layout::from_size_align()` can have size < align, so pads first. let layout = layout.pad_to_align(); @@ -26,9 +35,22 @@ unsafe fn alloc(&self, layout: Layout) -> *mut u8 { size = size.next_power_of_two(); } - // `krealloc()` is used instead of `kmalloc()` because the latter is - // an inline function and cannot be bound to as a result. - unsafe { bindings::krealloc(ptr::null(), size, bindings::GFP_KERNEL) as *mut u8 } + // SAFETY: + // + // * `ptr` is either null or a pointer returned from a previous k{re}alloc() by the function + // safety requirement. + // + // * `size` is greater than 0 since it's either a `layout.size()` (which cannot be zero + // according to the function safety requirement) or a result from `next_power_of_two()`. + unsafe { bindings::krealloc(ptr as *const core::ffi::c_void, size, flags) as *mut u8 } + } +} + +unsafe impl GlobalAlloc for KernelAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + // SAFETY: `ptr::null_mut()` is null and `layout` has a non-zero size by the function safety + // requirement. + unsafe { self.krealloc_with_flags(ptr::null_mut(), layout, bindings::GFP_KERNEL) } } unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { @@ -37,23 +59,30 @@ unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { } } - unsafe fn realloc(&self, ptr: *mut u8, _layout: Layout, new_size: usize) -> *mut u8 { - unsafe { - bindings::krealloc( - ptr as *const core::ffi::c_void, - new_size, - bindings::GFP_KERNEL, - ) as *mut u8 - } + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + // SAFETY: + // * `new_size` when rounded up to the nearest multiple of `layout.align()`, will not + // overflow `isize` by the function safety requirement. + // * `layout.align()` is a proper alignment (i.e. not zero and must be a power of two). + let layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; + + // SAFETY: + // * `ptr` is either null or a pointer allocated by this allocator by function safety + // requirement. + // * the size of `layout` is not zero because `new_size` is not zero by function safety + // requirement. + unsafe { self.krealloc_with_flags(ptr, layout, bindings::GFP_KERNEL) } } unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + // SAFETY: `ptr::null_mut()` is null and `layout` has a non-zero size by the function safety + // requirement. unsafe { - bindings::krealloc( - core::ptr::null(), - layout.size(), + self.krealloc_with_flags( + ptr::null_mut(), + layout, bindings::GFP_KERNEL | bindings::__GFP_ZERO, - ) as *mut u8 + ) } } }
Regards, Boqun
> Signed-off-by: Björn Roy Baron <bjorn3_gh@protonmail.com> > --- > rust/kernel/allocator.rs | 20 ++++++++++++++++++++ > 1 file changed, 20 insertions(+) > > diff --git a/rust/kernel/allocator.rs b/rust/kernel/allocator.rs > index 397a3dd57a9b..e0a27b1326b5 100644 > --- a/rust/kernel/allocator.rs > +++ b/rust/kernel/allocator.rs > @@ -21,6 +21,26 @@ unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { > bindings::kfree(ptr as *const core::ffi::c_void); > } > } > + > + unsafe fn realloc(&self, ptr: *mut u8, _layout: Layout, new_size: usize) -> *mut u8 { > + unsafe { > + bindings::krealloc( > + ptr as *const core::ffi::c_void, > + new_size, > + bindings::GFP_KERNEL, > + ) as *mut u8 > + } > + } > + > + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { > + unsafe { > + bindings::krealloc( > + core::ptr::null(), > + layout.size(), > + bindings::GFP_KERNEL | bindings::__GFP_ZERO, > + ) as *mut u8 > + } > + } > } > > #[global_allocator] > > --- > base-commit: d2e3115d717197cb2bc020dd1f06b06538474ac3 > change-id: 20230622-global_alloc_methods-abf5b5e38dba > > Best regards, > -- > Björn Roy Baron <bjorn3_gh@protonmail.com> >
| |