File Index
Files and directories
Sign in
FILE

iter.rs

File preview with syntax highlighting.

linux-6.19.14/rust/kernel/alloc/allocator/iter.rs RUST
  1// SPDX-License-Identifier: GPL-2.0
  2
  3use super::Vmalloc;
  4use crate::page;
  5use core::marker::PhantomData;
  6use core::ptr::NonNull;
  7
  8/// An [`Iterator`] of [`page::BorrowedPage`] items owned by a [`Vmalloc`] allocation.
  9///
 10/// # Guarantees
 11///
 12/// The pages iterated by the [`Iterator`] appear in the order as they are mapped in the CPU's
 13/// virtual address space ascendingly.
 14///
 15/// # Invariants
 16///
 17/// - `buf` is a valid and [`page::PAGE_SIZE`] aligned pointer into a [`Vmalloc`] allocation.
 18/// - `size` is the number of bytes from `buf` until the end of the [`Vmalloc`] allocation `buf`
 19///   points to.
 20pub struct VmallocPageIter<'a> {
 21    /// The base address of the [`Vmalloc`] buffer.
 22    buf: NonNull<u8>,
 23    /// The size of the buffer pointed to by `buf` in bytes.
 24    size: usize,
 25    /// The current page index of the [`Iterator`].
 26    index: usize,
 27    _p: PhantomData<page::BorrowedPage<'a>>,
 28}
 29
 30impl<'a> Iterator for VmallocPageIter<'a> {
 31    type Item = page::BorrowedPage<'a>;
 32
 33    fn next(&mut self) -> Option<Self::Item> {
 34        let offset = self.index.checked_mul(page::PAGE_SIZE)?;
 35
 36        // Even though `self.size()` may be smaller than `Self::page_count() * page::PAGE_SIZE`, it
 37        // is always a number between `(Self::page_count() - 1) * page::PAGE_SIZE` and
 38        // `Self::page_count() * page::PAGE_SIZE`, hence the check below is sufficient.
 39        if offset < self.size() {
 40            self.index += 1;
 41        } else {
 42            return None;
 43        }
 44
 45        // TODO: Use `NonNull::add()` instead, once the minimum supported compiler version is
 46        // bumped to 1.80 or later.
 47        //
 48        // SAFETY: `offset` is in the interval `[0, (self.page_count() - 1) * page::PAGE_SIZE]`,
 49        // hence the resulting pointer is guaranteed to be within the same allocation.
 50        let ptr = unsafe { self.buf.as_ptr().add(offset) };
 51
 52        // SAFETY: `ptr` is guaranteed to be non-null given that it is derived from `self.buf`.
 53        let ptr = unsafe { NonNull::new_unchecked(ptr) };
 54
 55        // SAFETY:
 56        // - `ptr` is a valid pointer to a `Vmalloc` allocation.
 57        // - `ptr` is valid for the duration of `'a`.
 58        Some(unsafe { Vmalloc::to_page(ptr) })
 59    }
 60
 61    fn size_hint(&self) -> (usize, Option<usize>) {
 62        let remaining = self.page_count().saturating_sub(self.index);
 63
 64        (remaining, Some(remaining))
 65    }
 66}
 67
 68impl<'a> VmallocPageIter<'a> {
 69    /// Creates a new [`VmallocPageIter`] instance.
 70    ///
 71    /// # Safety
 72    ///
 73    /// - `buf` must be a [`page::PAGE_SIZE`] aligned pointer into a [`Vmalloc`] allocation.
 74    /// - `buf` must be valid for at least the lifetime of `'a`.
 75    /// - `size` must be the number of bytes from `buf` until the end of the [`Vmalloc`] allocation
 76    ///   `buf` points to.
 77    pub unsafe fn new(buf: NonNull<u8>, size: usize) -> Self {
 78        // INVARIANT: By the safety requirements, `buf` is a valid and `page::PAGE_SIZE` aligned
 79        // pointer into a [`Vmalloc`] allocation.
 80        Self {
 81            buf,
 82            size,
 83            index: 0,
 84            _p: PhantomData,
 85        }
 86    }
 87
 88    /// Returns the size of the backing [`Vmalloc`] allocation in bytes.
 89    ///
 90    /// Note that this is the size the [`Vmalloc`] allocation has been allocated with. Hence, this
 91    /// number may be smaller than `[`Self::page_count`] * [`page::PAGE_SIZE`]`.
 92    #[inline]
 93    pub fn size(&self) -> usize {
 94        self.size
 95    }
 96
 97    /// Returns the number of pages owned by the backing [`Vmalloc`] allocation.
 98    #[inline]
 99    pub fn page_count(&self) -> usize {
100        self.size().div_ceil(page::PAGE_SIZE)
101    }
102}
~/ Read-only file preview.