Andrew Ballance
2025-Mar-16 11:17 UTC
[PATCH v2 0/3] rust: alloc: add Vec::resize and Vec::truncate
This patch series implements the Vec::truncate and Vec::resize methods that were needed by the nova driver and removes the corresponding item from their task list changes in v2: - updated safety comments - fixed rustdoc comment spacing - reworded commit messages to be imperative - Link to v1: https://lore.kernel.org/rust-for-linux/20250315024235.5282-1-andrewjballance at gmail.com/ Andrew Ballance (3): rust: alloc: add Vec::truncate method rust: alloc: add Vec::resize method gpu: nova-core: remove completed Vec extentions from task list Documentation/gpu/nova/core/todo.rst | 10 ----- rust/kernel/alloc/kvec.rs | 62 ++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 10 deletions(-) -- 2.48.1
Andrew Ballance
2025-Mar-16 11:17 UTC
[PATCH v2 1/3] rust: alloc: add Vec::truncate method
implement the equivalent to the std's Vec::truncate
on the kernel's Vec type.
Signed-off-by: Andrew Ballance <andrewjballance at gmail.com>
---
rust/kernel/alloc/kvec.rs | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
index ae9d072741ce..18bcc59f0b38 100644
--- a/rust/kernel/alloc/kvec.rs
+++ b/rust/kernel/alloc/kvec.rs
@@ -452,6 +452,42 @@ pub fn reserve(&mut self, additional: usize, flags:
Flags) -> Result<(), AllocEr
Ok(())
}
+
+ /// 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.
+ /// # Examples
+ ///
+ /// ```
+ /// let mut v = kernel::kvec![1, 2, 3]?;
+ /// v.truncate(1);
+ /// assert_eq!(v.len(), 1);
+ /// assert_eq!(&v, &[1]);
+ ///
+ /// # Ok::<(), Error>(())
+ /// ```
+ pub fn truncate(&mut self, len: usize) {
+ if len >= self.len() {
+ return;
+ }
+
+ let drop_range = len..self.len();
+
+ // SAFETY: `drop_range` is a subrange of `[0, len)` by the bounds check
above.
+ let ptr: *mut [T] = unsafe { self.get_unchecked_mut(drop_range) };
+
+ // SAFETY:
+ // - this will always shrink the vector because of the above bounds
check
+ // - [`new_len`, `self.len`) will be dropped through the call to
`drop_in_place` below
+ unsafe { self.set_len(len) };
+
+ // SAFETY:
+ // - the dropped values are valid `T`s by the type invariant
+ // - we are allowed to invalidate [`new_len`, `old_len`) because we
just changed the
+ // len, therefore we have exclusive access to [`new_len`, `old_len`)
+ unsafe { ptr::drop_in_place(ptr) };
+ }
}
impl<T: Clone, A: Allocator> Vec<T, A> {
--
2.48.1
implement the equivalent of the rust std's Vec::resize
on the kernel's Vec type.
Signed-off-by: Andrew Ballance <andrewjballance at gmail.com>
---
rust/kernel/alloc/kvec.rs | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
index 18bcc59f0b38..eb6d40a1bf8b 100644
--- a/rust/kernel/alloc/kvec.rs
+++ b/rust/kernel/alloc/kvec.rs
@@ -554,6 +554,32 @@ pub fn from_elem(value: T, n: usize, flags: Flags) ->
Result<Self, AllocError> {
Ok(v)
}
+
+ /// Resizes the [`Vec`] so that `len` is equal to `new_len`.
+ ///
+ /// If `new_len` is smaller than `len`, the `Vec` is [`Vec::truncate`]d.
+ /// If `new_len` is larger, each new slot is filled with clones of `value`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let mut v = kernel::kvec![1, 2, 3]?;
+ /// v.resize(1, 42, GFP_KERNEL)?;
+ /// assert_eq!(&v, &[1]);
+ ///
+ /// v.resize(3, 42, GFP_KERNEL)?;
+ /// assert_eq!(&v, &[1, 42, 42]);
+ ///
+ /// # Ok::<(), Error>(())
+ /// ```
+ pub fn resize(&mut self, new_len: usize, value: T, flags: Flags) ->
Result<(), AllocError> {
+ if new_len > self.len() {
+ self.extend_with(new_len - self.len(), value, flags)
+ } else {
+ self.truncate(new_len);
+ Ok(())
+ }
+ }
}
impl<T, A> Drop for Vec<T, A>
--
2.48.1
Andrew Ballance
2025-Mar-16 11:17 UTC
[PATCH v2 3/3] gpu: nova-core: remove completed Vec extentions from task list
The requested Vec methods have been implemented thus, removes the completed item from the nova task list Signed-off-by: Andrew Ballance <andrewjballance at gmail.com> --- Documentation/gpu/nova/core/todo.rst | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Documentation/gpu/nova/core/todo.rst b/Documentation/gpu/nova/core/todo.rst index ca08377d3b73..234d753d3eac 100644 --- a/Documentation/gpu/nova/core/todo.rst +++ b/Documentation/gpu/nova/core/todo.rst @@ -190,16 +190,6 @@ Rust abstraction for debugfs APIs. | Reference: Export GSP log buffers | Complexity: Intermediate -Vec extensions --------------- - -Implement ``Vec::truncate`` and ``Vec::resize``. - -Currently this is used for some experimental code to parse the vBIOS. - -| Reference vBIOS support -| Complexity: Beginner - GPU (general) ============ -- 2.48.1
Danilo Krummrich
2025-Mar-16 19:19 UTC
[PATCH v2 1/3] rust: alloc: add Vec::truncate method
On Sun, Mar 16, 2025 at 06:16:42AM -0500, Andrew Ballance wrote:> implement the equivalent to the std's Vec::truncate > on the kernel's Vec type. > > Signed-off-by: Andrew Ballance <andrewjballance at gmail.com> > --- > rust/kernel/alloc/kvec.rs | 36 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 36 insertions(+) > > diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs > index ae9d072741ce..18bcc59f0b38 100644 > --- a/rust/kernel/alloc/kvec.rs > +++ b/rust/kernel/alloc/kvec.rs > @@ -452,6 +452,42 @@ pub fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), AllocEr > > Ok(()) > } > + > + /// 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. > + /// # Examples > + /// > + /// ``` > + /// let mut v = kernel::kvec![1, 2, 3]?; > + /// v.truncate(1); > + /// assert_eq!(v.len(), 1); > + /// assert_eq!(&v, &[1]); > + /// > + /// # Ok::<(), Error>(()) > + /// ``` > + pub fn truncate(&mut self, len: usize) { > + if len >= self.len() { > + return; > + } > + > + let drop_range = len..self.len(); > + > + // SAFETY: `drop_range` is a subrange of `[0, len)` by the bounds check above. > + let ptr: *mut [T] = unsafe { self.get_unchecked_mut(drop_range) }; > + > + // SAFETY: > + // - this will always shrink the vector because of the above bounds check > + // - [`new_len`, `self.len`) will be dropped through the call to `drop_in_place` belowWe've just figured out that this part is not needed after all, sorry for the inconvenience. No need to resend for this though, I can remove this line when applying the patch.> + unsafe { self.set_len(len) }; > + > + // SAFETY: > + // - the dropped values are valid `T`s by the type invariant > + // - we are allowed to invalidate [`new_len`, `old_len`) because we just changed the > + // len, therefore we have exclusive access to [`new_len`, `old_len`) > + unsafe { ptr::drop_in_place(ptr) }; > + } > } > > impl<T: Clone, A: Allocator> Vec<T, A> { > -- > 2.48.1 >
On Sun, Mar 16, 2025 at 7:17?AM Andrew Ballance <andrewjballance at gmail.com> wrote:> > implement the equivalent of the rust std's Vec::resize > on the kernel's Vec type. > > Signed-off-by: Andrew Ballance <andrewjballance at gmail.com> > --- > rust/kernel/alloc/kvec.rs | 26 ++++++++++++++++++++++++++ > 1 file changed, 26 insertions(+) > > diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs > index 18bcc59f0b38..eb6d40a1bf8b 100644 > --- a/rust/kernel/alloc/kvec.rs > +++ b/rust/kernel/alloc/kvec.rs > @@ -554,6 +554,32 @@ pub fn from_elem(value: T, n: usize, flags: Flags) -> Result<Self, AllocError> { > > Ok(v) > } > + > + /// Resizes the [`Vec`] so that `len` is equal to `new_len`. > + /// > + /// If `new_len` is smaller than `len`, the `Vec` is [`Vec::truncate`]d. > + /// If `new_len` is larger, each new slot is filled with clones of `value`. > + /// > + /// # Examples > + /// > + /// ``` > + /// let mut v = kernel::kvec![1, 2, 3]?; > + /// v.resize(1, 42, GFP_KERNEL)?; > + /// assert_eq!(&v, &[1]); > + /// > + /// v.resize(3, 42, GFP_KERNEL)?; > + /// assert_eq!(&v, &[1, 42, 42]); > + /// > + /// # Ok::<(), Error>(()) > + /// ``` > + pub fn resize(&mut self, new_len: usize, value: T, flags: Flags) -> Result<(), AllocError> { > + if new_len > self.len() { > + self.extend_with(new_len - self.len(), value, flags) > + } else { > + self.truncate(new_len); > + Ok(()) > + } > + }You can avoid underflow checking in debug builds by using `checked_sub`: match new_len.checked_sub(self.len()) { Some(n) => self.extend_with(n, value, flags), None => { self.truncate(new_len); Ok(()) } }> } > > impl<T, A> Drop for Vec<T, A> > -- > 2.48.1 > >Either way: Reviewed-by: Tamir Duberstein <tamird at gmail.com>
Danilo Krummrich
2025-Apr-07 13:07 UTC
[PATCH v2 0/3] rust: alloc: add Vec::resize and Vec::truncate
On 3/16/25 12:16 PM, Andrew Ballance wrote:> This patch series implements the Vec::truncate and Vec::resize methods > that were needed by the nova driver and removes the corresponding item > from their task list > > changes in v2: > - updated safety comments > - fixed rustdoc comment spacing > - reworded commit messages to be imperative > - Link to v1: https://lore.kernel.org/rust-for-linux/20250315024235.5282-1-andrewjballance at gmail.com/ > > Andrew Ballance (3): > rust: alloc: add Vec::truncate method > rust: alloc: add Vec::resize methodWith the following changes, applied to rust/alloc-next, thanks! - Rewrote safety comment of set_len(). - Use checked_sub(), as suggested by Tamir.> gpu: nova-core: remove completed Vec extentions from task listApplied to nova-next, thanks!> Documentation/gpu/nova/core/todo.rst | 10 ----- > rust/kernel/alloc/kvec.rs | 62 ++++++++++++++++++++++++++++ > 2 files changed, 62 insertions(+), 10 deletions(-) >