From nobody Fri Apr 3 11:10:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D05AA31AAA3; Fri, 20 Feb 2026 09:52:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581126; cv=none; b=OBEg6R2aaAWA/35URZbVzzFCT3xdo1HLJtuJ3qReCMMOCC3tYaDXDRHf4O2qB48PdU7GBgegkLb0hL3L1iB86VgrF6O9caZgaVfcBu2vaJfZQEgK4/1v73qqg5SGcNgp6/MrDOvmwWD+2AQIg14Xo3yyC0VrKZqL1JgjAaunUiA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581126; c=relaxed/simple; bh=+PodXl/wwBV+PA5BRedOUZgBWeTtGynnDCp6iX2CeiQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VM8wuCrMeUT6GMIN3Lf5Bcz32GsS5lC3z/wCX38kSYgT48W+bxPd0nII10LbhLF9kHxXvOBPROo704Nrgc4wVR4b9F91hH0zgIR4FulV7+1EKzXMKH+wYfDjulzVvjWwFDpyRvqYK0frkARwV+qHSxMSlTusb3Jg4IQSLtCpw60= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ppi1/XPY; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ppi1/XPY" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CCB4AC116C6; Fri, 20 Feb 2026 09:51:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771581126; bh=+PodXl/wwBV+PA5BRedOUZgBWeTtGynnDCp6iX2CeiQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ppi1/XPYegHcMDBduaR2AnqAkljs+pg+qcNju89css9+XCAA0jXc1xa5GCd6lccdF sygwslGFM1sjSX+cc1WCOxc9MrsU8O9OAQSF7HWz6gzaDOzuDVDrgz/8jS0Yytcykm S/5/P/ZBaJZao2Ot0T5DiNLPV06ob5YYtkVhg+dZAAkYIGTGaiUz9puarlTz1QpKBT SihqUp4jb2y9DuxrgGlLS++EpC+3RSBEmYi2jPMC2kCINRotKFCfLxNHHS0P2WQ1Zz +alFa0pKOZvRtmwZd7zpfG7S+Z764JzwodHRmUqWBd4wHZ8Ihj35r6ODrJtkFOKUvc kXMjlj21r3OtQ== From: Andreas Hindborg Date: Fri, 20 Feb 2026 10:51:10 +0100 Subject: [PATCH v15 1/9] rust: types: Add Ownable/Owned types Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260220-unique-ref-v15-1-893ed86b06cc@kernel.org> References: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> In-Reply-To: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> To: Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Trevor Gross , Danilo Krummrich , Greg Kroah-Hartman , Dave Ertman , Ira Weiny , Leon Romanovsky , Paul Moore , Serge Hallyn , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Alexander Viro , Christian Brauner , Jan Kara , Igor Korotin , Daniel Almeida , Lorenzo Stoakes , "Liam R. Howlett" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Boqun Feng Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-block@vger.kernel.org, linux-security-module@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-pm@vger.kernel.org, linux-pci@vger.kernel.org, Andreas Hindborg , Asahi Lina , Oliver Mangold X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=11400; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=ceazmDY9zMprkGKe4DZha/pUGe1Tz44cJElMoCN5Ww8=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpmC6eV2ZYvrOTK3GwhcNVSnYwa0jqhZycgxRw5 QAdJb+eFTaJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZgungAKCRDhuBo+eShj d/e/EAC578jug50o8pjquFcaOzJNQRtvp4mbQZhiWMJ5iKm9oustdqkgktfqn0ktoOPq6qzDSAf nCit66IsOx8Y5QwgAwpn5vgRuyydcCmTf25MIVyMGUzAoVqwSFgGaKYgqUSXo0pyf5CNfPEp6LM KEWAtxej9ZRYs8lmvR9ioAPmKDqvmdTW/o3cbjkbhVg8ggJ4KardbP9cXSBrn4ZGotp4sFki8LP 4IHRo85AS/Occfn1IJ3K+iIQqvj1JnyuzSj+ZOZiS9ubqNbq3240QVNCdQ6lBGxFJZb/gWJirx6 0spbB8Rt+9F1zlcymRrZDeOHuoputD/1g6NkCwsHer8mOSW2kzZhnCYKaDBE2wVqguZ/g+HExDm D2VXlCtYClx/+6NFFdg2OOjJ4aOrw+JUFMgJSv8IHtiXgdgZ/tiEVggwcRCFCX0L4fXLR6IATd5 nghyX8WSexXNIv9kp25GkSSTtJvBuMJQIU1gkGP+e4BZyb4hi50P2jTxyuFZ5zxfbcOXFRxz8GS 68OhvCuxZCdAyb5E45zsp1a/wiwzEyVSa1JDadKJOaJ0xhqkvBUjWiuJ7R7SpSSFYsShWY1vo2m U7PewVmuduHLx6zTOAWTZfVI8lbOtLpSEmh+HK4Rd4CQ1/u51PHr7nnQRIzdUZRRA5dBUlH5ZOq z5YBURXQAJRbopg== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 From: Asahi Lina By analogy to `AlwaysRefCounted` and `ARef`, an `Ownable` type is a (typically C FFI) type that *may* be owned by Rust, but need not be. Unlike `AlwaysRefCounted`, this mechanism expects the reference to be unique within Rust, and does not allow cloning. Conceptually, this is similar to a `KBox`, except that it delegates resource management to the `T` instead of using a generic allocator. [ om: - Split code into separate file and `pub use` it from types.rs. - Make from_raw() and into_raw() public. - Remove OwnableMut, and make DerefMut dependent on Unpin instead. - Usage example/doctest for Ownable/Owned. - Fixes to documentation and commit message. ] Link: https://lore.kernel.org/all/20250202-rust-page-v1-1-e3170d7fe55e@asah= ilina.net/ Signed-off-by: Asahi Lina Co-developed-by: Oliver Mangold Signed-off-by: Oliver Mangold Reviewed-by: Boqun Feng Reviewed-by: Daniel Almeida [ Andreas: Updated documentation, examples, and formatting ] Reviewed-by: Gary Guo Co-developed-by: Andreas Hindborg Signed-off-by: Andreas Hindborg --- rust/kernel/lib.rs | 1 + rust/kernel/owned.rs | 196 +++++++++++++++++++++++++++++++++++++++++++= ++++ rust/kernel/sync/aref.rs | 5 ++ rust/kernel/types.rs | 11 ++- 4 files changed, 212 insertions(+), 1 deletion(-) diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 696f62f85eb5f..a2bec807f03f1 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -121,6 +121,7 @@ pub mod of; #[cfg(CONFIG_PM_OPP)] pub mod opp; +pub mod owned; pub mod page; #[cfg(CONFIG_PCI)] pub mod pci; diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs new file mode 100644 index 0000000000000..d566ad0aa1c99 --- /dev/null +++ b/rust/kernel/owned.rs @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Unique owned pointer types for objects with custom drop logic. +//! +//! These pointer types are useful for C-allocated objects which by API-co= ntract +//! are owned by Rust, but need to be freed through the C API. + +use core::{ + mem::ManuallyDrop, + ops::{ + Deref, + DerefMut, // + }, + pin::Pin, + ptr::NonNull, // +}; + +/// Types that specify their own way of performing allocation and destruct= ion. Typically, this trait +/// is implemented on types from the C side. +/// +/// Implementing this trait allows types to be referenced via the [`Owned<= Self>`] pointer type. This +/// is useful when it is desirable to tie the lifetime of the reference to= an owned object, rather +/// than pass around a bare reference. [`Ownable`] types can define custom= drop logic that is +/// executed when the owned reference [`Owned`] pointing to the obje= ct is dropped. +/// +/// Note: The underlying object is not required to provide internal refere= nce counting, because it +/// represents a unique, owned reference. If reference counting (on the Ru= st side) is required, +/// [`AlwaysRefCounted`](crate::types::AlwaysRefCounted) should be impleme= nted. +/// +/// # Safety +/// +/// Implementers must ensure that the [`release()`](Self::release) functio= n frees the underlying +/// object in the correct way for a valid, owned object of this type. +/// +/// # Examples +/// +/// A minimal example implementation of [`Ownable`] and its usage with [`O= wned`] looks like +/// this: +/// +/// ``` +/// # #![expect(clippy::disallowed_names)] +/// # use core::cell::Cell; +/// # use core::ptr::NonNull; +/// # use kernel::sync::global_lock; +/// # use kernel::alloc::{flags, kbox::KBox, AllocError}; +/// # use kernel::types::{Owned, Ownable}; +/// +/// // Let's count the allocations to see if freeing works. +/// kernel::sync::global_lock! { +/// // SAFETY: we call `init()` right below, before doing anything els= e. +/// unsafe(uninit) static FOO_ALLOC_COUNT: Mutex =3D 0; +/// } +/// // SAFETY: We call `init()` only once, here. +/// unsafe { FOO_ALLOC_COUNT.init() }; +/// +/// struct Foo; +/// +/// impl Foo { +/// fn new() -> Result> { +/// // We are just using a `KBox` here to handle the actual alloca= tion, as our `Foo` is +/// // not actually a C-allocated object. +/// let result =3D KBox::new( +/// Foo {}, +/// flags::GFP_KERNEL, +/// )?; +/// let result =3D NonNull::new(KBox::into_raw(result)) +/// .expect("Raw pointer to newly allocation KBox is null, thi= s should never happen."); +/// // Count new allocation +/// *FOO_ALLOC_COUNT.lock() +=3D 1; +/// // SAFETY: We just allocated the `Self`, thus it is valid and = there cannot be any other +/// // Rust references. Calling `into_raw()` makes us responsible = for ownership and we won't +/// // use the raw pointer anymore. Thus we can transfer ownership= to the `Owned`. +/// Ok(unsafe { Owned::from_raw(result) }) +/// } +/// } +/// +/// // SAFETY: The implementation of `release` in this trait implementatio= n correctly frees the +/// // owned `Foo`. +/// unsafe impl Ownable for Foo { +/// unsafe fn release(this: NonNull) { +/// // SAFETY: The [`KBox`] is still alive. We can pass owne= rship to the [`KBox`], as +/// // by requirement on calling this function, the `Self` will no= longer be used by the +/// // caller. +/// drop(unsafe { KBox::from_raw(this.as_ptr()) }); +/// // Count released allocation +/// *FOO_ALLOC_COUNT.lock() -=3D 1; +/// } +/// } +/// +/// { +/// let foo =3D Foo::new().expect("Failed to allocate a Foo. This shoul= dn't happen"); +/// assert!(*FOO_ALLOC_COUNT.lock() =3D=3D 1); +/// } +/// // `foo` is out of scope now, so we expect no live allocations. +/// assert!(*FOO_ALLOC_COUNT.lock() =3D=3D 0); +/// ``` +pub unsafe trait Ownable { + /// Releases the object. + /// + /// # Safety + /// + /// Callers must ensure that: + /// - `this` points to a valid `Self`. + /// - `*this` is no longer used after this call. + unsafe fn release(this: NonNull); +} + +/// A mutable reference to an owned `T`. +/// +/// The [`Ownable`] is automatically freed or released when an instance of= [`Owned`] is +/// dropped. +/// +/// # Invariants +/// +/// - The [`Owned`] has exclusive access to the instance of `T`. +/// - The instance of `T` will stay alive at least as long as the [`Owned<= T>`] is alive. +pub struct Owned { + ptr: NonNull, +} + +impl Owned { + /// Creates a new instance of [`Owned`]. + /// + /// This function takes over ownership of the underlying object. + /// + /// # Safety + /// + /// Callers must ensure that: + /// - `ptr` points to a valid instance of `T`. + /// - Ownership of the underlying `T` can be transferred to the `Self<= T>` (i.e. operations + /// which require ownership will be safe). + /// - An `Owned` is a mutable reference to the underlying object. A= s such, + /// the object must not be accessed (read or mutated) through any po= inter + /// other than the created `Owned`. Opt-out is still possible sim= ilar to + /// a mutable reference (e.g. by using [`Opaque`]). + /// + /// [`Opaque`]: kernel::types::Opaque + pub unsafe fn from_raw(ptr: NonNull) -> Self { + // INVARIANT: By function safety requirement: + // - The resulting object has exclusive access to the `T` pointed = to by `ptr`. + // - The `T` object pointed to by `ptr` is alive at least as long = as the returned `Self`. + Self { ptr } + } + + /// Consumes the [`Owned`], returning a raw pointer. + /// + /// This function does not drop the underlying `T`. When this function= returns, ownership of the + /// underlying `T` is with the caller. + pub fn into_raw(me: Self) -> NonNull { + ManuallyDrop::new(me).ptr + } + + /// Get a pinned mutable reference to the data owned by this `Owned= `. + pub fn as_pin_mut(&mut self) -> Pin<&mut T> { + // SAFETY: The type invariants guarantee that the object is valid,= and that we can safely + // return a mutable reference to it. + let unpinned =3D unsafe { self.ptr.as_mut() }; + + // SAFETY: We never hand out unpinned mutable references to the da= ta in + // `Self`, unless the contained type is `Unpin`. + unsafe { Pin::new_unchecked(unpinned) } + } +} + +// SAFETY: It is safe to send an [`Owned`] to another thread when the u= nderlying `T` is [`Send`], +// because of the ownership invariant. Sending an [`Owned`] is equivale= nt to sending the `T`. +unsafe impl Send for Owned {} + +// SAFETY: It is safe to send [`&Owned`] to another thread when the und= erlying `T` is [`Sync`], +// because of the ownership invariant. Sending an [`&Owned`] is equival= ent to sending the `&T`. +unsafe impl Sync for Owned {} + +impl Deref for Owned { + type Target =3D T; + + fn deref(&self) -> &Self::Target { + // SAFETY: The type invariants guarantee that the object is valid. + unsafe { self.ptr.as_ref() } + } +} + +impl DerefMut for Owned { + fn deref_mut(&mut self) -> &mut Self::Target { + // SAFETY: The type invariants guarantee that the object is valid,= and that we can safely + // return a mutable reference to it. + unsafe { self.ptr.as_mut() } + } +} + +impl Drop for Owned { + fn drop(&mut self) { + // SAFETY: The type invariants guarantee that the `Owned` owns the= object we're about to + // release. + unsafe { T::release(self.ptr) }; + } +} diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs index 0d24a0432015d..e175aefe86151 100644 --- a/rust/kernel/sync/aref.rs +++ b/rust/kernel/sync/aref.rs @@ -29,6 +29,11 @@ /// Rust code, the recommendation is to use [`Arc`](crate::sync::Arc) to c= reate reference-counted /// instances of a type. /// +/// Note: Implementing this trait allows types to be wrapped in an [`ARef<= Self>`]. It requires an +/// internal reference count and provides only shared references. If uniqu= e references are required +/// [`Ownable`](crate::types::Ownable) should be implemented which allows = types to be wrapped in an +/// [`Owned`](crate::types::Owned). +/// /// # Safety /// /// Implementers must ensure that increments to the reference count keep t= he object alive in memory diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index 9c5e7dbf16323..4aec7b699269a 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -11,7 +11,16 @@ }; use pin_init::{PinInit, Wrapper, Zeroable}; =20 -pub use crate::sync::aref::{ARef, AlwaysRefCounted}; +pub use crate::{ + owned::{ + Ownable, + Owned, // + }, + sync::aref::{ + ARef, + AlwaysRefCounted, // + }, // +}; =20 /// Used to transfer ownership to and from foreign (non-Rust) languages. /// --=20 2.51.2 From nobody Fri Apr 3 11:10:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8FD71313555; Fri, 20 Feb 2026 09:53:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581183; cv=none; b=uCstUmkEVyI8cBCfJKKzSNycjkWB+ViAqg2DAblnICv0R8Atu/rFY0e3GlPAHT7FphSI3NETAJxxZ3Y0ykXGz4o9a92HdZb3YUP2aI1zN3zQQu3WOJR6u/vg49D+OnyiR6mqi6qcmxeiXFPiR/FIcePTr5VbwlffwVQfBaFs25k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581183; c=relaxed/simple; bh=ddK1ak//TXQr8RhJb4UqmdreS3kf7nw+QCC2K6EoCxw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jyh6+hlkHqOaM0WFOYE2yspbn43TlzR5kQDoqNkFzK66RT+rWm0TiIFTvhndrKFTb14ymTfuxeeUONU8hJxLaRFDEWGPYBTVfGSx+odAdHTVISe0uqSMaaP/Z1fJtzAL8YWi4xbosa09dsSAflIbJg9yr8DrGyNrebUxn4XfJKw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IFtErZvi; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IFtErZvi" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 71A23C116C6; Fri, 20 Feb 2026 09:52:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771581183; bh=ddK1ak//TXQr8RhJb4UqmdreS3kf7nw+QCC2K6EoCxw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IFtErZviVRIApr6JWYfKXzVbkUGI6C+9RufmKoBvnZqEeLCDWkVI3Q/SJtdTbCzQR vgoQlixEpBPL+9yLVAiikQxNm396Ai5Il9xiFoxQthJVJzcotcQ7nI5XiwFIh0CQye gP6zB2PvlxB663nMuu3+MsHDV5ipt+0TGbWvMbDAontvp8TfivE+XHVAxEPdTFuB22 h2ReNknc2LOBLPSLDqPQ15nHesOVmBZexzoR93HVXhx33ms6LPJ0ifL3Tq1AteTKn/ rgsINYFvJsGYdZ5pojR2KIQK8DQsWBkZ1PtTsnxWSVi3Q+j8fHa8WlwSOrZRugyvSj RFYh/fAGImvBg== From: Andreas Hindborg Date: Fri, 20 Feb 2026 10:51:11 +0100 Subject: [PATCH v15 2/9] rust: rename `AlwaysRefCounted` to `RefCounted`. Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260220-unique-ref-v15-2-893ed86b06cc@kernel.org> References: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> In-Reply-To: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> To: Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Trevor Gross , Danilo Krummrich , Greg Kroah-Hartman , Dave Ertman , Ira Weiny , Leon Romanovsky , Paul Moore , Serge Hallyn , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Alexander Viro , Christian Brauner , Jan Kara , Igor Korotin , Daniel Almeida , Lorenzo Stoakes , "Liam R. Howlett" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Boqun Feng Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-block@vger.kernel.org, linux-security-module@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-pm@vger.kernel.org, linux-pci@vger.kernel.org, Andreas Hindborg , Oliver Mangold , Viresh Kumar X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=34430; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=rrFhqQU4IAhH0CwwR7UUnxUjhCeP2K7g8e+HurhZR8Y=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpmC6fMCX27NHQuaTFZouXnIyuw2rXNVorCpirC nZ8sP1GM26JAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZgunwAKCRDhuBo+eShj d8l2D/9MD4TS4CpKaoxKHuZEf/zrYfO+kjBz0KKeSa4OEoyT7aE7TbwtMwPAh+nfGD/weyi+Rka gQ2G5HZ/JE/6qTY14ApsC3tqiyW9prOkSBbY7iW0HemUWp8/biRmZRspIvhnCMG1M9vy52j8xTf dVcKg3lQBLah78mqZWx4tRjOWFN7yu59RNq+OjLl4BCWQPYF6V545CSxi9aSWjSjafshA32M3DH 66/nAGtmMiH9gRKSHbekNyHU4VCc4ca98QRYePObvT3gHRcM6IETZIM7mwV5TQO1vLh6+dv7vNj C1aXO3G7VyVP62+ConUn0aTzPCb+c/gbZCW6AMIcZMl3F22rg+1uas61nnW/ER7XrAWUH2U8BJx w99K8sGUFeAxMJ+5La5DR9J++AP+sLoz2qZEwMSTAUFrrNK068cEUutnqeZFZ1TiHc2MnrEJ5na R0+Tv8QHU3zroFYs8VT1kaltT5EnLTOPElU1bG6WU35+/SV0HetW6PCrVnt8eRnCmenu1lr30zw jawJQyuBySmIznRkhvM58Vd/iB6v0oZF6mII1y55IW+6lRYBmbiXLzzh6t1S/IXQX9BgHJFVyJc EkGI4EtC+NgIF5Af6fiHqEIOL91B75DhnLoENeuhG5W/bSu9XuO/qjj2BUbQwgVbqi+OujUPSXa oRsQSb1tT3x9u7w== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 From: Oliver Mangold There are types where it may both be reference counted in some cases and owned in others. In such cases, obtaining `ARef` from `&T` would be unsound as it allows creation of `ARef` copy from `&Owned`. Therefore, we split `AlwaysRefCounted` into `RefCounted` (which `ARef` would require) and a marker trait to indicate that the type is always reference counted (and not `Ownable`) so the `&T` -> `ARef` conversion is possible. - Rename `AlwaysRefCounted` to `RefCounted`. - Add a new unsafe trait `AlwaysRefCounted`. - Implement the new trait `AlwaysRefCounted` for the newly renamed `RefCounted` implementations. This leaves functionality of existing implementers of `AlwaysRefCounted` intact. Suggested-by: Alice Ryhl Reviewed-by: Daniel Almeida Signed-off-by: Oliver Mangold [ Andreas: Updated commit message and rebase on rust-6.20-7.0 ] Acked-by: Igor Korotin Acked-by: Danilo Krummrich Acked-by: Viresh Kumar Reviewed-by: Gary Guo Co-developed-by: Andreas Hindborg Signed-off-by: Andreas Hindborg --- rust/kernel/auxiliary.rs | 7 +++++- rust/kernel/block/mq/request.rs | 15 +++++++------ rust/kernel/cred.rs | 13 ++++++++++-- rust/kernel/device.rs | 10 ++++++--- rust/kernel/device/property.rs | 7 +++++- rust/kernel/drm/device.rs | 10 ++++++--- rust/kernel/drm/gem/mod.rs | 8 ++++--- rust/kernel/fs/file.rs | 16 ++++++++++---- rust/kernel/i2c.rs | 16 +++++++++----- rust/kernel/mm.rs | 15 +++++++++---- rust/kernel/mm/mmput_async.rs | 9 ++++++-- rust/kernel/opp.rs | 10 ++++++--- rust/kernel/owned.rs | 2 +- rust/kernel/pci.rs | 10 ++++++++- rust/kernel/pid_namespace.rs | 12 +++++++++-- rust/kernel/platform.rs | 7 +++++- rust/kernel/sync/aref.rs | 47 ++++++++++++++++++++++++++-----------= ---- rust/kernel/task.rs | 10 ++++++--- rust/kernel/types.rs | 3 ++- rust/kernel/usb.rs | 15 ++++++++++--- 20 files changed, 176 insertions(+), 66 deletions(-) diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index 56f3c180e8f69..234003341294f 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -11,6 +11,7 @@ driver, error::{from_result, to_result, Result}, prelude::*, + sync::aref::{AlwaysRefCounted, RefCounted}, types::Opaque, ThisModule, }; @@ -258,7 +259,7 @@ unsafe impl device::AsBusDe= vice for Device kernel::impl_device_context_into_aref!(Device); =20 // SAFETY: Instances of `Device` are always reference-counted. -unsafe impl crate::sync::aref::AlwaysRefCounted for Device { +unsafe impl RefCounted for Device { fn inc_ref(&self) { // SAFETY: The existence of a shared reference guarantees that the= refcount is non-zero. unsafe { bindings::get_device(self.as_ref().as_raw()) }; @@ -277,6 +278,10 @@ unsafe fn dec_ref(obj: NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a +// `&Device`. +unsafe impl AlwaysRefCounted for Device {} + impl AsRef> for Device { fn as_ref(&self) -> &device::Device { // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a p= ointer to a valid diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request= .rs index ce3e30c81cb5e..cf013b9e2cacf 100644 --- a/rust/kernel/block/mq/request.rs +++ b/rust/kernel/block/mq/request.rs @@ -9,7 +9,7 @@ block::mq::Operations, error::Result, sync::{ - aref::{ARef, AlwaysRefCounted}, + aref::{ARef, AlwaysRefCounted, RefCounted}, atomic::Relaxed, Refcount, }, @@ -229,11 +229,10 @@ unsafe impl Send for Request {} // mutate `self` are internally synchronized` unsafe impl Sync for Request {} =20 -// SAFETY: All instances of `Request` are reference counted. This -// implementation of `AlwaysRefCounted` ensure that increments to the ref = count -// keeps the object alive in memory at least until a matching reference co= unt -// decrement is executed. -unsafe impl AlwaysRefCounted for Request { +// SAFETY: All instances of `Request` are reference counted. This imple= mentation of `RefCounted` +// ensure that increments to the ref count keeps the object alive in memor= y at least until a +// matching reference count decrement is executed. +unsafe impl RefCounted for Request { fn inc_ref(&self) { self.wrapper_ref().refcount().inc(); } @@ -255,3 +254,7 @@ unsafe fn dec_ref(obj: core::ptr::NonNull) { } } } + +// SAFETY: We currently do not implement `Ownable`, thus it is okay to obt= ain an `ARef` +// from a `&Request` (but this will change in the future). +unsafe impl AlwaysRefCounted for Request {} diff --git a/rust/kernel/cred.rs b/rust/kernel/cred.rs index ffa156b9df377..20ef0144094be 100644 --- a/rust/kernel/cred.rs +++ b/rust/kernel/cred.rs @@ -8,7 +8,12 @@ //! //! Reference: =20 -use crate::{bindings, sync::aref::AlwaysRefCounted, task::Kuid, types::Opa= que}; +use crate::{ + bindings, + sync::aref::RefCounted, + task::Kuid, + types::{AlwaysRefCounted, Opaque}, +}; =20 /// Wraps the kernel's `struct cred`. /// @@ -76,7 +81,7 @@ pub fn euid(&self) -> Kuid { } =20 // SAFETY: The type invariants guarantee that `Credential` is always ref-c= ounted. -unsafe impl AlwaysRefCounted for Credential { +unsafe impl RefCounted for Credential { #[inline] fn inc_ref(&self) { // SAFETY: The existence of a shared reference means that the refc= ount is nonzero. @@ -90,3 +95,7 @@ unsafe fn dec_ref(obj: core::ptr::NonNull) { unsafe { bindings::put_cred(obj.cast().as_ptr()) }; } } + +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a +// `&Credential`. +unsafe impl AlwaysRefCounted for Credential {} diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index 71b200df0f400..2a3bed19b9495 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -7,8 +7,8 @@ use crate::{ bindings, fmt, prelude::*, - sync::aref::ARef, - types::{ForeignOwnable, Opaque}, + sync::aref::{ARef, RefCounted}, + types::{AlwaysRefCounted, ForeignOwnable, Opaque}, }; use core::{any::TypeId, marker::PhantomData, ptr}; =20 @@ -490,7 +490,7 @@ pub fn fwnode(&self) -> Option<&property::FwNode> { kernel::impl_device_context_into_aref!(Device); =20 // SAFETY: Instances of `Device` are always reference-counted. -unsafe impl crate::sync::aref::AlwaysRefCounted for Device { +unsafe impl RefCounted for Device { fn inc_ref(&self) { // SAFETY: The existence of a shared reference guarantees that the= refcount is non-zero. unsafe { bindings::get_device(self.as_raw()) }; @@ -502,6 +502,10 @@ unsafe fn dec_ref(obj: ptr::NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a +// `&Device`. +unsafe impl AlwaysRefCounted for Device {} + // SAFETY: As by the type invariant `Device` can be sent to any thread. unsafe impl Send for Device {} =20 diff --git a/rust/kernel/device/property.rs b/rust/kernel/device/property.rs index 3a332a8c53a9e..a8bb824ad0ec1 100644 --- a/rust/kernel/device/property.rs +++ b/rust/kernel/device/property.rs @@ -14,6 +14,7 @@ fmt, prelude::*, str::{CStr, CString}, + sync::aref::{AlwaysRefCounted, RefCounted}, types::{ARef, Opaque}, }; =20 @@ -359,7 +360,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Resul= t { } =20 // SAFETY: Instances of `FwNode` are always reference-counted. -unsafe impl crate::types::AlwaysRefCounted for FwNode { +unsafe impl RefCounted for FwNode { fn inc_ref(&self) { // SAFETY: The existence of a shared reference guarantees that the // refcount is non-zero. @@ -373,6 +374,10 @@ unsafe fn dec_ref(obj: ptr::NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a +// `&FwNode`. +unsafe impl AlwaysRefCounted for FwNode {} + enum Node<'a> { Borrowed(&'a FwNode), Owned(ARef), diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs index 3ce8f62a00569..38ce7f389ed00 100644 --- a/rust/kernel/drm/device.rs +++ b/rust/kernel/drm/device.rs @@ -11,8 +11,8 @@ error::from_err_ptr, error::Result, prelude::*, - sync::aref::{ARef, AlwaysRefCounted}, - types::Opaque, + sync::aref::{AlwaysRefCounted, RefCounted}, + types::{ARef, Opaque}, }; use core::{alloc::Layout, mem, ops::Deref, ptr, ptr::NonNull}; =20 @@ -198,7 +198,7 @@ fn deref(&self) -> &Self::Target { =20 // SAFETY: DRM device objects are always reference counted and the get/put= functions // satisfy the requirements. -unsafe impl AlwaysRefCounted for Device { +unsafe impl RefCounted for Device { fn inc_ref(&self) { // SAFETY: The existence of a shared reference guarantees that the= refcount is non-zero. unsafe { bindings::drm_dev_get(self.as_raw()) }; @@ -213,6 +213,10 @@ unsafe fn dec_ref(obj: NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a +// `&Device`. +unsafe impl AlwaysRefCounted for Device {} + impl AsRef for Device { fn as_ref(&self) -> &device::Device { // SAFETY: `bindings::drm_device::dev` is valid as long as the DRM= device itself is valid, diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index a7f682e95c018..ad6840a440165 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -10,8 +10,7 @@ drm::driver::{AllocImpl, AllocOps}, error::{to_result, Result}, prelude::*, - sync::aref::{ARef, AlwaysRefCounted}, - types::Opaque, + types::{ARef, AlwaysRefCounted, Opaque}, }; use core::{ops::Deref, ptr::NonNull}; =20 @@ -253,7 +252,7 @@ extern "C" fn free_callback(obj: *mut bindings::drm_gem= _object) { } =20 // SAFETY: Instances of `Object` are always reference-counted. -unsafe impl crate::types::AlwaysRefCounted for Object { +unsafe impl crate::types::RefCounted for Object { fn inc_ref(&self) { // SAFETY: The existence of a shared reference guarantees that the= refcount is non-zero. unsafe { bindings::drm_gem_object_get(self.as_raw()) }; @@ -267,6 +266,9 @@ unsafe fn dec_ref(obj: NonNull) { unsafe { bindings::drm_gem_object_put(obj.as_raw()) } } } +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a +// `&Object`. +unsafe impl crate::types::AlwaysRefCounted for Object = {} =20 impl super::private::Sealed for Object {} =20 diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 23ee689bd2400..06e457d62a939 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -12,8 +12,8 @@ cred::Credential, error::{code::*, to_result, Error, Result}, fmt, - sync::aref::{ARef, AlwaysRefCounted}, - types::{NotThreadSafe, Opaque}, + sync::aref::RefCounted, + types::{ARef, AlwaysRefCounted, NotThreadSafe, Opaque}, }; use core::ptr; =20 @@ -197,7 +197,7 @@ unsafe impl Sync for File {} =20 // SAFETY: The type invariants guarantee that `File` is always ref-counted= . This implementation // makes `ARef` own a normal refcount. -unsafe impl AlwaysRefCounted for File { +unsafe impl RefCounted for File { #[inline] fn inc_ref(&self) { // SAFETY: The existence of a shared reference means that the refc= ount is nonzero. @@ -212,6 +212,10 @@ unsafe fn dec_ref(obj: ptr::NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a +// `&File`. +unsafe impl AlwaysRefCounted for File {} + /// Wraps the kernel's `struct file`. Not thread safe. /// /// This type represents a file that is not known to be safe to transfer a= cross thread boundaries. @@ -233,7 +237,7 @@ pub struct LocalFile { =20 // SAFETY: The type invariants guarantee that `LocalFile` is always ref-co= unted. This implementation // makes `ARef` own a normal refcount. -unsafe impl AlwaysRefCounted for LocalFile { +unsafe impl RefCounted for LocalFile { #[inline] fn inc_ref(&self) { // SAFETY: The existence of a shared reference means that the refc= ount is nonzero. @@ -249,6 +253,10 @@ unsafe fn dec_ref(obj: ptr::NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a +// `&LocalFile`. +unsafe impl AlwaysRefCounted for LocalFile {} + impl LocalFile { /// Constructs a new `struct file` wrapper from a file descriptor. /// diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 792a71b154630..683950057423d 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -17,8 +17,10 @@ of, prelude::*, types::{ + ARef, AlwaysRefCounted, - Opaque, // + Opaque, + RefCounted, // }, // }; =20 @@ -31,8 +33,6 @@ }, // }; =20 -use kernel::types::ARef; - /// An I2C device id table. #[repr(transparent)] #[derive(Clone, Copy)] @@ -407,7 +407,7 @@ pub fn get(index: i32) -> Result> { kernel::impl_device_context_into_aref!(I2cAdapter); =20 // SAFETY: Instances of `I2cAdapter` are always reference-counted. -unsafe impl crate::types::AlwaysRefCounted for I2cAdapter { +unsafe impl crate::types::RefCounted for I2cAdapter { fn inc_ref(&self) { // SAFETY: The existence of a shared reference guarantees that the= refcount is non-zero. unsafe { bindings::i2c_get_adapter(self.index()) }; @@ -418,6 +418,9 @@ unsafe fn dec_ref(obj: NonNull) { unsafe { bindings::i2c_put_adapter(obj.as_ref().as_raw()) } } } +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from an +// `&I2cAdapter`. +unsafe impl AlwaysRefCounted for I2cAdapter {} =20 /// The i2c board info representation /// @@ -483,7 +486,7 @@ unsafe impl device::AsBusDe= vice for I2cClient) { unsafe { bindings::put_device(&raw mut (*obj.as_ref().as_raw()).de= v) } } } +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from an +// `&I2cClient`. +unsafe impl AlwaysRefCounted for I2cClient {} =20 impl AsRef> for I2cClient<= Ctx> { fn as_ref(&self) -> &device::Device { diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs index 4764d7b68f2a7..dd9e3969e7206 100644 --- a/rust/kernel/mm.rs +++ b/rust/kernel/mm.rs @@ -13,8 +13,8 @@ =20 use crate::{ bindings, - sync::aref::{ARef, AlwaysRefCounted}, - types::{NotThreadSafe, Opaque}, + sync::aref::RefCounted, + types::{ARef, AlwaysRefCounted, NotThreadSafe, Opaque}, }; use core::{ops::Deref, ptr::NonNull}; =20 @@ -55,7 +55,7 @@ unsafe impl Send for Mm {} unsafe impl Sync for Mm {} =20 // SAFETY: By the type invariants, this type is always refcounted. -unsafe impl AlwaysRefCounted for Mm { +unsafe impl RefCounted for Mm { #[inline] fn inc_ref(&self) { // SAFETY: The pointer is valid since self is a reference. @@ -69,6 +69,9 @@ unsafe fn dec_ref(obj: NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a `&Mm`. +unsafe impl AlwaysRefCounted for Mm {} + /// 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 @@ -91,7 +94,7 @@ unsafe impl Send for MmWithUser {} unsafe impl Sync for MmWithUser {} =20 // SAFETY: By the type invariants, this type is always refcounted. -unsafe impl AlwaysRefCounted for MmWithUser { +unsafe impl RefCounted for MmWithUser { #[inline] fn inc_ref(&self) { // SAFETY: The pointer is valid since self is a reference. @@ -105,6 +108,10 @@ unsafe fn dec_ref(obj: NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a +// `&MmWithUser`. +unsafe impl AlwaysRefCounted for MmWithUser {} + // Make all `Mm` methods available on `MmWithUser`. impl Deref for MmWithUser { type Target =3D Mm; diff --git a/rust/kernel/mm/mmput_async.rs b/rust/kernel/mm/mmput_async.rs index b8d2f051225c7..aba4ce675c860 100644 --- a/rust/kernel/mm/mmput_async.rs +++ b/rust/kernel/mm/mmput_async.rs @@ -10,7 +10,8 @@ use crate::{ bindings, mm::MmWithUser, - sync::aref::{ARef, AlwaysRefCounted}, + sync::aref::RefCounted, + types::{ARef, AlwaysRefCounted}, }; use core::{ops::Deref, ptr::NonNull}; =20 @@ -34,7 +35,7 @@ unsafe impl Send for MmWithUserAsync {} unsafe impl Sync for MmWithUserAsync {} =20 // SAFETY: By the type invariants, this type is always refcounted. -unsafe impl AlwaysRefCounted for MmWithUserAsync { +unsafe impl RefCounted for MmWithUserAsync { #[inline] fn inc_ref(&self) { // SAFETY: The pointer is valid since self is a reference. @@ -48,6 +49,10 @@ unsafe fn dec_ref(obj: NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` +// from a `&MmWithUserAsync`. +unsafe impl AlwaysRefCounted for MmWithUserAsync {} + // Make all `MmWithUser` methods available on `MmWithUserAsync`. impl Deref for MmWithUserAsync { type Target =3D MmWithUser; diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs index a760fac287655..06fe2ca776a4f 100644 --- a/rust/kernel/opp.rs +++ b/rust/kernel/opp.rs @@ -16,8 +16,8 @@ ffi::{c_char, c_ulong}, prelude::*, str::CString, - sync::aref::{ARef, AlwaysRefCounted}, - types::Opaque, + sync::aref::RefCounted, + types::{ARef, AlwaysRefCounted, Opaque}, }; =20 #[cfg(CONFIG_CPU_FREQ)] @@ -1041,7 +1041,7 @@ unsafe impl Send for OPP {} unsafe impl Sync for OPP {} =20 /// SAFETY: The type invariants guarantee that [`OPP`] is always refcounte= d. -unsafe impl AlwaysRefCounted for OPP { +unsafe impl RefCounted for OPP { fn inc_ref(&self) { // SAFETY: The existence of a shared reference means that the refc= ount is nonzero. unsafe { bindings::dev_pm_opp_get(self.0.get()) }; @@ -1053,6 +1053,10 @@ unsafe fn dec_ref(obj: ptr::NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from an +// `&OPP`. +unsafe impl AlwaysRefCounted for OPP {} + impl OPP { /// Creates an owned reference to a [`OPP`] from a valid pointer. /// diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs index d566ad0aa1c99..b8d3b9c725cf6 100644 --- a/rust/kernel/owned.rs +++ b/rust/kernel/owned.rs @@ -25,7 +25,7 @@ /// /// Note: The underlying object is not required to provide internal refere= nce counting, because it /// represents a unique, owned reference. If reference counting (on the Ru= st side) is required, -/// [`AlwaysRefCounted`](crate::types::AlwaysRefCounted) should be impleme= nted. +/// [`RefCounted`](crate::types::RefCounted) should be implemented. /// /// # Safety /// diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 82e128431f080..a73551dedee8f 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -19,6 +19,10 @@ }, prelude::*, str::CStr, + sync::aref::{ + AlwaysRefCounted, + RefCounted, // + }, types::Opaque, ThisModule, // }; @@ -458,7 +462,7 @@ unsafe impl device::AsBusDe= vice for Device impl crate::dma::Device for Device {} =20 // SAFETY: Instances of `Device` are always reference-counted. -unsafe impl crate::sync::aref::AlwaysRefCounted for Device { +unsafe impl RefCounted for Device { fn inc_ref(&self) { // SAFETY: The existence of a shared reference guarantees that the= refcount is non-zero. unsafe { bindings::pci_dev_get(self.as_raw()) }; @@ -470,6 +474,10 @@ unsafe fn dec_ref(obj: NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a +// `&Device`. +unsafe impl AlwaysRefCounted for Device {} + impl AsRef> for Device { fn as_ref(&self) -> &device::Device { // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a p= ointer to a valid diff --git a/rust/kernel/pid_namespace.rs b/rust/kernel/pid_namespace.rs index 979a9718f153d..4f6a94540e33d 100644 --- a/rust/kernel/pid_namespace.rs +++ b/rust/kernel/pid_namespace.rs @@ -7,7 +7,11 @@ //! C header: [`include/linux/pid_namespace.h`](srctree/include/linux/pid_= namespace.h) and //! [`include/linux/pid.h`](srctree/include/linux/pid.h) =20 -use crate::{bindings, sync::aref::AlwaysRefCounted, types::Opaque}; +use crate::{ + bindings, + sync::aref::RefCounted, + types::{AlwaysRefCounted, Opaque}, +}; use core::ptr; =20 /// Wraps the kernel's `struct pid_namespace`. Thread safe. @@ -41,7 +45,7 @@ pub unsafe fn from_ptr<'a>(ptr: *const bindings::pid_name= space) -> &'a Self { } =20 // SAFETY: Instances of `PidNamespace` are always reference-counted. -unsafe impl AlwaysRefCounted for PidNamespace { +unsafe impl RefCounted for PidNamespace { #[inline] fn inc_ref(&self) { // SAFETY: The existence of a shared reference means that the refc= ount is nonzero. @@ -55,6 +59,10 @@ unsafe fn dec_ref(obj: ptr::NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from +// a `&PidNamespace`. +unsafe impl AlwaysRefCounted for PidNamespace {} + // SAFETY: // - `PidNamespace::dec_ref` can be called from any thread. // - It is okay to send ownership of `PidNamespace` across thread boundari= es. diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index ed889f079cab6..9f1cd0b8fb0bc 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -13,6 +13,7 @@ irq::{self, IrqRequest}, of, prelude::*, + sync::aref::{AlwaysRefCounted, RefCounted}, types::Opaque, ThisModule, }; @@ -481,7 +482,7 @@ pub fn optional_irq_by_name(&self, name: &CStr) -> Resu= lt> { impl crate::dma::Device for Device {} =20 // SAFETY: Instances of `Device` are always reference-counted. -unsafe impl crate::sync::aref::AlwaysRefCounted for Device { +unsafe impl RefCounted for Device { fn inc_ref(&self) { // SAFETY: The existence of a shared reference guarantees that the= refcount is non-zero. unsafe { bindings::get_device(self.as_ref().as_raw()) }; @@ -493,6 +494,10 @@ unsafe fn dec_ref(obj: NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a +// `&Device`. +unsafe impl AlwaysRefCounted for Device {} + impl AsRef> for Device { fn as_ref(&self) -> &device::Device { // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a p= ointer to a valid diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs index e175aefe86151..61caddfd89619 100644 --- a/rust/kernel/sync/aref.rs +++ b/rust/kernel/sync/aref.rs @@ -19,11 +19,9 @@ =20 use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNul= l}; =20 -/// Types that are _always_ reference counted. +/// Types that are internally reference counted. /// /// It allows such types to define their own custom ref increment and decr= ement functions. -/// Additionally, it allows users to convert from a shared reference `&T` = to an owned reference -/// [`ARef`]. /// /// This is usually implemented by wrappers to existing structures on the = C side of the code. For /// Rust code, the recommendation is to use [`Arc`](crate::sync::Arc) to c= reate reference-counted @@ -40,9 +38,8 @@ /// at least until matching decrements are performed. /// /// Implementers must also ensure that all instances are reference-counted= . (Otherwise they -/// won't be able to honour the requirement that [`AlwaysRefCounted::inc_r= ef`] keep the object -/// alive.) -pub unsafe trait AlwaysRefCounted { +/// won't be able to honour the requirement that [`RefCounted::inc_ref`] k= eep the object alive.) +pub unsafe trait RefCounted { /// Increments the reference count on the object. fn inc_ref(&self); =20 @@ -55,11 +52,27 @@ pub unsafe trait AlwaysRefCounted { /// Callers must ensure that there was a previous matching increment t= o the reference count, /// and that the object is no longer used after its reference count is= decremented (as it may /// result in the object being freed), unless the caller owns another = increment on the refcount - /// (e.g., it calls [`AlwaysRefCounted::inc_ref`] twice, then calls - /// [`AlwaysRefCounted::dec_ref`] once). + /// (e.g., it calls [`RefCounted::inc_ref`] twice, then calls [`RefCou= nted::dec_ref`] once). unsafe fn dec_ref(obj: NonNull); } =20 +/// Always reference-counted type. +/// +/// It allows deriving a counted reference [`ARef`] from a `&T`. +/// +/// This provides some convenience, but it allows "escaping" borrow checks= on `&T`. As it +/// complicates attempts to ensure that a reference to T is unique, it is = optional to provide for +/// [`RefCounted`] types. See *Safety* below. +/// +/// # Safety +/// +/// Implementers must ensure that no safety invariants are violated by upg= rading an `&T` to an +/// [`ARef`]. In particular that implies [`AlwaysRefCounted`] and [`cra= te::types::Ownable`] +/// cannot be implemented for the same type, as this would allow violating= the uniqueness guarantee +/// of [`crate::types::Owned`] by dereferencing it into an `&T` and obt= aining an [`ARef`] from +/// that. +pub unsafe trait AlwaysRefCounted: RefCounted {} + /// An owned reference to an always-reference-counted object. /// /// The object's reference count is automatically decremented when an inst= ance of [`ARef`] is @@ -70,7 +83,7 @@ pub unsafe trait AlwaysRefCounted { /// /// The pointer stored in `ptr` is non-null and valid for the lifetime of = the [`ARef`] instance. In /// particular, the [`ARef`] instance owns an increment on the underlying = object's reference count. -pub struct ARef { +pub struct ARef { ptr: NonNull, _p: PhantomData, } @@ -79,16 +92,16 @@ pub struct ARef { // it effectively means sharing `&T` (which is safe because `T` is `Sync`)= ; additionally, it needs // `T` to be `Send` because any thread that has an `ARef` may ultimatel= y access `T` using a // mutable reference, for example, when the reference count reaches zero a= nd `T` is dropped. -unsafe impl Send for ARef {} +unsafe impl Send for ARef {} =20 // SAFETY: It is safe to send `&ARef` to another thread when the underl= ying `T` is `Sync` // because it effectively means sharing `&T` (which is safe because `T` is= `Sync`); additionally, // it needs `T` to be `Send` because any thread that has a `&ARef` may = clone it and get an // `ARef` on that thread, so the thread may ultimately access `T` using= a mutable reference, for // example, when the reference count reaches zero and `T` is dropped. -unsafe impl Sync for ARef {} +unsafe impl Sync for ARef {} =20 -impl ARef { +impl ARef { /// Creates a new instance of [`ARef`]. /// /// It takes over an increment of the reference count on the underlyin= g object. @@ -117,12 +130,12 @@ pub unsafe fn from_raw(ptr: NonNull) -> Self { /// /// ``` /// use core::ptr::NonNull; - /// use kernel::sync::aref::{ARef, AlwaysRefCounted}; + /// use kernel::sync::aref::{ARef, RefCounted}; /// /// struct Empty {} /// /// # // SAFETY: TODO. - /// unsafe impl AlwaysRefCounted for Empty { + /// unsafe impl RefCounted for Empty { /// fn inc_ref(&self) {} /// unsafe fn dec_ref(_obj: NonNull) {} /// } @@ -140,7 +153,7 @@ pub fn into_raw(me: Self) -> NonNull { } } =20 -impl Clone for ARef { +impl Clone for ARef { fn clone(&self) -> Self { self.inc_ref(); // SAFETY: We just incremented the refcount above. @@ -148,7 +161,7 @@ fn clone(&self) -> Self { } } =20 -impl Deref for ARef { +impl Deref for ARef { type Target =3D T; =20 fn deref(&self) -> &Self::Target { @@ -165,7 +178,7 @@ fn from(b: &T) -> Self { } } =20 -impl Drop for ARef { +impl Drop for ARef { fn drop(&mut self) { // SAFETY: The type invariants guarantee that the `ARef` owns the = reference we're about to // decrement. diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs index 49fad6de06740..0a6e38d984560 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -9,8 +9,8 @@ ffi::{c_int, c_long, c_uint}, mm::MmWithUser, pid_namespace::PidNamespace, - sync::aref::ARef, - types::{NotThreadSafe, Opaque}, + sync::aref::{AlwaysRefCounted, RefCounted}, + types::{ARef, NotThreadSafe, Opaque}, }; use core::{ cmp::{Eq, PartialEq}, @@ -348,7 +348,7 @@ pub fn active_pid_ns(&self) -> Option<&PidNamespace> { } =20 // SAFETY: The type invariants guarantee that `Task` is always refcounted. -unsafe impl crate::sync::aref::AlwaysRefCounted for Task { +unsafe impl RefCounted for Task { #[inline] fn inc_ref(&self) { // SAFETY: The existence of a shared reference means that the refc= ount is nonzero. @@ -362,6 +362,10 @@ unsafe fn dec_ref(obj: ptr::NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a +// `&Task`. +unsafe impl AlwaysRefCounted for Task {} + impl Kuid { /// Get the current euid. #[inline] diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index 4aec7b699269a..9b96aa2ebdb7e 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -18,7 +18,8 @@ }, sync::aref::{ ARef, - AlwaysRefCounted, // + AlwaysRefCounted, + RefCounted, // }, // }; =20 diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs index d10b65e9fb6ad..089823b608333 100644 --- a/rust/kernel/usb.rs +++ b/rust/kernel/usb.rs @@ -12,7 +12,8 @@ error::{from_result, to_result, Result}, prelude::*, str::CStr, - types::{AlwaysRefCounted, Opaque}, + sync::aref::{AlwaysRefCounted, RefCounted}, + types::Opaque, ThisModule, }; use core::{ @@ -365,7 +366,7 @@ fn as_ref(&self) -> &Device { } =20 // SAFETY: Instances of `Interface` are always reference-counted. -unsafe impl AlwaysRefCounted for Interface { +unsafe impl RefCounted for Interface { fn inc_ref(&self) { // SAFETY: The invariants of `Interface` guarantee that `self.as_r= aw()` // returns a valid `struct usb_interface` pointer, for which we wi= ll @@ -379,6 +380,10 @@ unsafe fn dec_ref(obj: NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a +// `&Interface`. +unsafe impl AlwaysRefCounted for Interface {} + // SAFETY: A `Interface` is always reference-counted and can be released f= rom any thread. unsafe impl Send for Interface {} =20 @@ -416,7 +421,7 @@ fn as_raw(&self) -> *mut bindings::usb_device { kernel::impl_device_context_into_aref!(Device); =20 // SAFETY: Instances of `Device` are always reference-counted. -unsafe impl AlwaysRefCounted for Device { +unsafe impl RefCounted for Device { fn inc_ref(&self) { // SAFETY: The invariants of `Device` guarantee that `self.as_raw(= )` // returns a valid `struct usb_device` pointer, for which we will @@ -430,6 +435,10 @@ unsafe fn dec_ref(obj: NonNull) { } } =20 +// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `AR= ef` from a +// `&Device`. +unsafe impl AlwaysRefCounted for Device {} + impl AsRef> for Device { fn as_ref(&self) -> &device::Device { // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a p= ointer to a valid --=20 2.51.2 From nobody Fri Apr 3 11:10:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 43A4F313555; Fri, 20 Feb 2026 09:52:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581150; cv=none; b=pJDZKuE1cBMBF8aAnMI3oeaeFymV2tWw5DKTQ2lNQd0qybzOryJ/MwRl4c14HuY+kOURG+gJC2c1cWVaU7/acQaX0BpO02/rYFmgv9DI8wPBeVIGfVHLH6itfHOjYQ+xOVTPaET3FG6WciFUTPoCVZboCiSN3jgBLDFknCt6Sek= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581150; c=relaxed/simple; bh=p1tAAxGtFcTpyH8kJIKfeUGx7oWCMIhnPZTORNKDSkA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=i7WkwltfO4W14TRFBxaOgfgMHKHhKr0FTo840VW3C7QdmB0VY0vFQgYdGx1yDa0XkPgQ0kRTV8l/Mxu/6tvk1cCoGgauqY4Cc2BTEMEHJnK5054/iLT/JpnmfSABe8uCyjXVOOhvdXSdf8bk9DLRoG3/PfadZFxC8gKOs9UcuUY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=d6XvHSje; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="d6XvHSje" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BDF9CC116C6; Fri, 20 Feb 2026 09:52:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771581150; bh=p1tAAxGtFcTpyH8kJIKfeUGx7oWCMIhnPZTORNKDSkA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=d6XvHSjei+/LwJ6azNn0RPBMuwdHY2AUX0AF3emYW7STF/HogUS8+EUDj3T/d19XL M63tMOohnyibTXmGAA8TjFTHjntaGwGgaWECiP1PdArTlNK6cF+a8rn77fraqEu+l9 rn4fJ/3HCn2AgMP6t4ZiM/z1B6w0A1LmozVngj7jLLVZsyjZdW4/HiMQDPyiE6cNMI nfC64/bFJMDvOeTurZ43+8l5zYJaQm2IBou+xxGbOSbBAnkOr723pFGtHUjzOeMbfI a92ibJGQDcq5yHyAYOwdM9XEoJFtH8+0zVarlQ9bdDXdTxUaadxXKkMTGrInY8ibAE X3eDPCS21Z1EA== From: Andreas Hindborg Date: Fri, 20 Feb 2026 10:51:12 +0100 Subject: [PATCH v15 3/9] rust: Add missing SAFETY documentation for `ARef` example Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260220-unique-ref-v15-3-893ed86b06cc@kernel.org> References: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> In-Reply-To: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> To: Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Trevor Gross , Danilo Krummrich , Greg Kroah-Hartman , Dave Ertman , Ira Weiny , Leon Romanovsky , Paul Moore , Serge Hallyn , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Alexander Viro , Christian Brauner , Jan Kara , Igor Korotin , Daniel Almeida , Lorenzo Stoakes , "Liam R. Howlett" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Boqun Feng Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-block@vger.kernel.org, linux-security-module@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-pm@vger.kernel.org, linux-pci@vger.kernel.org, Andreas Hindborg , Oliver Mangold X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=1777; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=0VuAJevCkYFZAUYzbU/zIm1O124y3qethT0WcgbappU=; b=owEBbAKT/ZANAwAKAeG4Gj55KGN3AcsmYgBpmC6g+5r9c8hNIwBUmEKkWqrvZg384pxiRXLng +3sV++OUXmJAjIEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZguoAAKCRDhuBo+eShj d5gpD/jlKR4PuCzBrXKPcsSwhxSkegz1CUJdeYgrGfzZ9wRiOA/5ps4xbsU55RhyGnWoOb0+UvN QLyLhxhnDxODib1nUdt+EH74woUiQ1+tSfuwhD/bmb2FztVhX3YKoEIkULGbHAx7bZMUJVOxEKa FTaTy3ZNbg3E9hVWN3t0ZptiN7JGgd+inoLuRa9KrdX9z+nRozTCjZvNFqLryaBWUjuFU86k5UB ndhZG3zO3CHLHZ3z+qqqDH5U/qFXlhUm5dto71y9MBC57gO+G/fnEPs1340ZkwHrJUrSZ2RRhng vOz2ypc4kr7lIgN8Tn7SoifY0uYtm/8mKwDLDehcon3lIy6oZMQalCOO8kvFlSGwHiblbqE/Ibk FP+61QHkX7mYrBRbYPsNJqbi25f/rIUbNGNMfHo18A/2rmSA16Ds2/5vlwny+0hxv96/dQXcNXa 2JpXulj0V+7noIw53LO/jknBTxQuYwd74HeM9KGf5ilIhCgdD9cQBxuvEPa3spLHS4xCVcSKCW5 ukWuT4E7G7nRnUgSvozkeLAmTJqIWoNZFw2ZCTbmePW9Kbta+NjprXLwLR+a7Jrv1ch2bGyV6dK oUFVz73j3T569jm9Nl4Fyf8gsz/VEi/Q1MU5ShzSbfQjtr5+AfgxWjMQb9XxQkSWc4kBeFvYT0a wHpjkhcaZd+5z X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 From: Oliver Mangold SAFETY comment in rustdoc example was just 'TODO'. Fixed. Signed-off-by: Oliver Mangold Reviewed-by: Daniel Almeida Co-developed-by: Andreas Hindborg Signed-off-by: Andreas Hindborg --- rust/kernel/sync/aref.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs index 61caddfd89619..efe16a7fdfa5d 100644 --- a/rust/kernel/sync/aref.rs +++ b/rust/kernel/sync/aref.rs @@ -129,12 +129,14 @@ pub unsafe fn from_raw(ptr: NonNull) -> Self { /// # Examples /// /// ``` - /// use core::ptr::NonNull; - /// use kernel::sync::aref::{ARef, RefCounted}; + /// # use core::ptr::NonNull; + /// # use kernel::sync::aref::{ARef, RefCounted}; /// /// struct Empty {} /// - /// # // SAFETY: TODO. + /// // SAFETY: The `RefCounted` implementation for `Empty` does not co= unt references and never + /// // frees the underlying object. Thus we can act as owning an incre= ment on the refcount for + /// // the object that we pass to the newly created `ARef`. /// unsafe impl RefCounted for Empty { /// fn inc_ref(&self) {} /// unsafe fn dec_ref(_obj: NonNull) {} @@ -142,7 +144,7 @@ pub unsafe fn from_raw(ptr: NonNull) -> Self { /// /// let mut data =3D Empty {}; /// let ptr =3D NonNull::::new(&mut data).unwrap(); - /// # // SAFETY: TODO. + /// // SAFETY: We keep `data` around longer than the `ARef`. /// let data_ref: ARef =3D unsafe { ARef::from_raw(ptr) }; /// let raw_ptr: NonNull =3D ARef::into_raw(data_ref); /// --=20 2.51.2 From nobody Fri Apr 3 11:10:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 05ABB31AAA3; Fri, 20 Feb 2026 09:51:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581111; cv=none; b=jCm4PUK3j6SlKaWlLflnAhpnXPDC5xXbT4997R7r+QAu62Z6m60bUitduOeOHSh5a7MAZ93QiXKJTtHXPmH4xxqYuad8kUWDxk4Uvl7ZhsPEoIsLfiD2yn24VpzcfdAF8EFXW5rR8i7ANkVB5VNdPNXetMmZ75XFhAEPpfme+Hk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581111; c=relaxed/simple; bh=PBOESvJWRqEQ2bmBI+MqZdyLdwyA7OsD4YPXBLOYQLU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=MzMFTRupQRbm+Bros7FocBFH6/IIvqFpzgFWo6d6Bz1RNCkQCv8zh/QEfvdCqU2qciXwzniSCm8omUIm2G4cTFnqBY6n2HR0fhK0KTJvzuPJPqk7hwpWFj7d22f34zziC4tFs74NjerFWZZU4D38lbTeUYEy8efulkRpj8cgIZA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oSMnR2VB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oSMnR2VB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 50E18C116D0; Fri, 20 Feb 2026 09:51:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771581110; bh=PBOESvJWRqEQ2bmBI+MqZdyLdwyA7OsD4YPXBLOYQLU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=oSMnR2VBFiYF7mSjxjkfNVi7njkjNf3PLhFrBmpcM9d4pWK/GXd5fkMSWFUZ6VD2x 5eWFNCJJkIsdUzWD77f02RYiEeD4v6skYIt2XW4ao3NA2rgWmQjg+wQhZGtGTM0+Zj QiUHPRguHu8S8fyOflkwjbIMsLyOrB/J3XN0Hx2jcXaSuNOpyqtRqMaEsgaUkyYUeX KxMtJKZRfO/w92vTqQMucveSOe8zWyt3q17hU4n7gBLOq3rKrBHkil4p0WmBHZZPXk G1/C+VImEEajDd/Cp9FfpLnahW7HziI4vghEkK4AbpaRBMnwIhHj6tE38PTOuLCsH6 mzUUw11uwWtqQ== From: Andreas Hindborg Date: Fri, 20 Feb 2026 10:51:13 +0100 Subject: [PATCH v15 4/9] rust: aref: update formatting of use statements Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260220-unique-ref-v15-4-893ed86b06cc@kernel.org> References: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> In-Reply-To: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> To: Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Trevor Gross , Danilo Krummrich , Greg Kroah-Hartman , Dave Ertman , Ira Weiny , Leon Romanovsky , Paul Moore , Serge Hallyn , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Alexander Viro , Christian Brauner , Jan Kara , Igor Korotin , Daniel Almeida , Lorenzo Stoakes , "Liam R. Howlett" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Boqun Feng Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-block@vger.kernel.org, linux-security-module@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-pm@vger.kernel.org, linux-pci@vger.kernel.org, Andreas Hindborg X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=753; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=PBOESvJWRqEQ2bmBI+MqZdyLdwyA7OsD4YPXBLOYQLU=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpmC6hzPFPu7KGUd6cRx7n7GKtIx6VHoVNewyV0 EXg0W57W8CJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZguoQAKCRDhuBo+eShj dxM1EACnIHiAlYn9gPgqZulCKlNlf50uQDXyF9B5lqzxCB4xzKIk29CViLlfREtNEQpmiNQ6TtS hzd1FYLf8u5dAvd4QayeNLUYTUptXcQrByNp2EdNsAhuMhgCPbvxv+5XzO7Yb4c2iwvxXZ/GV3F Ez583A3k+mRd7YqWWpEj4RFpnKFo5uIsu+8LJckCpHdVp+QBP16CQHoJpF/FjhcEYaulQ62G4kF NkTJmahq5F85IlPLQZ9bZfLgDII15NQvFGJDbj6tOPcVDVLOZrSpdw9wHnDj5K7h4UE2FTUpyZ8 sl8Hk5h+JXj/1GqZbQyHuxIM2mJq3l3W8UusstI+ftPaYNK+cRNg5aEEWt/uP7WYBqUR2R+rFez NF32cG5Xgq9fKisyoiE0H808A3G9U4UA8GIZlqilG16eM24JIQWAw/cbRleD8D7YDiPtRb6id5R yRJBMLPT83Cz61htPmBosbIHLJX7srwu8C40hy8wXT8NeJvJKVYf2HY8q1ViVS9uaHBWecAHYjJ qa0FaiULDIt0mIIUOHhDKnldiiopsOPUz3D+Fz0tJhlLaaw602DiBfp+t8ghomDp+O6GNvrZA5m yzaE5kR1WUPNuPs0iFLB5ez3KpIEebt3HS7YpUVYt1xLlkOuC4mg364/IymHXlngTS1mnkrgVVf wmnQL4v1G3QBseQ== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 Update formatting if use statements in preparation for next commit. Signed-off-by: Andreas Hindborg --- rust/kernel/sync/aref.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs index efe16a7fdfa5d..3c63c9a5fb9be 100644 --- a/rust/kernel/sync/aref.rs +++ b/rust/kernel/sync/aref.rs @@ -17,7 +17,12 @@ //! [`Arc`]: crate::sync::Arc //! [`Arc`]: crate::sync::Arc =20 -use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNul= l}; +use core::{ + marker::PhantomData, + mem::ManuallyDrop, + ops::Deref, + ptr::NonNull, // +}; =20 /// Types that are internally reference counted. /// --=20 2.51.2 From nobody Fri Apr 3 11:10:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9223631D36B; Fri, 20 Feb 2026 09:52:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581142; cv=none; b=MmIuegpHWGrsRDF1mmSsJzNjd0H65Nepfbsn4/BUkfxRXAa4apOXq3k5kynkAgnMj94KSFCitjJK2pGHvnu5O0Ysu9y96HI4urn7gMM9O0OmMGT7Z+AKxK7AvRhaT2Tku4pVNmT4SbPf5Z0IvtKcdOa/K5SLB16UkSJZ78cP3fw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581142; c=relaxed/simple; bh=h7Qzs2dunn+wg3aAaY3py9l1nvsdaskPimJWqJqhgnc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mdYfW372xLhZrMrKDG4ni/+AjKhip9XZIh7lju589aUg220Fhv3jaWuBiWA3EynAmsSdt1n1ms2QeTazhmq4d/pdRkC9bWSzSrbR8oeZQCxD92Af/oBK+h2iB4a4f+8nbQqxzKP16YzMmVVlIy9HCyIMHs8nqIvfQxwnssvChyI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RKSy6Ndf; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RKSy6Ndf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EC8BAC116C6; Fri, 20 Feb 2026 09:52:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771581142; bh=h7Qzs2dunn+wg3aAaY3py9l1nvsdaskPimJWqJqhgnc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=RKSy6Ndf5g/d3iF10cr7qU9GA3dAzvE6yRcPhOX1hpStIChQIrjw7nQgKcZmt5+3P TibSAEtSJiXiQM1YSNytMSHxCIHwqhUR/w6jbDy+B+rTv6UetXQXZQiIpHS/6FzOjx inOgVbKYfxT1bwxlETsRyvf1Aiv34dlMJfeU389ZmcZUNNRnbAz8FNmGTMwynraHmU Tysy/+klBw1qaZlRGkvxm6n9B6E2eqaATPUOaQk40vYGEAuUBCcF3QZyKVUqFtzYoK g/esHuF2KDBNNs7WL2Py0+MBmv4SluexGcDi2gUC5mj+RPzuP35Po5MYP4LObjKAKc a7oGglzGFwdvg== From: Andreas Hindborg Date: Fri, 20 Feb 2026 10:51:14 +0100 Subject: [PATCH v15 5/9] rust: Add `OwnableRefCounted` Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260220-unique-ref-v15-5-893ed86b06cc@kernel.org> References: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> In-Reply-To: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> To: Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Trevor Gross , Danilo Krummrich , Greg Kroah-Hartman , Dave Ertman , Ira Weiny , Leon Romanovsky , Paul Moore , Serge Hallyn , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Alexander Viro , Christian Brauner , Jan Kara , Igor Korotin , Daniel Almeida , Lorenzo Stoakes , "Liam R. Howlett" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Boqun Feng Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-block@vger.kernel.org, linux-security-module@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-pm@vger.kernel.org, linux-pci@vger.kernel.org, Andreas Hindborg , Oliver Mangold X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=10327; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=zcotFrEtdFYtqkneNkBZwYCdrxeK2+RRB4qJPSlD1DY=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpmC6irxNsgUEJMElTY4A222N7Or6D8uhpD50Ox weTgJRgPWyJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZguogAKCRDhuBo+eShj d7vAD/0UpQQklci23qrfs3aXYOj+5817LSmZiQsn+zWunjLvs0tiOAF5R7rPMlRCPDz1ND3nnSP KeUVIf6+ULRMskvQCYVtXmxEtvOxhcxPYr8/3kQiKTVrXVv0mfjGMeo1FIcmoJ0GYqY1t5pM6HR KYyJuggbKa4Y8VLVJG63moXevMBV0B6FXFXIuSbc6nZMGTYhqaeOSAp/tmfO3z1u5qeY+YjwGRB J5Lu/LOkUR6uRakyHFiYRXTxPkA342V2L1ZSquJrl8uiBTSohjED99IHOK+yNQS5SqcqKei8Or6 ulKmeK3iKoY0XosxP0r4PdQGNAtyIbXEskYS0CDlWROoXZ56LEuGgqD/+A1fb3pO5Epr6VHgCLJ k33vlLk/h8K0xbpOw1HfM7pK5g5RS/lKuGgth9VN3IZbwqQZse+VMJoiamADB+LRFU/GXnmclOF TN/toq2c/7EVrje2XItX9jY5O9UGs0JRqRqLjMahG/ao9HNU+QxM/ZXpojIjJq2u4wRJ3FbCJXr tzGcnfSHlAau7CdGJcVXkVySkBkhE8Ag9+Hb4HL8Cd6zrJg0FoPXuqrHPurXqJDTQUlMgn1lve9 GjpSJNUrl33zzhRcwDh8E+5i9tGM9HitJY7w43VP0ASSV5qiwb2HXfBYmVW0aJsmH3Np6VgQotb 6gDfp1VkSFYzgOQ== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 From: Oliver Mangold Types implementing one of these traits can safely convert between an `ARef` and an `Owned`. This is useful for types which generally are accessed through an `ARef` but have methods which can only safely be called when the reference is unique, like e.g. `block::mq::Request::end_ok()`. Signed-off-by: Oliver Mangold [ Andreas: Fix formatting, update documentation, fix error handling in examples. ] Co-developed-by: Andreas Hindborg Signed-off-by: Andreas Hindborg --- rust/kernel/owned.rs | 143 +++++++++++++++++++++++++++++++++++++++++++= +--- rust/kernel/sync/aref.rs | 15 ++++- rust/kernel/types.rs | 1 + 3 files changed, 150 insertions(+), 9 deletions(-) diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs index b8d3b9c725cf6..a9bc871e07ce1 100644 --- a/rust/kernel/owned.rs +++ b/rust/kernel/owned.rs @@ -14,18 +14,24 @@ pin::Pin, ptr::NonNull, // }; +use kernel::{ + sync::aref::ARef, + types::RefCounted, // +}; =20 /// Types that specify their own way of performing allocation and destruct= ion. Typically, this trait /// is implemented on types from the C side. /// -/// Implementing this trait allows types to be referenced via the [`Owned<= Self>`] pointer type. This -/// is useful when it is desirable to tie the lifetime of the reference to= an owned object, rather -/// than pass around a bare reference. [`Ownable`] types can define custom= drop logic that is -/// executed when the owned reference [`Owned`] pointing to the obje= ct is dropped. +/// Implementing this trait allows types to be referenced via the [`Owned<= Self>`] pointer type. +/// - This is useful when it is desirable to tie the lifetime of an objec= t reference to an owned +/// object, rather than pass around a bare reference. +/// - [`Ownable`] types can define custom drop logic that is executed whe= n the owned reference +/// of type [`Owned<_>`] pointing to the object is dropped. /// /// Note: The underlying object is not required to provide internal refere= nce counting, because it /// represents a unique, owned reference. If reference counting (on the Ru= st side) is required, -/// [`RefCounted`](crate::types::RefCounted) should be implemented. +/// [`RefCounted`] should be implemented. [`OwnableRefCounted`] should be = implemented if conversion +/// between unique and shared (reference counted) ownership is needed. /// /// # Safety /// @@ -63,8 +69,7 @@ /// Foo {}, /// flags::GFP_KERNEL, /// )?; -/// let result =3D NonNull::new(KBox::into_raw(result)) -/// .expect("Raw pointer to newly allocation KBox is null, thi= s should never happen."); +/// let result =3D NonNull::new(KBox::into_raw(result)).ok_or(ENOM= EM)?; /// // Count new allocation /// *FOO_ALLOC_COUNT.lock() +=3D 1; /// // SAFETY: We just allocated the `Self`, thus it is valid and = there cannot be any other @@ -88,11 +93,12 @@ /// } /// /// { -/// let foo =3D Foo::new().expect("Failed to allocate a Foo. This shoul= dn't happen"); +/// let foo =3D Foo::new()?; /// assert!(*FOO_ALLOC_COUNT.lock() =3D=3D 1); /// } /// // `foo` is out of scope now, so we expect no live allocations. /// assert!(*FOO_ALLOC_COUNT.lock() =3D=3D 0); +/// # Ok::<(), Error>(()) /// ``` pub unsafe trait Ownable { /// Releases the object. @@ -194,3 +200,124 @@ fn drop(&mut self) { unsafe { T::release(self.ptr) }; } } + +/// A trait for objects that can be wrapped in either one of the reference= types [`Owned`] and +/// [`ARef`]. +/// +/// # Examples +/// +/// A minimal example implementation of [`OwnableRefCounted`], [`Ownable`]= and its usage with +/// [`ARef`] and [`Owned`] looks like this: +/// +/// ``` +/// # #![expect(clippy::disallowed_names)] +/// # use core::cell::Cell; +/// # use core::ptr::NonNull; +/// # use kernel::alloc::{flags, kbox::KBox, AllocError}; +/// # use kernel::sync::aref::{ARef, RefCounted}; +/// # use kernel::types::{Owned, Ownable, OwnableRefCounted}; +/// +/// // An internally refcounted struct for demonstration purposes. +/// // +/// // # Invariants +/// // +/// // - `refcount` is always non-zero for a valid object. +/// // - `refcount` is >1 if there is more than one Rust reference to it. +/// // +/// struct Foo { +/// refcount: Cell, +/// } +/// +/// impl Foo { +/// fn new() -> Result> { +/// // We are just using a `KBox` here to handle the actual alloca= tion, as our `Foo` is +/// // not actually a C-allocated object. +/// let result =3D KBox::new( +/// Foo { +/// refcount: Cell::new(1), +/// }, +/// flags::GFP_KERNEL, +/// )?; +/// let result =3D NonNull::new(KBox::into_raw(result)).ok_or(ENOM= EM)?; +/// // SAFETY: We just allocated the `Self`, thus it is valid and = there cannot be any other +/// // Rust references. Calling `into_raw()` makes us responsible = for ownership and +/// // we won't use the raw pointer anymore, thus we can transfer = ownership to the `Owned`. +/// Ok(unsafe { Owned::from_raw(result) }) +/// } +/// } +/// +/// // SAFETY: We increment and decrement each time the respective functio= n is called and only free +/// // the `Foo` when the refcount reaches zero. +/// unsafe impl RefCounted for Foo { +/// fn inc_ref(&self) { +/// self.refcount.replace(self.refcount.get() + 1); +/// } +/// +/// unsafe fn dec_ref(this: NonNull) { +/// // SAFETY: By requirement on calling this function, the refcou= nt is non-zero, +/// // implying the underlying object is valid. +/// let refcount =3D unsafe { &this.as_ref().refcount }; +/// let new_refcount =3D refcount.get() - 1; +/// if new_refcount =3D=3D 0 { +/// // The `Foo` will be dropped when `KBox` goes out of scope. +/// // SAFETY: The [`KBox`] is still alive as the old ref= count is 1. We can pass +/// // ownership to the [`KBox`] as by requirement on calling = this function, +/// // the `Self` will no longer be used by the caller. +/// unsafe { KBox::from_raw(this.as_ptr()) }; +/// } else { +/// refcount.replace(new_refcount); +/// } +/// } +/// } +/// +/// impl OwnableRefCounted for Foo { +/// fn try_from_shared(this: ARef) -> Result, ARef> { +/// if this.refcount.get() =3D=3D 1 { +/// // SAFETY: The `Foo` is still alive and has no other Rust = references as the refcount +/// // is 1. +/// Ok(unsafe { Owned::from_raw(ARef::into_raw(this)) }) +/// } else { +/// Err(this) +/// } +/// } +/// } +/// +/// // SAFETY: This implementation of `release()` is safe for any valid `S= elf`. +/// unsafe impl Ownable for Foo { +/// unsafe fn release(this: NonNull) { +/// // SAFETY: Using `dec_ref()` from [`RefCounted`] to release is= okay, as the refcount is +/// // always 1 for an [`Owned`]. +/// unsafe{ Foo::dec_ref(this) }; +/// } +/// } +/// +/// let foo =3D Foo::new()?; +/// let mut foo =3D ARef::from(foo); +/// { +/// let bar =3D foo.clone(); +/// assert!(Owned::try_from(bar).is_err()); +/// } +/// assert!(Owned::try_from(foo).is_ok()); +/// # Ok::<(), Error>(()) +/// ``` +pub trait OwnableRefCounted: RefCounted + Ownable + Sized { + /// Checks if the [`ARef`] is unique and converts it to an [`Owned`] i= f that is the case. + /// Otherwise it returns again an [`ARef`] to the same underlying obje= ct. + fn try_from_shared(this: ARef) -> Result, ARef= >; + + /// Converts the [`Owned`] into an [`ARef`]. + fn into_shared(this: Owned) -> ARef { + // SAFETY: Safe by the requirements on implementing the trait. + unsafe { ARef::from_raw(Owned::into_raw(this)) } + } +} + +impl TryFrom> for Owned { + type Error =3D ARef; + /// Tries to convert the [`ARef`] to an [`Owned`] by calling + /// [`try_from_shared()`](OwnableRefCounted::try_from_shared). In case= the [`ARef`] is not + /// unique, it returns again an [`ARef`] to the same underlying object. + fn try_from(b: ARef) -> Result, Self::Error> { + T::try_from_shared(b) + } +} diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs index 3c63c9a5fb9be..77f6c8dc411eb 100644 --- a/rust/kernel/sync/aref.rs +++ b/rust/kernel/sync/aref.rs @@ -23,6 +23,10 @@ ops::Deref, ptr::NonNull, // }; +use kernel::types::{ + OwnableRefCounted, + Owned, // +}; =20 /// Types that are internally reference counted. /// @@ -35,7 +39,10 @@ /// Note: Implementing this trait allows types to be wrapped in an [`ARef<= Self>`]. It requires an /// internal reference count and provides only shared references. If uniqu= e references are required /// [`Ownable`](crate::types::Ownable) should be implemented which allows = types to be wrapped in an -/// [`Owned`](crate::types::Owned). +/// [`Owned`](crate::types::Owned). Implementing the trait +/// [`OwnableRefCounted`] allows to convert between unique and +/// shared references (i.e. [`Owned`](crate::types::Owned) and +/// [`ARef`](crate::types::Owned)). /// /// # Safety /// @@ -185,6 +192,12 @@ fn from(b: &T) -> Self { } } =20 +impl From> for ARef { + fn from(b: Owned) -> Self { + T::into_shared(b) + } +} + impl Drop for ARef { fn drop(&mut self) { // SAFETY: The type invariants guarantee that the `ARef` owns the = reference we're about to diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index 9b96aa2ebdb7e..f43c091eeb8b7 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -14,6 +14,7 @@ pub use crate::{ owned::{ Ownable, + OwnableRefCounted, Owned, // }, sync::aref::{ --=20 2.51.2 From nobody Fri Apr 3 11:10:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 71EF131D36B; Fri, 20 Feb 2026 09:52:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581158; cv=none; b=PVv1MFrmhoLCPAySm8Hccbs6fV/qS2mhK9TD2NM5bhoa7oGWu0P8KdnHDrWjED1ihjXJqumMcV6tR6mr9wjReCMN0yYkrsGqOHYCrDzBfOQ84meGsBk4bi+b9goUQWmoMdpvr9sO0wCHEIvOUcB/zXqg9NHgKJ6u8sVgesJYQLw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581158; c=relaxed/simple; bh=TzCUGpEDUTKD6tcoKokHDlQAGVLw4XXksTwjbV99rHQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=MegYNEdIWg8ck5duvli9r8oC9OWVnzg7AXPvqs2YU5XAP0LL5RCt/Ar/9uPWHlD87r9LnIrZWcyFJPIZ5qCVbhHcaVay+rvjWKDx5H32kziTSSr75Np4KSg+kCKDmhIQDJC/lgK1fPbt5z9wryPlRYMOkfrEuOVZH4Az+y42K5s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cPkoJgHz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cPkoJgHz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BA1BCC116C6; Fri, 20 Feb 2026 09:52:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771581158; bh=TzCUGpEDUTKD6tcoKokHDlQAGVLw4XXksTwjbV99rHQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=cPkoJgHzjTOK4adLqKvtWOk0lV5xxjHFhFd25u0lCbutgaak9HaBvj5iIti9G5zzW t5vdRzwJCLIKRG+RRSwnAgaRKFt8OQCM5Bsl53NinxBG8sVCTF4QNaeLdH9UxPUy38 SnApW6PeCr6R83MsQ4DvuDxOcpHt19YUEVb8MoxXaiN0eIPQECQ/Mvy2ooVEw6Susy EaQEmFLvxd1MwRXs2wqSCWeHSLIcYvdOQxH7HmLfJLbN8RM7dhkJKZWm6wOC3jReXI d2uxnfQYxQPohdutcdThilJmAB86H/L0DvpS2d8rLyBBWYMWfuezR7qHlVEqzMZcsA g8ACwDxkQlGnQ== From: Andreas Hindborg Date: Fri, 20 Feb 2026 10:51:15 +0100 Subject: [PATCH v15 6/9] rust: page: update formatting of `use` statements Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260220-unique-ref-v15-6-893ed86b06cc@kernel.org> References: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> In-Reply-To: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> To: Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Trevor Gross , Danilo Krummrich , Greg Kroah-Hartman , Dave Ertman , Ira Weiny , Leon Romanovsky , Paul Moore , Serge Hallyn , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Alexander Viro , Christian Brauner , Jan Kara , Igor Korotin , Daniel Almeida , Lorenzo Stoakes , "Liam R. Howlett" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Boqun Feng Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-block@vger.kernel.org, linux-security-module@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-pm@vger.kernel.org, linux-pci@vger.kernel.org, Andreas Hindborg X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=910; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=TzCUGpEDUTKD6tcoKokHDlQAGVLw4XXksTwjbV99rHQ=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpmC6j7xMqrOaWhqb9sz3GGfZ0fqISUkN5QKA93 RZup+H7tAiJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZguowAKCRDhuBo+eShj d0DZD/0dTBrrqUbBOcxFA2tD+zDIiI+fVqhQyXpWOHZTJ14cd+6Va4NBWr4jjedyZ060dAaM1sA Femvxpu86flN8RTIjT1fu/C1Xs2xhYXBJFk5pYbKzIzYG18wMgunFXxKnF8fzwQj5Q55A0x6dSX d4sn/PolHwlhr/GJeDpRZbrCiypzkXj4a4yuOdjQNdooFyEfvj+8NbUSFgbidam5i/qUWNQCy2d 5iGDU7RejE+DaQPyVc7RRenEMGW0GkVZqQIEcFj4QpDcCqUBduVmeMKJTAq4Hey9md/SCJ1RiPu CYiacAclAAKm9n0ybuxbdSJxi0PTvf+fzWIA6n95kw67kRWiUY8YtQvAd+IN3vL64EW5L1uib+H RyPos2pTret4c2ZrRxYKFRRWWTZpDs2Ar6HDMojnmuJ+5+74601NEJqBPN9Xk0AYTrR2TglyTjd Z/2T9Aex4ZOhAl3GsayG4AEAIJ14DcEej1m+GxHfGKpvmAU4FjhP2JkEKPlWbTdmeZO702b17nw ZBIdWaLXJx3pPL4ZrTHqGfdpWlSYag7OkRTNCKhDn0JGyNU85S3MWU7JwuBf0oStMiFrR352hs3 eH+ufisPMWgHK5PriCQ5BN9Wrjq/QaF7Y/kQaK5SfsooyRg3R42rIYY7jf5WnRUHCZCREvdgm5P RQI1LGOLLZoKTjw== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 Update formatting in preparation for next patch Signed-off-by: Andreas Hindborg --- rust/kernel/page.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs index 432fc0297d4a8..bf3bed7e2d3fe 100644 --- a/rust/kernel/page.rs +++ b/rust/kernel/page.rs @@ -3,17 +3,23 @@ //! Kernel page allocation and management. =20 use crate::{ - alloc::{AllocError, Flags}, + alloc::{ + AllocError, + Flags, // + }, bindings, error::code::*, error::Result, - uaccess::UserSliceReader, + uaccess::UserSliceReader, // }; use core::{ marker::PhantomData, mem::ManuallyDrop, ops::Deref, - ptr::{self, NonNull}, + ptr::{ + self, + NonNull, // + }, // }; =20 /// A bitwise shift for the page size. --=20 2.51.2 From nobody Fri Apr 3 11:10:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B54F732D7F1; Fri, 20 Feb 2026 09:52:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581134; cv=none; b=LXdJc6mroYhPOexp3IouZujNpKNUb9qEmmRDvr74BnDvLBlGYzTZuswYfbim6UCzeulsRKBWYDLEFzvaU7v4YFPJICiwoKtvMeaxvN0n8br4iivnJmfr/MpIIq4gIS/7clHWG5WAJhg4Uojtn4EQXGnootN17yiprtiV3ItaizI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581134; c=relaxed/simple; bh=PtI8dWeXLCFOQOrt2qgQQvMv1kCph8ZiB7DPs66Ug2g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=O2aqGj7/GWhrmc55O5l88qkrTlsyZBjSWAEAgkAOKfm0QY7CB07kICvxgMMwN44e3J5IeMXeWUE5QJs0AJGwUq++be4UDkNYKHgc5E9PkWq1h5jhb7aL06wRCPfEC+21FHZdbTSKSZ3ulo5zL1GF10XAU9oXOL8XWJCKA/zI3ro= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dXf1Qrrr; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="dXf1Qrrr" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F1CE7C116D0; Fri, 20 Feb 2026 09:52:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771581134; bh=PtI8dWeXLCFOQOrt2qgQQvMv1kCph8ZiB7DPs66Ug2g=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=dXf1QrrrR70di7dbarSVglO5Fj69PyruSvuzBcvFbhIgzxWo02br6JPUlDXhjXmrf f2scy0IQU1JRq7+r9QecQihcBPbcNzeRSvZ6jgaehMhs8Gbx6Z+S6H8KZUv2+xBnq4 JsH2OTUHS/7hhdnj41GxFJLGN5jwFe2t9y8LAuDRMaouj9svA8xL1j2RnxYikI5h2f XHsusFjjM2ekUAXmqKbnHx8P8of1p6T43UBEdAzQBGEAtMe3ULzWcnOIxjlBD1IbSF hl9elv7O1k0c6N97uk3jhqX1zXltTxyl0SvULg0R6tWDEr5umcPNpw4ijbCbIuauY5 U8dz0BwB7aBmw== From: Andreas Hindborg Date: Fri, 20 Feb 2026 10:51:16 +0100 Subject: [PATCH v15 7/9] rust: page: convert to `Ownable` Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260220-unique-ref-v15-7-893ed86b06cc@kernel.org> References: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> In-Reply-To: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> To: Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Trevor Gross , Danilo Krummrich , Greg Kroah-Hartman , Dave Ertman , Ira Weiny , Leon Romanovsky , Paul Moore , Serge Hallyn , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Alexander Viro , Christian Brauner , Jan Kara , Igor Korotin , Daniel Almeida , Lorenzo Stoakes , "Liam R. Howlett" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Boqun Feng Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-block@vger.kernel.org, linux-security-module@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-pm@vger.kernel.org, linux-pci@vger.kernel.org, Andreas Hindborg , Asahi Lina , Asahi Lina X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=4163; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=6+8Px7vkn1ot/UgoHpPh8rLqE5ThXe9Oldbg1lnNpkQ=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpmC6k7RfPZnsjTWms0x9n3CTffEUPkBah98XHN US147G+SoWJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZgupAAKCRDhuBo+eShj dxYZEACJweMLFS/q9Dm1TgYuSREDX3pcc2WCm7GWxm9txjo/5gTIwW/zXsrX37z7tZ7o8YtyFuU XPbg69eje9pdUXHRDilmI6KlU04ShDeZo812lmJgMV+NJah9iv3QblmQzw7greeD5ArcP/t6vKo APQIUEo8OhYDi7+Uf6HTmglpJKqvQ37nXcRmvFcb4IpLEOAsnFpJ2teFebTrtY1ca/oOlB6arNy Vh+HOpyc3Li9e2JdhRQHGMkXi5AmQqLKQsnRE6H7Pmjxm/E1QYVN/FWyxoaYRHErjHQ4rO7QHTh LFS/qf5NBk6Q1EUaS2GDmls3B+57VJ2NEIUyMgh9cIb6lMN6+T3EVVEfzqeSGpC8z0+5S3VuJFI IPZTv68uPsljfOb8QNysrowdf6KzGXFH047Qk/Ge74gJg9+kgRzTqZI+JxmDn0LWubhvo4TmabC o/AvVXVxiKLL2sD0wxsRBXTFNfAh4inpSRigkmlQv+6HTpUJEBuqNeHBIRdwaqQu1+yv2+MG9kt 0G6BaCyhb6YVQvgSbIjRp6zmRk7Bs4V0aPzqF392zR0XbO1NwkuiPa/HAtknhIqS6WhL8Yi+QrA NSRqhV9l6Ad5sxLvkIIEGANdFOBAcK6kzuMfnuOZH0MLB63dDTOtkdp6KERDBSi3aTNZ8lPLNAW 28WxMmyqzFhJnMA== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 From: Asahi Lina This allows Page references to be returned as borrowed references, without necessarily owning the struct page. Signed-off-by: Asahi Lina [ Andreas: Fix formatting and add a safety comment. ] Signed-off-by: Andreas Hindborg --- rust/kernel/page.rs | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs index bf3bed7e2d3fe..4591b7b01c3d2 100644 --- a/rust/kernel/page.rs +++ b/rust/kernel/page.rs @@ -10,6 +10,11 @@ bindings, error::code::*, error::Result, + types::{ + Opaque, + Ownable, + Owned, // + }, uaccess::UserSliceReader, // }; use core::{ @@ -83,7 +88,7 @@ pub const fn page_align(addr: usize) -> usize { /// /// [`VBox`]: kernel::alloc::VBox /// [`Vmalloc`]: kernel::alloc::allocator::Vmalloc -pub struct BorrowedPage<'a>(ManuallyDrop, PhantomData<&'a Page>); +pub struct BorrowedPage<'a>(ManuallyDrop>, PhantomData<&'a Own= ed>); =20 impl<'a> BorrowedPage<'a> { /// Constructs a [`BorrowedPage`] from a raw pointer to a `struct page= `. @@ -93,7 +98,9 @@ impl<'a> BorrowedPage<'a> { /// - `ptr` must point to a valid `bindings::page`. /// - `ptr` must remain valid for the entire lifetime `'a`. pub unsafe fn from_raw(ptr: NonNull) -> Self { - let page =3D Page { page: ptr }; + let page: Owned =3D + // SAFETY: By function safety requirements `ptr` is non null a= nd valid for 'a. + unsafe { Owned::from_raw(NonNull::new_unchecked(ptr.as_ptr().c= ast())) }; =20 // INVARIANT: The safety requirements guarantee that `ptr` is vali= d for the entire lifetime // `'a`. @@ -126,8 +133,9 @@ pub trait AsPageIter { /// # Invariants /// /// The pointer is valid, and has ownership over the page. +#[repr(transparent)] pub struct Page { - page: NonNull, + page: Opaque, } =20 // SAFETY: Pages have no logic that relies on them staying on a given thre= ad, so moving them across @@ -161,19 +169,20 @@ impl Page { /// # Ok::<(), kernel::alloc::AllocError>(()) /// ``` #[inline] - pub fn alloc_page(flags: Flags) -> Result { + pub fn alloc_page(flags: Flags) -> Result, AllocError> { // SAFETY: Depending on the value of `gfp_flags`, this call may sl= eep. Other than that, it // is always safe to call this method. let page =3D unsafe { bindings::alloc_pages(flags.as_raw(), 0) }; let page =3D NonNull::new(page).ok_or(AllocError)?; - // INVARIANT: We just successfully allocated a page, so we now hav= e ownership of the newly - // allocated page. We transfer that ownership to the new `Page` ob= ject. - Ok(Self { page }) + // SAFETY: We just successfully allocated a page, so we now have o= wnership of the newly + // allocated page. We transfer that ownership to the new `Owned` object. + // Since `Page` is transparent, we can cast the pointer directly. + Ok(unsafe { Owned::from_raw(page.cast()) }) } =20 /// Returns a raw pointer to the page. pub fn as_ptr(&self) -> *mut bindings::page { - self.page.as_ptr() + Opaque::cast_into(&self.page) } =20 /// Get the node id containing this page. @@ -348,10 +357,13 @@ pub unsafe fn copy_from_user_slice_raw( } } =20 -impl Drop for Page { +// SAFETY: `Owned` objects returned by Page::alloc_page() follow the= requirements of +// the Ownable abstraction. +unsafe impl Ownable for Page { #[inline] - fn drop(&mut self) { + unsafe fn release(this: NonNull) { // SAFETY: By the type invariants, we have ownership of the page a= nd can free it. - unsafe { bindings::__free_pages(self.page.as_ptr(), 0) }; + // Since Page is transparent, we can cast the raw pointer directly. + unsafe { bindings::__free_pages(this.cast().as_ptr(), 0) }; } } --=20 2.51.2 From nobody Fri Apr 3 11:10:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9190232A3D4; Fri, 20 Feb 2026 09:51:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581118; cv=none; b=mOFLfBHnP9F6NScxzsnnUIifc5u2dGMHtkLX5h36qVveBepn3yAbH6Zx9z/01hR8QKGlJ0vKWfVBfWV0uhLo2PuFXPBmZNOvY1XQTLOIMONGlr3cWi+Ouzx8YnywCj/0dkzSoxxCjmaR+zeCvSRvYUTjWwLxkw0RCQEbhR+Fcqw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581118; c=relaxed/simple; bh=B5FbaZHoWu3lXzLWsvxiL2xffXnxnFX4nBQhSLyFXlg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IOTUxU6z2+czOHRXbeknDh8POtedWbbLmq+PnJMVdsDuhXb9cLfQuap838qTZrSs3D7K8g9e5Pp7uPM+8c6TT2ETrfkLqakF4Wo31woi97gJ6OTuT2PV0TM6pCcaqGprKKQodaTJP9Wck4bIIz+4UeFYkaqvhYee1YmQRTFPWWs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TBlUoq08; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TBlUoq08" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2FC2AC116C6; Fri, 20 Feb 2026 09:51:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771581118; bh=B5FbaZHoWu3lXzLWsvxiL2xffXnxnFX4nBQhSLyFXlg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=TBlUoq08h8THjyqgOPa5qFuSUJ9EA2rl/GDN9uRVQwt25XUkK2RxR0vWqjtTL+7yR cxoufxtl3dRE9KagTQfI7RkbgRykxBYpq8jJ357TWuSs3n6WeNy78TnJ/OsGZlbPKT Thm6Otw7Q8bFXfFocqjTXBUKiV7Vq5W/wpQDQS4W6T/s8x/iBPpgcY0S/jf3hOLE33 0EliLnOFmz9t6PWADdrJir83Vzp8lwr1ATpcd8KGS9kH3OtcrnuhXChO/0fBhJkudy zok60YIdfXuLJ3TKGwePrpf4o1T+iRXL6mZVb9VWayQRcEU3mgx8PQfbIuGjqMAxUD GWwJKsOvDrPrg== From: Andreas Hindborg Date: Fri, 20 Feb 2026 10:51:17 +0100 Subject: [PATCH v15 8/9] rust: implement `ForeignOwnable` for `Owned` Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260220-unique-ref-v15-8-893ed86b06cc@kernel.org> References: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> In-Reply-To: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> To: Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Trevor Gross , Danilo Krummrich , Greg Kroah-Hartman , Dave Ertman , Ira Weiny , Leon Romanovsky , Paul Moore , Serge Hallyn , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Alexander Viro , Christian Brauner , Jan Kara , Igor Korotin , Daniel Almeida , Lorenzo Stoakes , "Liam R. Howlett" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Boqun Feng Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-block@vger.kernel.org, linux-security-module@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-pm@vger.kernel.org, linux-pci@vger.kernel.org, Andreas Hindborg X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=2835; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=B5FbaZHoWu3lXzLWsvxiL2xffXnxnFX4nBQhSLyFXlg=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpmC6lQ8ViWhXfTBxkBwYXwCvpZEQQpsFdLjSWt Z/0DPcp01iJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZgupQAKCRDhuBo+eShj dynCD/wPCHcbzgHFtI1xHdF07F3Sl7RvyuqebxX7QafkNthmS2wK+6fYvfrTUdnL1z/OBT1a29v Ekv+847w5ksZlRBgGMKWxazpNxfKF5eWQvBoKPWlYxkyWDMvo5kyar5hxw0w3x3COrfeu9QKl56 KhsRSpsbaevfgdJSut7YliqvTpAiGKoUhon8VZJN9MfpgxHFA8h4daaTbVL7VknN+9j2z7j7sy1 Sgk87Kl23zumku0CP8xCTL/v2iQdTZkeAo0DqBaYMIqW99TDPpzpfzfY0vMKWUdz3CKfi0NVOL1 ha+JjyDc1y9rbdiDLBax6CvmSMa3YTUcETVRBpfR1iK9Nv5jfwJ/ahTThdwfuq27a98NOsjeZM7 xSMg0DOPOZm2bogbOUFEwQxYUeZawSZw5998KQzSnn9YHKJwKEyRhqKqLDSfv8O35BgPsTCYfZx ulAarVM09f3S8iZXGFdpWCwIIZXvoyMEV5vsnhvNxrcgESzwem5PCkmknWlGyJB4BTjaB7CVwu4 EhB+2yo3w2A6G3YxFFEK2Y+4pBEXalKlRTVLSKaOAPoKkXmw4MtJptUOgpKFlnAlWsJJPvDVAPX Zj4fG0pZkGwmYQf3x8c6EhW/QFvUIWp3kCah+QYzszA1iz7lJcu0LsCpfHpmCOqa9mFhCq4JFVx H3Cwg/+isbapMRQ== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 Implement `ForeignOwnable` for `Owned`. This allows use of `Owned` in places such as the `XArray`. Note that `T` does not need to implement `ForeignOwnable` for `Owned` to implement `ForeignOwnable`. Signed-off-by: Andreas Hindborg --- rust/kernel/owned.rs | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs index a9bc871e07ce1..b115b4f3db6d0 100644 --- a/rust/kernel/owned.rs +++ b/rust/kernel/owned.rs @@ -16,7 +16,10 @@ }; use kernel::{ sync::aref::ARef, - types::RefCounted, // + types::{ + ForeignOwnable, // + RefCounted, + }, // }; =20 /// Types that specify their own way of performing allocation and destruct= ion. Typically, this trait @@ -120,6 +123,7 @@ pub unsafe trait Ownable { /// /// - The [`Owned`] has exclusive access to the instance of `T`. /// - The instance of `T` will stay alive at least as long as the [`Owned<= T>`] is alive. +#[repr(transparent)] pub struct Owned { ptr: NonNull, } @@ -201,6 +205,45 @@ fn drop(&mut self) { } } =20 +// SAFETY: We derive the pointer to `T` from a valid `T`, so the returned +// pointer satisfy alignment requirements of `T`. +unsafe impl ForeignOwnable for Owned { + const FOREIGN_ALIGN: usize =3D core::mem::align_of::>(); + + type Borrowed<'a> =3D &'a T; + type BorrowedMut<'a> =3D Pin<&'a mut T>; + + fn into_foreign(self) -> *mut kernel::ffi::c_void { + let ptr =3D self.ptr.as_ptr().cast(); + core::mem::forget(self); + ptr + } + + unsafe fn from_foreign(ptr: *mut kernel::ffi::c_void) -> Self { + Self { + // SAFETY: By function safety contract, `ptr` came from + // `into_foreign` and cannot be null. + ptr: unsafe { NonNull::new_unchecked(ptr.cast()) }, + } + } + + unsafe fn borrow<'a>(ptr: *mut kernel::ffi::c_void) -> Self::Borrowed<= 'a> { + // SAFETY: By function safety requirements, `ptr` is valid for use= as a + // reference for `'a`. + unsafe { &*ptr.cast() } + } + + unsafe fn borrow_mut<'a>(ptr: *mut kernel::ffi::c_void) -> Self::Borro= wedMut<'a> { + // SAFETY: By function safety requirements, `ptr` is valid for use= as a + // unique reference for `'a`. + let inner =3D unsafe { &mut *ptr.cast() }; + + // SAFETY: We never move out of inner, and we do not hand out muta= ble + // references when `T: !Unpin`. + unsafe { Pin::new_unchecked(inner) } + } +} + /// A trait for objects that can be wrapped in either one of the reference= types [`Owned`] and /// [`ARef`]. /// --=20 2.51.2 From nobody Fri Apr 3 11:10:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2FF3332AAA5; Fri, 20 Feb 2026 09:52:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581166; cv=none; b=KsBpnbKtPhXTTTjufJKpYNm1N/CW17AjQjCXn+mNjuAg23pgyZSOcxSZK+poZ8hGvU6QEDFROcZ8Mu7IrLQo3cv/nRDvqANJJ69M8cK7OBordzw7SJbt2LyBQM9rZ6E7aldTSPt4utVhi83g1xXc/58dksHcKXKGGr9oFvQ4V30= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771581166; c=relaxed/simple; bh=4kJUgBgTj0V7kRaDlo9MltCBPjRgIT4dj8eMOKXfB5o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=E3Ow4vpIRY9JuFMWKuo00YNMZ40cA9krFD99qobD5MYulbGLlXpAzHPJ8jOZsduav+OseBBFE2oFSwoYrT2wTLCzlUSjqs9ZwfeiXn9MADqy5EpbeLkKoQsq5bjhruhWq6IvmZaZkiXRdZRiCzS9Qs0V2Cnl7Mk7M3y5aJAcbr4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Pa9f/rFM; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Pa9f/rFM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 952BDC116C6; Fri, 20 Feb 2026 09:52:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771581166; bh=4kJUgBgTj0V7kRaDlo9MltCBPjRgIT4dj8eMOKXfB5o=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Pa9f/rFMzl4E/wPD8ciUx13iCfAgUF6vmSFXaR6Ks+u5bb5DAJXeMviiLdxh2MJv8 8+qc5hza/6VMGw4cPNgIQtSvcyxAvv/XWpRWhKCTzzjefbOVYgl2Bn+9VGuU00cEAc jTvBr1iVHBszyNOkPQO3sX9uTj+4qv9eIpWpokFIoB5BYxSyamUEEtpnqHSLtYolX3 imBdySgeUu1FiifVSkCzKnQQ5D89I3lmT78VRrlGo0C4YvUidrWgNYFLXT3STRDR1B TCUlRIjeq31xVyq9aJ1FHRa6M6evLAQpUau+Rs7uGaiXXLTqvstat9/ewV25hDKnY2 FyieTCY2HPk1g== From: Andreas Hindborg Date: Fri, 20 Feb 2026 10:51:18 +0100 Subject: [PATCH v15 9/9] rust: page: add `from_raw()` Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260220-unique-ref-v15-9-893ed86b06cc@kernel.org> References: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> In-Reply-To: <20260220-unique-ref-v15-0-893ed86b06cc@kernel.org> To: Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Trevor Gross , Danilo Krummrich , Greg Kroah-Hartman , Dave Ertman , Ira Weiny , Leon Romanovsky , Paul Moore , Serge Hallyn , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Alexander Viro , Christian Brauner , Jan Kara , Igor Korotin , Daniel Almeida , Lorenzo Stoakes , "Liam R. Howlett" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Boqun Feng Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-block@vger.kernel.org, linux-security-module@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-pm@vger.kernel.org, linux-pci@vger.kernel.org, Andreas Hindborg , Andreas Hindborg X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=1098; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=4kJUgBgTj0V7kRaDlo9MltCBPjRgIT4dj8eMOKXfB5o=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpmC6mLFWJC4FUrb2akl8BDN0BW5kYHddNAH8R6 ePI4Cw2p8aJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZgupgAKCRDhuBo+eShj d4hjD/9a6KYUv/3QDTCUbU4jBZySYMrlWTE3KyUKD7sMA5hI7Q0Tt6utA8LOxT6+fWgt78T6dsP YLaKTrcMsbBbF9ZlaZrHl8lklZikAR4xxXgnPSPGr59l/ggK4Mo7kCUQdgwUuC8ahkpgb3RVcUP l5OhLwF21W8lWV0hEx409t8Kzk3WeW2aOLHrkVtgPaBMUoTkJvPAEdi/M7QMEd7KvTGtBEN10Sd uhQioHELdqQTvuoGD/2Nklb8dMjHCDjnPf6DJyD7DydQTfEn2hjA6jQdq7K8J00MQuP/InZd1qU EMO1sfL3nqfaUHKHOpGHjKARDrvThnL2r030YD0tcCw2YZMWv5umGNAlyGF1CNCEDVa59lBEGmW owSPtNvf3UrEKKpr7iymtNmm91VsmBBLGJ8Zwg5nZHvn44w2XR5sr6sXo0Qe5IlG+RZQPG7y+cX rB+YoFcD82kVzVU3ZT/1RJWC2PZPOs34ie+0a+iU/I3k5swQfcovtHfPX+UM5RXMZmUiFZJmvKU FWReMNdU9IC65rTvBqhTBOmM6OZJu8DGdagZs9ZIcaXPj84ZEtd+dYi7mQlLkTxwBnCjC0nwacH JuKEKkSC25+lzZDp9QXvecJqUf1eC1gnMOjlYogawynT0QOSpqelvJDq1GJeBuRYH3wCvocTQ8u WWDeedFFS03kT+w== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 Add a method to `Page` that allows construction of an instance from `struct page` pointer. Signed-off-by: Andreas Hindborg --- rust/kernel/page.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs index 4591b7b01c3d2..803f3e3d76b22 100644 --- a/rust/kernel/page.rs +++ b/rust/kernel/page.rs @@ -191,6 +191,17 @@ pub fn nid(&self) -> i32 { unsafe { bindings::page_to_nid(self.as_ptr()) } } =20 + /// Create a `&Page` from a raw `struct page` pointer + /// + /// # Safety + /// + /// `ptr` must be valid for use as a reference for the duration of `'a= `. + pub unsafe fn from_raw<'a>(ptr: *const bindings::page) -> &'a Self { + // SAFETY: By function safety requirements, ptr is not null and is + // valid for use as a reference. + unsafe { &*Opaque::cast_from(ptr).cast::() } + } + /// Runs a piece of code with this page mapped to an address. /// /// The page is unmapped when this call returns. --=20 2.51.2