From nobody Wed Oct 1 21:27:10 2025 Received: from mail-24416.protonmail.ch (mail-24416.protonmail.ch [109.224.244.16]) (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 7D8202D876F; Wed, 1 Oct 2025 09:03:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=109.224.244.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759309440; cv=none; b=EpvJqPUQ5wq+GXTpOCBD3muD3RIgdJl/UVEVP3o7ZQKSkvA8Dk/dgSWpjq8QPtewFcQktSL5lYhf4chg5HmoPmf+FUsQ4BcCR4kBT/CKwlUyhX0389YVBGufsxenEYci53N6qj9nDwtBBbRoRIzSSrMcb61PfcCsH+IQavvWEf8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759309440; c=relaxed/simple; bh=z63AlyB/Lgx2QP51GJZlyDIfxMw2+ee+9raPI6J+m4I=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=F4dy3jX0EBkzDGIGQ6GGib/vIaSLuE0Eftn4oqzkMtGcqOB5HdCqj24iry2J4uD6UKqgDvgwCTfTeSY4Xix3d5Cdsf22hCe3PYD8i6+uDysmQptUNqQNEvs7XqavL5ESCefKDOtVN2FnKF8sFdku9aaVX6ZSujnMJUDJXVlDnP0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me; spf=pass smtp.mailfrom=pm.me; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b=L9sVTHvM; arc=none smtp.client-ip=109.224.244.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pm.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b="L9sVTHvM" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pm.me; s=protonmail3; t=1759309434; x=1759568634; bh=YoI0D4NsBDAriHqvQCNsBFedVGBNu9amEcT5uTdvatQ=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=L9sVTHvMw4CrqyW+CsE9JaQwJVAo1oLei/965QD0Gyr/xDd3x3VmDqqRNN3EFvHIk qGvW/IOiRXZVGs8Zr2Uq8BIN3mik48n48AVNcQP1l+nVzynsk4SMgmHLXQlJNoTdfe Cm4n60ytoVcTxx7SSgp/RinH/mV59nr4yshFcbU2mereAc5tJw964pisXmwPgf/OpG 13YwgYGTYP713AHIAY+4JhTjT/Bd+AT3oizcLDvUnAzlaBa1Rvg+88iwzhw/wXdIH7 aZAZT/Qt8P6F01QOBu/dt2/yIl1UIICk7e6k2xtccYTWmxRcfKqmu+Abj9W8qHHTwA WlYhCb22qDDQw== Date: Wed, 01 Oct 2025 09:03:46 +0000 To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?Q?Bj=C3=B6rn_Roy_Baron?= , Andreas Hindborg , Alice Ryhl , Trevor Gross , Benno Lossin , Danilo Krummrich , Greg Kroah-Hartman , Dave Ertman , Ira Weiny , Leon Romanovsky , "Rafael J. Wysocki" , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Alexander Viro , Christian Brauner , Jan Kara , Lorenzo Stoakes , "Liam R. Howlett" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?Q?Krzysztof_Wilczy=C5=84ski?= , Asahi Lina From: Oliver Mangold Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-block@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, Oliver Mangold Subject: [PATCH v12 1/4] rust: types: Add Ownable/Owned types Message-ID: <20251001-unique-ref-v12-1-fa5c31f0c0c4@pm.me> In-Reply-To: <20251001-unique-ref-v12-0-fa5c31f0c0c4@pm.me> References: <20251001-unique-ref-v12-0-fa5c31f0c0c4@pm.me> Feedback-ID: 31808448:user:proton X-Pm-Message-ID: 4c3d84e501b0f9cf1753def9896c6efd7ea89700 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- rust/kernel/lib.rs | 1 + rust/kernel/owned.rs | 195 +++++++++++++++++++++++++++++++++++++++++++= ++++ rust/kernel/sync/aref.rs | 5 ++ rust/kernel/types.rs | 2 + 4 files changed, 203 insertions(+) diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index ed53169e795c0badf548025a57f946fa18bc73e3..3aea741f668b7d7a1a16e8e4537= e5edba997259c 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -92,6 +92,7 @@ pub mod init; pub mod io; pub mod ioctl; +pub mod owned; pub mod jump_label; #[cfg(CONFIG_KUNIT)] pub mod kunit; diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs new file mode 100644 index 0000000000000000000000000000000000000000..38f70a20fb965305d14836498a0= e7ad73166c6c4 --- /dev/null +++ b/rust/kernel/owned.rs @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Unique reference types for objects with custom destructors. They shoul= d be used for C-allocated +//! objects which by API-contract are owned by Rust, but need to be freed = through the C API. + +use core::{ + marker::PhantomData, + mem::ManuallyDrop, + ops::{Deref, DerefMut}, + pin::Pin, + ptr::NonNull, +}; + +/// Type allocated and destroyed on the C side, but owned by Rust. +/// +/// Implementing this trait allows types to be wrapped in an [`Owned= `]. Such types can +/// define their own custom destructor function to be called when the [`Ow= ned`] is +/// dropped. +/// +/// Note: The underlying object is not required to provide internal refere= nce counting, because it +/// represents a unique, owned reference. If reference counting (on the Ru= st side) is required, +/// [`AlwaysRefCounted`](crate::types::AlwaysRefCounted) should be impleme= nted. +/// +/// # Safety +/// +/// Implementers must ensure that the [`release()`](Self::release) functio= n frees the underlying +/// object in the correct way for a valid, owned object of this type. +/// +/// # Examples +/// +/// A minimal example implementation of [`Ownable`] and its usage with [`O= wned`] looks like this: +/// +/// ``` +/// # #![expect(clippy::disallowed_names)] +/// use core::cell::Cell; +/// use core::ptr::NonNull; +/// use kernel::sync::global_lock; +/// use kernel::alloc::{flags, kbox::KBox, AllocError}; +/// use kernel::types::{Owned, Ownable}; +/// +/// // Let's count the allocations to see if freeing works. +/// kernel::sync::global_lock! { +/// // SAFETY: we call `init()` right below, before doing anything els= e. +/// unsafe(uninit) static FOO_ALLOC_COUNT: Mutex =3D 0; +/// } +/// // SAFETY: We call `init()` only once, here. +/// unsafe { FOO_ALLOC_COUNT.init() }; +/// +/// struct Foo { +/// } +/// +/// impl Foo { +/// fn new() -> Result, AllocError> { +/// // We are just using a `KBox` here to handle the actual alloca= tion, as our `Foo` is +/// // not actually a C-allocated object. +/// let result =3D KBox::new( +/// Foo {}, +/// flags::GFP_KERNEL, +/// )?; +/// let result =3D NonNull::new(KBox::into_raw(result)) +/// .expect("Raw pointer to newly allocation KBox is null, thi= s should never happen."); +/// // Count new allocation +/// *FOO_ALLOC_COUNT.lock() +=3D 1; +/// // SAFETY: We just allocated the `Self`, thus it is valid and = there cannot be any other +/// // Rust references. Calling `into_raw()` makes us responsible = for ownership and we won't +/// // use the raw pointer anymore. Thus we can transfer ownership= to the `Owned`. +/// Ok(unsafe { Owned::from_raw(result) }) +/// } +/// } +/// +/// // SAFETY: What out `release()` function does is safe of any valid `Se= lf`. +/// unsafe impl Ownable for Foo { +/// unsafe fn release(this: NonNull) { +/// // The `Foo` will be dropped when `KBox` goes out of scope. +/// // SAFETY: The [`KBox`] is still alive. We can pass owne= rship to the [`KBox`], as +/// // by requirement on calling this function, the `Self` will no= longer be used by the +/// // caller. +/// unsafe { KBox::from_raw(this.as_ptr()) }; +/// // Count released allocation +/// *FOO_ALLOC_COUNT.lock() -=3D 1; +/// } +/// } +/// +/// { +/// let foo =3D Foo::new().expect("Failed to allocate a Foo. This shoul= dn't happen"); +/// assert!(*FOO_ALLOC_COUNT.lock() =3D=3D 1); +/// } +/// // `foo` is out of scope now, so we expect no live allocations. +/// assert!(*FOO_ALLOC_COUNT.lock() =3D=3D 0); +/// ``` +pub unsafe trait Ownable { + /// Releases the object. + /// + /// # Safety + /// + /// Callers must ensure that: + /// - `this` points to a valid `Self`. + /// - `*this` is no longer referenced after this call. + unsafe fn release(this: NonNull); +} + +/// An owned reference to an [`Ownable`] object. +/// +/// The [`Ownable`] is automatically freed or released when an instance of= [`Owned`] is +/// dropped. +/// +/// # Invariants +/// +/// - The [`Owned`] has exclusive access to the instance of `T`. +/// - The instance of `T` will stay alive at least as long as the [`Owned<= T>`] is alive. +pub struct Owned { + ptr: NonNull, + _p: PhantomData, +} + +// 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 Owned { + /// Creates a new instance of [`Owned`]. + /// + /// It takes over ownership of the underlying object. + /// + /// # Safety + /// + /// Callers must ensure that: + /// - `ptr` points to a valid instance of `T`. + /// - Ownership of the underlying `T` can be transferred to the `Self<= T>` (i.e. operations + /// which require ownership will be safe). + /// - No other Rust references to the underlying object exist. This im= plies that the underlying + /// object is not accessed through `ptr` anymore after the function = call (at least until the + /// the `Self` is dropped. + /// - The C code follows the usual shared reference requirements. That= is, the kernel will never + /// mutate or free the underlying object (excluding interior mutabil= ity that follows the usual + /// rules) while Rust owns it. + /// - In case `T` implements [`Unpin`] the previous requirement is ext= ended from shared to + /// mutable reference requirements. That is, the kernel will not mut= ate or free the underlying + /// object and is okay with it being modified by Rust code. + pub unsafe fn from_raw(ptr: NonNull) -> Self { + Self { + ptr, + _p: PhantomData, + } + } + + /// Consumes the [`Owned`], returning a raw pointer. + /// + /// This function does not actually relinquish ownership of the object= . After calling this + /// function, the caller is responsible for ownership previously manag= ed + /// by the [`Owned`]. + 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 get_pin_mut(&mut self) -> Pin<&mut T> { + // SAFETY: The type invariants guarantee that the object is valid,= and that we can safely + // return a mutable reference to it. + let unpinned =3D unsafe { self.ptr.as_mut() }; + + // SAFETY: We never hand out unpinned mutable references to the da= ta in + // `Self`, unless the contained type is `Unpin`. + unsafe { Pin::new_unchecked(unpinned) } + } +} + +impl Deref for Owned { + type Target =3D T; + + fn deref(&self) -> &Self::Target { + // SAFETY: The type invariants guarantee that the object is valid. + unsafe { self.ptr.as_ref() } + } +} + +impl DerefMut for Owned { + fn deref_mut(&mut self) -> &mut Self::Target { + // SAFETY: The type invariants guarantee that the object is valid,= and that we can safely + // return a mutable reference to it. + unsafe { self.ptr.as_mut() } + } +} + +impl Drop for Owned { + fn drop(&mut self) { + // SAFETY: The type invariants guarantee that the `Owned` owns the= object we're about to + // release. + unsafe { T::release(self.ptr) }; + } +} diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs index dbd77bb68617cab786fe4a1168d697e30a6de299..f8085cfe50db0798c3cdadab35a= c6e2826c315f9 100644 --- a/rust/kernel/sync/aref.rs +++ b/rust/kernel/sync/aref.rs @@ -14,6 +14,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 dc0a02f5c3cfc532d1fa5f209b40dd79cbe0fb37..7bc07c38cd6cb6abb59384e20a7= 93f28633a9eac 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -11,6 +11,8 @@ }; use pin_init::{PinInit, Wrapper, Zeroable}; =20 +pub use crate::owned::{Ownable, Owned}; + pub use crate::sync::aref::{ARef, AlwaysRefCounted}; =20 /// Used to transfer ownership to and from foreign (non-Rust) languages. --=20 2.51.0 From nobody Wed Oct 1 21:27:10 2025 Received: from mail-4322.protonmail.ch (mail-4322.protonmail.ch [185.70.43.22]) (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 D465D2D7DC3; Wed, 1 Oct 2025 09:04:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.22 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759309458; cv=none; b=GS2rSYVmaBL6ArAAn9GKCyyfcfuyj3jE5J9iQ4oK0d/2j4lti8kk7kPOFF4uvXxP4RHRQ8rLPilBqW5aD+XTy7srl06MK9qdl/KXqJzOD3KCQeu7Yy3PAobIQ6Me4dJin2qbRxZuUrU9OQOWE0NDEeO7dUAPrn0V3eJ3b28x51U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759309458; c=relaxed/simple; bh=5y4zcj1gcvZvNmKWuKMwTDLi8RpSjzPpgkNs3XB53Jw=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=aOZQrqxVoHNuum2Ds83AlmqZ84xYX0N6ZTbea+rtlaq+OOCYcI0d4IpdB9X0J/41nNGCA/0+zvXud+Z2XZOPZma7Qpl6rs/xc+DS5q+bdYZWB5YxuoqDDT2mTNxh6Zh3FF9tvC3PHuoAOC6m0E9uq9QgDmQUlYWnVTLaFvzP24A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me; spf=pass smtp.mailfrom=pm.me; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b=d5UfwiDU; arc=none smtp.client-ip=185.70.43.22 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pm.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b="d5UfwiDU" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pm.me; s=protonmail3; t=1759309444; x=1759568644; bh=FjV73AOvmni5qllqj0qFi4KSNxDrPzQBA0xgDZ9fnZI=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=d5UfwiDUT5ymEQv/pDsAm+K1X8i543KkOtLNNXY7IW1hlbG/AIdHKo0THHcEhzjoh y+dUfXdrHu4jXV5THsuDIW6IsgPtzA/ZDYkzBa1sP4B7YCujyIO6trc5G12qHfR4n5 veySkNvwXmCuhNtOgiAbEatzXByaH0yThVQ+ERKZsd7ztNt9Qv9B3FrQfv+IqoPBXE mGZXCd3wZIdWFv3esm9S+e5ZxPxdyVY8YW/sMx7mAYFFfYSZK9PCkMOzesBxPHCXbF 9PyDdj40+yB5n6w1zQ8OqeCtdOHmV+q+5WU7bx/tcNoADVPB8Z7BIJZiCgHYpf4ZiN 5YptVjLSeD01Q== Date: Wed, 01 Oct 2025 09:03:58 +0000 To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?Q?Bj=C3=B6rn_Roy_Baron?= , Andreas Hindborg , Alice Ryhl , Trevor Gross , Benno Lossin , Danilo Krummrich , Greg Kroah-Hartman , Dave Ertman , Ira Weiny , Leon Romanovsky , "Rafael J. Wysocki" , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Alexander Viro , Christian Brauner , Jan Kara , Lorenzo Stoakes , "Liam R. Howlett" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?Q?Krzysztof_Wilczy=C5=84ski?= , Asahi Lina From: Oliver Mangold Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-block@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, Oliver Mangold Subject: [PATCH v12 2/4] `AlwaysRefCounted` is renamed to `RefCounted`. Message-ID: <20251001-unique-ref-v12-2-fa5c31f0c0c4@pm.me> In-Reply-To: <20251001-unique-ref-v12-0-fa5c31f0c0c4@pm.me> References: <20251001-unique-ref-v12-0-fa5c31f0c0c4@pm.me> Feedback-ID: 31808448:user:proton X-Pm-Message-ID: 0b6ef3b8e154e0877a631c62412421623f34cbde Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" `AlwaysRefCounted` will become a marker trait to indicate that it is allowed to obtain an `ARef` from a `&T`, which cannot be allowed for types which are also Ownable. Signed-off-by: Oliver Mangold Suggested-by: Alice Ryhl --- rust/kernel/auxiliary.rs | 7 +++++- rust/kernel/block/mq/request.rs | 14 +++++++----- rust/kernel/cred.rs | 7 +++++- rust/kernel/device.rs | 9 ++++++-- rust/kernel/device/property.rs | 7 +++++- rust/kernel/drm/device.rs | 9 ++++++-- rust/kernel/drm/gem/mod.rs | 7 +++++- rust/kernel/fs/file.rs | 13 ++++++++++-- rust/kernel/mm.rs | 12 +++++++++-- rust/kernel/mm/mmput_async.rs | 7 +++++- rust/kernel/opp.rs | 7 +++++- rust/kernel/owned.rs | 2 +- rust/kernel/pci.rs | 7 +++++- rust/kernel/pid_namespace.rs | 7 +++++- rust/kernel/platform.rs | 7 +++++- rust/kernel/sync/aref.rs | 47 ++++++++++++++++++++++++++-----------= ---- rust/kernel/task.rs | 7 +++++- rust/kernel/types.rs | 2 +- 18 files changed, 136 insertions(+), 42 deletions(-) diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index 4749fb6bffef34000d9029fecfd6553414feeae0..b5253521be1be7ded9727e596cb= 8402f9f9079a6 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -10,6 +10,7 @@ driver, error::{from_result, to_result, Result}, prelude::*, + sync::aref::{AlwaysRefCounted, RefCounted}, types::Opaque, ThisModule, }; @@ -245,7 +246,7 @@ extern "C" fn release(dev: *mut bindings::device) { kernel::impl_device_context_into_aref!(Device); =20 // SAFETY: Instances of `Device` are always reference-counted. -unsafe impl crate::types::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()) }; @@ -264,6 +265,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 fefd394f064a7127dc9e4b6a246f6d11267ad247..6c074ca1d14e399e6505205cfd1= 9e702dbc4a914 100644 --- a/rust/kernel/block/mq/request.rs +++ b/rust/kernel/block/mq/request.rs @@ -8,6 +8,7 @@ bindings, block::mq::Operations, error::Result, + sync::aref::RefCounted, types::{ARef, AlwaysRefCounted, Opaque}, }; use core::{ @@ -231,11 +232,10 @@ fn atomic_relaxed_op_unless(target: &AtomicU64, op: i= mpl Fn(u64) -> u64, pred: u .is_ok() } =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) { let refcount =3D &self.wrapper_ref().refcount(); =20 @@ -265,3 +265,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 2599f01e8b285f2106aefd27c315ae2aff25293c..d2b6a6b7430e8ee885706a894a2= bd6b1b39e81cb 100644 --- a/rust/kernel/cred.rs +++ b/rust/kernel/cred.rs @@ -10,6 +10,7 @@ =20 use crate::{ bindings, + sync::aref::RefCounted, task::Kuid, types::{AlwaysRefCounted, Opaque}, }; @@ -74,7 +75,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. @@ -88,3 +89,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 b8613289de8e7cea3ad7e32ec088eedc28ebf723..b2e297db102f3cac4d719e5e8a0= 23bc022a88051 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -6,7 +6,8 @@ =20 use crate::{ bindings, - types::{ARef, ForeignOwnable, Opaque}, + sync::aref::RefCounted, + types::{ARef, AlwaysRefCounted, ForeignOwnable, Opaque}, }; use core::{fmt, marker::PhantomData, ptr}; =20 @@ -292,7 +293,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::types::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()) }; @@ -304,6 +305,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 49ee12a906dbadbe932e207fc7a0d1d622125f5f..7f61caff2959bc1f70d61276ac4= 79f03f2565a41 100644 --- a/rust/kernel/device/property.rs +++ b/rust/kernel/device/property.rs @@ -13,6 +13,7 @@ error::{to_result, Result}, prelude::*, str::{CStr, CString}, + sync::aref::{AlwaysRefCounted, RefCounted}, types::{ARef, Opaque}, }; =20 @@ -358,7 +359,7 @@ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core= ::fmt::Result { } =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. @@ -372,6 +373,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 3bb7c83966cf2d2acfdf9053fc5b25ca7607da2b..0c0e57082d4a96981fa88a289fe= e9c091a4d2ed5 100644 --- a/rust/kernel/drm/device.rs +++ b/rust/kernel/drm/device.rs @@ -10,7 +10,8 @@ error::from_err_ptr, error::Result, prelude::*, - types::{ARef, AlwaysRefCounted, Opaque}, + sync::aref::{AlwaysRefCounted, RefCounted}, + types::{ARef, Opaque}, }; use core::{mem, ops::Deref, ptr, ptr::NonNull}; =20 @@ -182,7 +183,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()) }; @@ -194,6 +195,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 b71821cfb5eaa00eb3a95646fa0a8b8a1ad0790b..8ef012f4fde4796013e86d5eef2= b3077449ed984 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -10,6 +10,7 @@ drm::driver::{AllocImpl, AllocOps}, error::{to_result, Result}, prelude::*, + sync::aref::RefCounted, types::{ARef, AlwaysRefCounted, Opaque}, }; use core::{mem, ops::Deref, ptr::NonNull}; @@ -55,7 +56,7 @@ pub trait IntoGEMObject: Sized + super::private::Sealed += AlwaysRefCounted { } =20 // SAFETY: All gem objects are refcounted. -unsafe impl AlwaysRefCounted for T { +unsafe impl RefCounted for T { 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()) }; @@ -74,6 +75,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 +// `&T`. +unsafe impl crate::types::AlwaysRefCounted for T {} + /// Trait which must be implemented by drivers using base GEM objects. pub trait DriverObject: BaseDriverObject> { /// Parent `Driver` for this object. diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 35fd5db35c465279acb3b88dc3c90c8f95d29cf4..7b457443774d127538053268f1d= bb4f8254c66d2 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -11,6 +11,7 @@ bindings, cred::Credential, error::{code::*, Error, Result}, + sync::aref::RefCounted, types::{ARef, AlwaysRefCounted, NotThreadSafe, Opaque}, }; use core::ptr; @@ -190,7 +191,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. @@ -205,6 +206,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. @@ -226,7 +231,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. @@ -242,6 +247,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/mm.rs b/rust/kernel/mm.rs index 43f525c0d16ce87340ba4f991c45d4e82a050eae..dd9e3969e720662de0f032f1f66= 9ac37e64edc7d 100644 --- a/rust/kernel/mm.rs +++ b/rust/kernel/mm.rs @@ -13,6 +13,7 @@ =20 use crate::{ bindings, + sync::aref::RefCounted, types::{ARef, AlwaysRefCounted, NotThreadSafe, Opaque}, }; use core::{ops::Deref, ptr::NonNull}; @@ -54,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. @@ -68,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 @@ -90,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. @@ -104,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 9289e05f7a676b577e4edf45949c0fab6aacec14..aba4ce675c860e46e04b9535acc= fb3d611ec28fe 100644 --- a/rust/kernel/mm/mmput_async.rs +++ b/rust/kernel/mm/mmput_async.rs @@ -10,6 +10,7 @@ use crate::{ bindings, mm::MmWithUser, + sync::aref::RefCounted, types::{ARef, AlwaysRefCounted}, }; use core::{ops::Deref, ptr::NonNull}; @@ -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 08126035d2c66f849e4893ff2418d46d28bee84c..172dcfe5fd7be2110fdf08402a7= e287c5d073cf4 100644 --- a/rust/kernel/opp.rs +++ b/rust/kernel/opp.rs @@ -16,6 +16,7 @@ ffi::c_ulong, prelude::*, str::CString, + sync::aref::RefCounted, types::{ARef, AlwaysRefCounted, Opaque}, }; =20 @@ -1042,7 +1043,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()) }; @@ -1054,6 +1055,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 38f70a20fb965305d14836498a0e7ad73166c6c4..466b7ecda6d9f4f54852ca0b59b= 36ac882ab3f47 100644 --- a/rust/kernel/owned.rs +++ b/rust/kernel/owned.rs @@ -19,7 +19,7 @@ /// /// Note: The underlying object is not required to provide internal refere= nce counting, because it /// represents a unique, owned reference. If reference counting (on the Ru= st side) is required, -/// [`AlwaysRefCounted`](crate::types::AlwaysRefCounted) should be impleme= nted. +/// [`RefCounted`](crate::types::RefCounted) should be implemented. /// /// # Safety /// diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 887ee611b55310e7edbd512f9017b708ff9d7bd8..9d7861fc4b99ef67859296a400b= ac87e1bafdd2a 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -13,6 +13,7 @@ io::Io, io::IoRaw, str::CStr, + sync::aref::{AlwaysRefCounted, RefCounted}, types::{ARef, Opaque}, ThisModule, }; @@ -455,7 +456,7 @@ pub fn set_master(&self) { impl crate::dma::Device for Device {} =20 // SAFETY: Instances of `Device` are always reference-counted. -unsafe impl crate::types::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()) }; @@ -467,6 +468,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 0e93808e4639b37dd77add5d79f64058dac7cb87..4f6a94540e33d73eb9f2faa416b= ca66df3b66940 100644 --- a/rust/kernel/pid_namespace.rs +++ b/rust/kernel/pid_namespace.rs @@ -9,6 +9,7 @@ =20 use crate::{ bindings, + sync::aref::RefCounted, types::{AlwaysRefCounted, Opaque}, }; use core::ptr; @@ -44,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. @@ -58,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 8f028c76f9fa6154f440b48921ba16573a9d3c54..75c382040e27e9f40bff6a66d35= 409318379133d 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -12,6 +12,7 @@ io::{mem::IoRequest, Resource}, of, prelude::*, + sync::aref::{AlwaysRefCounted, RefCounted}, types::Opaque, ThisModule, }; @@ -292,7 +293,7 @@ pub fn io_request_by_name(&self, name: &CStr) -> Option= > { impl crate::dma::Device for Device {} =20 // SAFETY: Instances of `Device` are always reference-counted. -unsafe impl crate::types::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()) }; @@ -304,6 +305,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 f8085cfe50db0798c3cdadab35ac6e2826c315f9..e029b4c046449a6b0bb61bb6369= ac26f9495b2ad 100644 --- a/rust/kernel/sync/aref.rs +++ b/rust/kernel/sync/aref.rs @@ -4,11 +4,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 @@ -25,9 +23,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 @@ -40,11 +37,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 to derive 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 to violat= e the uniqueness guarantee +/// of [`crate::types::Owned`] by derefencing it into an `&T` and obtai= ning 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 @@ -55,7 +68,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, } @@ -64,16 +77,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. @@ -102,12 +115,12 @@ pub unsafe fn from_raw(ptr: NonNull) -> Self { /// /// ``` /// use core::ptr::NonNull; - /// use kernel::types::{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) {} /// } @@ -125,7 +138,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. @@ -133,7 +146,7 @@ fn clone(&self) -> Self { } } =20 -impl Deref for ARef { +impl Deref for ARef { type Target =3D T; =20 fn deref(&self) -> &Self::Target { @@ -150,7 +163,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 7d0935bc325cb8755f6878688d623d5d1da37225..ce20a91c3f9bf2ae94c3354b0ce= 66c8b3a26e616 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -9,6 +9,7 @@ ffi::{c_int, c_long, c_uint}, mm::MmWithUser, pid_namespace::PidNamespace, + sync::aref::{AlwaysRefCounted, RefCounted}, types::{ARef, NotThreadSafe, Opaque}, }; use core::{ @@ -347,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::types::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. @@ -361,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 7bc07c38cd6cb6abb59384e20a793f28633a9eac..8ef01393352bb2510524bf070ad= 4141147ed945f 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -13,7 +13,7 @@ =20 pub use crate::owned::{Ownable, Owned}; =20 -pub use crate::sync::aref::{ARef, AlwaysRefCounted}; +pub use crate::sync::aref::{ARef, AlwaysRefCounted, RefCounted}; =20 /// Used to transfer ownership to and from foreign (non-Rust) languages. /// --=20 2.51.0 From nobody Wed Oct 1 21:27:10 2025 Received: from mail-24418.protonmail.ch (mail-24418.protonmail.ch [109.224.244.18]) (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 D2F752D9EF4; Wed, 1 Oct 2025 09:04:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=109.224.244.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759309465; cv=none; b=YkKAUV80+NpQ0JwtVDqMvgZXg7EKbPpueWa227qlDS+rMpZ8DnobYbd7qhfQOcoOwLg1TzF17KfTlI9Q2LNm0cMpOStcoqMOQqyXjLR8vSz29asDD8m+bhBOEx4h/08FdrtdNl8Mp2eOzSXrza4KJ0q19+PVRlkjx0gUJ+zhHMI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759309465; c=relaxed/simple; bh=Lau7OAV0t+rECLHLfNwRhmqkvfiQQwtB9F6PCmoc5oI=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ic77VQCxJ6IdHdzig0xKLYR5GPDy2t1TUYMwOqgi+MqaLBCp3IImW4fy3CHL05j6Ndn+8hU9fNUIh0iRqerFMTUdnrmCyMHWxZlIyFlTc3mEpJbBjfC/XkYD6k10RjRleN7wxCy7bssKqkqpQdzt2sJNSEfqVFQ+MQvHCOB7uyc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me; spf=pass smtp.mailfrom=pm.me; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b=oMmk1RTJ; arc=none smtp.client-ip=109.224.244.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pm.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b="oMmk1RTJ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pm.me; s=protonmail3; t=1759309460; x=1759568660; bh=fssLc+fEIJ9sBuAHQfTYDJPSK2dP+xUCFgdJy3AY7go=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=oMmk1RTJ8/wiD0SCWtIOdeIspDkJJb+oBRz3PvNzwvBuuSWFNAG4caZHfOeJaFUc2 kXlrgCZwBtLMcYpGvTnk2fePqEC6kdvvNTCzu/XTWGWRHaZyWIe9UF5kGa/+OyD2iy BppGHvJeSbsyQ+iv2q7y34i2tO42AdRmjc0G1iF0If85oHo38oHBrTE8C+6Rnry2Gl BxXLON+Ls71xPHV66jpCjIGoXsldN6TgHhlbO/5WyWWR2o74PpvSz7ww+iwTMjWVR9 1YoxJV2BH41U+HLHnz/UF+VYijBHXNgzOOfDd8W0tjNQMJX19L2uvKwDSl8uvRyH0v GLO0p6eNKGVCg== Date: Wed, 01 Oct 2025 09:04:11 +0000 To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?Q?Bj=C3=B6rn_Roy_Baron?= , Andreas Hindborg , Alice Ryhl , Trevor Gross , Benno Lossin , Danilo Krummrich , Greg Kroah-Hartman , Dave Ertman , Ira Weiny , Leon Romanovsky , "Rafael J. Wysocki" , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Alexander Viro , Christian Brauner , Jan Kara , Lorenzo Stoakes , "Liam R. Howlett" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?Q?Krzysztof_Wilczy=C5=84ski?= , Asahi Lina From: Oliver Mangold Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-block@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, Oliver Mangold Subject: [PATCH v12 3/4] rust: Add missing SAFETY documentation for `ARef` example Message-ID: <20251001-unique-ref-v12-3-fa5c31f0c0c4@pm.me> In-Reply-To: <20251001-unique-ref-v12-0-fa5c31f0c0c4@pm.me> References: <20251001-unique-ref-v12-0-fa5c31f0c0c4@pm.me> Feedback-ID: 31808448:user:proton X-Pm-Message-ID: 8ab9517ccdb9c0bc9ac966b0661995277141b944 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" SAFETY comment in rustdoc example was just 'TODO'. Fixed. Signed-off-by: Oliver Mangold --- 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 e029b4c046449a6b0bb61bb6369ac26f9495b2ad..97cfddd9ec2ad788a4a659f404a= 9b6790da08e29 100644 --- a/rust/kernel/sync/aref.rs +++ b/rust/kernel/sync/aref.rs @@ -119,7 +119,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 having a = refcount on 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) {} @@ -127,7 +129,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.0 From nobody Wed Oct 1 21:27:10 2025 Received: from mail-24418.protonmail.ch (mail-24418.protonmail.ch [109.224.244.18]) (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 8C90E2D8788 for ; Wed, 1 Oct 2025 09:04:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=109.224.244.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759309482; cv=none; b=sF/SBLM0F7Pw2efgmvb79mrYee11vnTP0iYaKYxZioxTIQS05NOYQGyk0nmK61cCxGxWOvjCLGElJpyMEI+kbwbWp2tCcPhhfWq9/2dCJw+qHi2YQmEluwP/MJvFsvy14b+KEdZ5rlK2GMYy4fKuAwug1R0KrzsFPzgdoD4ocdY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759309482; c=relaxed/simple; bh=wGzu/YJLmjjXeXLIWypdaKjxbslobXvvvheND7JZWhY=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=bQH/xCbnsBNDbYU8iuD44L8tZkuYWQv1C4JJqpijUxgpftCYtiw5uvDqsEUn/v3gvfCYw6fW7qIS9iE1uJpilSSZNpcnmJ8WBLxnIEoKYJ0zVjTIeu2UoDrPDbIiwE548s5lj1NetMsYWQkSGV7rvsYIUzgpSv3g9bl9jAMP8DQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me; spf=pass smtp.mailfrom=pm.me; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b=rKJ0zo80; arc=none smtp.client-ip=109.224.244.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pm.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b="rKJ0zo80" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pm.me; s=protonmail3; t=1759309474; x=1759568674; bh=yp/Ky9qZB+Lu2rfaJfq2n9npeG17/rIKND2/1FJbPUU=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=rKJ0zo808K9+5xv+W+fbxwG7qVsIwuWt2mbyuJGFLiXXCoVZoeZVu3SLq6+wnhkS6 9zijPkbcHDElLMm9/Bee795eT9ukcv732jQW0DzyAcKr2VRZ1+2dtJnGpOLuFZrPqN aPNucRfz0HQpb322WmUDY63i/Vgx6HMh7ngXDaU0QPiQuiwBDxzSCL6yPIZAFw1GeA nDhkHM9HYJpYUij3nie0NTuQ1iweAHh3D6/dswrnS/XIriKSAwKVWOynLjJPuGuqOd x3yAkCadMoBGsr2QK3jsBXIvGOJqiwutO+rPE/LLNa83zA4uTWVa6Oy2Ri/h1QqHs3 QzBkgjOw5SMzw== Date: Wed, 01 Oct 2025 09:04:27 +0000 To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?Q?Bj=C3=B6rn_Roy_Baron?= , Andreas Hindborg , Alice Ryhl , Trevor Gross , Benno Lossin , Danilo Krummrich , Greg Kroah-Hartman , Dave Ertman , Ira Weiny , Leon Romanovsky , "Rafael J. Wysocki" , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Alexander Viro , Christian Brauner , Jan Kara , Lorenzo Stoakes , "Liam R. Howlett" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?Q?Krzysztof_Wilczy=C5=84ski?= , Asahi Lina From: Oliver Mangold Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-block@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, Oliver Mangold Subject: [PATCH v12 4/4] rust: Add `OwnableRefCounted` Message-ID: <20251001-unique-ref-v12-4-fa5c31f0c0c4@pm.me> In-Reply-To: <20251001-unique-ref-v12-0-fa5c31f0c0c4@pm.me> References: <20251001-unique-ref-v12-0-fa5c31f0c0c4@pm.me> Feedback-ID: 31808448:user:proton X-Pm-Message-ID: 273bbd2e0c664caf1e93c782e9d3dde288208540 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: Andreas Hindborg --- rust/kernel/owned.rs | 125 +++++++++++++++++++++++++++++++++++++++++++= +++- rust/kernel/sync/aref.rs | 11 ++++- rust/kernel/types.rs | 2 +- 3 files changed, 135 insertions(+), 3 deletions(-) diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs index 466b7ecda6d9f4f54852ca0b59b36ac882ab3f47..ad38a4d378fa8fcf934f1c41cd9= 02d79a2c8baa5 100644 --- a/rust/kernel/owned.rs +++ b/rust/kernel/owned.rs @@ -3,6 +3,7 @@ //! Unique reference types for objects with custom destructors. They shoul= d be used for C-allocated //! objects which by API-contract are owned by Rust, but need to be freed = through the C API. =20 +use crate::sync::aref::{ARef, RefCounted}; use core::{ marker::PhantomData, mem::ManuallyDrop, @@ -19,7 +20,8 @@ /// /// Note: The underlying object is not required to provide internal refere= nce counting, because it /// represents a unique, owned reference. If reference counting (on the Ru= st side) is required, -/// [`RefCounted`](crate::types::RefCounted) should be implemented. +/// [`RefCounted`] should be implemented. [`OwnableRefCounted`] should be = implemented if conversion +/// between unique and shared (reference counted) ownership is needed. /// /// # Safety /// @@ -193,3 +195,124 @@ fn drop(&mut self) { unsafe { T::release(self.ptr) }; } } + +/// A trait for objects that can be wrapped in either one of the reference= types [`Owned`] and +/// [`ARef`]. +/// +/// # Examples +/// +/// A minimal example implementation of [`OwnableRefCounted`], [`Ownable`]= and its usage with +/// [`ARef`] and [`Owned`] looks like this: +/// +/// ``` +/// # #![expect(clippy::disallowed_names)] +/// use core::cell::Cell; +/// use core::ptr::NonNull; +/// use kernel::alloc::{flags, kbox::KBox, AllocError}; +/// use kernel::sync::aref::{ARef, RefCounted}; +/// use kernel::types::{Owned, Ownable, OwnableRefCounted}; +/// +/// // Example internally refcounted struct. +/// // +/// // # Invariants +/// // +/// // - `refcount` is always non-zero for a valid object. +/// // - `refcount` is >1 if there are more then 1 Rust references to it. +/// // +/// struct Foo { +/// refcount: Cell, +/// } +/// +/// impl Foo { +/// fn new() -> Result, AllocError> { +/// // We are just using a `KBox` here to handle the actual alloca= tion, as our `Foo` is +/// // not actually a C-allocated object. +/// let result =3D KBox::new( +/// Foo { +/// refcount: Cell::new(1), +/// }, +/// flags::GFP_KERNEL, +/// )?; +/// let result =3D NonNull::new(KBox::into_raw(result)) +/// .expect("Raw pointer to newly allocation KBox is null, thi= s should never happen."); +/// // SAFETY: We just allocated the `Self`, thus it is valid and = there cannot be any other +/// // Rust references. Calling `into_raw()` makes us responsible = for ownership and +/// // we won't use the raw pointer anymore, thus we can transfer = ownership to the `Owned`. +/// Ok(unsafe { Owned::from_raw(result) }) +/// } +/// } +/// +/// // SAFETY: We increment and decrement each time the respective functio= n is called and only free +/// // the `Foo` when the refcount reaches zero. +/// unsafe impl RefCounted for Foo { +/// fn inc_ref(&self) { +/// self.refcount.replace(self.refcount.get() + 1); +/// } +/// +/// unsafe fn dec_ref(this: NonNull) { +/// // SAFETY: By requirement on calling this function, the refcou= nt is non-zero, +/// // implying the underlying object is valid. +/// let refcount =3D unsafe { &this.as_ref().refcount }; +/// let new_refcount =3D refcount.get() - 1; +/// if new_refcount =3D=3D 0 { +/// // The `Foo` will be dropped when `KBox` goes out of scope. +/// // SAFETY: The [`KBox`] is still alive as the old ref= count is 1. We can pass +/// // ownership to the [`KBox`] as by requirement on calling = this function, +/// // the `Self` will no longer be used by the caller. +/// unsafe { KBox::from_raw(this.as_ptr()) }; +/// } else { +/// refcount.replace(new_refcount); +/// } +/// } +/// } +/// +/// impl OwnableRefCounted for Foo { +/// fn try_from_shared(this: ARef) -> Result, ARef> { +/// if this.refcount.get() =3D=3D 1 { +/// // SAFETY: The `Foo` is still alive and has no other Rust = references as the refcount +/// // is 1. +/// Ok(unsafe { Owned::from_raw(ARef::into_raw(this)) }) +/// } else { +/// Err(this) +/// } +/// } +/// } +/// +/// // SAFETY: What out `release()` function does is safe of any valid `Se= lf`. +/// unsafe impl Ownable for Foo { +/// unsafe fn release(this: NonNull) { +/// // SAFETY: Using `dec_ref()` from [`RefCounted`] to release is= okay, as the refcount is +/// // always 1 for an [`Owned`]. +/// unsafe{ Foo::dec_ref(this) }; +/// } +/// } +/// +/// let foo =3D Foo::new().expect("Failed to allocate a Foo. This shouldn'= t happen"); +/// 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()); +/// ``` +pub trait OwnableRefCounted: RefCounted + Ownable + Sized { + /// Checks if the [`ARef`] is unique and convert it to an [`Owned`] it= that is that 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 97cfddd9ec2ad788a4a659f404a9b6790da08e29..605c56b3d634e048cdfe1524881= ab1e2e76ae3a4 100644 --- a/rust/kernel/sync/aref.rs +++ b/rust/kernel/sync/aref.rs @@ -15,7 +15,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`](crate::types::OwnableRefCounted) allows to conve= rt between unique and +/// shared references (i.e. [`Owned`](crate::types::Owned) and +/// [`ARef`](crate::types::Owned)). /// /// # Safety /// @@ -165,6 +168,12 @@ fn from(b: &T) -> Self { } } =20 +impl From> for = ARef { + fn from(b: crate::types::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 8ef01393352bb2510524bf070ad4141147ed945f..a9b72709d0d3c7fc58444a19fae= 896aed7506128 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -11,7 +11,7 @@ }; use pin_init::{PinInit, Wrapper, Zeroable}; =20 -pub use crate::owned::{Ownable, Owned}; +pub use crate::owned::{Ownable, OwnableRefCounted, Owned}; =20 pub use crate::sync::aref::{ARef, AlwaysRefCounted, RefCounted}; =20 --=20 2.51.0