Skip to contentSkip to conversation

rust: alloc: kvec doc example and allocator unit tests

PATCH Superseded Hui Zhu 5 participants 11 messages Jul 30, 2025 – Jul 31, 2025

Subsystems (2)

v6 of 8 Superseded Latest is v8 →

lore
Share & tools
lore

Hui Zhu

author
#0 lore raw

v6 cover rust: alloc: kvec doc example and allocator unit tests

From: Hui Zhu <[email protected]>

This patchset adds KUnit tests for allocator alignment guarantees and improves kvec documentation.

Patch 1 adds KUnit tests for verifying alignment guarantees in Rust kernel allocators. Tests cover Kmalloc, Vmalloc and KVmalloc with both standard (128B) and large page-aligned (8192B) allocations.

Patch 2 adds a practical usage example for KVec::as_slice method, showing how to create KVec, push elements and convert to a slice.

Both patches are co-developed with Geliang Tang. Based on [1]. Tested on x86_64 using KUnit.

Changelog:
v6:
According to the comments of Danilo, updated test for allocator.rs and allocator rebase onto [1].
v5:
According to the comments of Danilo, change to use generic struct and allocator Generics in allocator.rs.
v4:
According to the comments of, add the error check for push. v3:
According to the comments of Danilo and Boqun, move KVec test to doc example and move VBox to allocator unit tests.
v2:
According to the comments of Danilo, updated the commit to samples the usage of VBox and KVec.

[1] https://lore.kernel.org/lkml/[email protected]/

Hui Zhu (2):
rust: allocator: add KUnit tests for alignment guarantees
rust: alloc: kvec: add doc example for as_slice method

 rust/kernel/alloc/allocator.rs | 56 ++++++++++++++++++++++++++++++++++
 rust/kernel/alloc/kvec.rs      | 10 ++++++
 2 files changed, 66 insertions(+)
Signature · 1 line
2.43.0
author
#1 lore raw

PATCH v6 1/2 rust: allocator: add KUnit tests for alignment guarantees

From: Hui Zhu <[email protected]>

Add a test module to verify memory alignment guarantees for Rust kernel allocators.
The tests cover Kmalloc, Vmalloc and KVmalloc allocators with both standard and large page-aligned allocations.

Key features of the tests:
1. Creates alignment-constrained types:
- 128-byte aligned Blob
- 8192-byte (4-page) aligned LargeAlignBlob
2. Validates allocators using TestAlign helper which:
- Checks address alignment masks
- Supports uninitialized allocations
3. Tests all three allocators with both alignment requirements:
- Kmalloc with 128B and 8192B
- Vmalloc with 128B and 8192B
- KVmalloc with 128B and 8192B

---
 rust/kernel/alloc/allocator.rs | 56 ++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)
rust/kernel/alloc/allocator.rs +56 -0
index 63f271624428..1f173038cec9 100644
@@ -184,3 +184,59 @@ unsafe fn realloc(
         unsafe { ReallocFunc::KVREALLOC.call(ptr, layout, old_layout, flags, nid) }
     }
 }
