public inbox for rust-for-linux@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/3] rust: alloc: add KVVec shrinking method
@ 2026-02-14 20:35 Shivam Kalra via B4 Relay
  2026-02-14 20:35 ` [PATCH v5 1/3] rust: kvec: implement shrink_to for KVVec Shivam Kalra via B4 Relay
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Shivam Kalra via B4 Relay @ 2026-02-14 20:35 UTC (permalink / raw)
  To: Danilo Krummrich, Lorenzo Stoakes, Vlastimil Babka,
	Liam R. Howlett, Uladzislau Rezki, Miguel Ojeda, Boqun Feng,
	Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Alice Ryhl, Trevor Gross, Greg Kroah-Hartman,
	Arve Hjønnevåg, Todd Kjos, Christian Brauner,
	Carlos Llamas
  Cc: rust-for-linux, linux-kernel, Shivam Kalra

This series adds a shrink_to() method to KVVec to allow explicit
capacity reduction for memory reclamation.

Problem:
When elements are removed from a KVVec, the allocated capacity is not
reduced. The underlying C allocators (krealloc/kvrealloc) don't shrink
memory in-place. This can cause significant memory waste in scenarios
with variable workloads.

Solution:
- Patch 1: Implements shrink_to(min_capacity, flags) method specifically
  for KVVec (Vec<T, KVmalloc>). For kmalloc allocations, the method
  delegates to realloc(), letting the allocator decide whether shrinking
  is worthwhile. For vmalloc allocations (detected via is_vmalloc_addr),
  shrinking only occurs if at least one page of memory can be freed,
  using an explicit alloc+copy+free (deep copy) since vrealloc does not
  yet support in-place shrinking. A TODO comment marks this for future
  replacement with a generic implementation using A::realloc() once
  allocators properly support shrinking.
- Patch 2: Adds KUnit tests for the new shrink_to method, verifying
  page-based shrinking, empty vector handling, no-op behavior, and
  min_capacity respect.
- Patch 3: Uses shrink_to() in the Rust binder driver to reclaim memory
  when processes are deregistered. Uses a conservative shrinking
  strategy (trigger at len < cap / 4, shrink to len * 2) to avoid
  shrink-then-regrow oscillation while equalizing capacity more
  aggressively when it diverges far from usage.

Testing:
- KUnit tests pass (rust_kvec test suite).
- Kernel boots successfully in QEMU with CONFIG_ANDROID_BINDER_IPC_RUST=y.

Changes since v4:
- Added is_vmalloc_addr() check: kmalloc allocations now delegate to
  realloc() directly, keeping semantics as close as possible to the
  future generic implementation. Only vmalloc allocations use the
  page-threshold + deep copy path. (Danilo Krummrich)
- Updated doc comment to describe kmalloc vs vmalloc behavior
  separately: kmalloc delegates to realloc(), vmalloc only shrinks if
  at least one page can be freed via deep copy. (Danilo Krummrich)
- Fixed import style to follow kernel coding guidelines (multi-line
  block import for page::{AsPageIter, PAGE_SIZE}). (Danilo Krummrich)
- Dropped duplicate TODO comment inside shrink_to() body; the TODO
  above the impl block already covers this. (Danilo Krummrich)
- Structured SAFETY comments as lists when justifying multiple
  conditions. (Danilo Krummrich)
- Moved semicolons outside unsafe blocks per kernel style.
  (Danilo Krummrich)
- Changed binder shrink target from cap / 2 to len * 2, so that
  capacity equalizes to usage more aggressively when it has diverged
  far from the length. (Alice Ryhl)

Changes since v3:
- Dropped the Shrinkable trait entirely - it was not needed for the
  KVVec-specific implementation. (Danilo Krummrich)
- Removed shrink_to_fit() method. Only shrink_to() is implemented.
  (Danilo Krummrich)
- Implemented shrink_to() only for KVVec (impl<T> Vec<T, KVmalloc>)
  instead of as a generic method, since that covers the actual use
  case in binder. (Danilo Krummrich, Alice Ryhl)
- Added TODO comment explaining this is a temporary KVVec-specific
  implementation that should be replaced with a generic
  Vec<T, A>::shrink_to() calling A::realloc() once the underlying
  allocators properly support shrinking via realloc. (Danilo Krummrich)
- Changed binder shrink strategy to be less aggressive to avoid
  shrink-then-regrow oscillation: now triggers when len < cap / 4 and
  shrinks to cap / 2. (Alice Ryhl)
- Removed the cap > 128 threshold check in binder. (Alice Ryhl)
- Fixed commit prefix from "rust: binder:" to "rust_binder:".
  (Alice Ryhl)
- Updated test suite to focus on KVVec-specific behavior.

Changes since v2:
- Introduced new Shrinkable marker trait to distinguish allocators that
  benefit from shrinking (Vmalloc) from those that don't (Kmalloc).
- Shrinking now only occurs for vmalloc-backed buffers when at least one
  page can be freed, avoiding unnecessary work for kmalloc buffers.
  (Suggested by Danilo Krummrich)
- Split into 4 patches: Shrinkable trait introduction is now a
  separate patch to improve reviewability.
- Uses explicit alloc+copy+free since vrealloc doesn't yet support
  in-place shrinking; TODO added for future optimization when vrealloc
  gains that capability. (Discussed with Danilo Krummrich)
- Fixed minor KVVec/KVec terminology (binder uses KVVec not KVec).
- Expanded KUnit tests to cover different allocator backends and
  page-boundary shrinking behavior.

Changes since v1:
- Resend with correct threading (no code changes).
- Removed base-commit.
- Added explicit lore link to dependency in cover letter.

[1] https://lore.kernel.org/lkml/20260130205424.261700-1-shivamklr@cock.li/
[2] https://lore.kernel.org/lkml/20260131154016.270385-1-shivamklr@cock.li/
[3] https://lore.kernel.org/lkml/20260207-binder-shrink-vec-v3-v3-0-8ff388563427@cock.li/
[4] https://lore.kernel.org/lkml/20260212-binder-shrink-vec-v3-v4-0-bd02f06bf2cd@zohomail.in/

Signed-off-by: Shivam Kalra <shivamkalra98@zohomail.in>
---
Shivam Kalra (3):
      rust: kvec: implement shrink_to for KVVec
      rust: alloc: add KUnit tests for KVVec shrink_to
      rust_binder: shrink all_procs when deregistering processes

 drivers/android/binder/context.rs |  11 ++
 rust/kernel/alloc/kvec.rs         | 226 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 236 insertions(+), 1 deletion(-)
---
base-commit: 3c4ae63073d84abee5d81ce46d86a94e9dae9c89
change-id: 20260212-binder-shrink-vec-v3-c8c1131efbf7

Best regards,
-- 
Shivam Kalra <shivamkalra98@zohomail.in>



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v5 1/3] rust: kvec: implement shrink_to for KVVec
  2026-02-14 20:35 [PATCH v5 0/3] rust: alloc: add KVVec shrinking method Shivam Kalra via B4 Relay
@ 2026-02-14 20:35 ` Shivam Kalra via B4 Relay
  2026-02-14 20:35 ` [PATCH v5 2/3] rust: alloc: add KUnit tests for KVVec shrink_to Shivam Kalra via B4 Relay
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Shivam Kalra via B4 Relay @ 2026-02-14 20:35 UTC (permalink / raw)
  To: Danilo Krummrich, Lorenzo Stoakes, Vlastimil Babka,
	Liam R. Howlett, Uladzislau Rezki, Miguel Ojeda, Boqun Feng,
	Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Alice Ryhl, Trevor Gross, Greg Kroah-Hartman,
	Arve Hjønnevåg, Todd Kjos, Christian Brauner,
	Carlos Llamas
  Cc: rust-for-linux, linux-kernel, Shivam Kalra

From: Shivam Kalra <shivamkalra98@zohomail.in>

Implement shrink_to method specifically for `KVVec` (i.e.,
`Vec<T, KVmalloc>`). `shrink_to` reduces the vector's capacity to a
specified minimum.

For kmalloc-backed allocations, the method delegates to realloc(),
letting the allocator decide whether shrinking is worthwhile. For
vmalloc-backed allocations (detected via is_vmalloc_addr), shrinking
only occurs if at least one page of memory can be freed, using an
explicit alloc+copy+free since vrealloc does not yet support in-place
shrinking.

A TODO note marks this for future replacement with a generic shrink_to
for all allocators that uses A::realloc() once the underlying allocators
properly support shrinking via realloc.

Suggested-by: Alice Ryhl <aliceryhl@google.com>
Suggested-by: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Shivam Kalra <shivamkalra98@zohomail.in>
---
 rust/kernel/alloc/kvec.rs | 114 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 113 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
index ac8d6f763ae81..e7bc439538e49 100644
--- a/rust/kernel/alloc/kvec.rs
+++ b/rust/kernel/alloc/kvec.rs
@@ -9,7 +9,10 @@
 };
 use crate::{
     fmt,
-    page::AsPageIter, //
+    page::{
+        AsPageIter,
+        PAGE_SIZE, //
+    },
 };
 use core::{
     borrow::{Borrow, BorrowMut},
@@ -734,6 +737,115 @@ pub fn retain(&mut self, mut f: impl FnMut(&mut T) -> bool) {
         self.truncate(num_kept);
     }
 }
+// TODO: This is a temporary KVVec-specific implementation. It should be replaced with a generic
+// `shrink_to()` for `impl<T, A: Allocator> Vec<T, A>` that uses `A::realloc()` once the
+// underlying allocators properly support shrinking via realloc.
+impl<T> Vec<T, KVmalloc> {
+    /// Shrinks the capacity of the vector with a lower bound.
+    ///
+    /// The capacity will remain at least as large as both the length and the supplied value.
+    /// If the current capacity is less than the lower limit, this is a no-op.
+    ///
+    /// For `kmalloc` allocations, this delegates to `realloc()`, which decides whether
+    /// shrinking is worthwhile. For `vmalloc` allocations, shrinking only occurs if the
+    /// operation would free at least one page of memory, and performs a deep copy since
+    /// `vrealloc` does not yet support in-place shrinking.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// // Allocate enough capacity to span multiple pages.
+    /// let elements_per_page = kernel::page::PAGE_SIZE / core::mem::size_of::<u32>();
+    /// let mut v = KVVec::with_capacity(elements_per_page * 4, GFP_KERNEL)?;
+    /// v.push(1, GFP_KERNEL)?;
+    /// v.push(2, GFP_KERNEL)?;
+    ///
+    /// v.shrink_to(0, GFP_KERNEL)?;
+    /// # Ok::<(), Error>(())
+    /// ```
+    pub fn shrink_to(&mut self, min_capacity: usize, flags: Flags) -> Result<(), AllocError> {
+        let target_cap = core::cmp::max(self.len(), min_capacity);
+
+        if self.capacity() <= target_cap {
+            return Ok(());
+        }
+
+        if Self::is_zst() {
+            return Ok(());
+        }
+
+        // For kmalloc allocations, delegate to realloc() and let the allocator decide
+        // whether shrinking is worthwhile.
+        //
+        // SAFETY: `self.ptr` points to a valid `KVmalloc` allocation.
+        if !unsafe { bindings::is_vmalloc_addr(self.ptr.as_ptr().cast()) } {
+            let new_layout = ArrayLayout::<T>::new(target_cap).map_err(|_| AllocError)?;
+
+            // SAFETY:
+            // - `self.ptr` is valid and was previously allocated with `KVmalloc`.
+            // - `self.layout` matches the `ArrayLayout` of the preceding allocation.
+            let ptr = unsafe {
+                KVmalloc::realloc(
+                    Some(self.ptr.cast()),
+                    new_layout.into(),
+                    self.layout.into(),
+                    flags,
+                    NumaNode::NO_NODE,
+                )?
+            };
+
+            self.ptr = ptr.cast();
+            self.layout = new_layout;
+            return Ok(());
+        }
+
+        // Only shrink if we would free at least one page.
+        let current_size = self.capacity() * core::mem::size_of::<T>();
+        let target_size = target_cap * core::mem::size_of::<T>();
+        let current_pages = current_size.div_ceil(PAGE_SIZE);
+        let target_pages = target_size.div_ceil(PAGE_SIZE);
+
+        if current_pages <= target_pages {
+            return Ok(());
+        }
+
+        if target_cap == 0 {
+            if !self.layout.is_empty() {
+                // SAFETY:
+                // - `self.ptr` was previously allocated with `KVmalloc`.
+                // - `self.layout` matches the `ArrayLayout` of the preceding allocation.
+                unsafe { KVmalloc::free(self.ptr.cast(), self.layout.into()) };
+            }
+            self.ptr = NonNull::dangling();
+            self.layout = ArrayLayout::empty();
+            return Ok(());
+        }
+
+        // SAFETY: `target_cap <= self.capacity()` and original capacity was valid.
+        let new_layout = unsafe { ArrayLayout::<T>::new_unchecked(target_cap) };
+
+        let new_ptr = KVmalloc::alloc(new_layout.into(), flags, NumaNode::NO_NODE)?;
+
+        // SAFETY:
+        // - `self.as_ptr()` is valid for reads of `self.len()` elements of `T`.
+        // - `new_ptr` is valid for writes of at least `target_cap >= self.len()` elements.
+        // - The two allocations do not overlap since `new_ptr` is freshly allocated.
+        // - Both pointers are properly aligned for `T`.
+        unsafe {
+            ptr::copy_nonoverlapping(self.as_ptr(), new_ptr.as_ptr().cast::<T>(), self.len())
+        };
+
+        // SAFETY:
+        // - `self.ptr` was previously allocated with `KVmalloc`.
+        // - `self.layout` matches the `ArrayLayout` of the preceding allocation.
+        unsafe { KVmalloc::free(self.ptr.cast(), self.layout.into()) };
+
+        self.ptr = new_ptr.cast::<T>();
+        self.layout = new_layout;
+
+        Ok(())
+    }
+}
 
 impl<T: Clone, A: Allocator> Vec<T, A> {
     /// Extend the vector by `n` clones of `value`.

-- 
2.43.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v5 2/3] rust: alloc: add KUnit tests for KVVec shrink_to
  2026-02-14 20:35 [PATCH v5 0/3] rust: alloc: add KVVec shrinking method Shivam Kalra via B4 Relay
  2026-02-14 20:35 ` [PATCH v5 1/3] rust: kvec: implement shrink_to for KVVec Shivam Kalra via B4 Relay
@ 2026-02-14 20:35 ` Shivam Kalra via B4 Relay
  2026-02-15 22:10   ` Danilo Krummrich
  2026-02-14 20:35 ` [PATCH v5 3/3] rust_binder: shrink all_procs when deregistering processes Shivam Kalra via B4 Relay
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Shivam Kalra via B4 Relay @ 2026-02-14 20:35 UTC (permalink / raw)
  To: Danilo Krummrich, Lorenzo Stoakes, Vlastimil Babka,
	Liam R. Howlett, Uladzislau Rezki, Miguel Ojeda, Boqun Feng,
	Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Alice Ryhl, Trevor Gross, Greg Kroah-Hartman,
	Arve Hjønnevåg, Todd Kjos, Christian Brauner,
	Carlos Llamas
  Cc: rust-for-linux, linux-kernel, Shivam Kalra

