On Thu, Aug 1, 2024 at 4:02 PM Benno Lossin <benno.lossin@xxxxxxxxx> wrote: > > On 01.08.24 14:58, Alice Ryhl wrote: > > diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs > > new file mode 100644 > > index 000000000000..ed2db893fb79 > > --- /dev/null > > +++ b/rust/kernel/mm.rs > > @@ -0,0 +1,337 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +// Copyright (C) 2024 Google LLC. > > + > > +//! Memory management. > > +//! > > +//! C header: [`include/linux/mm.h`](../../../../include/linux/mm.h) > > + > > +use crate::{ > > + bindings, > > + types::{ARef, AlwaysRefCounted, Opaque}, > > +}; > > + > > +use core::{ > > + ops::Deref, > > + ptr::{self, NonNull}, > > +}; > > + > > +pub mod virt; > > + > > +/// A wrapper for the kernel's `struct mm_struct`. > > +/// > > +/// Since `mm_users` may be zero, the associated address space may not exist anymore. You must use > > Can it also be the case that the space never existed to begin with? Then > I would write "the associated address space may not exist." > > Also I think it makes more sense to use "You can use [`mmget_not_zero`] > to be able to access the address space." instead of the second sentence. I'm not sure if it can be the case that the space never existed, but I'll reword. > > +/// [`mmget_not_zero`] before accessing the address space. > > +/// > > +/// The `ARef<Mm>` smart pointer holds an `mmgrab` refcount. Its destructor may sleep. > > +/// > > +/// # Invariants > > +/// > > +/// Values of this type are always refcounted. > > Would be good to record the refcount used in the invariant. Ok. > > +/// > > +/// [`mmget_not_zero`]: Mm::mmget_not_zero > > +pub struct Mm { > > + mm: Opaque<bindings::mm_struct>, > > +} > > + > > +// SAFETY: It is safe to call `mmdrop` on another thread than where `mmgrab` was called. > > +unsafe impl Send for Mm {} > > +// SAFETY: All methods on `Mm` can be called in parallel from several threads. > > +unsafe impl Sync for Mm {} > > + > > +// SAFETY: By the type invariants, this type is always refcounted. > > +unsafe impl AlwaysRefCounted for Mm { > > + fn inc_ref(&self) { > > + // SAFETY: The pointer is valid since self is a reference. > > + unsafe { bindings::mmgrab(self.as_raw()) }; > > + } > > + > > + unsafe fn dec_ref(obj: NonNull<Self>) { > > + // SAFETY: The caller is giving up their refcount. > > + unsafe { bindings::mmdrop(obj.cast().as_ptr()) }; > > + } > > +} > > + > > +/// A wrapper for the kernel's `struct mm_struct`. > > +/// > > +/// This type is used only when `mm_users` is known to be non-zero at compile-time. It can be used > > I find the "This type is used only when" a bit weird, what about "Like > an [`Mm`], but with non-zero `mm_users`."? Will reword. > > +/// to access the associated address space. > > +/// > > +/// The `ARef<MmWithUser>` smart pointer holds an `mmget` refcount. Its destructor may sleep. > > +/// > > +/// # Invariants > > +/// > > +/// Values of this type are always refcounted. The value of `mm_users` is non-zero. > > +#[repr(transparent)] > > +pub struct MmWithUser { > > + mm: Mm, > > +} > > + > > +// SAFETY: It is safe to call `mmput` on another thread than where `mmget` was called. > > +unsafe impl Send for MmWithUser {} > > +// SAFETY: All methods on `MmWithUser` can be called in parallel from several threads. > > +unsafe impl Sync for MmWithUser {} > > + > > +// SAFETY: By the type invariants, this type is always refcounted. > > +unsafe impl AlwaysRefCounted for MmWithUser { > > + fn inc_ref(&self) { > > + // SAFETY: The pointer is valid since self is a reference. > > + unsafe { bindings::mmget(self.as_raw()) }; > > + } > > + > > + unsafe fn dec_ref(obj: NonNull<Self>) { > > + // SAFETY: The caller is giving up their refcount. > > + unsafe { bindings::mmput(obj.cast().as_ptr()) }; > > + } > > +} > > + > > +// Make all `Mm` methods available on `MmWithUser`. > > +impl Deref for MmWithUser { > > + type Target = Mm; > > + > > + #[inline] > > + fn deref(&self) -> &Mm { > > + &self.mm > > + } > > +} > > + > > +/// A wrapper for the kernel's `struct mm_struct`. > > +/// > > +/// This type is identical to `MmWithUser` except that it uses `mmput_async` when dropping a > > +/// refcount. This means that the destructor of `ARef<MmWithUserAsync>` is safe to call in atomic > > +/// context. > > Missing Invariants. Hmm. Structs will inherit invariants from their fields, no? > > +#[repr(transparent)] > > +pub struct MmWithUserAsync { > > + mm: MmWithUser, > > +} > > + > > +// SAFETY: It is safe to call `mmput_async` on another thread than where `mmget` was called. > > +unsafe impl Send for MmWithUserAsync {} > > +// SAFETY: All methods on `MmWithUserAsync` can be called in parallel from several threads. > > +unsafe impl Sync for MmWithUserAsync {} > > + > > +// SAFETY: By the type invariants, this type is always refcounted. > > +unsafe impl AlwaysRefCounted for MmWithUserAsync { > > + fn inc_ref(&self) { > > + // SAFETY: The pointer is valid since self is a reference. > > + unsafe { bindings::mmget(self.as_raw()) }; > > + } > > + > > + unsafe fn dec_ref(obj: NonNull<Self>) { > > + // SAFETY: The caller is giving up their refcount. > > + unsafe { bindings::mmput_async(obj.cast().as_ptr()) }; > > + } > > +} > > + > > +// Make all `MmWithUser` methods available on `MmWithUserAsync`. > > +impl Deref for MmWithUserAsync { > > + type Target = MmWithUser; > > + > > + #[inline] > > + fn deref(&self) -> &MmWithUser { > > + &self.mm > > + } > > +} > > + > > +// These methods are safe to call even if `mm_users` is zero. > > +impl Mm { > > + /// Call `mmgrab` on `current.mm`. > > + #[inline] > > + pub fn mmgrab_current() -> Option<ARef<Mm>> { > > + // SAFETY: It's safe to get the `mm` field from current. > > + let mm = unsafe { > > + let current = bindings::get_current(); > > + (*current).mm > > + }; > > + > > + let mm = NonNull::new(mm)?; > > + > > + // SAFETY: We just checked that `mm` is not null. > > + unsafe { bindings::mmgrab(mm.as_ptr()) }; > > + > > + // SAFETY: We just created an `mmgrab` refcount. Layouts are compatible due to > > + // repr(transparent). > > + Some(unsafe { ARef::from_raw(mm.cast()) }) > > + } > > + > > + /// Returns a raw pointer to the inner `mm_struct`. > > + #[inline] > > + pub fn as_raw(&self) -> *mut bindings::mm_struct { > > + self.mm.get() > > + } > > + > > + /// Obtain a reference from a raw pointer. > > + /// > > + /// # Safety > > + /// > > + /// The caller must ensure that `ptr` points at an `mm_struct`, and that it is not deallocated > > + /// during the lifetime 'a. > > + #[inline] > > + pub unsafe fn from_raw_mm<'a>(ptr: *const bindings::mm_struct) -> &'a Mm { > > Why not just `from_raw`? See response to Danilo. Alice