From nobody Thu Apr 2 01:46:18 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 AA95E2D6E6F; Tue, 24 Feb 2026 11:20:43 +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=1771932043; cv=none; b=Ct1P7UQa6ZPqeRNb0r6QYxcS4MWU2f9RodNsE/+Ku9+YIWM0vNuRcZb21BrLVwmgsiR+8DjUUAtnQ9xK3Le6q0C6y5AqdShfZscxFURMGXU4t2rS6Kj+AqTNT3A0nH75AH2PdIJ7zXGml0mxNfJyWNjRwTK+Xwwxtk7KUE1Ocd0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771932043; c=relaxed/simple; bh=jLcwJmCU6NuD58W2dvDRqr7xKpNKXDGKLW9pDqZ3mBg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=COfBpdq5jhItWAO4F7BjY6RXEVp4L7Vs+AZnCEs4gA3PlKMgl+cllL2ZFwWicMGnj7oURi2DvI3aTunEE5D4hW5HTbd5WJPAUYGFDqBIGQYTrhg67HCtpYNJZo0/WtlRiKGFMBEG2TynKbj+v0es2tcKGhvQjLVwLCRoe2marg0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FnD6iV9K; 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="FnD6iV9K" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A8595C2BC86; Tue, 24 Feb 2026 11:20:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771932043; bh=jLcwJmCU6NuD58W2dvDRqr7xKpNKXDGKLW9pDqZ3mBg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=FnD6iV9K9NZ7mJJSAL00XOjIPTg6UsieDGlm3jaXgSc4Rc9rMU8mCbbe0Ub0QU04s j+XA7mBrzuVEuqRfQI92KsNlua/cpKJgCXIE8vr6AZo0jhnoNhVLUoWlWaAfplH4CX T5sAiTOh3WoLzwRvaEg5Hlr+AzFOgVnxNtBg8DyOwJeF38TDShZKCUIt4HUXRybDpW R/l7zwbU3DLkv6fDnzGUcBYSBRH3Eu5wt2beNLcG/kisJ4dWaJfnvuLRpJeRdFTgfv ylStit7gCo0yNJCiejtjQZi34htmpdrmCKcOiapJ3ywb88WPPGD50uHtZIJnTb+Acb HTH87pF60sZqQ== From: Andreas Hindborg Date: Tue, 24 Feb 2026 12:17:56 +0100 Subject: [PATCH v16 01/10] rust: alloc: add `KBox::into_nonnull` 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: <20260224-unique-ref-v16-1-c21afcb118d3@kernel.org> References: <20260224-unique-ref-v16-0-c21afcb118d3@kernel.org> In-Reply-To: <20260224-unique-ref-v16-0-c21afcb118d3@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 , Vlastimil Babka , Uladzislau Rezki , 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=1062; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=jLcwJmCU6NuD58W2dvDRqr7xKpNKXDGKLW9pDqZ3mBg=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpnYj0TV4DAv2lVFJSr3recsWpK7mpdMvf0fOO4 GsqOYqcl7SJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZ2I9AAKCRDhuBo+eShj dxXvD/4uTFSqjCY3iWHRTIEAh2NylxI+XqsaQVjNHfa55ZJJLgTNfYUvcse4RyQozv7pvyVWd9X RTV+xLwmBnbBtZhV/uwmF8F2kvjU113KJpO3sMatO2yNc358Ve7JZhap3nzmvf689b+moR9KW8U 8ifp9shwqd9GxSnUqYmJQww4ytW7n6vmrS9fdCG0VpncaoHbclEqKrb8kHlDpPWubp6c+Qu+ywV ZSm0AOEF5voLr6yFpDRkglqwU7L54LiXgfITkIb6UbNJrDRXOO57QGjUnybgV9oIPGKKkwQwRZQ uZX42y2zKXJNwE7e0PtSQh/G9iJSeO6OlIl3XlsH9/nwxhmAe99bikE2XWCyvXsybp6xdn8BHKc r54RW+VeOtJ8HA3/xoWs07B2k0WCCDEs5APzVEAOAAzVtB0PabBsu+U6ama860OueMRxHOILlcZ +Xf+pOsN30kSX9dsaxnpoC6hcm2hPWPJL/HaytSlHURknmIo6ZknstZlgrOJ6sPfuOgZPJ9KatI nzNP0Z3U5LkY0BatvObNNaHXd8Ke66SruMP3igQJaaJm0DeDpUNWuOdkv9+3giycXGQXpdPIHCt lQVZzP3lDsyullj2okwbZRVi01SEBePzKduMTuRLyTs6JjpW7tCsxzzCAC0M5H7le096T5lOwCQ cYxZVgcHcuck6nQ== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 Add a method to consume a `Box` and return a `NonNull`. This is a convenience wrapper around `Self::into_raw` for callers that need a `NonNull` pointer rather than a raw pointer. Signed-off-by: Andreas Hindborg --- rust/kernel/alloc/kbox.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs index 622b3529edfcb..e6efdd572aeea 100644 --- a/rust/kernel/alloc/kbox.rs +++ b/rust/kernel/alloc/kbox.rs @@ -213,6 +213,14 @@ pub fn leak<'a>(b: Self) -> &'a mut T { // which points to an initialized instance of `T`. unsafe { &mut *Box::into_raw(b) } } + + /// Consumes the `Box` and returns a `NonNull`. + /// + /// Like [`Self::into_raw`], but returns a `NonNull`. + pub fn into_nonnull(b: Self) -> NonNull { + // SAFETY: `KBox::into_raw` returns a valid pointer. + unsafe { NonNull::new_unchecked(Self::into_raw(b)) } + } } =20 impl Box, A> --=20 2.51.2 From nobody Thu Apr 2 01:46:18 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 342F637BE96; Tue, 24 Feb 2026 11:19: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=1771931971; cv=none; b=qiTC8NtQiDyCI6M0jQw9apRFdojij8pxqcW+o8bKeAeK23rVQUVhMK+quUNBd/zMbhFxP+o8Yb083XKbjfAofzGAh4SRdDSRmgKvz/IUQzVs7aRd1svDyrsJK9TGxidqnKu6J7gzNAujRkfu2tFCbQQT8Strv+y4AQVauLiHmSo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771931971; c=relaxed/simple; bh=vsbKnA/MqIcTGDzEOIbnd0zjHmEAks3lbNLt2RyB7cQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dfWYRcuFWoCRW3HUKij8BMuD0eLhXLfFUpdeqFF4va9sjWoq6tJ9Hxf1KArMWY5A5rkJgMQUQvVRL5A7dUMtlnhE5qAaQBybPUwvyw9WDKg64Ojl3a8N+EZ1PjJTNaC8KFpNIwKo78mOnv4Jd/cmuhcQEIFZRM/1lJEpc3XHXIg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=rSIs5xaY; 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="rSIs5xaY" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 145B2C2BC9E; Tue, 24 Feb 2026 11:19:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771931970; bh=vsbKnA/MqIcTGDzEOIbnd0zjHmEAks3lbNLt2RyB7cQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=rSIs5xaYwbO5bV7v8Fd9jXQHDqD1BtoGXO0cKq94E3mv00JGkBy4JIxudPQzenNMI HPxAqq0Lm4b2+I6NCv2CTMYvcHsaFanOnvhBDXTcY8RmBPMZPhGv645Y5GlvI69/pY oON4gMp27HHpgc3Uta97xstv9G2bvE8BvKYENLp//cx0w8YYNtq0g/6D3xuoi/8SyX ccFUI8GVPnmUp9xPFNnpEoJSXw52iXeudZrCuDcfNFjvRgKOTzM5Bq52dtvp4xCkfo 03IrqVwPaSbEF2zTJS29fLDVFygFHtUC29gSL9VPhhyjIk+gwYHE+TpZ9UhhtwJL4x 3Rqpyrwjcn5Ag== From: Andreas Hindborg Date: Tue, 24 Feb 2026 12:17:57 +0100 Subject: [PATCH v16 02/10] 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: <20260224-unique-ref-v16-2-c21afcb118d3@kernel.org> References: <20260224-unique-ref-v16-0-c21afcb118d3@kernel.org> In-Reply-To: <20260224-unique-ref-v16-0-c21afcb118d3@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 , Vlastimil Babka , Uladzislau Rezki , 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=10433; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=t20FLxM+uzXpAHcpcxVIpgEft5jpKX8+J1Yew1bC0XQ=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpnYj1/GeK2UnMGGaWmFO3qx7xN6IcSm5HMxR0M 5KazgtSMa6JAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZ2I9QAKCRDhuBo+eShj dwW1EADCes/KZywz5ZPjVovKtSjgO6zrEQxUF0rmxbpyo53QWGEmM85gKhsm+MK4tMKt46pY9YA QAspBuLPArM1uD62f2ijqru2/wUcL1XwYRO8BPin0+Qb9E1qmTasIj+q9K+/KKa8j6EviTylola 8AmYFe+Bdd1aNEa3bsa+NWtpMab5LadsRVv4ZKfZwj1A4psSmL6nco/8A+0zsa2gWWjqIoqkNcb xzvnyW7aUqkOn2R4+4B9uS4Do92bSTTieFqBTfJnH/jPfxQ/sW65TQHZL+tGn3UfEHDvCCeNPbT 0lsBZqayFdfJVexiuOE/CNzThWoLh3i7TN+AJ1QnSauY48/PLRLceuBQp438n7FeQTp/FMGl4sa 5yNqdVrHs6IEVEXRg85Vnx8gHQJ4KJgK++t74+pfx+fgu4Uk/uLiJXhJdG16M8JeY+xfcyti8b1 kpBkE0OZ41RzJ79DuN08oBiR5GYQMk2JUAaD8ubckWB1+ZyTZ8S8luKUKZDPdlbp4P4HUuQxKon TDI9GxlwB2vR4rC0i9csouooPmMuuhCixWLHDU/errKfpZhV1S5vHt/E0isliSvN6QuKpz3MjRZ yx/s/ffY5RBpkdhxUPeQs/WyS2c7jOk8QY7jv+RYxzAW8gNaqeodFXRr7tjq5VD4FHXI8Jb57dM XWhQiJY7qHFCIMw== 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. Change safety requirements, safety comments. Use a reference for `release`. ] Reviewed-by: Gary Guo Co-developed-by: Andreas Hindborg Signed-off-by: Andreas Hindborg --- rust/kernel/lib.rs | 1 + rust/kernel/owned.rs | 181 +++++++++++++++++++++++++++++++++++++++++++= ++++ rust/kernel/sync/aref.rs | 5 ++ rust/kernel/types.rs | 11 ++- 4 files changed, 197 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..26bc325eee406 --- /dev/null +++ b/rust/kernel/owned.rs @@ -0,0 +1,181 @@ +// 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. +/// +/// # 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 KBox::into_nonnull(result); +/// // Count new allocation +/// *FOO_ALLOC_COUNT.lock() +=3D 1; +/// // SAFETY: +/// // - We just allocated the `Self`, thus it is valid and we ow= n it. +/// // - We can transfer this ownership to the `from_raw` method. +/// Ok(unsafe { Owned::from_raw(result) }) +/// } +/// } +/// +/// impl Ownable for Foo { +/// unsafe fn release(&mut self) { +/// // SAFETY: The [`KBox`] is still alive. We can pass owne= rship to the [`KBox`], as +/// // by requirement on calling this function. +/// drop(unsafe { KBox::from_raw(self) }); +/// // Count released allocation +/// *FOO_ALLOC_COUNT.lock() -=3D 1; +/// } +/// } +/// +/// { +/// 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 trait Ownable { + /// Tear down this `Ownable`. + /// + /// Implementers of `Ownable` can use this function to clean up the us= e of `Self`. This can + /// include freeing the underlying object. + /// + /// # Safety + /// + /// Callers must ensure that the caller has exclusive ownership of `T`= , and this ownership can + /// be transferred to the `release` method. + unsafe fn release(&mut self); +} + +/// A mutable reference to an owned `T`. +/// +/// The [`Ownable`] is automatically freed or released when an instance of= [`Owned`] is +/// dropped. +/// +/// # Invariants +/// +/// - Until `T::release` is called, this `Owned` exclusively owns the u= nderlying `T`. +/// - The `T` value is pinned. +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`. + /// - Until `T::release` is called, the returned `Owned` exclusivel= y owns the underlying `T`. + pub unsafe fn from_raw(ptr: NonNull) -> Self { + // INVARIANT: By funvtion safety requirement we satisfy the first = invariant of `Self`. + // We treat `T` as pinned from now on. + 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: By type invariant `T` is pinned. + 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: By existence of `&mut self` we exclusively own `self` a= nd the underlying `T`. As + // we are dropping `self`, we can transfer ownership of the `T` to= the `release` method. + unsafe { T::release(self.ptr.as_mut()) }; + } +} 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 Thu Apr 2 01:46:18 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 343602D6E6F; Tue, 24 Feb 2026 11:19:40 +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=1771931981; cv=none; b=VXnkAsR/JHakyaPvz+kOzxyTzXqDwCRB+8zbg9KD4MBboz/lyAh+oh6KM8wXZdGqHTZpLwHLvsmGNxJDF5Lt3Vc71MgWUEXvNb0Bh0NuNn7VdDgIMYNY40HqwO0h6p9aUDXyntI8QocA42VNT5l7/iF41L4gdhTl4ZCZw/4B6gA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771931981; c=relaxed/simple; bh=0YZVbySI3yuPIcDgrgoXTbAsy3+dzCAjeC8TdscJ5XE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=aGWBF+yMwevXxTiWGP9bCpqoIKXZ8ivYaInyBvtXfyL+IW8Wj8sJvmRGI1O9/7qBoijvasT3YQIqToSIwEdP3E0ppR0NhX78FEEsRZ8a26Y0C0RBjbIixSYjkQYGVW5dZhoe9kRNyqDW+Zqag+Z/5AX4iIESwKV3Y8ryjLlb4Rw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=USD99sra; 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="USD99sra" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5E33EC19422; Tue, 24 Feb 2026 11:19:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771931980; bh=0YZVbySI3yuPIcDgrgoXTbAsy3+dzCAjeC8TdscJ5XE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=USD99sraL3dmevkXfcFkS1N7+WZ253AePZVxc0glHYTGtixbTm6ZmUnU80v7/sEL4 OL1nXvyImuRWd+aTe1IWmsutTfdoVjQFhjua6RI+P6OjlQF9+u94ltpH7KVT9TqDdf PyZKwiu4GEO/84BzCCd2V0Nu/Csj1eDZlW4qLSwCT37o6W2Ze33ECgIbC1S8KRkR0K 43SwK8gcRuDXWplRewy861tQpGj6e9wq05UZQroFGhkpErUS9VE5aMPn5LkdFRQkB3 UvRehLvG4+FbhN0yvawJbbf1Zvi11Rl9Juf42bATyVKdc/3lKPnaaGpbNtiT2IZOm6 O1eILmnzHR1Mw== From: Andreas Hindborg Date: Tue, 24 Feb 2026 12:17:58 +0100 Subject: [PATCH v16 03/10] 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: <20260224-unique-ref-v16-3-c21afcb118d3@kernel.org> References: <20260224-unique-ref-v16-0-c21afcb118d3@kernel.org> In-Reply-To: <20260224-unique-ref-v16-0-c21afcb118d3@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 , Vlastimil Babka , Uladzislau Rezki , 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=34432; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=wgQM95w8i8Ntbx/81R1URe+JQRVrFT/pcDtd5+qrMsk=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpnYj2LDdwDjuscOUfDxmS1nnbsoJnsFdiHd7IK wKvvi1Efe+JAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZ2I9gAKCRDhuBo+eShj dzc2EAClF+sIcpf0rhHQHSH8cJ5/+uziAnVO+YqgnBDVCNaH+ikHuZuUkHxMsXbD5WNZNCl8j/L ieCbOIXPpebDSqQIpFCFafgSleGhtKDqzIYiMxrZpGZMCTT2qqCJmn9TTG6wqGM851QPU7dIfK/ Z7Ri/sknzYEwHkLpq3PWHSkgVmP/BCyVyuOlBTxfpvAORjTlUzgQNf+lf9IAvzdhIH6z7PG8LDd idiVp1JdlX4iHD0K5t5B8M56+0vVSy5/zrpJQeDBMRcWIoNZXhVlx6XM+oSkElabff+VRhZS6xJ lQpB+U/VFcjWYW/TWtoqwgwusNEKbqyqVCEKEu6T9bjJi7AImhgiYF7f8YWgZYyC5ayJqoiFv5c wDIwbiSfGH0ZCAenElpqEc+VXwZ0uG1BMiU/DNEereCBun1y2a/JV6ur1Y1tN9Aenl22/J6DPNR 8xo2F6fNVCZbcGgvQKVWQbRiMzZ5vLTUfjY6JZBJ+fTeMV5mrF/NfKxvi6QsMW6uGSIBhp44txL Q8eM7StcBSN8PuFbsJ34vadSPl37R35FePYBUeyDcAmqpFFgKZabwZVuevKoshZGGOtN4sjtGxz gI2GJKQ6Pes0Eho/J4U/QJ2yidHL0lKzNB4Nam/NmELa7qR4cPhHNgKHrQiXM36Yam2Iv2VY+PB j80TW0TxLjgOGzA== 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 26bc325eee406..41451aa320cff 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. /// /// # Examples /// 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 Thu Apr 2 01:46:18 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 8CF7137C0E6; Tue, 24 Feb 2026 11:19:21 +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=1771931961; cv=none; b=VvAyoXtfGRpwCnJRQ99NzYh1AoHZb9k09xJtDS2syqzS2U+Z5xboPX1I2iExIKzHljHhW2iyCwpa4ZvS+TK+I/Wx+Wktyj6qe426IrSwj4xnGhGHCWDXyEy5kocCNedmqoaf53+fx8hynd1WcAIpTfFSQussfEle42biiOjbMpE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771931961; c=relaxed/simple; bh=fnHuKwO7YKsiBEzcJ4WSpUwI9pJ1E1um3MRGk7ZK9EA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pdUednw5llYB2X4zs9gUpZjFds1Ek9dilpJhpmSeyqzftsPg6ws/KvwbpIFfEpYpxLBTzC91o1Y1LGcq0RkXJzrHUWOH4bn2wW5t5wnbhBXUNRm7UtNfA6JHmRiVYsaDSyZgYp5fEFZZTUw5iyz/nY11pNrip1ylFNkiViYv6uw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tFUvOs9g; 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="tFUvOs9g" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F3475C2BCB2; Tue, 24 Feb 2026 11:19:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771931961; bh=fnHuKwO7YKsiBEzcJ4WSpUwI9pJ1E1um3MRGk7ZK9EA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=tFUvOs9gyzy7Ba7ekjjypN2kAfFvNhFK6Ym27l7W170CaSEHNkLV7YYAlGJ5DY17V owZdqMEDEr5KFkPWDencHzpnD6natiZrnAmC/FLAi4Z9Lz9zfRJbd1sxhstw3Hl1qy u3TmQQtb1p0mU4qoPVMfcuGSdi/6NzTWthDZ8/25H8RJLWbJ/6pT30wRAygqhzSOXc POq8PYVHC3gY7LnkY5G1YFdreQr6i4ir+kQ0NPvmhP8liRwLK0+oaicE1UhUTsYKpW VCO6Y+I1ha5MuldT5BNfYVtKlVWFlcwhaRF0Ial+V7749Z0vgjvOQ47+NKhdP80WIe oTCMnGg6JKtEQ== From: Andreas Hindborg Date: Tue, 24 Feb 2026 12:17:59 +0100 Subject: [PATCH v16 04/10] 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: <20260224-unique-ref-v16-4-c21afcb118d3@kernel.org> References: <20260224-unique-ref-v16-0-c21afcb118d3@kernel.org> In-Reply-To: <20260224-unique-ref-v16-0-c21afcb118d3@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 , Vlastimil Babka , Uladzislau Rezki , 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=1545; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=hSYEjFGzugCDI1W/rekaqf2DA13xvb84HHFFaBF1/aI=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpnYj39reO0a7D2MQbsv0XqEQumCgi03QYrtHI/ ZYn1cQw0UOJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZ2I9wAKCRDhuBo+eShj d918D/0dNadTGYW4J53gaqBX2Pq2oWBZGwS79C0CdceTypFO5fLqCVqxcqXPCooqVOZ11C6YMVf nMG3oUX/TxD3GSgCMT32HQCYprMppcd53Pt4ne9SNDH001yDQwxMLHtNTKcpRyRCyvPkSn61Ot7 vx4Rx/e7RRI1FkWXDubxT9H0137dXGskODt5t9Asv4KyYOrxv3ulMIDkJLQowoKQOF5s92uqIoJ xNbZr7Cbui2WcPA3z4Dv8hBkHETBbOiI9ZWyX/vzBhf9FVBTLhRq15q63fsDd2YSOhGsYcE0Kaw cxbfsyFqBCEmYKLrPq0/LCZBV2szgX041hacce/RW4TaXwcLNA8OqKFfDi4nyc9aWdzP0ZDo52u Y3S3xvgTa0o/JNmM0+RHewjsPyAuXGTZ9qDhKv4T0ZBVi3WBBJRL8tMGAz4NNmBm2xCWAeGh5JN JLBXN0Mzj+uh0wtXz1/YIW41PFoS8isp3E0P6XlRIQOe1/Bh6TvPXSeAk5mKDYpSyP8aQRAOoqM aIbdQNjcoDaMVPrUz6IKm/FAi9LvWEI55GbXkoXGV+VkvL5MamXv9diHQKLqnMGH8yQ2QuG9zaK PpvAvvEKSA2iT7kc50MybsG6wBDt9DwvNXXuJgSCkdHVO8ISQKjqIjAonQP04V0i/0C64vwIodc nSi+sCMbQh0moHA== 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 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs index 61caddfd89619..76deab0cb225e 100644 --- a/rust/kernel/sync/aref.rs +++ b/rust/kernel/sync/aref.rs @@ -134,7 +134,9 @@ pub unsafe fn from_raw(ptr: NonNull) -> Self { /// /// 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 Thu Apr 2 01:46:18 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 12C5F37B3F1; Tue, 24 Feb 2026 11:19:59 +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=1771932000; cv=none; b=LiS3yTA435sRCp8M4ggbR4sE1VH/X0WtrtYNDAph/Xoo1HXwTs4WHQ5O8204P/e0jmT8CysindzEp4492WIqs+yWIt9OWZvCAt6/NT7KFL2Ux68t+wh7IUfJLKm+PbHwdUwJxUMU0yfKn1EP4lIbA1C6Yfsr8hhrscH/GM7gE7Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771932000; c=relaxed/simple; bh=Cv+ro0rgKKTNndu1LXkpKQFAsbhVDrLwsjlr+g88uog=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IuS8V5LqCf3GOYBfBY8xfJHt9i3AP5wMH/xSK8FVMEHzoxIUuLUvSOkMst72+P+tZu7yv2tEHZOpK0fMeEXFPDBL0eumg/5VJLcVqx049uZX3R31n9cTWLtW7rdbU38tRkQ8mfszAGEGKI7Zlr/zr4LHhCy5IXxgb3Spf3WRa8k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HdqzLYlm; 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="HdqzLYlm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 58D8BC116D0; Tue, 24 Feb 2026 11:19:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771931999; bh=Cv+ro0rgKKTNndu1LXkpKQFAsbhVDrLwsjlr+g88uog=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=HdqzLYlmRb3TVe2hLfyaAeT0QbXfs78M3TRb3E0NDn89wwEK4fRY5WmX/jrbvQDL1 5efYY+T10vBU1kIR5uTfVO3tiDrUgzG3MA9Lrwtrwz4HKPEbbPB8bDxQMstX90wLNe 7/caSsxNgBpZvhZeSictKOSRKfaRaTFAzeDwXGE31oo+tEmVF9c+kKOlzDasQD/O/g Df5fKMfSAXTsGZ4+ZBGt1VgcrMx5lTp1WYHN1ovyzgjrqrFdWR6h/nW9T9Pwkz4Uzs +Ypjx0M41BhOmxFpplST2zMxs7sA+EpkwwuD0XjHB8jvF8sgOKiS/IjVU2yAdOvgPp l2F1QjiQtEcHA== From: Andreas Hindborg Date: Tue, 24 Feb 2026 12:18:00 +0100 Subject: [PATCH v16 05/10] 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: <20260224-unique-ref-v16-5-c21afcb118d3@kernel.org> References: <20260224-unique-ref-v16-0-c21afcb118d3@kernel.org> In-Reply-To: <20260224-unique-ref-v16-0-c21afcb118d3@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 , Vlastimil Babka , Uladzislau Rezki , 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=Cv+ro0rgKKTNndu1LXkpKQFAsbhVDrLwsjlr+g88uog=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpnYj3SgJinL4mzNCGJB/VLOiKjYIotpZTAeQ5d eiujQ/x9mmJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZ2I9wAKCRDhuBo+eShj d3ysD/0XSb30S75V7XwmTKiRWjUL3YRT0n+cqNFGirejC2hDTAlc45ifHqn5BqDHPpxlN4259sn JL858hlbzJzoatv7LAvF11urCZjNWN6J+hdE6QOW4BHuyJ2yLNgGV676GOzDcToOmfPOKBOgNav tClWhpadwI3oyrs+v8v+kuwlOCEl+P2GCkpjQ6T8UsDk36ZDMF37vBtR1JG1J/hUUx0ZWQzewXq rUs0v6+QsxeaIe0GKCi4tT5p7avyJU1e7T0WAorLYzLb4jidXod3lnSQxQqZosDciGhCkn2iUpf Kp2xH+AWuSEyVLUdMOUp6pAc4hS3QfB05dKeQCbTXd7XTaF98QhLuW9F1R1JDwk5lzrl/n6ifHW a4iHIRVLfU6EleuG6f5MBh8/SKyj+faoS9mKgJbkfoD4kW8Hr8YRBrKrsFqsDE/2lKCzUudOupA oFpnOowIQqCm7iXRyVGnIxaKDMd+HqJ6KhuH1QJDojEgMZsLHZrpLcQYKAETyk0MOR2xhCmSmpN OMxoqfGwnO8Xwzk7fNHWAXezkISwJ6wFPmkG4Wb2vz6E0QPkHEtAjA6pNZwjtmarcSBnlX3axhb h1srotfFPhfGHOeu86lBShAiJD4EDSb9IoWPjgEh4imYv7anzzgS1wA5qJtX6rSLm9DxpJHzFfy Pqz7QVN5g1wyAIA== 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 76deab0cb225e..8c23662a7e6a1 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 Thu Apr 2 01:46:18 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 58A7F2D6E6F; Tue, 24 Feb 2026 11:20:15 +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=1771932015; cv=none; b=jKLChLCdQix41D7/EvnFJmAuvs2PoWNNiQz24gfmywnuUsIk5ExEQvvt7IDYDumDfJo6DY/moXFFHEk1eTJpXEspZJ7JPcH07T+s/AIu4xWEK3kcpXP5MJt9T9DYMl3zr/9zXYlwaEOi0o/pBCL7GbfJ6J3+oK+scdRDwic3sio= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771932015; c=relaxed/simple; bh=JggglvJ6In5NjyG9cb3gNeXDKlzHHyenXMWlyo8o2lM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uMR/njacwT3/s33hCEpCLBMxLLgszKFWxdOxHG/lhl+dmrF6J1p4waz7lXQSlcTLpDm15+6B/WUpuTWYr7QTfLr3iafmei4VDsnlj/qY+osLX9TBlqe/hFsxaLeHfGmuam9saqq8MatjwB7cY/JlGoJYB9bVRvKbb2VT2sZwztA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aNssuOP5; 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="aNssuOP5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EFC6BC2BC86; Tue, 24 Feb 2026 11:20:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771932014; bh=JggglvJ6In5NjyG9cb3gNeXDKlzHHyenXMWlyo8o2lM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=aNssuOP5zEA5Q8YbZrc/LPKDE7zYlXSfAKQcFEZP7jlGhNdWD7K3vgb/8JuMCbSKj sRYof202vY1EkJossiiTLzwKqb43Ir49CXTBhnIZ+mZ689yrDOVUKBOx01m8h5kyf8 8WY9g5pPBFR3Bbez8+MmnmldKx19r0m/0cgdfLUC2GGK6blea4l0jLzAdB+DCij9tW 1ekeqzQJMk96FLSkZxmda7vkwUUnJQYnlWnHHKJz97cGoQOM2RE/2796eBRCV4iidl 38jhPPfbXMHGeoeHEQHTtwkowEFHB7JZjBuBdcOIQlYZPe03kY/vA7ehejlT6FgXUg G3dzR9wmcQU3Q== From: Andreas Hindborg Date: Tue, 24 Feb 2026 12:18:01 +0100 Subject: [PATCH v16 06/10] 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: <20260224-unique-ref-v16-6-c21afcb118d3@kernel.org> References: <20260224-unique-ref-v16-0-c21afcb118d3@kernel.org> In-Reply-To: <20260224-unique-ref-v16-0-c21afcb118d3@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 , Vlastimil Babka , Uladzislau Rezki , 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=9162; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=8N0h104IBF2e2+JRzyJ7DGf+5EXk4kuLv1rDkhMGOrs=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpnYj47tkh8OfRv4bSoX+RikRPhSLDzaVQfjSA+ F4pqjb/IVOJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZ2I+AAKCRDhuBo+eShj d3kvD/0Sjzth4qhacazePkc+c8VIM5Rt53V2JWQd/Wo276l6EKFwBgft7QUpggXWNtbOhURo/DP 5/rmwLtzIKvmgA20HV4N2QwspETuB5+UL1OsOdkQ+JS4j3nXYxTf5tsP8nui1QuLpL6++0AfoU1 6/tK76nPLNiJDVK7yDU/P1i5QB1miza3cNHl16gSzw4MJO+8eLbZvrQc7a/LjAqBwxHIUiUuWi1 nCEKB7YrLShGr96rtoiFiseNIc60OJP+uI8v4iOQRx1UUdgAKfzTzumTLiYOdLRJDfgQAhrM+CC IpnQymSG23zXJM3zW4xlyFHPMINLvl6PJOvUsTRrPU6+z3XkkIubOiGvQrUa2RZdLxXewRZT7dn oASs3tbrM6NkgLK3i6bAgtWcmuHpTszuxQSuOyfrHZVPbbJyzSsKHI/3A9OVKi2V7Gr48ToL81v NzwRASwTv+ZZPOEYP4q1AxKsmuXuPP0yjI2jJo01wUYKiZehd3sL5mmrTBvGpwD5wp+OzLyBIcM fTjs6GafKZOSsjj6fV+oFwrMOyWYTM1dFZszE7xqjF3rUlFodg9fbMvTeRkfVhppD6H4LNHTASd QsE36vPMKcCEDT3GThzCjj9Acn5vPqL/9MSUTiJJ41HdkzaIha1WIR3NcDPC8g9PzptX2HMoh1P 14KYbR50+Hg0uBg== 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 | 136 +++++++++++++++++++++++++++++++++++++++++++= ++-- rust/kernel/sync/aref.rs | 15 +++++- rust/kernel/types.rs | 1 + 3 files changed, 146 insertions(+), 6 deletions(-) diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs index 41451aa320cff..c81c2ea88124b 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. /// /// # Examples /// @@ -179,3 +185,123 @@ fn drop(&mut self) { unsafe { T::release(self.ptr.as_mut()) }; } } + +/// 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 KBox::into_nonnull(result); +/// // SAFETY: +/// // - We just allocated the `Self`, thus it is valid and we ow= n it. +/// // - We can transfer this ownership to the `from_raw` method. +/// 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) +/// } +/// } +/// } +/// +/// impl Ownable for Foo { +/// unsafe fn release(&mut self) { +/// // SAFETY: Using `dec_ref()` from [`RefCounted`] to release is= okay, as the refcount is +/// // always 1 for an [`Owned`]. +/// unsafe{ Foo::dec_ref(NonNull::new_unchecked(self)) }; +/// } +/// } +/// +/// 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 8c23662a7e6a1..a849ebae4313b 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 Thu Apr 2 01:46:18 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 CFCC737BE83; Tue, 24 Feb 2026 11:19:01 +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=1771931941; cv=none; b=t5o8OaIDKMXLEBCMp1wNSkRy6kzU11k4Xg8hL8gpeYAlowMjfmfk1DZYiA6RsFiHrBkgTj8Ly4AANeKNG77YKQ0kes2CjNdrz2vIqNEEHZjQHiOsVAWDSQ1lGihpO0uZ8IpxThapQ3BaP34iN07CZMtbU2AMBMDA4Gxu6Op3H3s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771931941; c=relaxed/simple; bh=TzCUGpEDUTKD6tcoKokHDlQAGVLw4XXksTwjbV99rHQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SC4xSsnQLuZhNraIQxkolHaQLFuNCzjK462fNet7Fck8P6tBY6Q9uOzOh26IlOss5jBtGbI7O3n0/LXCdDiPVS9m/FXSQKMveSuggMofcN1kOdq/qtC8os+11cmG0O1Y9cbMIi9vlewaJdWJBpetGnDvPu4UxkCF30y8ndgfPsU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MOu8qMmm; 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="MOu8qMmm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EB733C116D0; Tue, 24 Feb 2026 11:18:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771931941; bh=TzCUGpEDUTKD6tcoKokHDlQAGVLw4XXksTwjbV99rHQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=MOu8qMmmrykyBB4CVhwqsAo8Gs8bS7U6AafB15auu2pLImpGtcvmUXOPslyfKs2el cA6Tgr0KiCNDlclglU7X5nBYMurMj/c4b5jgIPllHvoz8I5zv55L8nL/QYuioiqNz0 bFHwNBCzqEwNzza99Dotcw3hy2WSMt1k4v0Nu1ObFnuzzPCJTaZJR09VKnQPVNu0Ie YiaCR0DXwqb5L1MTAH33VJOtane4KNMsI/15XTFxxb0XWg50vHeumHbafF+RW87C0o zS7G0Yc9SFTSe1i5chVbdD//SENR7XS47MSpwMtFs06smyoMu66VTyAuEoDPiztBuc FG8EIBIcIDBog== From: Andreas Hindborg Date: Tue, 24 Feb 2026 12:18:02 +0100 Subject: [PATCH v16 07/10] 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: <20260224-unique-ref-v16-7-c21afcb118d3@kernel.org> References: <20260224-unique-ref-v16-0-c21afcb118d3@kernel.org> In-Reply-To: <20260224-unique-ref-v16-0-c21afcb118d3@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 , Vlastimil Babka , Uladzislau Rezki , 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/ZANAwAKAeG4Gj55KGN3AcsmYgBpnYj5ytywbjKxCmfhmUDrIuCRIXch3CamTuuGv j824oj6dJyJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZ2I+QAKCRDhuBo+eShj d33LD/4tIWyZ+fNIywG0iGTvb2DorpPWbOHBNN9ywRijqdgN4kCYPMclfyWq5jb0IYw6fO5XvGS n3w8ZMsfLfCWPUxLJdLXezRidEemIyeulj0g1sXIMUJtJCTE5KGLt1cF2TlmAqfIGDb1Hxva9+n a17hvt6TxHT6vtxd6YhnJcIRECoOoIi6t163hqhNU+3Hy46/GrL+c+nTkA/ZlnfxLgaXP1+VGB7 I5d4mn9T5xF6HdI3RAI44jmR25J4E5AypWhSJtFg83rD1WbnwAcDa+Ow11Emd7UpvLdl7IYKorJ VNJ5BCcmWvA7Uv5SbU6NqZ46lpaYD0303kqPl4SzHPc9ZgGpj1itJTcAZZg+7N11zMJ6N5UNtgL 55lUMrNsD4c2ho5ywzGrZm+g8TjNVjqpCx+CcfiRj100RVyVJxpUoJsKKhElKn7CNCCvKJQk37C ckI1Utyd486+FYBxr0xjySMGhSl+kuUkGVSs7o4WGXtaGlBup26dnSeAkV0hwb7PIJTnVEqhNG9 kkzffHhBC7rgSMVm/7JPpUvyMDnshDU2+oBO08eew7B5Exm7GXhrbIxkwxtnS8isIL6D8vMXvdR 1M7UgSTMkNpZejv8PvjASBdsv1PFNoFB4h/GbJw5gpvV2ud0ebXXQu7h+wVO6KP4Jt9TmyvfoVj JnTkk1uh31vgExw== 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 Thu Apr 2 01:46:18 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 25104379974; Tue, 24 Feb 2026 11:20:34 +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=1771932034; cv=none; b=eIjYjEpJX8Guo5AmbS5O9/jnIkVJ5sdLq79wo/jNKFB9ccoyUKoTBtQle2SBXscenBr5qRghDLuBcnxIe4OAkZV1K8mOu/Uwt8+KnoOxQ8+0Ppa27dyiT1C/lGQ00n9n8+WmVnHNGS9qmzRb+/BRdHVyXSjC8J4F6ZjbhvCTrQ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771932034; c=relaxed/simple; bh=8blkgRGad5yywyXctIGzlJVTqzYWum47B0ORZDHUOHs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VfceK/lxzDGwrbLaEmVZeolPzJjydbq8XUz9qJjO+DpoPZL3dN7R6CtvlvdYtVsFfTMLI1LDbMJuLA1/o/GZoAbWWD4yZqAxhdw3UxIlOnKGXT3Z+W1HnWe8JuymGwcdC825Xtl4rErCDlBQCDxZCU07h4PzNM76Vnks3NBTlNM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=diiRtWQG; 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="diiRtWQG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ECCD5C116D0; Tue, 24 Feb 2026 11:20:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771932034; bh=8blkgRGad5yywyXctIGzlJVTqzYWum47B0ORZDHUOHs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=diiRtWQGbNsdc0h1Enpi/pVNcSAaCWR19qvAIJoesAE0mu5EUaR8gi6E2meijCd3l 97m65gcugi/MEpeLuoE/El+ebtQwyFcqdyp15jnsHJkkBIDPu1Kgk4LkUufqBenC1c UR3PJJ+hys5NdZ2nbMk43WX7u9weWHc2W4hh20fReiF4KkuRcqpf232RVYMMUpfBOT sufS5qXIN0A3yfDCqynIeneINu4gSc2NH6Xbl3ER2z7OAPwIkka8a27jugFup+0bRf MOW4Xg3d4YH05H0TJJ4S2hVRhnqjSVnOV3XT3525keF7NACqpz7ed4h4T18APxCRpI sB5T08oMsNdpQ== From: Andreas Hindborg Date: Tue, 24 Feb 2026 12:18:03 +0100 Subject: [PATCH v16 08/10] 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: <20260224-unique-ref-v16-8-c21afcb118d3@kernel.org> References: <20260224-unique-ref-v16-0-c21afcb118d3@kernel.org> In-Reply-To: <20260224-unique-ref-v16-0-c21afcb118d3@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 , Vlastimil Babka , Uladzislau Rezki , 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=4409; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=7QArePJ/pjN7cnWoG0Oe4tA+Fg7KV4ZTWL57uMIfL+M=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpnYj6lI/S2fx31p6OdqYp54cwV/ZbM95Hj1Ip+ BqHsBArEFuJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZ2I+gAKCRDhuBo+eShj d+jAEADCyxHHAeQ9w9chDL5by1fVQ/N2FPpmL6SwLswTZkGUfXNDnAk/H82ilVO62oy5hZ8KaRu OsXJgrKn/02LDtIGs2dErMz/Xm62Qw5RikfQFgd9ILpgPHQVjUd0Ca+NiFC0tMiwf1M3TzX10oy 2yJ9a35fdQZVecuk8gGwNztfDXC23g11XjYUzukzr8/UWRzywluZ14HPZn9o6W5mhLO1LYimTiH VlMKHqHyUtOyQ6p4LP/hQInN6A7D47XFx6TIgiMk7ZVKHIQJQQY/ViRDDdrAeAKPp1gZo+xW/Xl 4bOBdBlhIm48CYKt1te/GksCvwE2aAcqV8I5r9hMUrrkDYNxK7UEYiKWGPsQ53aALJMQJSA5XDi GxVnZA+oOSsx9RzjngNovD1jQjVKTOGiL86/RdGb4XjSoqtZBX949dgVrJgW8bWMUvo9a3r5uy+ ldnSR7x9fOoPEo2o1Cge0zxUDTim5d/ze7bCnukyq16eD+03/qtca55aDF45XNeEjR6hpoqERA7 9JRoT/7cP19VcrIwkeZZwE6R8oqhoQUcNdxjMVkbxpWASF76Ml63W3g58rOQphacvZGhixvI2tO gwE7QuRGxSCGpSYFerpnwT0LxJnhUo+JtZUCQR7AlZC7pGrkFNCOJChGHYLZQfCP/45/0U7y8AC OtZo8io7bnV4TnQ== 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 | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs index bf3bed7e2d3fe..e21f02ae47b72 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 P= age>); =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: NonNull =3D + // SAFETY: By function safety requirements `ptr` is non null. + unsafe { NonNull::new_unchecked(ptr.as_ptr().cast()) }; =20 // INVARIANT: The safety requirements guarantee that `ptr` is vali= d for the entire lifetime // `'a`. @@ -105,7 +112,8 @@ impl<'a> Deref for BorrowedPage<'a> { type Target =3D Page; =20 fn deref(&self) -> &Self::Target { - &self.0 + // SAFETY: By type invariant `self.0` is convertible to a referenc= e for `'a`. + unsafe { self.0.as_ref() } } } =20 @@ -126,8 +134,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 +170,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 +358,12 @@ pub unsafe fn copy_from_user_slice_raw( } } =20 -impl Drop for Page { +impl Ownable for Page { #[inline] - fn drop(&mut self) { - // 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) }; + unsafe fn release(&mut self) { + let ptr: *mut Self =3D self; + // SAFETY: By the function safety requirements, we have ownership = of the page and can free + // it. Since Page is transparent, we can cast the raw pointer dire= ctly. + unsafe { bindings::__free_pages(ptr.cast(), 0) }; } } --=20 2.51.2 From nobody Thu Apr 2 01:46:18 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 13BEA37BE83; Tue, 24 Feb 2026 11:19:49 +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=1771931990; cv=none; b=P5RoDRMoTv3DjTA/e5CaDwwHSol7MuvHZ8IuTafApLWu/wAPqLr9YhGC0ZgT9czsvHbhJngj4GiChMFCqu7uZyH4N9IgR7q6zHUCeuYsIKhbnL8W18nkXsKiFqd/fbuMGZrXZfuVUjQNiGWEUXF2/i31pzrqH1DX/GQrAgILNuQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771931990; c=relaxed/simple; bh=ZXVxYHlu0zHczyQ9RV4gzKJTzAnDzspoUnWv3esNFwE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=X4uwGX8PrsSagcSxu+BHaiCmyAlb8MKNMHpDn2PDFblxeTGogxhGpC0FvL9x3Bva9G9mvABwZa8aiZ97ZiRqID0bsyYxDywHrnBAp+nY9BRg/riJYp70KU9/V3l6wOsJJdFfyk4XL5q8MADu/Mb4BTiEdkZFSY3CkATlMmFrtqo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dDpqaaZj; 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="dDpqaaZj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 71FE0C116D0; Tue, 24 Feb 2026 11:19:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771931989; bh=ZXVxYHlu0zHczyQ9RV4gzKJTzAnDzspoUnWv3esNFwE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=dDpqaaZjsrKAAuBigQMTjSHyxPwyewaJ+Kh431pzCvN3W/5M0RWV/9LsDjrc8NJAn ji8U2nnjIczOlsmv9Cc8A8/xV2GqUP5ESuXy4HSP6AgQdIH6Q8oYe45W47lN8bPXWy dYy9O/c+OBIQAmB31y7RS0nduullT7ZOft6gWwXrfyBcNTM1LXOndDBQcMGZdltFCt kblbrFJuhKDqAQxsaH0YxOn7BGEr/kRvVDvQlDVo5VToqaNaIw5A9B4B2yN5sWcz62 jzbZSa9w5/3bCsNch90KohlPX2hcU2oWOPDfWIc7OQeB8SrVG8zCEdClApUuvgU7+4 MhoQkxKQ68UDg== From: Andreas Hindborg Date: Tue, 24 Feb 2026 12:18:04 +0100 Subject: [PATCH v16 09/10] 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: <20260224-unique-ref-v16-9-c21afcb118d3@kernel.org> References: <20260224-unique-ref-v16-0-c21afcb118d3@kernel.org> In-Reply-To: <20260224-unique-ref-v16-0-c21afcb118d3@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 , Vlastimil Babka , Uladzislau Rezki , 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=2791; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=ZXVxYHlu0zHczyQ9RV4gzKJTzAnDzspoUnWv3esNFwE=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpnYj7ybE9TfHosMN/v3D3om/fVXrbbm9j9l/ed /oqHH++SfWJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZ2I+wAKCRDhuBo+eShj dyh4D/4seiQJBYM348GadM5XGPLQ2AkZegX5kl5/dCXU3YauTHjS275rRpJntm2vV2eW/wX4Fz6 I1vb5+83Hx2A47fK+9mEi/LG+DaNNVI0qsjDismLwy7V7Yf6z5qVr3Ds6gcMrdJ0hFGGOnMZXks j7xsnNXbvg1HgxnWNbz9QmWQyFXDdI/FPHe09R9WUkuszYtFJ6qlaZQdDQ+pvsCqN4xFC7UsKWu sQl1MmCT3Q+1hIHi3ZRrSJGt2CGuXKmrozMQmciIRuPtoMfLbKAz7lkc1alwqFtIaRuVnS68GS4 dggi4hKlQl8QBTRR4CJQbohp5P/tZtnyBtAmFfLuCUJUBcZmoXKlflQTZiLJlrcdqOlWvIdx8y1 gkz87chPU0yBGd4aT6TQJZDZzBWa0fGffmvzrdVSUyHT9YreCKsvCEke4GTJArXO7EuthJtMBbC Vs6Aysbti08nBgBd4lvF2FhwN5A8dMJprHs3joAecEV7pDVW2w4lEwJ+1prv8vz9B1E+2z8BGwC V+7yKZGJYnbUBKB47yqVr1MB1+6MqPRX/7WGPTuKF8MYcKTweCSf8OEgYbXPnA3yzm4VM9iQzGO PQXZTqVa3Oj1y5UELjmLwoh6RupeHLk7qDU84qKlFWCv66hFoQvwVTVJ1U8574/2NN/ArwwjTyv BK4RQHMK0lR4VdA== 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 c81c2ea88124b..505ac2200d2d6 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 @@ -114,6 +117,7 @@ pub trait Ownable { /// /// - Until `T::release` is called, this `Owned` exclusively owns the u= nderlying `T`. /// - The `T` value is pinned. +#[repr(transparent)] pub struct Owned { ptr: NonNull, } @@ -186,6 +190,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 Thu Apr 2 01:46:18 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 AD94437BE6C; Tue, 24 Feb 2026 11:20:24 +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=1771932024; cv=none; b=Elk2pyx1rEzRPq+trzhlNSJwDdmcWvLRccWdSu9hJzoSSxGnlUCCDKg0wugUbCACLLQd5dEAqlr4NLbi0gU6SHHvMvACZJST4/kY8A939wl3+n1ISRuPxcyscq2g2npFVm+jAhH+1B2KCRMYP2Rkl1aWP7fm/u9b+1Pby8XW/6Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771932024; c=relaxed/simple; bh=u+CxE4WAb4lLYs646rqUMrYESFoSfCpkJ/yBahV7oWU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kFm+r1S20Zpsjg4ZHRX3suZihP8ZOYekr1m5+VXqDpCBgd1qWmpF71Xm51dLf8mZx9hDH62ICF3Y6WRGo4bPqj3we82MpMZy07KfXmdblRiwRZ3KwIwT1V2gtBajg3FcyNPqnDx4qSyWXbNRGRiFTmjMRLVreyqXa45k4Ek3C7o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lEbr9SH4; 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="lEbr9SH4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 953B3C116D0; Tue, 24 Feb 2026 11:20:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771932024; bh=u+CxE4WAb4lLYs646rqUMrYESFoSfCpkJ/yBahV7oWU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=lEbr9SH4g+vkYJTX1S89jMNlf3p84ZRU/v6+jnkKrqULJxEJdYlaFLJCqESxXcBdB 95iKFGtV5tH/t/0vNO+wxU1aDpsO11zqlfymtcsNTA4YvmO9YR5aYjFFMj7Ln8loPY rEgIKnAaxeg9kAjJlVwUqwUS0bEBBgWhB6fED96nwJgySVJezf35zzy0HLBtD08lQt 18In2j581km/tx1LLr/t4qqKAv5qEGQ1bpe2ctkMSNIPvMoiyy72CIAU4GrmCyvsRy yWMO3Jz5aMRBD1stVUIxNLV6DUau4VBUlFtdK8KkiaW/QzOk4ZH4TKPq+YaDfDzI1w ytRWw5P2ZZ/YQ== From: Andreas Hindborg Date: Tue, 24 Feb 2026 12:18:05 +0100 Subject: [PATCH v16 10/10] 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: <20260224-unique-ref-v16-10-c21afcb118d3@kernel.org> References: <20260224-unique-ref-v16-0-c21afcb118d3@kernel.org> In-Reply-To: <20260224-unique-ref-v16-0-c21afcb118d3@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 , Vlastimil Babka , Uladzislau Rezki , 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=1083; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=u+CxE4WAb4lLYs646rqUMrYESFoSfCpkJ/yBahV7oWU=; b=owEBbQKS/ZANAwAKAeG4Gj55KGN3AcsmYgBpnYj8LE4iboDu3XEQEDgUJPpBWv16iN6jxTcXc nc4VDozC1yJAjMEAAEKAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCaZ2I/AAKCRDhuBo+eShj d3r2EAC9HrXGAN5UQmY4yPBtdIt+D/gH6jEj9h2dHBDQcF6dzQMjKgBxItt5MpEuDUUqRp1qYP8 If2k0oZc8AYRDlxYq2p6mzw5+29obQYMI48OgM8Bfv5ZCxLkp/LfqJO/xM/TppNhuO+krTmAShb MCl0orP42ytvBWvpv+kpvZvNudBNTHqwxzk6KIC8d6Z0OqxgLrm2FYAfzdgre0WjeIRPhoj4yo5 Lc22cKyp/OyVtDzKciBOk7U3Dqo2qa5QbrgWdeR4srzD5HlhiRGErLc4geoJYKik0cT7Tuh+l9I ByT2s8DzyaJBwaWEzC9klxmxn8O+D6hrUFWbBSV0Km6LY1IblkmwNJOI+yHbB1vpCLe2+Ducl0f 3oav38GaY3BIWHZOz3/fU9i4RQoyFKsucZoj7GdL+0I29K5W+fIDEiVtPXb5VwLlS9uuOGZmLCf TArqmlPzTFT4FzZY5BIgFAJJ55D0M0j7VpIUm/zpXbEyRF5BXnMPHjxGxEQcMZVtJBDrNt+mGkP o6hstg9wsEObY5kFIUXlLbrqXnAEXEOA8z96T7KvE4sHClZAEUouSvzlF/evoKDuxwBvArbB0tN c+9pkL/JWcpGsrJzdlXjerAmFT8ic9gqMnxpaPOlQ7WQTf6RGMqRo+mJ5SnYrtDuJPHdl3QqHwe fXaCMyhvccgrgVg== 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 e21f02ae47b72..96f1ec125f043 100644 --- a/rust/kernel/page.rs +++ b/rust/kernel/page.rs @@ -192,6 +192,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 convertible to a shared reference with a lifetime 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 convertible to a shared + // reference. + unsafe { &*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