From: Shivam Kalra <shivamkalra98@zohomail.in>

Add comprehensive KUnit tests for the shrink_to method for KVVec.
The tests verify:
- Basic shrinking from multiple pages to fewer pages with data integrity
  preservation
- Empty vector shrinking to zero capacity
- No-op behavior when shrinking to a larger capacity than current
- Respect for min_capacity parameter when larger than vector length
These tests ensure that the shrinking logic correctly identifies when
memory can be reclaimed (by freeing at least one page) and that data
integrity is maintained throughout shrink operations.

Signed-off-by: Shivam Kalra <shivamkalra98@zohomail.in>
---
 rust/kernel/alloc/kvec.rs | 112 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 112 insertions(+)

diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
index e7bc439538e4..0d5d69296a9f 100644
--- a/rust/kernel/alloc/kvec.rs
+++ b/rust/kernel/alloc/kvec.rs
@@ -1510,4 +1510,116 @@ fn add(value: &mut [bool]) {
             func.push_within_capacity(false).unwrap();
         }
     }
+
+    #[test]
+    fn test_kvvec_shrink_to() {
+        use crate::page::PAGE_SIZE;
+
+        // Calculate elements per page for u32.
+        let elements_per_page = PAGE_SIZE / core::mem::size_of::<u32>();
+
+        // Create a vector with capacity spanning multiple pages.
+        let mut v = KVVec::<u32>::with_capacity(elements_per_page * 4, GFP_KERNEL).unwrap();
+
+        // Add a few elements.
+        v.push(1, GFP_KERNEL).unwrap();
+        v.push(2, GFP_KERNEL).unwrap();
+        v.push(3, GFP_KERNEL).unwrap();
+
+        let initial_capacity = v.capacity();
+        assert!(initial_capacity >= elements_per_page * 4);
+
+        // Shrink to a capacity that would free at least one page.
+        v.shrink_to(elements_per_page, GFP_KERNEL).unwrap();
+
+        // Capacity should have been reduced.
+        assert!(v.capacity() < initial_capacity);
+        assert!(v.capacity() >= elements_per_page);
+
+        // Elements should be preserved.
+        assert_eq!(v.len(), 3);
+        assert_eq!(v[0], 1);
+        assert_eq!(v[1], 2);
+        assert_eq!(v[2], 3);
+
+        // Shrink to zero (should shrink to len).
+        v.shrink_to(0, GFP_KERNEL).unwrap();
+
+        // Capacity should be at least the length.
+        assert!(v.capacity() >= v.len());
+
+        // Elements should still be preserved.
+        assert_eq!(v.len(), 3);
+        assert_eq!(v[0], 1);
+        assert_eq!(v[1], 2);
+        assert_eq!(v[2], 3);
+    }
+
+    #[test]
+    fn test_kvvec_shrink_to_empty() {
+        use crate::page::PAGE_SIZE;
+
+        let elements_per_page = PAGE_SIZE / core::mem::size_of::<u64>();
+
+        // Create a vector with large capacity but no elements.
+        let mut v = KVVec::<u64>::with_capacity(elements_per_page * 4, GFP_KERNEL).unwrap();
+
+        assert!(v.is_empty());
+        let initial_capacity = v.capacity();
+
+        // Shrink empty vector to zero.
+        v.shrink_to(0, GFP_KERNEL).unwrap();
+
+        // Should have freed the allocation.
+        assert!(v.capacity() < initial_capacity);
+        assert!(v.is_empty());
+    }
+
+    #[test]
+    fn test_kvvec_shrink_to_no_op() {
+        use crate::page::PAGE_SIZE;
+
+        let elements_per_page = PAGE_SIZE / core::mem::size_of::<u32>();
+
+        // Create a small vector.
+        let mut v = KVVec::<u32>::with_capacity(elements_per_page, GFP_KERNEL).unwrap();
+        v.push(1, GFP_KERNEL).unwrap();
+
+        let capacity_before = v.capacity();
+
+        // Try to shrink to a capacity larger than current - should be no-op.
+        v.shrink_to(capacity_before + 100, GFP_KERNEL).unwrap();
+
+        assert_eq!(v.capacity(), capacity_before);
+        assert_eq!(v.len(), 1);
+        assert_eq!(v[0], 1);
+    }
+
+    #[test]
+    fn test_kvvec_shrink_to_respects_min_capacity() {
+        use crate::page::PAGE_SIZE;
+
+        let elements_per_page = PAGE_SIZE / core::mem::size_of::<u32>();
+
+        // Create a vector with large capacity.
+        let mut v = KVVec::<u32>::with_capacity(elements_per_page * 4, GFP_KERNEL).unwrap();
+
+        // Add some elements.
+        for i in 0..10 {
+            v.push(i, GFP_KERNEL).unwrap();
+        }
+
+        // Shrink to a min_capacity larger than length.
+        let min_cap = elements_per_page * 2;
+        v.shrink_to(min_cap, GFP_KERNEL).unwrap();
+
+        // Capacity should be at least min_capacity.
+        assert!(v.capacity() >= min_cap);
+
+        // All elements preserved.
+        assert_eq!(v.len(), 10);
+        for i in 0..10 {
+            assert_eq!(v[i as usize], i);
+        }
+    }
 }

