rust: alloc: kvec: implement AsPageIter for VVec

Implement AsPageIter for VVec; this allows to iterate and borrow the
backing pages of a VVec. This, for instance, is useful in combination
with VVec backing a scatterlist.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Tested-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
Link: https://lore.kernel.org/r/20250820145434.94745-8-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
Danilo Krummrich
2025-08-20 16:53:43 +02:00
parent 9acb4e630c
commit 779db37373

View File

@@ -3,10 +3,11 @@
//! Implementation of [`Vec`]. //! Implementation of [`Vec`].
use super::{ use super::{
allocator::{KVmalloc, Kmalloc, Vmalloc}, allocator::{KVmalloc, Kmalloc, Vmalloc, VmallocPageIter},
layout::ArrayLayout, layout::ArrayLayout,
AllocError, Allocator, Box, Flags, AllocError, Allocator, Box, Flags,
}; };
use crate::page::AsPageIter;
use core::{ use core::{
borrow::{Borrow, BorrowMut}, borrow::{Borrow, BorrowMut},
fmt, fmt,
@@ -1017,6 +1018,43 @@ where
} }
} }
/// # Examples
///
/// ```
/// # use kernel::prelude::*;
/// use kernel::alloc::allocator::VmallocPageIter;
/// use kernel::page::{AsPageIter, PAGE_SIZE};
///
/// let mut vec = VVec::<u8>::new();
///
/// assert!(vec.page_iter().next().is_none());
///
/// vec.reserve(PAGE_SIZE, GFP_KERNEL)?;
///
/// let page = vec.page_iter().next().expect("At least one page should be available.\n");
///
/// // SAFETY: There is no concurrent read or write to the same page.
/// unsafe { page.fill_zero_raw(0, PAGE_SIZE)? };
/// # Ok::<(), Error>(())
/// ```
impl<T> AsPageIter for VVec<T> {
type Iter<'a>
= VmallocPageIter<'a>
where
T: 'a;
fn page_iter(&mut self) -> Self::Iter<'_> {
let ptr = self.ptr.cast();
let size = self.layout.size();
// SAFETY:
// - `ptr` is a valid pointer to the beginning of a `Vmalloc` allocation.
// - `ptr` is guaranteed to be valid for the lifetime of `'a`.
// - `size` is the size of the `Vmalloc` allocation `ptr` points to.
unsafe { VmallocPageIter::new(ptr, size) }
}
}
/// An [`Iterator`] implementation for [`Vec`] that moves elements out of a vector. /// An [`Iterator`] implementation for [`Vec`] that moves elements out of a vector.
/// ///
/// This structure is created by the [`Vec::into_iter`] method on [`Vec`] (provided by the /// This structure is created by the [`Vec::into_iter`] method on [`Vec`] (provided by the