From nobody Sat Feb 7 22:21:15 2026 Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 905BB1DEFD4 for ; Fri, 22 Nov 2024 15:41:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290067; cv=none; b=gfodf1Sszb28UuHudA/Noh7mYd3cuN35t8eI1baWMDcF1XiYCXQlk/MX8vVY4bCg10J3U0YlWu+ZB0PLvnIpo9r7DwMRWJ6kW9znpdO1s4Hhx9QXW7Af638G207IdVQwS0aSndXRTz4IehI4sEUaHfcXwPLEWHZ11MhJyHZTN5s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290067; c=relaxed/simple; bh=ZPc1KRKfoIOZWtqnzIede0sGQwVP3YDeDd6Hc6TOsWM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=mi7X5riRiO74q14jPhbHiL+UmG3DEmp5IJI6z+872MNVuWG1gjD7LNQnhnshEvuUoAYk2VXA6KYMf150fltY85I3CbcWt9z/MrmKme2EqGI3nU03W9iD518CzUnm/5Dd2jFYYhhU1o8lq/Uv30tbn+c9ATi9Go1a4bRMBSTI1VI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Lt0cnq9R; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Lt0cnq9R" Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-6ea8794f354so38156757b3.2 for ; Fri, 22 Nov 2024 07:41:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732290064; x=1732894864; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=ZJFWlPcRbAWY+HnVngOyCc1o+97QXNSOMi5+R+xDQr4=; b=Lt0cnq9R6iq3maHztCDfQZsHPt3233C3ixwgL7BF8I5ny9y5A1VRKGMRn0848mHRd2 FogXvSH+dCZuPa/KQZlz/jClcCnVdx4CKfxrM8AUcr+1tvkdjk46B2CS8xkXcF4h/VNt UZW5z1NqrpVJ+e9Gv43BX0sp94RhAih0fRFCwEpMFMNrDXbEsorOfi7p1gvuxR5zIoYL y4lmBc/G42GG4UI5thkBUrHdjheHgYxtMTFAucYKoDQ9CLEmQHjw8wSGcPJN5YLGralW Vzw3MmndGIlBehceYO5ppYoQYwGYsSFLM34dlUC7z5vYET2VqZX+j4E0AW+dHMytAjUL 64bg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732290064; x=1732894864; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ZJFWlPcRbAWY+HnVngOyCc1o+97QXNSOMi5+R+xDQr4=; b=KcoTcTi5UFh0WU1IQCRdDQmkKaomEiNjFcTy5wGHUZ7fOsNv+d/N1dZL/wtEw106cb MirQlCOQR73xQdiJQShLrDTK0tfYAn4h3jVOH1lQzDXlIBCpvcjLeYs6/tJR7/Zidcgc /+d/M1LhM2dZ/7P+DrKQufgPm1eKvXDeB58OQyJH9yPvyn8B88TN9NyKuZwrhfvg0X1P EaskcGsvYYKwpgxnx8xGozrviIR+esutJsenO7U23g3nnpGThuJdV5rKPIy6pLcHkXMG 2ONRM9w517Pb7CMiRApauBYH7xgNsYVmAo4Egs9YVtHZShMQNd14s9X9hJeGa911Be10 oxyw== X-Forwarded-Encrypted: i=1; AJvYcCVpKpY7g7axQPH1YDw3LxfX9xQWsQ/WJsNiD+LYN/KhdKcuc+lD8bXHSLJO9HmZVp3OIC1sNhBSrMZycZs=@vger.kernel.org X-Gm-Message-State: AOJu0YxB6pTSogEhpLLqefA+sFhAnuZorZeLeaKqi8Sb3EpXjIePxX/x NKQn6DnY7lAzHJGY6rB93YwYvRuRq19ybv/5fzyTc0S048H4MPcdTksDHHyAatKoxP6YT/nEx+G qjPT0SsivPi72Cg== X-Google-Smtp-Source: AGHT+IFkONJC35kmfVY70U61nS/i2+8qUNS80u+/hoQsPbcnJf4FyJ3hfmZEVlFS1n5cWkqU0f6+UfL+LNXTVJs= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:a05:690c:680d:b0:6ee:b693:f752 with SMTP id 00721157ae682-6eee0777adfmr474527b3.0.1732290064561; Fri, 22 Nov 2024 07:41:04 -0800 (PST) Date: Fri, 22 Nov 2024 15:40:26 +0000 In-Reply-To: <20241122-vma-v9-0-7127bfcdd54e@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241122-vma-v9-0-7127bfcdd54e@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=9971; i=aliceryhl@google.com; h=from:subject:message-id; bh=ZPc1KRKfoIOZWtqnzIede0sGQwVP3YDeDd6Hc6TOsWM=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnQKYHu02lowltad/mpq8VFaO/SbmENjK7ouQqb BP+7GBjeceJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZ0CmBwAKCRAEWL7uWMY5 RtBIEACzoJXZvz8inFVeNuo4OnCxriwsgPHZvem8VJonDGvKOqY3hV8gdgEW0K8ZCRVi3FxkX6Q rhi2LU17e0tNyuNS/fPXzgTVtlQ+uePX+T16VcOwD6Tok3wwoFlgJFYP9rkgdXCwPbTP1RDxVZI O0KP5gnzotaIObWIAXjiInjRdZzTbu3YtmSadyCpxmsvplUP30jlZPPQEtB8IdO9lXBfN+aoekT 8ol3fX/5me6J/ORV/A9ejQWpWz3GgcyhCfe7Z+y/+7cvWVFPxs3arcjCc0HMHPLabcK0RClafYY JiNexDK8yqS0gGZ+aYr+2c7FhCwv+6Klck+F9LsSSLgiXKK3VxKaFYAqAt/H5ketvAtoyPYcwIf Jjv6yuP4SQ9Js1cuTPVfq+ecqT60ApH2hc8GZnQ4Kd9UjBnMePsRewrTf5Osa1l9sfU4RCT8Wtx V6epoDSENmIwUkovL8UmHv18xLKpQCWU7aWYAxZuyjsBx8wxUpBAh+sDxz1MHYXLAiYqfNPDeyZ GoQ0KMDpW3H2jq+9YhKTCXVo+6Q85RXhvMNZcA5+oj1eki94TSGdEl13UC6kuaNaME/ROr2jR0N ljH+qZ+PVCKuKW6ETcGvkIkZ3tCYAlCN4p1AtzRwK5nz1lGdMpgjtgc77S7WlWJXRLmw0AIzo2M B1pjqpbr9pI51IQ== X-Mailer: b4 0.13.0 Message-ID: <20241122-vma-v9-1-7127bfcdd54e@google.com> Subject: [PATCH v9 1/8] mm: rust: add abstraction for struct mm_struct From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner , Jann Horn , Suren Baghdasaryan Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable These abstractions allow you to reference a `struct mm_struct` using both mmgrab and mmget refcounts. This is done using two Rust types: * Mm - represents an mm_struct where you don't know anything about the value of mm_users. * MmWithUser - represents an mm_struct where you know at compile time that mm_users is non-zero. This allows us to encode in the type system whether a method requires that mm_users is non-zero or not. For instance, you can always call `mmget_not_zero` but you can only call `mmap_read_lock` when mm_users is non-zero. It's possible to access current->mm without a refcount increment, but that is added in a later patch of this series. Signed-off-by: Alice Ryhl Acked-by: Lorenzo Stoakes (for mm bits) --- rust/helpers/helpers.c | 1 + rust/helpers/mm.c | 39 +++++++++ rust/kernel/lib.rs | 1 + rust/kernel/mm.rs | 219 +++++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 260 insertions(+) diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 6d90afd38c40..2ee3af594633 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -15,6 +15,7 @@ #include "err.c" #include "fs.c" #include "kunit.c" +#include "mm.c" #include "mutex.c" #include "page.c" #include "rbtree.c" diff --git a/rust/helpers/mm.c b/rust/helpers/mm.c new file mode 100644 index 000000000000..7201747a5d31 --- /dev/null +++ b/rust/helpers/mm.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include + +void rust_helper_mmgrab(struct mm_struct *mm) +{ + mmgrab(mm); +} + +void rust_helper_mmdrop(struct mm_struct *mm) +{ + mmdrop(mm); +} + +void rust_helper_mmget(struct mm_struct *mm) +{ + mmget(mm); +} + +bool rust_helper_mmget_not_zero(struct mm_struct *mm) +{ + return mmget_not_zero(mm); +} + +void rust_helper_mmap_read_lock(struct mm_struct *mm) +{ + mmap_read_lock(mm); +} + +bool rust_helper_mmap_read_trylock(struct mm_struct *mm) +{ + return mmap_read_trylock(mm); +} + +void rust_helper_mmap_read_unlock(struct mm_struct *mm) +{ + mmap_read_unlock(mm); +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index bf98caa6d6a5..104e619f5dbd 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -45,6 +45,7 @@ pub mod kunit; pub mod list; pub mod miscdevice; +pub mod mm; #[cfg(CONFIG_NET)] pub mod net; pub mod page; diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs new file mode 100644 index 000000000000..84cba581edaa --- /dev/null +++ b/rust/kernel/mm.rs @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (C) 2024 Google LLC. + +//! Memory management. +//! +//! C header: [`include/linux/mm.h`](srctree/include/linux/mm.h) + +use crate::{ + bindings, + types::{ARef, AlwaysRefCounted, NotThreadSafe, Opaque}, +}; +use core::{ops::Deref, ptr::NonNull}; + +/// A wrapper for the kernel's `struct mm_struct`. +/// +/// Since `mm_users` may be zero, the associated address space may not exi= st anymore. You can use +/// [`mmget_not_zero`] to be able to access the address space. +/// +/// The `ARef` smart pointer holds an `mmgrab` refcount. Its destructo= r may sleep. +/// +/// # Invariants +/// +/// Values of this type are always refcounted using `mmgrab`. +/// +/// [`mmget_not_zero`]: Mm::mmget_not_zero +#[repr(transparent)] +pub struct Mm { + mm: Opaque, +} + +// SAFETY: It is safe to call `mmdrop` on another thread than where `mmgra= b` was called. +unsafe impl Send for Mm {} +// SAFETY: All methods on `Mm` can be called in parallel from several thre= ads. +unsafe impl Sync for Mm {} + +// SAFETY: By the type invariants, this type is always refcounted. +unsafe impl AlwaysRefCounted for Mm { + #[inline] + fn inc_ref(&self) { + // SAFETY: The pointer is valid since self is a reference. + unsafe { bindings::mmgrab(self.as_raw()) }; + } + + #[inline] + unsafe fn dec_ref(obj: NonNull) { + // 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 like [`Mm`], but with non-zero `mm_users`. It can only be= used when `mm_users` can +/// be proven to be non-zero at compile-time, usually because the relevant= code holds an `mmget` +/// refcount. It can be used to access the associated address space. +/// +/// The `ARef` smart pointer holds an `mmget` refcount. Its de= structor may sleep. +/// +/// # Invariants +/// +/// Values of this type are always refcounted using `mmget`. 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 seve= ral threads. +unsafe impl Sync for MmWithUser {} + +// SAFETY: By the type invariants, this type is always refcounted. +unsafe impl AlwaysRefCounted for MmWithUser { + #[inline] + fn inc_ref(&self) { + // SAFETY: The pointer is valid since self is a reference. + unsafe { bindings::mmget(self.as_raw()) }; + } + + #[inline] + unsafe fn dec_ref(obj: NonNull) { + // 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 =3D Mm; + + #[inline] + fn deref(&self) -> &Mm { + &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> { + // SAFETY: It's safe to get the `mm` field from current. + let mm =3D unsafe { + let current =3D bindings::get_current(); + (*current).mm + }; + + if mm.is_null() { + return None; + } + + // SAFETY: The value of `current->mm` is guaranteed to be null or = a valid `mm_struct`. We + // just checked that it's not null. Furthermore, the returned `&Mm= ` is valid only for the + // duration of this function, and `current->mm` will stay valid fo= r that long. + let mm =3D unsafe { Mm::from_raw(mm) }; + + // This increments the refcount using `mmgrab`. + Some(ARef::from(mm)) + } + + /// 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 th= at it is not deallocated + /// during the lifetime 'a. + #[inline] + pub unsafe fn from_raw<'a>(ptr: *const bindings::mm_struct) -> &'a Mm { + // SAFETY: Caller promises that the pointer is valid for 'a. Layou= ts are compatible due to + // repr(transparent). + unsafe { &*ptr.cast() } + } + + /// Calls `mmget_not_zero` and returns a handle if it succeeds. + #[inline] + pub fn mmget_not_zero(&self) -> Option> { + // SAFETY: The pointer is valid since self is a reference. + let success =3D unsafe { bindings::mmget_not_zero(self.as_raw()) }; + + if success { + // SAFETY: We just created an `mmget` refcount. + Some(unsafe { ARef::from_raw(NonNull::new_unchecked(self.as_ra= w().cast())) }) + } else { + None + } + } +} + +// These methods require `mm_users` to be non-zero. +impl MmWithUser { + /// Obtain a reference from a raw pointer. + /// + /// # Safety + /// + /// The caller must ensure that `ptr` points at an `mm_struct`, and th= at `mm_users` remains + /// non-zero for the duration of the lifetime 'a. + #[inline] + pub unsafe fn from_raw<'a>(ptr: *const bindings::mm_struct) -> &'a MmW= ithUser { + // SAFETY: Caller promises that the pointer is valid for 'a. The l= ayout is compatible due + // to repr(transparent). + unsafe { &*ptr.cast() } + } + + /// Lock the mmap read lock. + #[inline] + pub fn mmap_read_lock(&self) -> MmapReadGuard<'_> { + // SAFETY: The pointer is valid since self is a reference. + unsafe { bindings::mmap_read_lock(self.as_raw()) }; + + // INVARIANT: We just acquired the read lock. + MmapReadGuard { + mm: self, + _nts: NotThreadSafe, + } + } + + /// Try to lock the mmap read lock. + #[inline] + pub fn mmap_read_trylock(&self) -> Option> { + // SAFETY: The pointer is valid since self is a reference. + let success =3D unsafe { bindings::mmap_read_trylock(self.as_raw()= ) }; + + if success { + // INVARIANT: We just acquired the read lock. + Some(MmapReadGuard { + mm: self, + _nts: NotThreadSafe, + }) + } else { + None + } + } +} + +/// A guard for the mmap read lock. +/// +/// # Invariants +/// +/// This `MmapReadGuard` guard owns the mmap read lock. +pub struct MmapReadGuard<'a> { + mm: &'a MmWithUser, + // `mmap_read_lock` and `mmap_read_unlock` must be called on the same = thread + _nts: NotThreadSafe, +} + +impl Drop for MmapReadGuard<'_> { + #[inline] + fn drop(&mut self) { + // SAFETY: We hold the read lock by the type invariants. + unsafe { bindings::mmap_read_unlock(self.mm.as_raw()) }; + } +} --=20 2.47.0.371.ga323438b13-goog From nobody Sat Feb 7 22:21:15 2026 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 71904138490 for ; Fri, 22 Nov 2024 15:41:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290070; cv=none; b=vDdnEknamHcRun+k0Y4TN9a2gPWbgfV/E2sH9aGrW5bSZ9l/rtfV1pWKVuAjL4YHPsxgoX7v4QSA42Q2Cw7kpTplsrqxNi7j18xVMiSl1temW8RlteBEyVAIE6eM7W2YUj+VG0OEwppUunAVLaJg5oEUsev4pfOD3QjoSJt16Ww= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290070; c=relaxed/simple; bh=r818IxuzXbN9g3c4yrMD7Y71e/4bceEXKMyljx6a6J0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ZvYOR+aWlEshDv8pmM3PsCvaijxbLvW3IacUlilJEnzqlM1GTGWZNceOkSQPhZGib/atDG0voQY3pqKxApmADzxfEwiwJzozT7PKrkdGZBt900sIMq9zBxcpRh/b1Uihr7BfSCpNa1z0llbC1NeOcHFKgV2dYL41M+RMcspIY2M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=mlaQhNFO; arc=none smtp.client-ip=209.85.128.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="mlaQhNFO" Received: by mail-wm1-f73.google.com with SMTP id 5b1f17b1804b1-4315dd8fe7fso19710025e9.3 for ; Fri, 22 Nov 2024 07:41:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732290067; x=1732894867; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=rpRgqzz82sEijd8ek2p3HLExnZlmTISx521fYTMYg7A=; b=mlaQhNFO+vrhYmlDCOi/LjUxjDeKols9SiJGVNb2gJ9XSsV7PXR4GSGbD/nS0g7GVi pgAgFRy1/vmOpQG0Ng2d4gOJJdhDeq8KeE9ONahjlSqKEiEggynsCC9lPuuacXhqt5ew 0ai15AOcQSFTHP+gc7NIsvO3H5SaJWY4w3a7sH4a5HnH1E/avZxsloDSQgcNHeiWUWOO R1nmZH8i0mn6KadzSsAoJW7AbSLCSAbXBKgJg5iA8rqOEZWSdBvlos2KlDxEoBcSVNJN SiybGSfvhM6xrEn2cyEOMhvE9/UVysdoeBI7jRa2p2Q0ymbc88QzZkU0uOj4vhSt26Ae aJTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732290067; x=1732894867; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=rpRgqzz82sEijd8ek2p3HLExnZlmTISx521fYTMYg7A=; b=mgF/q6faRUsBoq+DAZBp2JDqPtDqdr7IfMdqvjwI306pQjTcAo+INOFidjvUyWJdZc T14KmNj3Mr3U3WGqP/rBDvls0MxuLtT1E7yUqTCNdSAUeLrKPejIf9wsrhakCD0YhovH 40MrhZm2eFXcE15BJt+H6hrDoRIUc+0Zmn/izNP1/vShJiskdkPc2fUq77rjZFIu7NLh mNrazsBSAzM/lpNfhU9itAWcbIHpxSMhvP50zizYdyNNVslsH+/smdT0j8wgjQEQFVLQ E12UGmbWVpNDHKdEMgF9prgpjS/orEfRtluDRob8P/eRLKMQOVFFGuEB0f6eTr26VBUV 2Tcw== X-Forwarded-Encrypted: i=1; AJvYcCVZ/oVs1UIJ4ETEb6U/tisdzIzWO+ZkpPk8ZufuCqwvCa+ufYlXE98UjGQ/6aJGbnPhXWeRMu/a40+n1Ak=@vger.kernel.org X-Gm-Message-State: AOJu0YzbOwCsdXVpUWfqir7dXFqdwPAVrP66ldDt3X8kN7TNuD6DHdB3 nWsoFXKlcPAp+KIfmf6JduOoMhzTQVfAELOte2qJ5hlww+eI0QT1/njzSciv7+XxjDKJ4KMFEmp tPkZhCFhz0xqR9w== X-Google-Smtp-Source: AGHT+IESpHOo7osW11QO7Begd6/hgV+HnuolBUZ1nG+UDTyG0tnysPZ8TSCOWeW0XPKFP+U93HN/frQCkrDDEt4= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:a05:600c:1d0f:b0:42e:e66c:2a8e with SMTP id 5b1f17b1804b1-433ce4fa122mr290465e9.7.1732290066790; Fri, 22 Nov 2024 07:41:06 -0800 (PST) Date: Fri, 22 Nov 2024 15:40:27 +0000 In-Reply-To: <20241122-vma-v9-0-7127bfcdd54e@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241122-vma-v9-0-7127bfcdd54e@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=9346; i=aliceryhl@google.com; h=from:subject:message-id; bh=r818IxuzXbN9g3c4yrMD7Y71e/4bceEXKMyljx6a6J0=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnQKYH5R8PxJfDPHVIRhFqASmlS4/vOqLyQrhYP 00O1+uub3yJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZ0CmBwAKCRAEWL7uWMY5 RthAD/4+eTK7BgZe7rEzEuKSggCjNmJFDiXSil0wpt6Mtne5FMxrKaoPhFbPYUG7/eQKsmKd229 R+9N4RwgUgUz9BDTGtPkfqyzHqDWGgcDvh2HBj182rXM5D8w74KVjyOaD6qLk6K4zdAZxXKjbfQ 2vVRpOmJfMVsNxsv86dNQ+D98nJ0LmV2m6gqctO1QAIsXh38mtiOMuvFDh4NlHe0qyLeQp/aoD/ t8PsiCifW8wxZl5nfaOS1E4RuxMvOM2dxx0zrqWIfLMAE2RlhCrZpMYwnwVifnlvhRljlRmkbPX XFFk49kIp7UkagsYcfTJLpdeEIJlv/scIG8ko6s2WuT8XvSQOL14tgt8d2W1Z88SQD6++dY432o POxTp6FvrQbGURx2KiscUqumI4RiGASEFAjaBLWjk8j1qDcBDUp0nz1E1sOuukO9ibjVE61txXK PnGgib++npZ5+cYCldHT/A22ixyl9VwI3s0+iUGGJlJo1Tu7sqjaLd42Az9hG6a0PTW4Q5kXVcE Hsh7yvtZqWvj2o5XbjW9n2WGPZnQFv07376GF34phwW9EqaYwjLbjjHEGwiBQ2PpaL/Z4CgHc52 I48IUA9YXGDW+Vbed1yYkq9UwLdrLtszSN3Nvb9VOK6rEHAtc/liw2mXu9jYxYry7ThWaXmPpnx c1Ug0Ul61WNzz6A== X-Mailer: b4 0.13.0 Message-ID: <20241122-vma-v9-2-7127bfcdd54e@google.com> Subject: [PATCH v9 2/8] mm: rust: add vm_area_struct methods that require read access From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner , Jann Horn , Suren Baghdasaryan Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable This adds a type called VmAreaRef which is used when referencing a vma that you have read access to. Here, read access means that you hold either the mmap read lock or the vma read lock (or stronger). Additionally, a vma_lookup method is added to the mmap read guard, which enables you to obtain a &VmAreaRef in safe Rust code. This patch only provides a way to lock the mmap read lock, but a follow-up patch also provides a way to just lock the vma read lock. Acked-by: Lorenzo Stoakes (for mm bits) Signed-off-by: Alice Ryhl Reviewed-by: Jann Horn --- rust/helpers/mm.c | 6 ++ rust/kernel/mm.rs | 21 ++++++ rust/kernel/mm/virt.rs | 176 +++++++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 203 insertions(+) diff --git a/rust/helpers/mm.c b/rust/helpers/mm.c index 7201747a5d31..7b72eb065a3e 100644 --- a/rust/helpers/mm.c +++ b/rust/helpers/mm.c @@ -37,3 +37,9 @@ void rust_helper_mmap_read_unlock(struct mm_struct *mm) { mmap_read_unlock(mm); } + +struct vm_area_struct *rust_helper_vma_lookup(struct mm_struct *mm, + unsigned long addr) +{ + return vma_lookup(mm, addr); +} diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs index 84cba581edaa..ace8e7d57afe 100644 --- a/rust/kernel/mm.rs +++ b/rust/kernel/mm.rs @@ -12,6 +12,8 @@ }; use core::{ops::Deref, ptr::NonNull}; =20 +pub mod virt; + /// A wrapper for the kernel's `struct mm_struct`. /// /// Since `mm_users` may be zero, the associated address space may not exi= st anymore. You can use @@ -210,6 +212,25 @@ pub struct MmapReadGuard<'a> { _nts: NotThreadSafe, } =20 +impl<'a> MmapReadGuard<'a> { + /// Look up a vma at the given address. + #[inline] + pub fn vma_lookup(&self, vma_addr: usize) -> Option<&virt::VmAreaRef> { + // SAFETY: We hold a reference to the mm, so the pointer must be v= alid. Any value is okay + // for `vma_addr`. + let vma =3D unsafe { bindings::vma_lookup(self.mm.as_raw(), vma_ad= dr as _) }; + + if vma.is_null() { + None + } else { + // SAFETY: We just checked that a vma was found, so the pointe= r is valid. Furthermore, + // the returned area will borrow from this read lock guard, so= it can only be used + // while the mmap read lock is still held. + unsafe { Some(virt::VmAreaRef::from_raw(vma)) } + } + } +} + impl Drop for MmapReadGuard<'_> { #[inline] fn drop(&mut self) { diff --git a/rust/kernel/mm/virt.rs b/rust/kernel/mm/virt.rs new file mode 100644 index 000000000000..6df145fea128 --- /dev/null +++ b/rust/kernel/mm/virt.rs @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (C) 2024 Google LLC. + +//! Virtual memory. + +use crate::{bindings, types::Opaque}; + +/// A wrapper for the kernel's `struct vm_area_struct` with read access. +/// +/// It represents an area of virtual memory. +/// +/// # Invariants +/// +/// The caller must hold the mmap read lock or the vma read lock. +#[repr(transparent)] +pub struct VmAreaRef { + vma: Opaque, +} + +// Methods you can call when holding the mmap or vma read lock (or strong)= . They must be usable no +// matter what the vma flags are. +impl VmAreaRef { + /// Access a virtual memory area given a raw pointer. + /// + /// # Safety + /// + /// Callers must ensure that `vma` is valid for the duration of 'a, an= d that the mmap or vma + /// read lock (or stronger) is held for at least the duration of 'a. + #[inline] + pub unsafe fn from_raw<'a>(vma: *const bindings::vm_area_struct) -> &'= a Self { + // SAFETY: The caller ensures that the invariants are satisfied fo= r the duration of 'a. + unsafe { &*vma.cast() } + } + + /// Returns a raw pointer to this area. + #[inline] + pub fn as_ptr(&self) -> *mut bindings::vm_area_struct { + self.vma.get() + } + + /// Returns the flags associated with the virtual memory area. + /// + /// The possible flags are a combination of the constants in [`flags`]. + #[inline] + pub fn flags(&self) -> vm_flags_t { + // SAFETY: By the type invariants, the caller holds at least the m= map read lock, so this + // access is not a data race. + unsafe { (*self.as_ptr()).__bindgen_anon_2.vm_flags as _ } + } + + /// Returns the (inclusive) start address of the virtual memory area. + #[inline] + pub fn start(&self) -> usize { + // SAFETY: By the type invariants, the caller holds at least the m= map read lock, so this + // access is not a data race. + unsafe { (*self.as_ptr()).__bindgen_anon_1.__bindgen_anon_1.vm_sta= rt as _ } + } + + /// Returns the (exclusive) end address of the virtual memory area. + #[inline] + pub fn end(&self) -> usize { + // SAFETY: By the type invariants, the caller holds at least the m= map read lock, so this + // access is not a data race. + unsafe { (*self.as_ptr()).__bindgen_anon_1.__bindgen_anon_1.vm_end= as _ } + } + + /// Zap pages in the given page range. + /// + /// This clears page table mappings for the range at the leaf level, l= eaving all other page + /// tables intact, and freeing any memory referenced by the VMA in thi= s range. That is, + /// anonymous memory is completely freed, file-backed memory has its r= eference count on page + /// cache folio's dropped, any dirty data will still be written back t= o disk as usual. + #[inline] + pub fn zap_page_range_single(&self, address: usize, size: usize) { + // SAFETY: By the type invariants, the caller has read access to t= his VMA, which is + // sufficient for this method call. This method has no requirement= s on the vma flags. Any + // value of `address` and `size` is allowed. + unsafe { + bindings::zap_page_range_single( + self.as_ptr(), + address as _, + size as _, + core::ptr::null_mut(), + ) + }; + } +} + +/// The integer type used for vma flags. +#[doc(inline)] +pub use bindings::vm_flags_t; + +/// All possible flags for [`VmAreaRef`]. +pub mod flags { + use super::vm_flags_t; + use crate::bindings; + + /// No flags are set. + pub const NONE: vm_flags_t =3D bindings::VM_NONE as _; + + /// Mapping allows reads. + pub const READ: vm_flags_t =3D bindings::VM_READ as _; + + /// Mapping allows writes. + pub const WRITE: vm_flags_t =3D bindings::VM_WRITE as _; + + /// Mapping allows execution. + pub const EXEC: vm_flags_t =3D bindings::VM_EXEC as _; + + /// Mapping is shared. + pub const SHARED: vm_flags_t =3D bindings::VM_SHARED as _; + + /// Mapping may be updated to allow reads. + pub const MAYREAD: vm_flags_t =3D bindings::VM_MAYREAD as _; + + /// Mapping may be updated to allow writes. + pub const MAYWRITE: vm_flags_t =3D bindings::VM_MAYWRITE as _; + + /// Mapping may be updated to allow execution. + pub const MAYEXEC: vm_flags_t =3D bindings::VM_MAYEXEC as _; + + /// Mapping may be updated to be shared. + pub const MAYSHARE: vm_flags_t =3D bindings::VM_MAYSHARE as _; + + /// Page-ranges managed without `struct page`, just pure PFN. + pub const PFNMAP: vm_flags_t =3D bindings::VM_PFNMAP as _; + + /// Memory mapped I/O or similar. + pub const IO: vm_flags_t =3D bindings::VM_IO as _; + + /// Do not copy this vma on fork. + pub const DONTCOPY: vm_flags_t =3D bindings::VM_DONTCOPY as _; + + /// Cannot expand with mremap(). + pub const DONTEXPAND: vm_flags_t =3D bindings::VM_DONTEXPAND as _; + + /// Lock the pages covered when they are faulted in. + pub const LOCKONFAULT: vm_flags_t =3D bindings::VM_LOCKONFAULT as _; + + /// Is a VM accounted object. + pub const ACCOUNT: vm_flags_t =3D bindings::VM_ACCOUNT as _; + + /// Should the VM suppress accounting. + pub const NORESERVE: vm_flags_t =3D bindings::VM_NORESERVE as _; + + /// Huge TLB Page VM. + pub const HUGETLB: vm_flags_t =3D bindings::VM_HUGETLB as _; + + /// Synchronous page faults. (DAX-specific) + pub const SYNC: vm_flags_t =3D bindings::VM_SYNC as _; + + /// Architecture-specific flag. + pub const ARCH_1: vm_flags_t =3D bindings::VM_ARCH_1 as _; + + /// Wipe VMA contents in child on fork. + pub const WIPEONFORK: vm_flags_t =3D bindings::VM_WIPEONFORK as _; + + /// Do not include in the core dump. + pub const DONTDUMP: vm_flags_t =3D bindings::VM_DONTDUMP as _; + + /// Not soft dirty clean area. + pub const SOFTDIRTY: vm_flags_t =3D bindings::VM_SOFTDIRTY as _; + + /// Can contain `struct page` and pure PFN pages. + pub const MIXEDMAP: vm_flags_t =3D bindings::VM_MIXEDMAP as _; + + /// MADV_HUGEPAGE marked this vma. + pub const HUGEPAGE: vm_flags_t =3D bindings::VM_HUGEPAGE as _; + + /// MADV_NOHUGEPAGE marked this vma. + pub const NOHUGEPAGE: vm_flags_t =3D bindings::VM_NOHUGEPAGE as _; + + /// KSM may merge identical pages. + pub const MERGEABLE: vm_flags_t =3D bindings::VM_MERGEABLE as _; +} --=20 2.47.0.371.ga323438b13-goog From nobody Sat Feb 7 22:21:15 2026 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8EAE81DF738 for ; Fri, 22 Nov 2024 15:41:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290072; cv=none; b=dTi4GlrpgOwU/JKPsORus7Tapiv9Q8zNk12Yft6Glol12TApjYLogs6xl1pg28kzAq7SgMj8LPrufgU6hhNn7F5UqTCKjCeIWJlE2M47q8QdCvk4DdKV6Wk7SwT26Z1i4mPxEbZ2qWS2xhgdSeyRIuJ+Yb3MONiwQaoH7MbrW+s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290072; c=relaxed/simple; bh=0kJbDQ2R2LaDZDdpCyVYpygYX3kC3nlpmnRFMMkub60=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=nTpV6wsLKRzRg95s/fn3X9+r2F0Il5gll6pj1ypx/c+Vq2N2nbMqkpOf7tnVOMyVYuro8HzSxxYpIpEHQLgm03EhbytnJ4zUcrL0vVCyGf0KpZ/HwOddsEtFroTVM6FahHcI9xym9p35AV4Ydb21u5X9AoduBe7v6/zPiNpIL1s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=32NE2WEQ; arc=none smtp.client-ip=209.85.128.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="32NE2WEQ" Received: by mail-wm1-f73.google.com with SMTP id 5b1f17b1804b1-4316e2dde9eso19724135e9.2 for ; Fri, 22 Nov 2024 07:41:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732290069; x=1732894869; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=hYxLUop5CFzWW+VlEDd2o5nmfczomOBA2awiJyr0ME8=; b=32NE2WEQsDYftq4CMwJz4noYsOjr48OLjIcOntOBfIiYdqYXFhh4e92uvIubSprztX hIA4FsNe61g8NmT0SpXSrFVqBmbOlfIls4YmXu0zlAMEL0Jiry5dmuwVq8cPtBlZi+X7 p2ZRWDIAEkKWTw2H6UTd3F0lA/jXoDpmnuWCpo36PEoaq29RfICX9Em4qDmmgnZQNUAf c4mCYCR/ok5fuw3vjNzTjPvkljeQKzgqQM1EnM8th8AxjwPnKLzAqSzL4zNkRpz+sNy6 XA7bly+vEkp4svxKoR1a8tVmmEIyR9Na+kiW8IWlV5y4vU0wCWVYchDhQ+mmxxkpXiXY 25ZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732290069; x=1732894869; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=hYxLUop5CFzWW+VlEDd2o5nmfczomOBA2awiJyr0ME8=; b=G3L/WiQK1ZoGsio7JJ3rpesvaoAsyx8Q3xyf/4lY9olQ3IATGrqeHCbJZ3+4oYhk9S 0JpBk4ImwAYczOZTMXseglxewpZlTxrFIVG7w0oZTSCteWZ7BAX0DDNa9TLaI6WDFSiM Bg1mRjFUHtcxpbSlLeopjgfvMGHznuolZa5Zh9xwBT9vCRGo6K1qmQQ/l34o/h/PNYuD f1oZ/xP/1Wzx53W2lCQgRjKtY8o+O1pq/WKvVuomeVp947fZHm7LHb7JBYvwYuVfWS4D vELBttRSMpFRe3AFO6TnuRXQ/rWsN/CCjVzcYd9lOMQ6MMCI18ijJc66ritjmC4kVncX JkKw== X-Forwarded-Encrypted: i=1; AJvYcCUkkqYVemqde350Y7C/l4rTChadNSq7p9eDdkTUkBtTipaDqucjtF+FCQJ+VvTe/uZhVXYykCQLhfTRYX0=@vger.kernel.org X-Gm-Message-State: AOJu0YyzB3EAZ++vZ9G2zOOIUzjpf8whAc1zYb83VndM9RbNorN6BHUf kkSylBGNZfUgG6yxyvgOjkSFY1XcxLZ+jgdx33rM2Lq/XgNZvyo6n+BdH6dTMgHwka5kJJtv0BM vVpsI1yLdsEcIdQ== X-Google-Smtp-Source: AGHT+IEIKcYcdx6MVWct3b+zC6qUnAKNrcyvu2pxBZsUhCYdS8JAEE1PK1hh3wfuatjl0mJTsbCFOi6Ydty6B7I= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:a05:600c:35c4:b0:42e:d463:3ea7 with SMTP id 5b1f17b1804b1-433ce4b2e61mr290325e9.3.1732290069096; Fri, 22 Nov 2024 07:41:09 -0800 (PST) Date: Fri, 22 Nov 2024 15:40:28 +0000 In-Reply-To: <20241122-vma-v9-0-7127bfcdd54e@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241122-vma-v9-0-7127bfcdd54e@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=3694; i=aliceryhl@google.com; h=from:subject:message-id; bh=0kJbDQ2R2LaDZDdpCyVYpygYX3kC3nlpmnRFMMkub60=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnQKYIvyS3vYvaLl2hnXmTUoNnpgWbUaM0XAaBO 5Hd920hx1WJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZ0CmCAAKCRAEWL7uWMY5 RpyREACin3dfUAa6PzIT6e2p6DXDZa92oR0hkUItIreeOaz+aDB7QYUz1TQHXS+0/ggVZfuQ5qM PW6oK14yS9QIiu6J0zqJlQ+h9CcPk6ycDjrkQKKQQNlnLaoA1KUSopOA0/dXkvOqDZx7eh0rczd yRoj+CT4F/YkIYDETENVy6KMVZIMklx4enehQes6M1v/AftWAvbN7ZluoxYjzTtcsgsw2dpLQyx 7qtm2TIoTqNlAKvdXoxetMePlgiR9OmK4DFj9zSoknu222UrRAZLZrEQ8Us3nMTCd6rFI9dsVrh SCqn+C7ZJgAOZP0UDU7gBbCXtL0TdYszA+ja48fRu7t9eb8GZZZmuDMM6i2jHKgKcw5HKVmPW2U H4YawniEx4YivnbG2E58oYT2t6bhlDrlBu4OZ2PFnSo0O0TvsiX8919xV8I3dfRkiGz7bpC4icL Eeyu4sxt/8cUq/Bdr52weSKg05oKqakBtcrCfbQ0SFx0QyO/X+ZPpuoUjw5l6SIRSglewAePJui rlIdtOTOVSpaMVVvRJiCG1X7KKQLnOa9o/znQ2gVJjMOYupgju8s87HWBq/AKVyzZPO+9LI9JxH b7afReIFODoqSqosl36aTz7325JcyO+7kKY7zNDD5KnoFhgQa/Hj/u1nSsxHHiPTc/MT1lNXiLA Zar/2JKK9H6pk4Q== X-Mailer: b4 0.13.0 Message-ID: <20241122-vma-v9-3-7127bfcdd54e@google.com> Subject: [PATCH v9 3/8] mm: rust: add vm_insert_page From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner , Jann Horn , Suren Baghdasaryan Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The vm_insert_page method is only usable on vmas with the VM_MIXEDMAP flag, so we introduce a new type to keep track of such vmas. The approach used in this patch assumes that we will not need to encode many flag combinations in the type. I don't think we need to encode more than VM_MIXEDMAP and VM_PFNMAP as things are now. However, if that becomes necessary, using generic parameters in a single type would scale better as the number of flags increases. Acked-by: Lorenzo Stoakes (for mm bits) Signed-off-by: Alice Ryhl --- rust/kernel/mm/virt.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/rust/kernel/mm/virt.rs b/rust/kernel/mm/virt.rs index 6df145fea128..3e494e40b530 100644 --- a/rust/kernel/mm/virt.rs +++ b/rust/kernel/mm/virt.rs @@ -4,7 +4,14 @@ =20 //! Virtual memory. =20 -use crate::{bindings, types::Opaque}; +use crate::{ + bindings, + error::{to_result, Result}, + page::Page, + types::Opaque, +}; + +use core::ops::Deref; =20 /// A wrapper for the kernel's `struct vm_area_struct` with read access. /// @@ -85,6 +92,67 @@ pub fn zap_page_range_single(&self, address: usize, size= : usize) { ) }; } + + /// Check whether the `VM_MIXEDMAP` flag is set. + /// + /// This can be used to access methods that require `VM_MIXEDMAP` to b= e set. + #[inline] + pub fn as_mixedmap_vma(&self) -> Option<&VmAreaMixedMap> { + if self.flags() & flags::MIXEDMAP !=3D 0 { + // SAFETY: We just checked that `VM_MIXEDMAP` is set. All othe= r requirements are + // satisfied by the type invariants of `VmAreaRef`. + Some(unsafe { VmAreaMixedMap::from_raw(self.as_ptr()) }) + } else { + None + } + } +} + +/// A wrapper for the kernel's `struct vm_area_struct` with read access an= d `VM_MIXEDMAP` set. +/// +/// It represents an area of virtual memory. +/// +/// # Invariants +/// +/// The caller must hold the mmap read lock or the vma read lock. The `VM_= MIXEDMAP` flag must be +/// set. +#[repr(transparent)] +pub struct VmAreaMixedMap { + vma: VmAreaRef, +} + +// Make all `VmAreaRef` methods available on `VmAreaMixedMap`. +impl Deref for VmAreaMixedMap { + type Target =3D VmAreaRef; + + #[inline] + fn deref(&self) -> &VmAreaRef { + &self.vma + } +} + +impl VmAreaMixedMap { + /// Access a virtual memory area given a raw pointer. + /// + /// # Safety + /// + /// Callers must ensure that `vma` is valid for the duration of 'a, an= d that the mmap read lock + /// (or stronger) is held for at least the duration of 'a. The `VM_MIX= EDMAP` flag must be set. + #[inline] + pub unsafe fn from_raw<'a>(vma: *const bindings::vm_area_struct) -> &'= a Self { + // SAFETY: The caller ensures that the invariants are satisfied fo= r the duration of 'a. + unsafe { &*vma.cast() } + } + + /// Maps a single page at the given address within the virtual memory = area. + /// + /// This operation does not take ownership of the page. + #[inline] + pub fn vm_insert_page(&self, address: usize, page: &Page) -> Result { + // SAFETY: The caller has read access and has verified that `VM_MI= XEDMAP` is set. The page + // is order 0. The address is checked on the C side so it can take= any value. + to_result(unsafe { bindings::vm_insert_page(self.as_ptr(), address= as _, page.as_ptr()) }) + } } =20 /// The integer type used for vma flags. --=20 2.47.0.371.ga323438b13-goog From nobody Sat Feb 7 22:21:15 2026 Received: from mail-yb1-f201.google.com (mail-yb1-f201.google.com [209.85.219.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6E6811DE4D7 for ; Fri, 22 Nov 2024 15:41:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290074; cv=none; b=SiaBZBYcBJ2YPkdaaAAKisENgqej7pil02XQkWGzBBwN6XqdPvAxTd+KkGeMTPAx5Ny0jKX+YImHR76KIOUexQn0Guk8FunJpWQYJMWqrHtK2FAKidHGOZujmesYGonq1/rDB8UtA63DdD1orBr2a5Kow+rpDIN0y4BDGc9xeSA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290074; c=relaxed/simple; bh=fkBx2F6iPu2x+Ij6OXEgUbDcOuLkhOhWgbDBfI9k5bI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=a0ETWQ3s/n+bxXpvxNg6sduI+oiZ8nl3Wh3m1j3BY99eVb7EfbgKO+TRKIrLVpLbD4ItBfAQadrjWjNSg3w4RACP72a+GK23VPLMcQmTycr0p5yBtP9bwwf+txItcFAX/v7vzpDnNHTaOdFQ170nYa+AJrDrRkt5XxZj6G1MqJ0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=f8nQPmj2; arc=none smtp.client-ip=209.85.219.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="f8nQPmj2" Received: by mail-yb1-f201.google.com with SMTP id 3f1490d57ef6-e38bf015434so3562224276.2 for ; Fri, 22 Nov 2024 07:41:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732290071; x=1732894871; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=St2nivlEGlwAOUor5slXoMT0nSTJUF24z+m1sub+EPE=; b=f8nQPmj2vEqhrOmUlu8fwQe7cFQGW7NGHlav/ifz0q76YlVHBFiAjWEBwbTHLabJei GYfZ/WBlQ5w6Ynj5CSpJfj1Z8r+fvRPGMI4mZ/wY6hWsiSBDMBPGYrXhSKdyzeSRfn20 XBQpq7H6rMfMf6zWZqYqNRGq4pLwWfc0mtzC1pBhiyNBr++na/j+48oN6HNf0p+m40n1 tsRCwgMThVDJ/wbEXWbRCzleSu84t4TpJyLFLr8lDadXT9bh7YtX4a7RPLexNpSFYZEX kmpMwm40v1G+M+EZP0g2+oQIVjpP0yOUpslxNcmNYcDKjdwtwIpSeGFSK7i//sKz2FNt F5jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732290071; x=1732894871; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=St2nivlEGlwAOUor5slXoMT0nSTJUF24z+m1sub+EPE=; b=YYA/CN+hSsiSR5/SXa7HjGdIjMbxLMwi9zYAlBb3JkAHdQBeTyTGC/CJLnQx8IoJnp GuzDWpECHt0krmvEUzRPdAQOnlY4gt+5tjQ0O7nXTtQHwnNZ15tElDbD9Ros27SR66Kp OQNBHRM0b+EGlkNtCdZXbgSpxxvdKJUkCntVdlAhxK6h7FXOY8Zxk1OeLG6Aq4AavXan 2RvqrxjmO6v/NnQG3UkKCHo1xaPub7Cl1gA2qKBur45lC7fbmQf96ldhBH0e5TchPCzD ZJsK9Xwz9RupHE7TlOt5oI0GllIgYbsTJstYkDuN8E03y6Qw4jb0I8Z/URwnlDLf5oI6 lbBA== X-Forwarded-Encrypted: i=1; AJvYcCWOem+nJ06maD6zjlIco/QPeBvg1XvDN0/GAEV1SF3X2ePJ0iORciAEU5aq7zCpTCiLI/uaZRoQt2e6FFw=@vger.kernel.org X-Gm-Message-State: AOJu0YzQcFdGutkOsBFe+zGiND5ntJoHax09EMyrGuquvTl0hLaaNYvt ky+S/UIA25EnUNTxtMqIO98GEuQv/QOjHRwGidcmyR0796SjJJO0V+IZgR4IZJA3w0SfI91w5VY vQ80dJMa5BxAPog== X-Google-Smtp-Source: AGHT+IGihGzFbF764Ujgj/U6cdWN/yYJN8fQNEHsMDvsZY7MAEQSnHOETorjJsB9VNEV6/q+QcUl9/lfdUnOIbU= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:a25:d80d:0:b0:e38:14f9:cd0f with SMTP id 3f1490d57ef6-e38f8bd8497mr2055276.6.1732290071512; Fri, 22 Nov 2024 07:41:11 -0800 (PST) Date: Fri, 22 Nov 2024 15:40:29 +0000 In-Reply-To: <20241122-vma-v9-0-7127bfcdd54e@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241122-vma-v9-0-7127bfcdd54e@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=3903; i=aliceryhl@google.com; h=from:subject:message-id; bh=fkBx2F6iPu2x+Ij6OXEgUbDcOuLkhOhWgbDBfI9k5bI=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnQKYIUymIZaDH58EKhKDYnMp2XcdauVFk9Sm61 K6mH7jVt0qJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZ0CmCAAKCRAEWL7uWMY5 RgCfEACMPTyXW8HWQtwKk1nhcmhNoYFoxeHTiCbS+WoDdEOJSxJ3c+x20o6T0joQfWF8aB8rSS6 TASaxo1CMMJ3r+AoFuMY78oczohJuVeXyUhJYgUitIgivvPiZNixny1hlMWK0Xrj6gIkjjB8DTt jkShgEo5cB33v67l0sRgK4wmY1SauayQ1ntYHyWSybXHtGfF15xJ3/nhxtiJ6rZaW+//wB/mucA ufgaHuVbWelVOe8GUxHBfG+R7rvn1Gjt0BqCDOXbQttgKSLD5SyHoCyGDZq4UasnoQ5A/X4sk3v nS5AFaB7/Mg6hyyl4KYCIIKxl3EYd16h5ZFbo+I+ql56DHocbFh5CI7Ua008D79AQ7cM6njhjyX HZJNHusiqgZhJvlRJni+AS1QFL/iwVXkWRIXOx08LHJz2pTnYNIYsyEBlKI9TajaIn114X4JcFQ 9+tFvuikoWe3KltS+cRPIKw0yuhtnwOW8vrudu8qk8UDp+pqBa8KQUuUO/08gSQxQYsKSBjcT7+ Ek79cFhxL5FHrSgMjpezkk1oD6SyO4zAtCU10r04fonsgBprYzdRJO2mmucn3aUjaTxDCI/vbHs ZAh6Omw23AffKbI5tymnUbecXpHG+lxRMHay6RHD3Ue9KH3GvLvC5pyFaqY5NsXg3WVT95KLASX 5Qz6Pc2WbMCv8HQ== X-Mailer: b4 0.13.0 Message-ID: <20241122-vma-v9-4-7127bfcdd54e@google.com> Subject: [PATCH v9 4/8] mm: rust: add lock_vma_under_rcu From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner , Jann Horn , Suren Baghdasaryan Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Currently, the binder driver always uses the mmap lock to make changes to its vma. Because the mmap lock is global to the process, this can involve significant contention. However, the kernel has a feature called per-vma locks, which can significantly reduce contention. For example, you can take a vma lock in parallel with an mmap write lock. This is important because contention on the mmap lock has been a long-term recurring challenge for the Binder driver. This patch introduces support for using `lock_vma_under_rcu` from Rust. The Rust Binder driver will be able to use this to reduce contention on the mmap lock. Acked-by: Lorenzo Stoakes (for mm bits) Signed-off-by: Alice Ryhl Reviewed-by: Jann Horn --- rust/helpers/mm.c | 5 +++++ rust/kernel/mm.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 61 insertions(+) diff --git a/rust/helpers/mm.c b/rust/helpers/mm.c index 7b72eb065a3e..81b510c96fd2 100644 --- a/rust/helpers/mm.c +++ b/rust/helpers/mm.c @@ -43,3 +43,8 @@ struct vm_area_struct *rust_helper_vma_lookup(struct mm_s= truct *mm, { return vma_lookup(mm, addr); } + +void rust_helper_vma_end_read(struct vm_area_struct *vma) +{ + vma_end_read(vma); +} diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs index ace8e7d57afe..425b73a9dfe6 100644 --- a/rust/kernel/mm.rs +++ b/rust/kernel/mm.rs @@ -13,6 +13,7 @@ use core::{ops::Deref, ptr::NonNull}; =20 pub mod virt; +use virt::VmAreaRef; =20 /// A wrapper for the kernel's `struct mm_struct`. /// @@ -170,6 +171,32 @@ pub unsafe fn from_raw<'a>(ptr: *const bindings::mm_st= ruct) -> &'a MmWithUser { unsafe { &*ptr.cast() } } =20 + /// Attempt to access a vma using the vma read lock. + /// + /// This is an optimistic trylock operation, so it may fail if there i= s contention. In that + /// case, you should fall back to taking the mmap read lock. + /// + /// When per-vma locks are disabled, this always returns `None`. + #[inline] + pub fn lock_vma_under_rcu(&self, vma_addr: usize) -> Option> { + #[cfg(CONFIG_PER_VMA_LOCK)] + { + // SAFETY: Calling `bindings::lock_vma_under_rcu` is always ok= ay given an mm where + // `mm_users` is non-zero. + let vma =3D unsafe { bindings::lock_vma_under_rcu(self.as_raw(= ), vma_addr as _) }; + if !vma.is_null() { + return Some(VmaReadGuard { + // SAFETY: If `lock_vma_under_rcu` returns a non-null = ptr, then it points at a + // valid vma. The vma is stable for as long as the vma= read lock is held. + vma: unsafe { VmAreaRef::from_raw(vma) }, + _nts: NotThreadSafe, + }); + } + } + + None + } + /// Lock the mmap read lock. #[inline] pub fn mmap_read_lock(&self) -> MmapReadGuard<'_> { @@ -238,3 +265,32 @@ fn drop(&mut self) { unsafe { bindings::mmap_read_unlock(self.mm.as_raw()) }; } } + +/// A guard for the vma read lock. +/// +/// # Invariants +/// +/// This `VmaReadGuard` guard owns the vma read lock. +pub struct VmaReadGuard<'a> { + vma: &'a VmAreaRef, + // `vma_end_read` must be called on the same thread as where the lock = was taken + _nts: NotThreadSafe, +} + +// Make all `VmAreaRef` methods available on `VmaReadGuard`. +impl Deref for VmaReadGuard<'_> { + type Target =3D VmAreaRef; + + #[inline] + fn deref(&self) -> &VmAreaRef { + self.vma + } +} + +impl Drop for VmaReadGuard<'_> { + #[inline] + fn drop(&mut self) { + // SAFETY: We hold the read lock by the type invariants. + unsafe { bindings::vma_end_read(self.vma.as_ptr()) }; + } +} --=20 2.47.0.371.ga323438b13-goog From nobody Sat Feb 7 22:21:15 2026 Received: from mail-wr1-f73.google.com (mail-wr1-f73.google.com [209.85.221.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 815B21DFD95 for ; Fri, 22 Nov 2024 15:41:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290078; cv=none; b=sX11EksJf694G2EQclKRb7Pif6yvobTA7T7PQ+hftOaM3oCBVjIrTQBZVc6wGgRs41iI13zokHbGunVPDMfRpMEjY/7u2LrXCLb3UVtO61wYDje6JT7QV+5PWHe6EK+jCQZif5Eckfpkp24TsmHSvUSX2iPEUI9Z1xs/4kQoV/U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290078; c=relaxed/simple; bh=e90cBT06DiQlSWUKjCW8KaJiJvXBHZuG2g717B8IAkc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=nqgEE2Z183v2iulYI8ENF79PY37Jy9LEvsFL0Las1G0XLba+ty79W0uG00vjZdAtHE6e7zmtSpTZ4k77bZTOOfOcJpS8tOnBmhqE94yhhWYqGWObHvq1JyUuFO/HvQv1Bw3+csTp4gTpDTI0bRMMFecwpViXk9MknnATMN00p28= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=exeBluvj; arc=none smtp.client-ip=209.85.221.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="exeBluvj" Received: by mail-wr1-f73.google.com with SMTP id ffacd0b85a97d-3822ecd84b3so1147906f8f.3 for ; Fri, 22 Nov 2024 07:41:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732290074; x=1732894874; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=zQjQrA8l6WUO1Dv46YWyP2KzKGLvaWN5xjw1wa5cSc8=; b=exeBluvjMZI+V5Mulgs6I6swS2PpkVzxrBaGZiSsdo44VGsm33oycwkrroq6u/QEza tR5is5xV7kNFIJtjVljvq3HJdKv9Boask3WxN7B0gE1TEsT+l7UmHaOccX+Xo/0//99h 2Lc4la4/Et+98RctnUfk5bOws10SqKJWncpKKyvujf2wXRxg2rps11UmcgKGGoSjT9xS lnUYnWGpMx1RryL9KYnUGO649QT1A1BSfTpgbvcmNhwvEZ4DYd6zKPwrf0tv32a9vDxv nn8NSZ9zlVSy3J65gOMpcw9hFiE5MqO/gY0KoonNL53SiWmd8aK7XN/Q3VKZKpG3OGO3 8ZZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732290074; x=1732894874; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=zQjQrA8l6WUO1Dv46YWyP2KzKGLvaWN5xjw1wa5cSc8=; b=RbUevsQfeme4HvsElfzfX3b/y9lULby3dmJQ4CuSV0VmUAwvPJnKPCcHhWsbjDC+gM 8fCcPqYq9QyGBBBBP+AW0Kk4I2NMSv/IFatJdjQ+5KBnJoLWsznvTLIcggg2bJboeTCp 4G6C43P56COFyagpFcngdJyXXAfX4Q6zi4gn0fYWCLR/chDffLNs9jiHYTrFxubP7IjR gZc7ZjXeWxejfAFQVjQX7KC/ylvvPzW2PZX8EEsVol0STwnBcDlX1WJSDVl4AjDwD9Zo 1JXI2OxU8MbQfXhsy/QMskyJtttohngajT3zU9JmwD600ui6x4Gl5lBGkZPxosLvt5s/ tqXA== X-Forwarded-Encrypted: i=1; AJvYcCVnFNY77a51slWoSWBrWGAb6cLC8v7b4U5Mjn8icWRBYsEzg+uFADR+sqanPxnfujbp/NBasgsw8CDHYRY=@vger.kernel.org X-Gm-Message-State: AOJu0YzoJ6bnUx3jBriIwth5F5n8XsClogEw3m87jEqrPPgUaraQGvaR jgAsxDTYp9KeC+ymOuFyv9y291P2RnKZhOndAkdM/21s1yf3/kHcAMhfFcLY8Ph0HshwUGz1J1P rY9Oh2ZkCeHCqhw== X-Google-Smtp-Source: AGHT+IH2pPS49cAT9mdCjiMFAVekUdtncedHBNDeVISatyX0fCCBayouO8NUq4KgmU1yCNwvAR5MiYLmHLx8PcE= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:a5d:5e0c:0:b0:382:449d:a6ab with SMTP id ffacd0b85a97d-38260b452d1mr878f8f.1.1732290073825; Fri, 22 Nov 2024 07:41:13 -0800 (PST) Date: Fri, 22 Nov 2024 15:40:30 +0000 In-Reply-To: <20241122-vma-v9-0-7127bfcdd54e@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241122-vma-v9-0-7127bfcdd54e@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=3090; i=aliceryhl@google.com; h=from:subject:message-id; bh=e90cBT06DiQlSWUKjCW8KaJiJvXBHZuG2g717B8IAkc=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnQKYJ73Kuhs7y8NsLUpQQMtbfBgw4kDNtzBVg2 tUbFMPyS9eJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZ0CmCQAKCRAEWL7uWMY5 RkzaEACBEXTOYc+UZmggaAf5RKHc4bX3sRd3bEoHGg1TwzgV8P69eolFeBEDIMT4ozAtxjnoZMO 8H6ODCr80sTJ/14jsNEMfD8riO17u4t2Rct81AB6ASqN4eCABDEd93DFjjrtgNZxE5acubWPzlT rFWtgWhwIcyUvUkhX1ipVexr4/ZItTLyezntWLg4kBqVJ6uLepiaJctIk53F4rU8p9UZnAfC1P1 sPbE95Jb4S0oJhIGQoFaF6VtlUEV3joZaYJl1gGkuFnbWy6y1ije3pGCnWYv/099C2FtXKzKMEB e5mTT5LYuqJhZ3zf3gjfrNICehst0DXZPDIbpvzs199wF3CzRntxGAcRQkDApOhBkZj73Ntx6oj fO/MGb7TVIZgLhToYA91lnHYjCs18cIAwieUxn0k0tfq5NPUfYUYAad+koxMCGOauUvnCCB/DqC 2idZYlEiasHpiaOmj1judPSffxEnMkvDFLZtW2xroCdVECOMMYuFmW5fFv9hj5n2+yL3kmmcsoJ Sz/nfsJI5NF41/S/qA61Mo3l0d1XRZwMpxnEdzVm/KU47CaGRXonGb5rsfDf12bRSmzzvXthP/V vqtIKmQT4av/5On0EURF0tsQcFkV2DKivHNmMubOcOhsj3jFGHajd8ny39WSl7qKcFxdd3gePsV 7fPwbNtETlyL+wQ== X-Mailer: b4 0.13.0 Message-ID: <20241122-vma-v9-5-7127bfcdd54e@google.com> Subject: [PATCH v9 5/8] mm: rust: add mmput_async support From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner , Jann Horn , Suren Baghdasaryan Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Adds an MmWithUserAsync type that uses mmput_async when dropped but is otherwise identical to MmWithUser. This has to be done using a separate type because the thing we are changing is the destructor. Rust Binder needs this to avoid a certain deadlock. See commit 9a9ab0d96362 ("binder: fix race between mmput() and do_exit()") for details. It's also needed in the shrinker to avoid cleaning up the mm in the shrinker's context. Acked-by: Lorenzo Stoakes (for mm bits) Signed-off-by: Alice Ryhl --- rust/kernel/mm.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs index 425b73a9dfe6..50f4861ae4b9 100644 --- a/rust/kernel/mm.rs +++ b/rust/kernel/mm.rs @@ -98,6 +98,48 @@ fn deref(&self) -> &Mm { } } =20 +/// A wrapper for the kernel's `struct mm_struct`. +/// +/// This type is identical to `MmWithUser` except that it uses `mmput_asyn= c` when dropping a +/// refcount. This means that the destructor of `ARef` is= safe to call in atomic +/// context. +/// +/// # Invariants +/// +/// Values of this type are always refcounted using `mmget`. The value of = `mm_users` is non-zero. +#[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) { + // 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 =3D 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`. @@ -171,6 +213,13 @@ pub unsafe fn from_raw<'a>(ptr: *const bindings::mm_st= ruct) -> &'a MmWithUser { unsafe { &*ptr.cast() } } =20 + /// Use `mmput_async` when dropping this refcount. + #[inline] + pub fn into_mmput_async(me: ARef) -> ARef= { + // SAFETY: The layouts and invariants are compatible. + unsafe { ARef::from_raw(ARef::into_raw(me).cast()) } + } + /// Attempt to access a vma using the vma read lock. /// /// This is an optimistic trylock operation, so it may fail if there i= s contention. In that --=20 2.47.0.371.ga323438b13-goog From nobody Sat Feb 7 22:21:15 2026 Received: from mail-yw1-f201.google.com (mail-yw1-f201.google.com [209.85.128.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B7E41DFDAA for ; Fri, 22 Nov 2024 15:41:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290079; cv=none; b=rySJP9n2igHmE19JhbOfEHaVGNRDcM98gz8ISzveiJlBbv1/z9HQSRoYnT93EVlCKEYmo0Z0WClWMn/g2/qly9if2EdYXCzUTJ9kWrj8aoy+875g1Re8EZMB8WhXEdc6v/qe+jRQJaR72M0jSB9QN7Ad+cji95AprvDS58+MA/o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290079; c=relaxed/simple; bh=8XMIdsAyhjsVKz2sE1Ods0Tz2Vq4I2NxznUSr3oMZoc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=FfYrvWf/WzmJ1/MeqBNUgNUDJAVmBcwfcPx58BtfJH8HC4t6ttrtp38SNA4bE5u31lIQLsyRkHf8SxMI5p5WuD7We6mCVekBiqnxj6xmGq/9mG9i54H4e+PK0qTEAL0VfW0H7HiqMwvCXIpCR8rIpZAMZYQ3mzbfhFQ7iWiLGvE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=h+lluuPy; arc=none smtp.client-ip=209.85.128.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="h+lluuPy" Received: by mail-yw1-f201.google.com with SMTP id 00721157ae682-6eeeebc295dso912507b3.1 for ; Fri, 22 Nov 2024 07:41:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732290076; x=1732894876; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=L4qSVcgbBLdeeMk9S8eo1cKOTa/uPhWh7RI1+zhYfKE=; b=h+lluuPyZtB2FOANaI0ezavn47KdHAMy33FbtAhXP0zYJr1mYTcwzJLe5k3dpsmh7h Qjw5aH9qB7Cb5OhIvIIQk9TM9jShhkhNVSHbOOlg9UpX8GzsZX9YYE3QS0LvY3ALANWK 6jOYUodLeJRHpbMA2W4ZFuF9f1w644Na+JjPMn3wwv4GoWEMUFooLcNmSUt5bv2+pafc p6hfkuyYw7qIbEUI6gR464dLUbuqj+RVwG4PWrbhNClw1bBGpyILnHxrjzwsa4RBRCHf Vz2pqKTv6sHb4lwX0OZi281LjSLh2NoOOwunU2XBf1iCiZOvxnn7ET757AhJbsexN/GP JKSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732290076; x=1732894876; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=L4qSVcgbBLdeeMk9S8eo1cKOTa/uPhWh7RI1+zhYfKE=; b=pMxWcqAHQD/a04+XkZAQt/28gX05IPCVShQEZcc1ZtAP7GnJ07glJDDaomcLB/rha4 aB6O4olGnX/aV3s7CgGS0UO/accrQ76HAOys3kEIavcbPeW6KvqLl804F8FXi2gXkgGA 3IoapDM2vtqyl5p8PZloI8oxo2BMRLrxq4R4l+5ZjvN9aqTLjrSq9Zq2sFdYWeSdblsg IpPRd7KeCKp93jFLYSSRKvEiN4+uBxrrlLUoa7aDVMdOxUH7nTw3sj3uN6S4rsCRYV9A A37KbIgDfJgenNBoRQRb6cqNIVuktkidosXqgnWaUS+MPMzJYCtYNeLkJplSfpN2KTGv oqGA== X-Forwarded-Encrypted: i=1; AJvYcCXdgX8Lko0PLsfupi2P0BQnIhyt+RxJus/ozS6xwzFpUXPD/pKu1jCH6mF5zDw0cqFPVW69E3tbIrsiHtY=@vger.kernel.org X-Gm-Message-State: AOJu0YwmZk1bKR/u1ypqI1pcSjA1bpz43FwT5NYIldSDLx3nkEpd/CUC cjoKtzNkleXVw5GT8EzEV8mkfucVuu4BvMmns0xmc6SDFukrXzMu69VNwjnDMBBnUUa0bFn3/Bc c+gke+HsnbiGK+w== X-Google-Smtp-Source: AGHT+IEzCJ8qWwWmshtRsITg+icfUQjN5P4TA8fmdquEW+McT4r0JS2lWAyQ7jrcDuQUs5kS2JoVK2CCYBJKDgo= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:a81:d809:0:b0:6e2:12e5:356f with SMTP id 00721157ae682-6eee0a3cd59mr78657b3.3.1732290076176; Fri, 22 Nov 2024 07:41:16 -0800 (PST) Date: Fri, 22 Nov 2024 15:40:31 +0000 In-Reply-To: <20241122-vma-v9-0-7127bfcdd54e@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241122-vma-v9-0-7127bfcdd54e@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=7936; i=aliceryhl@google.com; h=from:subject:message-id; bh=8XMIdsAyhjsVKz2sE1Ods0Tz2Vq4I2NxznUSr3oMZoc=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnQKYKwgMhFK1o/1aUXbls2k8sejghL5FzITqk6 S2R7cFzIkiJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZ0CmCgAKCRAEWL7uWMY5 RgGdD/4iPoTTUbdLe33P5pBqMrDOdAKUntngkTdsYYX2OucalMMc62TwR9LizWRDXfNwM/sGDD/ 87pFB785Ie1GL1dBGmpBpL8gr8XP08IDdKU9PYdiWkrcl1M857BBrRZr5fvznourPha8Ge75nMF fUYwl16MYhoFseaPFlUXgdpty952Hj07bkZ3cbr/Dqaj+MHqd00kbuW3EhwLxiFieJRIA45bot+ ZUe+itpME+XKjA5eahHCbDq1h0yvWglatQsdgDi85VQesQtdZ0Awk9bWnS5n07udlTTvnqt2St0 HO74zVpaB/N+ERz3pBpj2ArIj5C8yo37m8gDSFiUsZ8cCkvBRYY8c9xia19JKX/pX4/kiSn74yu u5Wd9SN2cX/FGXGn1EXcbY8cmy242VYZ4LuF9ZKeUqA7YaKml4fBbSdYumBnHnsJhc1ZrBhPDpi rlqY2MgjKdUrO0KgIyDT0TdHU8Xcd4Q1cyRFQgg9AajEuLT9XLsKvhjNOqRnoKiVEO7xFvj19OP kQZOMqGPIuNlKhMPOGFMEVzwsGrJL3Qg2ViTs051E9a7EMgY/P0F+4ruzh3mNn1FTwrKAbYAKzo r0tx5ODyv4xYh6z0aAkpluZ/ILnd980jLVIk7IXf9lncUD+K9DFxBjBnN7MjDpOMjwaoYQwvsUE V+xrKnZ7t1hXKuQ== X-Mailer: b4 0.13.0 Message-ID: <20241122-vma-v9-6-7127bfcdd54e@google.com> Subject: [PATCH v9 6/8] mm: rust: add VmAreaNew for f_ops->mmap() From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner , Jann Horn , Suren Baghdasaryan Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable This type will be used when setting up a new vma in an f_ops->mmap() hook. Using a separate type from VmAreaRef allows us to have a separate set of operations that you are only able to use during the mmap() hook. For example, the VM_MIXEDMAP flag must not be changed after the initial setup that happens during the f_ops->mmap() hook. To avoid setting invalid flag values, the methods for clearing VM_MAYWRITE and similar involve a check of VM_WRITE, and return an error if VM_WRITE is set. Trying to use `try_clear_maywrite` without checking the return value results in a compilation error because the `Result` type is marked #[must_use]. For now, there's only a method for VM_MIXEDMAP and not VM_PFNMAP. When we add a VM_PFNMAP method, we will need some way to prevent you from setting both VM_MIXEDMAP and VM_PFNMAP on the same vma. Signed-off-by: Alice Ryhl Acked-by: Lorenzo Stoakes (for mm bits) Reviewed-by: Jann Horn --- rust/kernel/mm/virt.rs | 179 +++++++++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 178 insertions(+), 1 deletion(-) diff --git a/rust/kernel/mm/virt.rs b/rust/kernel/mm/virt.rs index 3e494e40b530..2a49c29a49c7 100644 --- a/rust/kernel/mm/virt.rs +++ b/rust/kernel/mm/virt.rs @@ -6,7 +6,7 @@ =20 use crate::{ bindings, - error::{to_result, Result}, + error::{code::EINVAL, to_result, Result}, page::Page, types::Opaque, }; @@ -155,6 +155,183 @@ pub fn vm_insert_page(&self, address: usize, page: &P= age) -> Result { } } =20 +/// A builder for setting up a vma in an `f_ops->mmap()` hook. +/// +/// # Invariants +/// +/// For the duration of 'a, the referenced vma must be undergoing initiali= zation in an +/// `f_ops->mmap()` hook. +pub struct VmAreaNew { + vma: VmAreaRef, +} + +// Make all `VmAreaRef` methods available on `VmAreaNew`. +impl Deref for VmAreaNew { + type Target =3D VmAreaRef; + + #[inline] + fn deref(&self) -> &VmAreaRef { + &self.vma + } +} + +impl VmAreaNew { + /// Access a virtual memory area given a raw pointer. + /// + /// # Safety + /// + /// Callers must ensure that `vma` is undergoing initial vma setup for= the duration of 'a. + #[inline] + pub unsafe fn from_raw<'a>(vma: *const bindings::vm_area_struct) -> &'= a Self { + // SAFETY: The caller ensures that the invariants are satisfied fo= r the duration of 'a. + unsafe { &*vma.cast() } + } + + /// Internal method for updating the vma flags. + /// + /// # Safety + /// + /// This must not be used to set the flags to an invalid value. + #[inline] + unsafe fn update_flags(&self, set: vm_flags_t, unset: vm_flags_t) { + let mut flags =3D self.flags(); + flags |=3D set; + flags &=3D !unset; + + // SAFETY: This is not a data race: the vma is undergoing initial = setup, so it's not yet + // shared. Additionally, `VmAreaNew` is `!Sync`, so it cannot be u= sed to write in parallel. + // The caller promises that this does not set the flags to an inva= lid value. + unsafe { (*self.as_ptr()).__bindgen_anon_2.__vm_flags =3D flags }; + } + + /// Set the `VM_MIXEDMAP` flag on this vma. + /// + /// This enables the vma to contain both `struct page` and pure PFN pa= ges. Returns a reference + /// that can be used to call `vm_insert_page` on the vma. + #[inline] + pub fn set_mixedmap(&self) -> &VmAreaMixedMap { + // SAFETY: We don't yet provide a way to set VM_PFNMAP, so this ca= nnot put the flags in an + // invalid state. + unsafe { self.update_flags(flags::MIXEDMAP, 0) }; + + // SAFETY: We just set `VM_MIXEDMAP` on the vma. + unsafe { VmAreaMixedMap::from_raw(self.vma.as_ptr()) } + } + + /// Set the `VM_IO` flag on this vma. + /// + /// This marks the vma as being a memory-mapped I/O region. + #[inline] + pub fn set_io(&self) { + // SAFETY: Setting the VM_IO flag is always okay. + unsafe { self.update_flags(flags::IO, 0) }; + } + + /// Set the `VM_DONTEXPAND` flag on this vma. + /// + /// This prevents the vma from being expanded with `mremap()`. + #[inline] + pub fn set_dontexpand(&self) { + // SAFETY: Setting the VM_DONTEXPAND flag is always okay. + unsafe { self.update_flags(flags::DONTEXPAND, 0) }; + } + + /// Set the `VM_DONTCOPY` flag on this vma. + /// + /// This prevents the vma from being copied on fork. This option is on= ly permanent if `VM_IO` + /// is set. + #[inline] + pub fn set_dontcopy(&self) { + // SAFETY: Setting the VM_DONTCOPY flag is always okay. + unsafe { self.update_flags(flags::DONTCOPY, 0) }; + } + + /// Set the `VM_DONTDUMP` flag on this vma. + /// + /// This prevents the vma from being included in core dumps. This opti= on is only permanent if + /// `VM_IO` is set. + #[inline] + pub fn set_dontdump(&self) { + // SAFETY: Setting the VM_DONTDUMP flag is always okay. + unsafe { self.update_flags(flags::DONTDUMP, 0) }; + } + + /// Returns whether `VM_READ` is set. + /// + /// This flag indicates whether userspace is mapping this vma as reada= ble. + #[inline] + pub fn get_read(&self) -> bool { + (self.flags() & flags::READ) !=3D 0 + } + + /// Try to clear the `VM_MAYREAD` flag, failing if `VM_READ` is set. + /// + /// This flag indicates whether userspace is allowed to make this vma = readable with + /// `mprotect()`. + /// + /// Note that this operation is irreversible. Once `VM_MAYREAD` has be= en cleared, it can never + /// be set again. + #[inline] + pub fn try_clear_mayread(&self) -> Result { + if self.get_read() { + return Err(EINVAL); + } + // SAFETY: Clearing `VM_MAYREAD` is okay when `VM_READ` is not set. + unsafe { self.update_flags(0, flags::MAYREAD) }; + Ok(()) + } + + /// Returns whether `VM_WRITE` is set. + /// + /// This flag indicates whether userspace is mapping this vma as writa= ble. + #[inline] + pub fn get_write(&self) -> bool { + (self.flags() & flags::WRITE) !=3D 0 + } + + /// Try to clear the `VM_MAYWRITE` flag, failing if `VM_WRITE` is set. + /// + /// This flag indicates whether userspace is allowed to make this vma = writable with + /// `mprotect()`. + /// + /// Note that this operation is irreversible. Once `VM_MAYWRITE` has b= een cleared, it can never + /// be set again. + #[inline] + pub fn try_clear_maywrite(&self) -> Result { + if self.get_write() { + return Err(EINVAL); + } + // SAFETY: Clearing `VM_MAYWRITE` is okay when `VM_WRITE` is not s= et. + unsafe { self.update_flags(0, flags::MAYWRITE) }; + Ok(()) + } + + /// Returns whether `VM_EXEC` is set. + /// + /// This flag indicates whether userspace is mapping this vma as execu= table. + #[inline] + pub fn get_exec(&self) -> bool { + (self.flags() & flags::EXEC) !=3D 0 + } + + /// Try to clear the `VM_MAYEXEC` flag, failing if `VM_EXEC` is set. + /// + /// This flag indicates whether userspace is allowed to make this vma = executable with + /// `mprotect()`. + /// + /// Note that this operation is irreversible. Once `VM_MAYEXEC` has be= en cleared, it can never + /// be set again. + #[inline] + pub fn try_clear_mayexec(&self) -> Result { + if self.get_exec() { + return Err(EINVAL); + } + // SAFETY: Clearing `VM_MAYEXEC` is okay when `VM_EXEC` is not set. + unsafe { self.update_flags(0, flags::MAYEXEC) }; + Ok(()) + } +} + /// The integer type used for vma flags. #[doc(inline)] pub use bindings::vm_flags_t; --=20 2.47.0.371.ga323438b13-goog From nobody Sat Feb 7 22:21:15 2026 Received: from mail-wr1-f73.google.com (mail-wr1-f73.google.com [209.85.221.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 409BC1DED7F for ; Fri, 22 Nov 2024 15:41:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290081; cv=none; b=ntnPtSMyO4QeNW7hWMKqgnkJA1GBlTVQJCLs/bkuNivPTAQjMFnqbPtQR81oYznUtkMK+DcIfcBM6lDsrjtnkUlNOvFpwCFBxlgfaCwdd10OBGQdvJ5XcY+n0wHKIVVxj+yO02e7N+JfXmRdCw6aic67TlCU6DqZBHgcWrH2o9A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290081; c=relaxed/simple; bh=CackrY4N4HrwWKJd4mh44KeNaf6Y+uJ77q1hA2gtWCE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=eX7mMpNXE3FaZtag0G5aGMsOoVGP3xfhIGVKPXAKj3qvR8+Yhs5Pseo/0YCTXLAAQD0RL4MkyJ9zJGBFjPuRMPX1fuqA3jecaZMBzlZgCuPGnKV2ZkmYPmtqrtkqauv1Swd/D3EKSI99005VsGHUyr4XJLwBmKivnczN1Q80EAk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=xt6GL1pd; arc=none smtp.client-ip=209.85.221.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="xt6GL1pd" Received: by mail-wr1-f73.google.com with SMTP id ffacd0b85a97d-382357b294aso1110075f8f.3 for ; Fri, 22 Nov 2024 07:41:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732290078; x=1732894878; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Jn+jmdJoGY3YsjVzLAxhBr/vpe9LejwdH758cgsIixQ=; b=xt6GL1pdPdxqiROk6TQ0Q5Ur21pHnbBtA8ZLODwpb8nyrHljLeaGvfZ8i2AItsBnAc x47e3sIdrah7cfoabC0rc4+6fHjqj3PM8ZZDPUSGIntU98B5Qu275ce9twYlhJ4g/QE4 qm+WdE26c+Lz2l5vTQppifI3yj8xuDKOdR7+lpKfkoTBhZ97Y5k/IWqQ04+rKILDaR23 8cHcK/JPQdku7gLPjWihlPNGMQ7iE5y3jRn8trJ7alvgXex8VjFSZrx0euU2St08V3R+ OT+mu4KkUMvcSZ8JxqWY4tQ5MZpS9efKENQrzINm5/9CG7f3wdtjZ/o9gAKI/QUkoqTn y8Jg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732290078; x=1732894878; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Jn+jmdJoGY3YsjVzLAxhBr/vpe9LejwdH758cgsIixQ=; b=MBth+2IpwE1dCcY2oHjDdp6GgXpRBHxMTNw/lu70IxLM+dm0w9m71byZJmrR57zcsl TOou3Uq/HeXz30Ij86Zbt5LAGslvffEF0BvWjvyx9/qp5xgKnV1+QdyTqGPjh6XKArdn /9LxTM69UO1aXvaNoyt/nn9NRb0GFx6WwKKXKp3RYLC08NAx/zODPNMp6jm1rtNrdAkr qEUoyQ7aTAQkXfAVDOb91bn9BNTWCI23QC+4QkoBzWD0K42KMCZatXjH43c0wROZfHEN jW5znOuXFiE+fEzqNSx6w75PUZK2lE6sb0Qj1zLZHz2O+gowOpVOM2dSlfZJP7kh8e4f Kfvw== X-Forwarded-Encrypted: i=1; AJvYcCV96dLRucWZOjE2MSwFrdsmqSWYmqE74DlHiWQ0i6tsOgiUiny9xkL+GjNfmpRZdZL/8ds4UgrUYOgUyBE=@vger.kernel.org X-Gm-Message-State: AOJu0YytNycfkpOT956Hc6h2jSMIS9U5HPogXalS3bOXdPLCRuSvkqkN ZCYc4TpicsJ5QJ0OStvtapGtidVibcWvj8SWIFNNIHYaoCrdE8L/r4xW10ASaHkFNssUg8hSTju AGhypXn5bVQnb+A== X-Google-Smtp-Source: AGHT+IEDL6wyaXq4KVeCa+5cSaT1eT6HwgjeW/qH+ytywyB3jjXDr+R/rDF3sLSLr/FXsbnoKOvq0/msM05k6g4= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:a5d:468d:0:b0:374:c0b5:565 with SMTP id ffacd0b85a97d-38260bdfb03mr927f8f.9.1732290078524; Fri, 22 Nov 2024 07:41:18 -0800 (PST) Date: Fri, 22 Nov 2024 15:40:32 +0000 In-Reply-To: <20241122-vma-v9-0-7127bfcdd54e@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241122-vma-v9-0-7127bfcdd54e@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=2821; i=aliceryhl@google.com; h=from:subject:message-id; bh=CackrY4N4HrwWKJd4mh44KeNaf6Y+uJ77q1hA2gtWCE=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnQKYKX/KFzHUB/ScZLT3bwuduBq3gubqN9dGbb zhWJO4uzlqJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZ0CmCgAKCRAEWL7uWMY5 RmMND/9qq+Sg908pb5iHFBsP7RY9cC5qNfZFzfWuBMKlhj48SWuaTddtGzGW+uv7CCplsCcgeHt HAc286bLeHj6SasQPWO5wZ1yfZ9lc/TEdx2iQTqII9TNxR36DXtL5SZprMoBXYVjQ2Tywws7lHY xlQMpm1oy10QRFyuA3mbbrIGpz9LxAx+SNJ3AXDcKnehoHsIxXQiGSTN2db7DA+AuFl2jYjV5lB VIMg44+BKCwfbBhCZtkpUj0U/EHsDy7A5LhsBKv1rFUGccDleWk7uPBbj/LXktuYJ6nYsCBxS9s h5j4yvM/qN4whXwUmWP0Go6PcPTEATyx+1v5ekMf+mhLwWf3qCcpStayFbm0BNFi07zT+4nsZvM E228lqBxIZHtoO2z91VI8fJpZPMSi41fki2pzwndXccNGEL+EyHY7OyKAhtunktx6JOtW+TYRCP mWZ7+rFxasmzyRndH3DcUNWreRDBKAAr2m0cX5l/2Mx2kQRt+ZbWLBDlSp1fcGwHy9p15TDDLPD SEPyL8FilnUErOT3rB+EoH3cywn1kC5I4rTeacyutzbqiCk6fcOTZ0bA8ZjX1uo5vgrXQrfcHqt BBIvXbcN36yINaxKYxh30yS6jPryfIoudkn5gxuUKV7Oo3BewdDxanK/Wgrg2EZeqqo5PeQTEMl mqmg/Y0+Mk6IEMA== X-Mailer: b4 0.13.0 Message-ID: <20241122-vma-v9-7-7127bfcdd54e@google.com> Subject: [PATCH v9 7/8] rust: miscdevice: add mmap support From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner , Jann Horn , Suren Baghdasaryan Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add the ability to write a file_operations->mmap hook in Rust when using the miscdevice abstraction. The `vma` argument to the `mmap` hook uses the `VmAreaNew` type from the previous commit; this type provides the correct set of operations for a file_operations->mmap hook. Acked-by: Lorenzo Stoakes (for mm bits) Signed-off-by: Alice Ryhl --- rust/kernel/miscdevice.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs index 7e2a79b3ae26..4e4b9476e092 100644 --- a/rust/kernel/miscdevice.rs +++ b/rust/kernel/miscdevice.rs @@ -11,6 +11,7 @@ use crate::{ bindings, error::{to_result, Error, Result, VTABLE_DEFAULT_ERROR}, + mm::virt::VmAreaNew, prelude::*, str::CStr, types::{ForeignOwnable, Opaque}, @@ -110,6 +111,11 @@ fn release(device: Self::Ptr) { drop(device); } =20 + /// Handle for mmap. + fn mmap(_device: ::Borrowed<'_>, _vma: &V= mAreaNew) -> Result { + kernel::build_error(VTABLE_DEFAULT_ERROR) + } + /// Handler for ioctls. /// /// The `cmd` argument is usually manipulated using the utilties in [`= kernel::ioctl`]. @@ -156,6 +162,7 @@ impl VtableHelper { const VTABLE: bindings::file_operations =3D bindings::file_operati= ons { open: Some(fops_open::), release: Some(fops_release::), + mmap: maybe_fn(T::HAS_MMAP, fops_mmap::), unlocked_ioctl: maybe_fn(T::HAS_IOCTL, fops_ioctl::), #[cfg(CONFIG_COMPAT)] compat_ioctl: if T::HAS_COMPAT_IOCTL { @@ -216,6 +223,27 @@ impl VtableHelper { 0 } =20 +/// # Safety +/// +/// `file` must be a valid file that is associated with a `MiscDeviceRegis= tration`. +/// `vma` must be a vma that is currently being mmap'ed with this file. +unsafe extern "C" fn fops_mmap( + file: *mut bindings::file, + vma: *mut bindings::vm_area_struct, +) -> c_int { + // SAFETY: The mmap call of a file can access the private data. + let private =3D unsafe { (*file).private_data }; + // SAFETY: Mmap calls can borrow the private data of the file. + let device =3D unsafe { ::borrow(private) }; + // SAFETY: The caller provides a vma that is undergoing initial VMA se= tup. + let area =3D unsafe { VmAreaNew::from_raw(vma) }; + + match T::mmap(device, area) { + Ok(()) =3D> 0, + Err(err) =3D> err.to_errno() as c_int, + } +} + /// # Safety /// /// `file` must be a valid file that is associated with a `MiscDeviceRegis= tration`. --=20 2.47.0.371.ga323438b13-goog From nobody Sat Feb 7 22:21:15 2026 Received: from mail-wr1-f73.google.com (mail-wr1-f73.google.com [209.85.221.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9737E1E0087 for ; Fri, 22 Nov 2024 15:41:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290084; cv=none; b=H25XnjCRoFLiMZO6Sv1muCKztKrCdoJtva6uKG/V7JvWsdx7I6T9YVqEiGp9HZWBO+nUD5deKLclCBaqr8lW8Z0mS9byQLJu83MjwErgDW0NzllHCM+8Z+Co8quTpXEPTSnrIWPvox7l6g0o6ZdX98B1RO6qDlagmiNITHLYFq8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732290084; c=relaxed/simple; bh=ELmBMFzYYsNvMdFa8fNaCj9uRohYnanctvoUqVOPrOk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=K99o7nUmNjJZ267fGkzP/OQycVQTh4Bax9AyNZgTxI2E9kQO1jrDclNp1ctROcxz2R7YBh/jHHNx2oe+julVlM9hNorYxo+qe2NDq4IonnWFJW7W8zkLRGGCfx0GqRpV4UFQdDCkkxLG3tBN/PbMNG1bBEmFx3eGi0Z6cf1Fu18= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=PiPbH8Pr; arc=none smtp.client-ip=209.85.221.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="PiPbH8Pr" Received: by mail-wr1-f73.google.com with SMTP id ffacd0b85a97d-3823326e95aso1225162f8f.3 for ; Fri, 22 Nov 2024 07:41:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732290081; x=1732894881; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=roehYhV9fbym2F/vf27bAbe0CuzVSCLFEeCVaGrDIRQ=; b=PiPbH8PrSptlYrwL9CMndBBziFdVbNpWofdJowxJDxp43IKr2Af/g3vCnQ5lwZ2Kru /01J27MtDZaAdavU6r0xH82AZpe7nYZC1jm6ChOsro8tGLRJfFwnqd5E3WqO9ApaEXsz 2/UmIe6JTTk3NVdW6hyU320lJw2R2hT6asOBYs7Av6b6logZNRQeFPWG6GwXZqkakTJA f+uc5HCgQySeok+dUPQ2eJNxyx9Nl9wUH9cVqUtKytDQqE323wfcuz7q6FB/zkIBlv4y uDmWdQVB2cW53R+BQzQPz6YMlFab5QxNbRnFPy9QSDnp6Wq6BVdwwdKE/LiRKwDdIMg2 g3Xw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732290081; x=1732894881; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=roehYhV9fbym2F/vf27bAbe0CuzVSCLFEeCVaGrDIRQ=; b=d1Qd2CXXCnctijjL6+mpHLD7WW6cxgQsR/vcYx18kYh9MxN6l88bMv9Xp3ClIIM9Kc yXHADsgVg+DY3FmBZDzSr1Z9tFQtn+hyogIEKxXtphdx+WZh/RSIirKxmhIjjLtG6AEL QaFj+YvH7zkAEftHQrUKRZ633wEDWe9Tqi5Y1Md33lblWefotR+9b0eyt3wBxXJsfwZx 3dGW93Rqd9Oa+akhF0Uv2b6QmwgEgF3nbyEJ05XXO6NLUp2blF6ZOg7sXGvM1XpVyETB eVM1VeKXtp9va6QSOqfajLZWu0e6S9B9UcjOY7V1vIFTxZMo3ticiFCk3McVQtpWKaS2 cQtw== X-Forwarded-Encrypted: i=1; AJvYcCXu743KLVF+QtBlBr/6zru7ru+LNyeenVvwlRdkdXt2fQu/qALFTBAv8d1lt0HawZt1CBvGpcCNFkkLxO0=@vger.kernel.org X-Gm-Message-State: AOJu0YxAaPulzdktb0V6rz5bAc0tNJQXRfZN7ft8VPW15HgvuQSg+ZG6 9vadJ8SvCMdxcyJKmpvebL7QaF4FAseX6necAseBxw8JQyIrNxeMDXCDp0r7rGeY20q8sWM+Q+g +NaKkdER8GTzVlQ== X-Google-Smtp-Source: AGHT+IF6HBbIQggNCbWVHzfdpf5qfU2oWZDDUICEvmMpzMP0kJSXWVx7hqPiHvLxeddSVZjHgvUjH2UBZr7vJN0= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:adf:fd05:0:b0:382:49ff:ef75 with SMTP id ffacd0b85a97d-38260bc27dcmr780f8f.7.1732290080932; Fri, 22 Nov 2024 07:41:20 -0800 (PST) Date: Fri, 22 Nov 2024 15:40:33 +0000 In-Reply-To: <20241122-vma-v9-0-7127bfcdd54e@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241122-vma-v9-0-7127bfcdd54e@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=5755; i=aliceryhl@google.com; h=from:subject:message-id; bh=ELmBMFzYYsNvMdFa8fNaCj9uRohYnanctvoUqVOPrOk=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnQKYLQtIIMMayOTF0V1fptgYQ4tpbvUzXCBxvI JXOixUouJmJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZ0CmCwAKCRAEWL7uWMY5 Rk7MEAC8HmptGWWIAH1NODYFTSG83oi5q2l+ljeKmvdiUHP1c39MD8JUUr8ZQY56Km1mjeH+R45 Bb+bq62Q5v4yR0Bmrf1RlL2cPshEqIV3SaIF1AMB972ROETbmB/IEny0owtXKbAJE8nuaGxBiW9 +Ni0SAFbcP30X2a80Cb2WQGk3ItYkrP3LfPzt43YJ52Y/9anw8UIoT3Q2tLGXMEaFRJ1qOqlsOh 2FxJkSANzWvBix5B/6xqMTf7BrLH60791UzrqLbz0FwyO2GFLZptvL45fwTdb8VCQAONjeNC6Px Q1YQnxM1+zc2qDrMjuFIaJ32y7wOsJNtrLDek249qEOCPFs4y7HYAUbOSy3fNlNcw8TLo7k48Sd 4+RbUJdtj/5k/Vw22wFASM8UZVyfIkvGegvIh2ETxFgNYbg6kFuOAVrxZJBBLN/TdeUgoZDOwpJ sACEu6DJGOnIWvhCKW0OVnw8hrEitbQC5tQz9YVTx2ejH9bDVn96NOSyhlvdNefp6z17zABlNUF 4qyGR6ezIJwaFa/6wtS0DYVYNM8+gGHWc2VjK7VLBH4KUkkAsFmk9F0xl0I87cgYZgWdh44pyge jLxj5Oa4qTkuqPfIZGEV8t+xZFHHKjHnp4P7oWDrnqJgAG26hj0Nv+fEuSr0tclsMTN/ap3OBJC wNxW0WcRdIeDHWQ== X-Mailer: b4 0.13.0 Message-ID: <20241122-vma-v9-8-7127bfcdd54e@google.com> Subject: [PATCH v9 8/8] task: rust: rework how current is accessed From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner , Jann Horn , Suren Baghdasaryan Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Introduce a new type called `CurrentTask` that lets you perform various operations that are only safe on the `current` task. Use the new type to provide a way to access the current mm without incrementing its refcount. With this change, you can write stuff such as let vma =3D current!().mm().lock_vma_under_rcu(addr); without incrementing any refcounts. Signed-off-by: Alice Ryhl Acked-by: Lorenzo Stoakes --- Reviewers: Does accessing task->mm on a non-current task require rcu protection? Christian: If you submit the PidNamespace abstractions this cycle, I'll update this to also apply to PidNamespace. --- rust/kernel/mm.rs | 22 ------------------ rust/kernel/task.rs | 64 ++++++++++++++++++++++++++++++++++++++++++-------= ---- 2 files changed, 51 insertions(+), 35 deletions(-) diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs index 50f4861ae4b9..f7d1079391ef 100644 --- a/rust/kernel/mm.rs +++ b/rust/kernel/mm.rs @@ -142,28 +142,6 @@ fn deref(&self) -> &MmWithUser { =20 // 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> { - // SAFETY: It's safe to get the `mm` field from current. - let mm =3D unsafe { - let current =3D bindings::get_current(); - (*current).mm - }; - - if mm.is_null() { - return None; - } - - // SAFETY: The value of `current->mm` is guaranteed to be null or = a valid `mm_struct`. We - // just checked that it's not null. Furthermore, the returned `&Mm= ` is valid only for the - // duration of this function, and `current->mm` will stay valid fo= r that long. - let mm =3D unsafe { Mm::from_raw(mm) }; - - // This increments the refcount using `mmgrab`. - Some(ARef::from(mm)) - } - /// Returns a raw pointer to the inner `mm_struct`. #[inline] pub fn as_raw(&self) -> *mut bindings::mm_struct { diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs index 9e59d86da42d..103d235eb844 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -94,6 +94,26 @@ unsafe impl Send for Task {} // synchronised by C code (e.g., `signal_pending`). unsafe impl Sync for Task {} =20 +/// Represents a [`Task`] obtained from the `current` global. +/// +/// This type exists to provide more efficient operations that are only va= lid on the current task. +/// For example, to retrieve the pid-namespace of a task, you must use rcu= protection unless it is +/// the current task. +/// +/// # Invariants +/// +/// Must be equal to `current` of some thread that is currently running so= mewhere. +pub struct CurrentTask(Task); + +// Make all `Task` methods available on `CurrentTask`. +impl Deref for CurrentTask { + type Target =3D Task; + #[inline] + fn deref(&self) -> &Task { + &self.0 + } +} + /// The type of process identifiers (PIDs). type Pid =3D bindings::pid_t; =20 @@ -121,27 +141,25 @@ pub fn current_raw() -> *mut bindings::task_struct { /// # Safety /// /// Callers must ensure that the returned object doesn't outlive the c= urrent task/thread. - pub unsafe fn current() -> impl Deref { - struct TaskRef<'a> { - task: &'a Task, - _not_send: NotThreadSafe, + pub unsafe fn current() -> impl Deref { + struct TaskRef { + task: *const CurrentTask, } =20 - impl Deref for TaskRef<'_> { - type Target =3D Task; + impl Deref for TaskRef { + type Target =3D CurrentTask; =20 fn deref(&self) -> &Self::Target { - self.task + // SAFETY: The returned reference borrows from this `TaskR= ef`, so it cannot outlive + // the `TaskRef`, which the caller of `Task::current()` ha= s promised will not + // outlive the task/thread for which `self.task` is the `c= urrent` pointer. Thus, it + // is okay to return a `CurrentTask` reference here. + unsafe { &*self.task } } } =20 - let current =3D Task::current_raw(); TaskRef { - // SAFETY: If the current thread is still running, the current= task is valid. Given - // that `TaskRef` is not `Send`, we know it cannot be transfer= red to another thread - // (where it could potentially outlive the caller). - task: unsafe { &*current.cast() }, - _not_send: NotThreadSafe, + task: Task::current_raw().cast(), } } =20 @@ -203,6 +221,26 @@ pub fn wake_up(&self) { } } =20 +impl CurrentTask { + /// Access the address space of this task. + /// + /// To increment the refcount of the referenced `mm`, you can use `ARe= f::from`. + #[inline] + pub fn mm(&self) -> Option<&MmWithUser> { + let mm =3D unsafe { (*self.as_ptr()).mm }; + + if mm.is_null() { + None + } else { + // SAFETY: If `current->mm` is non-null, then it references a = valid mm with a non-zero + // value of `mm_users`. The returned `&MmWithUser` borrows fro= m `CurrentTask`, so the + // `&MmWithUser` cannot escape the current task, meaning `mm_u= sers` can't reach zero + // while the reference is still live. + Some(unsafe { MmWithUser::from_raw(mm) }) + } + } +} + // SAFETY: The type invariants guarantee that `Task` is always refcounted. unsafe impl crate::types::AlwaysRefCounted for Task { fn inc_ref(&self) { --=20 2.47.0.371.ga323438b13-goog