-- 
2.43.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v5 3/3] rust_binder: shrink all_procs when deregistering processes
  2026-02-14 20:35 [PATCH v5 0/3] rust: alloc: add KVVec shrinking method Shivam Kalra via B4 Relay
  2026-02-14 20:35 ` [PATCH v5 1/3] rust: kvec: implement shrink_to for KVVec Shivam Kalra via B4 Relay
  2026-02-14 20:35 ` [PATCH v5 2/3] rust: alloc: add KUnit tests for KVVec shrink_to Shivam Kalra via B4 Relay
@ 2026-02-14 20:35 ` Shivam Kalra via B4 Relay
  2026-02-15 22:13 ` [PATCH v5 0/3] rust: alloc: add KVVec shrinking method Danilo Krummrich
  2026-02-16  8:45 ` Alice Ryhl
  4 siblings, 0 replies; 9+ messages in thread
From: Shivam Kalra via B4 Relay @ 2026-02-14 20:35 UTC (permalink / raw)
  To: Danilo Krummrich, Lorenzo Stoakes, Vlastimil Babka,
	Liam R. Howlett, Uladzislau Rezki, Miguel Ojeda, Boqun Feng,
	Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Alice Ryhl, Trevor Gross, Greg Kroah-Hartman,
	Arve Hjønnevåg, Todd Kjos, Christian Brauner,
	Carlos Llamas
  Cc: rust-for-linux, linux-kernel, Shivam Kalra

From: Shivam Kalra <shivamkalra98@zohomail.in>

When a process is deregistered from the binder context, the all_procs
vector may have significant unused capacity. Add logic to shrink the
vector using a conservative strategy that prevents shrink-then-regrow
oscillation.

The shrinking strategy triggers when length drops below 1/4 of capacity,
and shrinks to twice the current length rather than to the exact length.
This provides hysteresis to avoid repeated reallocations when the process
count fluctuates.

The shrink operation uses GFP_KERNEL and is allowed to fail gracefully
since it is purely an optimization. The vector remains valid and
functional even if shrinking fails.

Suggested-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Shivam Kalra <shivamkalra98@zohomail.in>
---
 drivers/android/binder/context.rs | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/android/binder/context.rs b/drivers/android/binder/context.rs
index 9cf437c025a20..ddddb66b35571 100644
--- a/drivers/android/binder/context.rs
+++ b/drivers/android/binder/context.rs
@@ -94,6 +94,17 @@ pub(crate) fn deregister_process(self: &Arc<Self>, proc: &Arc<Process>) {
         }
         let mut manager = self.manager.lock();
         manager.all_procs.retain(|p| !Arc::ptr_eq(p, proc));
+
+        // Shrink the vector if it has significant unused capacity to avoid memory waste,
+        // but use a conservative strategy to prevent shrink-then-regrow oscillation.
+        // Only shrink when length drops below 1/4 of capacity, and shrink to twice the length.
+        let len = manager.all_procs.len();
+        let cap = manager.all_procs.capacity();
+        if len < cap / 4 {
+            // Shrink to twice the current length. Ignore allocation failures since this
+            // is just an optimization; the vector remains valid even if shrinking fails.
+            let _ = manager.all_procs.shrink_to(len * 2, GFP_KERNEL);
+        }
     }
 
     pub(crate) fn set_manager_node(&self, node_ref: NodeRef) -> Result {

-- 
2.43.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v5 2/3] rust: alloc: add KUnit tests for KVVec shrink_to
  2026-02-14 20:35 ` [PATCH v5 2/3] rust: alloc: add KUnit tests for KVVec shrink_to Shivam Kalra via B4 Relay