+
+#[macros::kunit_tests(rust_allocator_kunit)]
+mod tests {
+    use super::*;
+    use core::mem::MaybeUninit;
+    use kernel::prelude::*;
+
+    #[test]
+    fn test_alignment() -> Result<()> {
+        const TEST_SIZE: usize = 1024;
+        const TEST_LARGE_ALIGN_SIZE: usize = kernel::page::PAGE_SIZE * 4;
+
+        // These two structs are used to test allocating aligned memory.
+        // they don't need to be accessed, so they're marked as dead_code.
+        #[expect(dead_code)]
+        #[repr(align(128))]
+        struct Blob([u8; TEST_SIZE]);
+        #[expect(dead_code)]
+        #[repr(align(8192))]
+        struct LargeAlignBlob([u8; TEST_LARGE_ALIGN_SIZE]);
+
+        struct TestAlign<T, A: Allocator>(Box<MaybeUninit<T>, A>);
+        impl<T, A: Allocator> TestAlign<T, A> {
+            fn new() -> Result<Self> {
+                Ok(Self(Box::<_, A>::new_uninit(GFP_KERNEL)?))
+            }
+
+            fn alignment_valid(&self, align: usize) -> bool {
+                assert!(align.is_power_of_two());
+
+                let addr = self.0.as_ptr() as usize;
+                addr & (align - 1) == 0
+            }
+        }
+
+        let ta = TestAlign::<Blob, Kmalloc>::new()?;
+        assert!(ta.alignment_valid(128));
+
+        let ta = TestAlign::<LargeAlignBlob, Kmalloc>::new()?;
+        assert!(ta.alignment_valid(8192));
+
+        let ta = TestAlign::<Blob, Vmalloc>::new()?;
+        assert!(ta.alignment_valid(128));
+
+        let ta = TestAlign::<LargeAlignBlob, Vmalloc>::new()?;
+        assert!(ta.alignment_valid(8192));
+
+        let ta = TestAlign::<Blob, KVmalloc>::new()?;
+        assert!(ta.alignment_valid(128));
+
+        let ta = TestAlign::<LargeAlignBlob, KVmalloc>::new()?;
+        assert!(ta.alignment_valid(8192));
+
+        Ok(())
+    }
+}
Signature · 1 line
2.43.0
maintainer Reviewed-by on v6 1/2
#2 lore raw

Re: [PATCH v6 1/2] rust: allocator: add KUnit tests for alignment guarantees

Quoted 19 lines · Hui Zhu

From: Hui Zhu <[email protected]>

Add a test module to verify memory alignment guarantees for Rust kernel allocators.
The tests cover Kmalloc, Vmalloc and KVmalloc allocators with both standard and large page-aligned allocations.

Key features of the tests:
1. Creates alignment-constrained types:
- 128-byte aligned Blob
- 8192-byte (4-page) aligned LargeAlignBlob
2. Validates allocators using TestAlign helper which:
- Checks address alignment masks
- Supports uninitialized allocations
3. Tests all three allocators with both alignment requirements:
- Kmalloc with 128B and 8192B
- Vmalloc with 128B and 8192B
- KVmalloc with 128B and 8192B

Quoted 3 lines
Reviewed-by on v6 1/2
#3 lore raw

Re: [PATCH v6 1/2] rust: allocator: add KUnit tests for alignment guarantees

In reply to Hui Zhu
Quoted 80 lines · Hui Zhu

From: Hui Zhu <[email protected]>

Add a test module to verify memory alignment guarantees for Rust kernel allocators.
The tests cover Kmalloc, Vmalloc and KVmalloc allocators with both standard and large page-aligned allocations.

Key features of the tests:
1. Creates alignment-constrained types:
- 128-byte aligned Blob
- 8192-byte (4-page) aligned LargeAlignBlob
2. Validates allocators using TestAlign helper which:
- Checks address alignment masks
- Supports uninitialized allocations
3. Tests all three allocators with both alignment requirements:
- Kmalloc with 128B and 8192B
- Vmalloc with 128B and 8192B
- KVmalloc with 128B and 8192B

---
  rust/kernel/alloc/allocator.rs | 56 ++++++++++++++++++++++++++++++++++
  1 file changed, 56 insertions(+)
rust/kernel/alloc/allocator.rs +46 -0
index 63f271624428..1f173038cec9 100644
@@ -184,3 +184,59 @@ unsafe fn realloc(
          unsafe { ReallocFunc::KVREALLOC.call(ptr, layout, old_layout, flags, nid) }
      }
  }
