Message ID | 20240911225449.152928-18-dakr@kernel.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Generic `Allocator` support for Rust | expand |
On Thu, 12 Sep 2024 00:52:53 +0200 Danilo Krummrich <dakr@kernel.org> wrote: > Now that all existing `Vec` users were moved to the kernel `Vec` type, > remove the `VecExt` extension. > > Reviewed-by: Alice Ryhl <aliceryhl@google.com> > Reviewed-by: Benno Lossin <benno.lossin@proton.me> > Signed-off-by: Danilo Krummrich <dakr@kernel.org> Reviewed-by: Gary Guo <gary@garyguo.net> > --- > rust/kernel/alloc.rs | 1 - > rust/kernel/alloc/vec_ext.rs | 185 ----------------------------------- > rust/kernel/prelude.rs | 5 +- > 3 files changed, 1 insertion(+), 190 deletions(-) > delete mode 100644 rust/kernel/alloc/vec_ext.rs > > diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs > index e8fbae2adadb..aabdf80e4f7b 100644 > --- a/rust/kernel/alloc.rs > +++ b/rust/kernel/alloc.rs > @@ -6,7 +6,6 @@ > pub mod allocator; > pub mod kbox; > pub mod kvec; > -pub mod vec_ext; > > #[cfg(any(test, testlib))] > pub mod allocator_test; > diff --git a/rust/kernel/alloc/vec_ext.rs b/rust/kernel/alloc/vec_ext.rs > deleted file mode 100644 > index 1297a4be32e8..000000000000 > --- a/rust/kernel/alloc/vec_ext.rs > +++ /dev/null > @@ -1,185 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0 > - > -//! Extensions to [`Vec`] for fallible allocations. > - > -use super::{AllocError, Flags}; > -use alloc::vec::Vec; > - > -/// Extensions to [`Vec`]. > -pub trait VecExt<T>: Sized { > - /// Creates a new [`Vec`] instance with at least the given capacity. > - /// > - /// # Examples > - /// > - /// ``` > - /// let v = Vec::<u32>::with_capacity(20, GFP_KERNEL)?; > - /// > - /// assert!(v.capacity() >= 20); > - /// # Ok::<(), Error>(()) > - /// ``` > - fn with_capacity(capacity: usize, flags: Flags) -> Result<Self, AllocError>; > - > - /// Appends an element to the back of the [`Vec`] instance. > - /// > - /// # Examples > - /// > - /// ``` > - /// let mut v = Vec::new(); > - /// v.push(1, GFP_KERNEL)?; > - /// assert_eq!(&v, &[1]); > - /// > - /// v.push(2, GFP_KERNEL)?; > - /// assert_eq!(&v, &[1, 2]); > - /// # Ok::<(), Error>(()) > - /// ``` > - fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError>; > - > - /// Pushes clones of the elements of slice into the [`Vec`] instance. > - /// > - /// # Examples > - /// > - /// ``` > - /// let mut v = Vec::new(); > - /// v.push(1, GFP_KERNEL)?; > - /// > - /// v.extend_from_slice(&[20, 30, 40], GFP_KERNEL)?; > - /// assert_eq!(&v, &[1, 20, 30, 40]); > - /// > - /// v.extend_from_slice(&[50, 60], GFP_KERNEL)?; > - /// assert_eq!(&v, &[1, 20, 30, 40, 50, 60]); > - /// # Ok::<(), Error>(()) > - /// ``` > - fn extend_from_slice(&mut self, other: &[T], flags: Flags) -> Result<(), AllocError> > - where > - T: Clone; > - > - /// Ensures that the capacity exceeds the length by at least `additional` elements. > - /// > - /// # Examples > - /// > - /// ``` > - /// let mut v = Vec::new(); > - /// v.push(1, GFP_KERNEL)?; > - /// > - /// v.reserve(10, GFP_KERNEL)?; > - /// let cap = v.capacity(); > - /// assert!(cap >= 10); > - /// > - /// v.reserve(10, GFP_KERNEL)?; > - /// let new_cap = v.capacity(); > - /// assert_eq!(new_cap, cap); > - /// > - /// # Ok::<(), Error>(()) > - /// ``` > - fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), AllocError>; > -} > - > -impl<T> VecExt<T> for Vec<T> { > - fn with_capacity(capacity: usize, flags: Flags) -> Result<Self, AllocError> { > - let mut v = Vec::new(); > - <Self as VecExt<_>>::reserve(&mut v, capacity, flags)?; > - Ok(v) > - } > - > - fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError> { > - <Self as VecExt<_>>::reserve(self, 1, flags)?; > - let s = self.spare_capacity_mut(); > - s[0].write(v); > - > - // SAFETY: We just initialised the first spare entry, so it is safe to increase the length > - // by 1. We also know that the new length is <= capacity because of the previous call to > - // `reserve` above. > - unsafe { self.set_len(self.len() + 1) }; > - Ok(()) > - } > - > - fn extend_from_slice(&mut self, other: &[T], flags: Flags) -> Result<(), AllocError> > - where > - T: Clone, > - { > - <Self as VecExt<_>>::reserve(self, other.len(), flags)?; > - for (slot, item) in core::iter::zip(self.spare_capacity_mut(), other) { > - slot.write(item.clone()); > - } > - > - // SAFETY: We just initialised the `other.len()` spare entries, so it is safe to increase > - // the length by the same amount. We also know that the new length is <= capacity because > - // of the previous call to `reserve` above. > - unsafe { self.set_len(self.len() + other.len()) }; > - Ok(()) > - } > - > - #[cfg(any(test, testlib))] > - fn reserve(&mut self, additional: usize, _flags: Flags) -> Result<(), AllocError> { > - Vec::reserve(self, additional); > - Ok(()) > - } > - > - #[cfg(not(any(test, testlib)))] > - fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), AllocError> { > - let len = self.len(); > - let cap = self.capacity(); > - > - if cap - len >= additional { > - return Ok(()); > - } > - > - if core::mem::size_of::<T>() == 0 { > - // The capacity is already `usize::MAX` for SZTs, we can't go higher. > - return Err(AllocError); > - } > - > - // We know cap is <= `isize::MAX` because `Layout::array` fails if the resulting byte size > - // is greater than `isize::MAX`. So the multiplication by two won't overflow. > - let new_cap = core::cmp::max(cap * 2, len.checked_add(additional).ok_or(AllocError)?); > - let layout = core::alloc::Layout::array::<T>(new_cap).map_err(|_| AllocError)?; > - > - let (old_ptr, len, cap) = destructure(self); > - > - // We need to make sure that `ptr` is either NULL or comes from a previous call to > - // `krealloc_aligned`. A `Vec<T>`'s `ptr` value is not guaranteed to be NULL and might be > - // dangling after being created with `Vec::new`. Instead, we can rely on `Vec<T>`'s capacity > - // to be zero if no memory has been allocated yet. > - let ptr = if cap == 0 { > - core::ptr::null_mut() > - } else { > - old_ptr > - }; > - > - // SAFETY: `ptr` is valid because it's either NULL or comes from a previous call to > - // `krealloc_aligned`. We also verified that the type is not a ZST. > - let new_ptr = unsafe { super::allocator::krealloc_aligned(ptr.cast(), layout, flags) }; > - if new_ptr.is_null() { > - // SAFETY: We are just rebuilding the existing `Vec` with no changes. > - unsafe { rebuild(self, old_ptr, len, cap) }; > - Err(AllocError) > - } else { > - // SAFETY: `ptr` has been reallocated with the layout for `new_cap` elements. New cap > - // is greater than `cap`, so it continues to be >= `len`. > - unsafe { rebuild(self, new_ptr.cast::<T>(), len, new_cap) }; > - Ok(()) > - } > - } > -} > - > -#[cfg(not(any(test, testlib)))] > -fn destructure<T>(v: &mut Vec<T>) -> (*mut T, usize, usize) { > - let mut tmp = Vec::new(); > - core::mem::swap(&mut tmp, v); > - let mut tmp = core::mem::ManuallyDrop::new(tmp); > - let len = tmp.len(); > - let cap = tmp.capacity(); > - (tmp.as_mut_ptr(), len, cap) > -} > - > -/// Rebuilds a `Vec` from a pointer, length, and capacity. > -/// > -/// # Safety > -/// > -/// The same as [`Vec::from_raw_parts`]. > -#[cfg(not(any(test, testlib)))] > -unsafe fn rebuild<T>(v: &mut Vec<T>, ptr: *mut T, len: usize, cap: usize) { > - // SAFETY: The safety requirements from this function satisfy those of `from_raw_parts`. > - let mut tmp = unsafe { Vec::from_raw_parts(ptr, len, cap) }; > - core::mem::swap(&mut tmp, v); > -} > diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs > index 80223cdaa485..07daccf6ca8e 100644 > --- a/rust/kernel/prelude.rs > +++ b/rust/kernel/prelude.rs > @@ -14,10 +14,7 @@ > #[doc(no_inline)] > pub use core::pin::Pin; > > -pub use crate::alloc::{flags::*, vec_ext::VecExt, Box, KBox, KVBox, KVVec, KVec, VBox, VVec}; > - > -#[doc(no_inline)] > -pub use alloc::vec::Vec; > +pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec}; > > #[doc(no_inline)] > pub use macros::{module, pin_data, pinned_drop, vtable, Zeroable};
diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs index e8fbae2adadb..aabdf80e4f7b 100644 --- a/rust/kernel/alloc.rs +++ b/rust/kernel/alloc.rs @@ -6,7 +6,6 @@ pub mod allocator; pub mod kbox; pub mod kvec; -pub mod vec_ext; #[cfg(any(test, testlib))] pub mod allocator_test; diff --git a/rust/kernel/alloc/vec_ext.rs b/rust/kernel/alloc/vec_ext.rs deleted file mode 100644 index 1297a4be32e8..000000000000 --- a/rust/kernel/alloc/vec_ext.rs +++ /dev/null @@ -1,185 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -//! Extensions to [`Vec`] for fallible allocations. - -use super::{AllocError, Flags}; -use alloc::vec::Vec; - -/// Extensions to [`Vec`]. -pub trait VecExt<T>: Sized { - /// Creates a new [`Vec`] instance with at least the given capacity. - /// - /// # Examples - /// - /// ``` - /// let v = Vec::<u32>::with_capacity(20, GFP_KERNEL)?; - /// - /// assert!(v.capacity() >= 20); - /// # Ok::<(), Error>(()) - /// ``` - fn with_capacity(capacity: usize, flags: Flags) -> Result<Self, AllocError>; - - /// Appends an element to the back of the [`Vec`] instance. - /// - /// # Examples - /// - /// ``` - /// let mut v = Vec::new(); - /// v.push(1, GFP_KERNEL)?; - /// assert_eq!(&v, &[1]); - /// - /// v.push(2, GFP_KERNEL)?; - /// assert_eq!(&v, &[1, 2]); - /// # Ok::<(), Error>(()) - /// ``` - fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError>; - - /// Pushes clones of the elements of slice into the [`Vec`] instance. - /// - /// # Examples - /// - /// ``` - /// let mut v = Vec::new(); - /// v.push(1, GFP_KERNEL)?; - /// - /// v.extend_from_slice(&[20, 30, 40], GFP_KERNEL)?; - /// assert_eq!(&v, &[1, 20, 30, 40]); - /// - /// v.extend_from_slice(&[50, 60], GFP_KERNEL)?; - /// assert_eq!(&v, &[1, 20, 30, 40, 50, 60]); - /// # Ok::<(), Error>(()) - /// ``` - fn extend_from_slice(&mut self, other: &[T], flags: Flags) -> Result<(), AllocError> - where - T: Clone; - - /// Ensures that the capacity exceeds the length by at least `additional` elements. - /// - /// # Examples - /// - /// ``` - /// let mut v = Vec::new(); - /// v.push(1, GFP_KERNEL)?; - /// - /// v.reserve(10, GFP_KERNEL)?; - /// let cap = v.capacity(); - /// assert!(cap >= 10); - /// - /// v.reserve(10, GFP_KERNEL)?; - /// let new_cap = v.capacity(); - /// assert_eq!(new_cap, cap); - /// - /// # Ok::<(), Error>(()) - /// ``` - fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), AllocError>; -} - -impl<T> VecExt<T> for Vec<T> { - fn with_capacity(capacity: usize, flags: Flags) -> Result<Self, AllocError> { - let mut v = Vec::new(); - <Self as VecExt<_>>::reserve(&mut v, capacity, flags)?; - Ok(v) - } - - fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError> { - <Self as VecExt<_>>::reserve(self, 1, flags)?; - let s = self.spare_capacity_mut(); - s[0].write(v); - - // SAFETY: We just initialised the first spare entry, so it is safe to increase the length - // by 1. We also know that the new length is <= capacity because of the previous call to - // `reserve` above. - unsafe { self.set_len(self.len() + 1) }; - Ok(()) - } - - fn extend_from_slice(&mut self, other: &[T], flags: Flags) -> Result<(), AllocError> - where - T: Clone, - { - <Self as VecExt<_>>::reserve(self, other.len(), flags)?; - for (slot, item) in core::iter::zip(self.spare_capacity_mut(), other) { - slot.write(item.clone()); - } - - // SAFETY: We just initialised the `other.len()` spare entries, so it is safe to increase - // the length by the same amount. We also know that the new length is <= capacity because - // of the previous call to `reserve` above. - unsafe { self.set_len(self.len() + other.len()) }; - Ok(()) - } - - #[cfg(any(test, testlib))] - fn reserve(&mut self, additional: usize, _flags: Flags) -> Result<(), AllocError> { - Vec::reserve(self, additional); - Ok(()) - } - - #[cfg(not(any(test, testlib)))] - fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), AllocError> { - let len = self.len(); - let cap = self.capacity(); - - if cap - len >= additional { - return Ok(()); - } - - if core::mem::size_of::<T>() == 0 { - // The capacity is already `usize::MAX` for SZTs, we can't go higher. - return Err(AllocError); - } - - // We know cap is <= `isize::MAX` because `Layout::array` fails if the resulting byte size - // is greater than `isize::MAX`. So the multiplication by two won't overflow. - let new_cap = core::cmp::max(cap * 2, len.checked_add(additional).ok_or(AllocError)?); - let layout = core::alloc::Layout::array::<T>(new_cap).map_err(|_| AllocError)?; - - let (old_ptr, len, cap) = destructure(self); - - // We need to make sure that `ptr` is either NULL or comes from a previous call to - // `krealloc_aligned`. A `Vec<T>`'s `ptr` value is not guaranteed to be NULL and might be - // dangling after being created with `Vec::new`. Instead, we can rely on `Vec<T>`'s capacity - // to be zero if no memory has been allocated yet. - let ptr = if cap == 0 { - core::ptr::null_mut() - } else { - old_ptr - }; - - // SAFETY: `ptr` is valid because it's either NULL or comes from a previous call to - // `krealloc_aligned`. We also verified that the type is not a ZST. - let new_ptr = unsafe { super::allocator::krealloc_aligned(ptr.cast(), layout, flags) }; - if new_ptr.is_null() { - // SAFETY: We are just rebuilding the existing `Vec` with no changes. - unsafe { rebuild(self, old_ptr, len, cap) }; - Err(AllocError) - } else { - // SAFETY: `ptr` has been reallocated with the layout for `new_cap` elements. New cap - // is greater than `cap`, so it continues to be >= `len`. - unsafe { rebuild(self, new_ptr.cast::<T>(), len, new_cap) }; - Ok(()) - } - } -} - -#[cfg(not(any(test, testlib)))] -fn destructure<T>(v: &mut Vec<T>) -> (*mut T, usize, usize) { - let mut tmp = Vec::new(); - core::mem::swap(&mut tmp, v); - let mut tmp = core::mem::ManuallyDrop::new(tmp); - let len = tmp.len(); - let cap = tmp.capacity(); - (tmp.as_mut_ptr(), len, cap) -} - -/// Rebuilds a `Vec` from a pointer, length, and capacity. -/// -/// # Safety -/// -/// The same as [`Vec::from_raw_parts`]. -#[cfg(not(any(test, testlib)))] -unsafe fn rebuild<T>(v: &mut Vec<T>, ptr: *mut T, len: usize, cap: usize) { - // SAFETY: The safety requirements from this function satisfy those of `from_raw_parts`. - let mut tmp = unsafe { Vec::from_raw_parts(ptr, len, cap) }; - core::mem::swap(&mut tmp, v); -} diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index 80223cdaa485..07daccf6ca8e 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -14,10 +14,7 @@ #[doc(no_inline)] pub use core::pin::Pin; -pub use crate::alloc::{flags::*, vec_ext::VecExt, Box, KBox, KVBox, KVVec, KVec, VBox, VVec}; - -#[doc(no_inline)] -pub use alloc::vec::Vec; +pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec}; #[doc(no_inline)] pub use macros::{module, pin_data, pinned_drop, vtable, Zeroable};