@ 2026-02-15 22:10   ` Danilo Krummrich
  0 siblings, 0 replies; 9+ messages in thread
From: Danilo Krummrich @ 2026-02-15 22:10 UTC (permalink / raw)
  To: Shivam Kalra via B4 Relay
  Cc: shivamkalra98, Lorenzo Stoakes, Vlastimil Babka, Liam R. Howlett,
	Uladzislau Rezki, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Greg Kroah-Hartman, Arve Hjønnevåg,
	Todd Kjos, Christian Brauner, Carlos Llamas, rust-for-linux,
	linux-kernel

On Sat Feb 14, 2026 at 9:35 PM CET, Shivam Kalra via B4 Relay wrote:
> diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
> index e7bc439538e4..0d5d69296a9f 100644
> --- a/rust/kernel/alloc/kvec.rs
> +++ b/rust/kernel/alloc/kvec.rs
> @@ -1510,4 +1510,116 @@ fn add(value: &mut [bool]) {
>              func.push_within_capacity(false).unwrap();
>          }
>      }
> +
> +    #[test]
> +    fn test_kvvec_shrink_to() {
> +        use crate::page::PAGE_SIZE;
> +
> +        // Calculate elements per page for u32.
> +        let elements_per_page = PAGE_SIZE / core::mem::size_of::<u32>();

NIT: Wouldn't it be a bit more straight forward to just use u8 for all the
tests?

> +    #[test]
> +    fn test_kvvec_shrink_to_empty() {
> +        use crate::page::PAGE_SIZE;
> +
> +        let elements_per_page = PAGE_SIZE / core::mem::size_of::<u64>();
> +
> +        // Create a vector with large capacity but no elements.
> +        let mut v = KVVec::<u64>::with_capacity(elements_per_page * 4, GFP_KERNEL).unwrap();
> +
> +        assert!(v.is_empty());
> +        let initial_capacity = v.capacity();
> +
> +        // Shrink empty vector to zero.
> +        v.shrink_to(0, GFP_KERNEL).unwrap();
> +
> +        // Should have freed the allocation.
> +        assert!(v.capacity() < initial_capacity);

I think this assert!() should rather check for v.capacity() == 0.

> +        assert!(v.is_empty());
> +    }

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v5 0/3] rust: alloc: add KVVec shrinking method
  2026-02-14 20:35 [PATCH v5 0/3] rust: alloc: add KVVec shrinking method Shivam Kalra via B4 Relay
                   ` (2 preceding siblings ...)
  2026-02-14 20:35 ` [PATCH v5 3/3] rust_binder: shrink all_procs when deregistering processes Shivam Kalra via B4 Relay
@ 2026-02-15 22:13 ` Danilo Krummrich
  2026-02-16  8:40   ` Alice Ryhl
  2026-02-16  9:41   ` Shivam Kalra
  2026-02-16  8:45 ` Alice Ryhl
  4 siblings, 2 replies; 9+ messages in thread
From: Danilo Krummrich @ 2026-02-15 22:13 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Alice Ryhl
  Cc: shivamkalra98, Lorenzo Stoakes, Vlastimil Babka, Liam R. Howlett,
	Uladzislau Rezki, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Carlos Llamas, rust-for-linux, linux-kernel

On Sat Feb 14, 2026 at 9:35 PM CET, Shivam Kalra via B4 Relay wrote:
> Shivam Kalra (3):
>       rust: kvec: implement shrink_to for KVVec
>       rust: alloc: add KUnit tests for KVVec shrink_to

Greg, Alice, I assume you want to take this through the Android tree?

With the comments in patch 2 addressed,

Acked-by: Danilo Krummrich <dakr@kernel.org>

>       rust_binder: shrink all_procs when deregistering processes

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v5 0/3] rust: alloc: add KVVec shrinking method
  2026-02-15 22:13 ` [PATCH v5 0/3] rust: alloc: add KVVec shrinking method Danilo Krummrich