+
+#[macros::kunit_tests(rust_allocator_kunit)]
+mod tests {
+    use super::*;
+    use core::mem::MaybeUninit;
+    use kernel::prelude::*;
+
+    #[test]
+    fn test_alignment() -> Result<()> {
+        const TEST_SIZE: usize = 1024;
+        const TEST_LARGE_ALIGN_SIZE: usize = kernel::page::PAGE_SIZE * 4;
+
+        // These two structs are used to test allocating aligned memory.
+        // they don't need to be accessed, so they're marked as dead_code.
+        #[expect(dead_code)]
+        #[repr(align(128))]
+        struct Blob([u8; TEST_SIZE]);
+        #[expect(dead_code)]
+        #[repr(align(8192))]
+        struct LargeAlignBlob([u8; TEST_LARGE_ALIGN_SIZE]);
+
+        struct TestAlign<T, A: Allocator>(Box<MaybeUninit<T>, A>);
+        impl<T, A: Allocator> TestAlign<T, A> {
+            fn new() -> Result<Self> {
+                Ok(Self(Box::<_, A>::new_uninit(GFP_KERNEL)?))
+            }
+
+            fn alignment_valid(&self, align: usize) -> bool {
+                assert!(align.is_power_of_two());
+
+                let addr = self.0.as_ptr() as usize;
+                addr & (align - 1) == 0
+            }
+        }
+
+        let ta = TestAlign::<Blob, Kmalloc>::new()?;
+        assert!(ta.alignment_valid(128));
+
+        let ta = TestAlign::<LargeAlignBlob, Kmalloc>::new()?;
+        assert!(ta.alignment_valid(8192));
+
+        let ta = TestAlign::<Blob, Vmalloc>::new()?;
+        assert!(ta.alignment_valid(128));
+
+        let ta = TestAlign::<LargeAlignBlob, Vmalloc>::new()?;
+        assert!(ta.alignment_valid(8192));

rust/kernel/alloc/allocator.rs unsafe fn realloc( · line 242

Quoted 10 lines
rust/kernel/alloc/allocator.rs +10 -0
+
+        let ta = TestAlign::<Blob, KVmalloc>::new()?;
+        assert!(ta.alignment_valid(128));
+
+        let ta = TestAlign::<LargeAlignBlob, KVmalloc>::new()?;
+        assert!(ta.alignment_valid(8192));
+
+        Ok(())
+    }
+}
Signature · 2 lines
Thanks,
  Kunwu.Chan(Tao.Chan)
#4 lore raw

Re: [PATCH v6 1/2] rust: allocator: add KUnit tests for alignment guarantees

In reply to Hui Zhu
Quoted 2 lines · Hui Zhu

+#[macros::kunit_tests(rust_allocator_kunit)]

Is there any reason for the _kunit suffix? If not, then we should avoid suffixing _kunit to every suite name.

I see we already have rust_kernel_kunit, but that one is because it is the KUnit file itself.

There is also rust_kvec_kunit, but we should clean that one up.

Quoted 1 line

+ fn test_alignment() -> Result<()> {

-> Result since the prelude is available.

Quoted 1 line

+ fn alignment_valid(&self, align: usize) -> bool {

We typically prefix these with is_.

I would also call it is_aligned_to, to match the upstream Rust one, which we could perhaps use if it becomes stable.

Cheers,
Miguel

author
#5 lore raw

Re: [PATCH v6 1/2] rust: allocator: add KUnit tests for alignment guarantees

2025年7月30日 17:16, "Miguel Ojeda" <[email protected] mailto:[email protected]?to=%22Miguel%20Ojeda%22%20%3Cmiguel.ojeda.sandonis%40gmail.com%3E > 写到:

Quoted 20 lines · Hui Zhu
Quoted 4 lines

+#[macros::kunit_tests(rust_allocator_kunit)]

Is there any reason for the _kunit suffix? If not, then we should avoid suffixing _kunit to every suite name.

I see we already have rust_kernel_kunit, but that one is because it is the KUnit file itself.

There is also rust_kvec_kunit, but we should clean that one up.

Quoted 3 lines

+ fn test_alignment() -> Result<()> {

-> Result since the prelude is available.

Quoted 1 line
Quoted 7 lines
Quoted 2 lines

+ fn alignment_valid(&self, align: usize) -> bool {

We typically prefix these with is_.

I would also call it is_aligned_to, to match the upstream Rust one, which we could perhaps use if it becomes stable.

Hi Miguel,

I sent the v7 version according to your comments.

Thanks,
Hui

Quoted 3 lines

Cheers,
Miguel

author
#6 lore raw

PATCH v6 2/2 rust: alloc: kvec: add doc example for as_slice method

In reply to Hui Zhu

From: Hui Zhu <[email protected]>

Add a practical usage example to the documentation of KVec::as_slice() showing how to:
Create a new KVec.
Push elements into it.
Convert to a slice via as_slice().

---
 rust/kernel/alloc/kvec.rs | 10 ++++++++++
 1 file changed, 10 insertions(+)
rust/kernel/alloc/kvec.rs +10 -0
index 92d0ed3f302e..f57e08c64929 100644
@@ -224,6 +224,16 @@ unsafe fn dec_len(&mut self, count: usize) -> &mut [T] {
     }
 
     /// Returns a slice of the entire vector.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = KVec::new();
+    /// v.push(1, GFP_KERNEL)?;
+    /// v.push(2, GFP_KERNEL)?;
+    /// assert_eq!(v.as_slice(), &[1, 2]);
+    /// # Ok::<(), Error>(())
+    /// ```
     #[inline]
     pub fn as_slice(&self) -> &[T] {
         self
Signature · 1 line
2.43.0
maintainer Reviewed-by on v6 2/2
#7 lore raw

Re: [PATCH v6 2/2] rust: alloc: kvec: add doc example for as_slice method

Quoted 11 lines · Hui Zhu

From: Hui Zhu <[email protected]>

Add a practical usage example to the documentation of KVec::as_slice() showing how to:
Create a new KVec.
Push elements into it.
Convert to a slice via as_slice().

It looks like this did not change since v5 where I gave my

tag. Please make sure to include the tag in future versions if you have not made any changes.

Alice

author
#8 lore raw

Re: [PATCH v6 2/2] rust: alloc: kvec: add doc example for as_slice method

2025年7月30日 16:03, "Alice Ryhl" <[email protected] mailto:[email protected]?to=%22Alice%20Ryhl%22%20%3Caliceryhl%40google.com%3E > 写到:

Quoted 16 lines · Hui Zhu
Quoted 10 lines

From: Hui Zhu <[email protected]>

Add a practical usage example to the documentation of KVec::as_slice() showing how to:
Create a new KVec.
Push elements into it.
Convert to a slice via as_slice().

Quoted 4 lines
Quoted 6 lines

It looks like this did not change since v5 where I gave my

tag. Please make sure to include the tag in future versions if you have not made any changes.

Oops!
Sorry for that. Fixed in the v7 version.

Best,
Hui

Quoted 3 lines

Alice

Reviewed-by on v6 2/2
#9 lore raw

Re: [PATCH v6 2/2] rust: alloc: kvec: add doc example for as_slice method

In reply to Hui Zhu
Quoted 26 lines · Hui Zhu

From: Hui Zhu <[email protected]>

Add a practical usage example to the documentation of KVec::as_slice() showing how to:
Create a new KVec.
Push elements into it.
Convert to a slice via as_slice().

---
  rust/kernel/alloc/kvec.rs | 10 ++++++++++
  1 file changed, 10 insertions(+)
rust/kernel/alloc/kvec.rs +3 -0
index 92d0ed3f302e..f57e08c64929 100644
@@ -224,6 +224,16 @@ unsafe fn dec_len(&mut self, count: usize) -> &mut [T] {
      }
 
      /// Returns a slice of the entire vector.
+    ///
+    /// # Examples
+    ///

rust/kernel/alloc/kvec.rs unsafe fn dec_len(&mut self, count: usize) -> &mut [T] { · line 239

Quoted 10 lines
rust/kernel/alloc/kvec.rs +7 -0
+    /// ```
+    /// let mut v = KVec::new();
+    /// v.push(1, GFP_KERNEL)?;
+    /// v.push(2, GFP_KERNEL)?;
+    /// assert_eq!(v.as_slice(), &[1, 2]);
+    /// # Ok::<(), Error>(())
+    /// ```
      #[inline]
      pub fn as_slice(&self) -> &[T] {
          self

LGTM.

Signature · 2 lines
Thanks,
  Kunwu.Chan(Tao.Chan)
maintainer
#10 lore raw

Re: [PATCH v6 2/2] rust: alloc: kvec: add doc example for as_slice method

In reply to Hui Zhu
Quoted 11 lines · Hui Zhu

From: Hui Zhu <[email protected]>

Add a practical usage example to the documentation of KVec::as_slice() showing how to:
Create a new KVec.
Push elements into it.
Convert to a slice via as_slice().

Thanks -- I will pick this one up after -rc1 is out.