lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251009204504.6b833fa1@nimda.home>
Date: Thu, 9 Oct 2025 20:45:04 +0300
From: Onur Özkan <work@...rozkan.dev>
To: Markus Probst <markus.probst@...teo.de>
Cc: Danilo Krummrich <dakr@...nel.org>, Miguel Ojeda <ojeda@...nel.org>,
 Alex Gaynor <alex.gaynor@...il.com>, Lee Jones <lee@...nel.org>, Pavel
 Machek <pavel@...nel.org>, Lorenzo Stoakes <lorenzo.stoakes@...cle.com>,
 Vlastimil Babka <vbabka@...e.cz>, "Liam R. Howlett"
 <Liam.Howlett@...cle.com>, Uladzislau Rezki <urezki@...il.com>, Boqun Feng
 <boqun.feng@...il.com>, Gary Guo <gary@...yguo.net>,
 bjorn3_gh@...tonmail.com, Benno Lossin <lossin@...nel.org>, Andreas
 Hindborg <a.hindborg@...nel.org>, Alice Ryhl <aliceryhl@...gle.com>, Trevor
 Gross <tmgross@...ch.edu>, rust-for-linux@...r.kernel.org,
 linux-kernel@...r.kernel.org, linux-leds@...r.kernel.org
Subject: Re: [PATCH 1/2] rust: add basic Pin<Vec<T, A>> abstractions

On Thu, 09 Oct 2025 17:07:56 +0000
Markus Probst <markus.probst@...teo.de> wrote:

Hi Markus,

I noticed a few typos in the code comments and the commit descriptions.

> Implement core Pin<Vec<T, A>> abstractions, incluing
>  * `Vec::pin` and `Vec::into_pin` for constructing a `Pin<Vec<T, A>>`.
>    If T does not implement `Unpin`, it values will never be moved.
>  * a extension for `Pin<Vec<T, A>>` allowing PinInit to be initialied
> on a Pin<Vec>, as well as truncating and poping values from the Vec
> 

"incluing" -> "including"
"it values will..." -> "its values will..."
"a extension" -> "an extension"
"initialied" -> "initialized"
"poping values" -> "popping values"

Thanks,
Onur