@ 2026-02-16  8:40   ` Alice Ryhl
  2026-02-16  9:41   ` Shivam Kalra
  1 sibling, 0 replies; 9+ messages in thread
From: Alice Ryhl @ 2026-02-16  8:40 UTC (permalink / raw)
  To: Danilo Krummrich
  Cc: Greg Kroah-Hartman, shivamkalra98, Lorenzo Stoakes,
	Vlastimil Babka, Liam R. Howlett, Uladzislau Rezki, Miguel Ojeda,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Arve Hjønnevåg,
	Todd Kjos, Christian Brauner, Carlos Llamas, rust-for-linux,
	linux-kernel

On Sun, Feb 15, 2026 at 11:13:15PM +0100, Danilo Krummrich wrote:
> On Sat Feb 14, 2026 at 9:35 PM CET, Shivam Kalra via B4 Relay wrote:
> > Shivam Kalra (3):
> >       rust: kvec: implement shrink_to for KVVec
> >       rust: alloc: add KUnit tests for KVVec shrink_to
> 
> Greg, Alice, I assume you want to take this through the Android tree?

Binder usually goes through char-misc, and yes I believe that would be
the simplest.

> With the comments in patch 2 addressed,
> 
> Acked-by: Danilo Krummrich <dakr@kernel.org>

Thanks!

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v5 0/3] rust: alloc: add KVVec shrinking method
  2026-02-14 20:35 [PATCH v5 0/3] rust: alloc: add KVVec shrinking method Shivam Kalra via B4 Relay
                   ` (3 preceding siblings ...)
  2026-02-15 22:13 ` [PATCH v5 0/3] rust: alloc: add KVVec shrinking method Danilo Krummrich
@ 2026-02-16  8:45 ` Alice Ryhl
  4 siblings, 0 replies; 9+ messages in thread
From: Alice Ryhl @ 2026-02-16  8:45 UTC (permalink / raw)
  To: shivamkalra98
  Cc: Danilo Krummrich, Lorenzo Stoakes, Vlastimil Babka,
	Liam R. Howlett, Uladzislau Rezki, Miguel Ojeda, Boqun Feng,
	Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Greg Kroah-Hartman, Arve Hjønnevåg,
	Todd Kjos, Christian Brauner, Carlos Llamas, rust-for-linux,
	linux-kernel

On Sun, Feb 15, 2026 at 02:05:20AM +0530, Shivam Kalra via B4 Relay wrote:
> This series adds a shrink_to() method to KVVec to allow explicit
> capacity reduction for memory reclamation.
> 
> Problem:
> When elements are removed from a KVVec, the allocated capacity is not
> reduced. The underlying C allocators (krealloc/kvrealloc) don't shrink
> memory in-place. This can cause significant memory waste in scenarios
> with variable workloads.

Overall looks good to me!

Reviewed-by: Alice Ryhl <aliceryhl@google.com>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v5 0/3] rust: alloc: add KVVec shrinking method
  2026-02-15 22:13 ` [PATCH v5 0/3] rust: alloc: add KVVec shrinking method Danilo Krummrich
  2026-02-16  8:40   ` Alice Ryhl
@ 2026-02-16  9:41   ` Shivam Kalra
  1 sibling, 0 replies; 9+ messages in thread