> Signed-off-by: Markus Probst <markus.probst@...teo.de>
> ---
>  rust/kernel/alloc.rs      |  1 +
>  rust/kernel/alloc/kvec.rs | 86
> +++++++++++++++++++++++++++++++++++++++ rust/kernel/prelude.rs    |
> 2 +- 3 files changed, 88 insertions(+), 1 deletion(-)
> 
> diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs
> index a2c49e5494d3..9c129eaf0625 100644
> --- a/rust/kernel/alloc.rs
> +++ b/rust/kernel/alloc.rs
> @@ -24,6 +24,7 @@
>  pub use self::kvec::KVec;
>  pub use self::kvec::VVec;
>  pub use self::kvec::Vec;
> +pub use self::kvec::PinnedVecExt;
>  
>  /// Indicates an allocation error.
>  #[derive(Copy, Clone, PartialEq, Eq, Debug)]
> diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
> index 3c72e0bdddb8..d5582a7f17e9 100644
> --- a/rust/kernel/alloc/kvec.rs
> +++ b/rust/kernel/alloc/kvec.rs
> @@ -16,11 +16,13 @@
>      ops::DerefMut,
>      ops::Index,
>      ops::IndexMut,
> +    pin::Pin,
>      ptr,
>      ptr::NonNull,
>      slice,
>      slice::SliceIndex,
>  };
> +use pin_init::PinInit;
>  
>  mod errors;
>  pub use self::errors::{InsertError, PushError, RemoveError};
> @@ -109,6 +111,21 @@ pub struct Vec<T, A: Allocator> {
>      _p: PhantomData<A>,
>  }
>  
> +/// Extension for Pin<Vec<T, A>>
> +pub trait PinnedVecExt<T> {
> +    /// Pin-initializes P and appends it to the back of the [`Vec`]
> instance without reallocating.
> +    fn push_pin_init<E: From<PushError<P>>, P: PinInit<T, E>>(&mut
> self, init: P) -> Result<(), E>; +
> +    /// Shortens the vector, setting the length to `len` and drops
> the removed values.
> +    /// If `len` is greater than or equal to the current length,
> this does nothing.
> +    ///
> +    /// This has no effect on the capacity and will not allocate.
> +    fn truncate(&mut self, len: usize);
> +
> +    /// Removes the last element from a vector and drops it
> returning true, or false if it is empty.
> +    fn pop(&mut self) -> bool;
> +}
> +
>  /// Type alias for [`Vec`] with a [`Kmalloc`] allocator.
>  ///
>  /// # Examples
> @@ -719,6 +736,18 @@ pub fn retain(&mut self, mut f: impl FnMut(&mut
> T) -> bool) { }
>          self.truncate(num_kept);
>      }
> +
> +    /// Constructs a new `Pin<Vec<T, A>>`.
> +    #[inline]
> +    pub fn pin(capacity: usize, flags: Flags) -> Result<Pin<Self>,
> AllocError> {
> +        Self::with_capacity(capacity, flags).map(Pin::<Self>::from)
> +    }
> +
> +    /// Convert a [`Vec<T,A>`] to a [`Pin<Vec<T,A>>`]. If `T` does
> not implement
> +    /// [`Unpin`], then its values will be pinned in memory and
> can't be moved.
> +    pub fn into_pin(this: Self) -> Pin<Self> {
> +        this.into()
> +    }
>  }
>  
>  impl<T: Clone, A: Allocator> Vec<T, A> {
> @@ -1294,6 +1323,63 @@ fn drop(&mut self) {
>      }
>  }
>  
> +impl<T, A: Allocator> PinnedVecExt<T> for Pin<Vec<T, A>> {
> +    fn truncate(&mut self, len: usize) {
> +        // SAFETY: truncate will not reallocate the Vec
> +        // CAST: Pin<Ptr> is a transparent wrapper of Ptr
> +        unsafe { &mut *core::ptr::from_mut(self).cast::<Vec<T, A>>()
> }.truncate(len);
> +    }
> +
> +    fn push_pin_init<E: From<PushError<P>>, P: PinInit<T, E>>(&mut
> self, init: P) -> Result<(), E> {
> +        // SAFETY: capacity, spare_capacity_mut and inc_len will not
> +        // reallocate the Vec.
> +        // CAST: Pin<Ptr> is a transparent wrapper of Ptr
> +        let this = unsafe { &mut
> *core::ptr::from_mut(self).cast::<Vec<T, A>>() }; +
> +        if this.len() < this.capacity() {
> +            let spare = this.spare_capacity_mut();
> +            // SAFETY: the length is less than the capacity, so
> `spare` is non-empty.
> +            unsafe {
> init.__pinned_init(spare.get_unchecked_mut(0).as_mut_ptr())? };
> +            // 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.
> +            unsafe { this.inc_len(1) };
> +            Ok(())
> +        } else {
> +            Err(E::from(PushError(init)))
> +        }
> +    }
> +
> +    fn pop(&mut self) -> bool {
> +        if self.is_empty() {
> +            return false;
> +        }
> +
> +        // SAFETY:
> +        // - We just checked that the length is at least one.
> +        // - dec_len will not reallocate the Vec
> +        // CAST: Pin<Ptr> is a transparent wrapper of Ptr
> +        let ptr: *mut [T] = unsafe {
> (*core::ptr::from_mut(self).cast::<Vec<T, A>>()).dec_len(1) }; +
> +        // SAFETY: the contract of `dec_len` guarantees that the
> elements in `ptr` are
> +        // valid elements whose ownership has been transferred to
> the caller.
> +        unsafe { ptr::drop_in_place(ptr) };
> +        true
> +    }
> +}
> +
> +impl<T, A: Allocator> From<Vec<T, A>> for Pin<Vec<T, A>> {
> +    /// Converts a `Vec<T, A>` into a `Pin<Vec<T, A>>`. If `T` does
> not implement [`Unpin`], then
> +    /// every value in v will be pinned in memory and can't be moved.
> +    ///
> +    /// This moves `v` into `Pin` without moving any of the values
> of `v` or allocating and copying
> +    /// any memory.
> +    fn from(v: Vec<T, A>) -> Self {
> +        // SAFETY: The values wrapped inside a `Pin<Vec<T, A>>`
> cannot be moved or replaced as long
> +        // as `T` does not implement `Unpin`.
> +        unsafe { Pin::new_unchecked(v) }
> +    }
> +}
> +
>  #[macros::kunit_tests(rust_kvec_kunit)]
>  mod tests {
>      use super::*;
> diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
> index 25fe97aafd02..7179e2ca2a14 100644
> --- a/rust/kernel/prelude.rs
> +++ b/rust/kernel/prelude.rs
> @@ -19,7 +19,7 @@
>      c_ushort, c_void,
>  };
>  
> -pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec,
> VBox, VVec, Vec}; +pub use crate::alloc::{flags::*, Box, KBox, KVBox,
> KVVec, KVec, PinnedVecExt, VBox, VVec, Vec}; 
>  #[doc(no_inline)]
>  pub use macros::{export, kunit_tests, module, vtable};


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