From: Shivam Kalra @ 2026-02-16  9:41 UTC (permalink / raw)
  To: Danilo Krummrich, Greg Kroah-Hartman, Alice Ryhl
  Cc: Lorenzo Stoakes, Vlastimil Babka, Liam R. Howlett,
	Uladzislau Rezki, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Carlos Llamas, rust-for-linux, linux-kernel

On 16/02/26 03:43, Danilo Krummrich wrote:
> On Sat Feb 14, 2026 at 9:35 PM CET, Shivam Kalra via B4 Relay wrote:
>> Shivam Kalra (3):
>>       rust: kvec: implement shrink_to for KVVec
>>       rust: alloc: add KUnit tests for KVVec shrink_to
> 
> Greg, Alice, I assume you want to take this through the Android tree?
> 
> With the comments in patch 2 addressed,
> 
> Acked-by: Danilo Krummrich <dakr@kernel.org>
> 
>>       rust_binder: shrink all_procs when deregistering processes
Thanks! Will fix both in v6.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-02-16  9:43 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-14 20:35 [PATCH v5 0/3] rust: alloc: add KVVec shrinking method Shivam Kalra via B4 Relay
2026-02-14 20:35 ` [PATCH v5 1/3] rust: kvec: implement shrink_to for KVVec Shivam Kalra via B4 Relay
2026-02-14 20:35 ` [PATCH v5 2/3] rust: alloc: add KUnit tests for KVVec shrink_to Shivam Kalra via B4 Relay
2026-02-15 22:10   ` Danilo Krummrich
2026-02-14 20:35 ` [PATCH v5 3/3] rust_binder: shrink all_procs when deregistering processes Shivam Kalra via B4 Relay
2026-02-15 22:13 ` [PATCH v5 0/3] rust: alloc: add KVVec shrinking method Danilo Krummrich
2026-02-16  8:40   ` Alice Ryhl
2026-02-16  9:41   ` Shivam Kalra
2026-02-16  8:45 ` Alice Ryhl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox