From nobody Mon Jun 8 07:21:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.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 9468C3C4561; Thu, 4 Jun 2026 20:14:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604076; cv=none; b=cBnJgb8MHx1JxZNz58amZqknPtIKNBkGyzNin/7v3LwVq0EkJmz28mOEPZytJItSw8tQ+at0KPjkGNXNULR77J4miwxsvA5FLMVSKtwszAZL8l3TfWSFCTTOISmcA2lmbr1cuRgN/TVaX/tt4Unfi8WB5m0i3z6lgxft/MFL058= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604076; c=relaxed/simple; bh=HIU6Nmu7iABl9KtQIYtvgtPsm8T0d+RqMDFg+vb7EbI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ePp8dXj9Ax8CCsqnDiwH+WwvUXmAat75FyX0dUe5J6/1z3nofKxSPgJe8H7J+FhAGL3YxDyLG4Wz8mjmRVYkhk7HDJVRBz2YRg4WBb+fakACZtywNfx+obY7kU0pnIW8RKabVaPy3ORd8Amjcv3fLt/IAgSZLHztHqBjQweE4vs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Koul0/fk; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Koul0/fk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0B1AB1F00899; Thu, 4 Jun 2026 20:14:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780604075; bh=G3TVjSgjK9G7CyHxcZcbdJi1JuXhkhXf1eJMpalGwTo=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=Koul0/fk1we1IaCTJ09OH1HS+PPhIUtV9DSBqsN9ivuoz0s/UmIQ2Q6kp6W8Z4/mu ZF/Yxkjr4/r0P88xOyitn3hyuyev9JS+RNCrRgXiJu6OF2AVGzhu6IrA0HGDgZIPm/ 4ClHjq1YDnPgBSpqrZJoqyanInFwWw7lbRXjOM7Nq/TN87cur4wSynpuOfJ6gJ0y9v s0NWv/VGyf9weS7al6hGSQv05pLvqg0uYB5M0n8n0KrVAa7vJJ1Te6vUe1WfIm0dft qxH6Gf/rEVZR2M6y4v/mPV2BgbRKXbCiXxY8/Q7JHtDuKZkxM9WnnuapYMrS8/RtVZ o7mhUs79w09Xg== From: Andreas Hindborg Date: Thu, 04 Jun 2026 22:11:13 +0200 Subject: [PATCH v17 01/10] rust: alloc: add `KBox::into_non_null` 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: <20260604-unique-ref-v17-1-7b4c3d2930b9@kernel.org> References: <20260604-unique-ref-v17-0-7b4c3d2930b9@kernel.org> In-Reply-To: <20260604-unique-ref-v17-0-7b4c3d2930b9@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 , Daniel Almeida , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Uladzislau Rezki , Lorenzo Stoakes , Vlastimil Babka , "Liam R. Howlett" , Igor Korotin , Pavel Tikhomirov , Boqun Feng , Igor Korotin , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka 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 , driver-core@lists.linux.dev X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1078; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=HIU6Nmu7iABl9KtQIYtvgtPsm8T0d+RqMDFg+vb7EbI=; b=owEBbQKS/ZANAwAKAfpQKQiqxb3QAcsmYgBqIdvnvaCfCPZprFYoyr5bjX3TfukME5Od6oPB9 tR7l/9inKGJAjMEAAEKAB0WIQRXitnI2WZ2JirAaob6UCkIqsW90AUCaiHb5wAKCRD6UCkIqsW9 0LVHD/9orCNW9km7eoo7svZph7kf2oFSscnDuSfnZbnknSzXSrxvmhwExeDA1cSgUg7ATS13m3M xpd+u7kmEAhHJpaerkAELxtghRA4/yE0MhmVrNvWeQpIHOya0srATnagWFriXahuqmMwDkzpWGf GT4mFbiGz+DAiE6iSQm7E3tvl785uUxtjXKpgqHSZT0HMbqOT0UxX4cztFf+i2cKC3D40Of5EDy BjE0KgRHNh66eYXVBnI1tjYOrOLbVNwfNdvhCpwo+PI38AbWVAU7qJCTO+yCPRsIVrcW+W3CM3x +tRe3sIbQORfl6dsfv+Noz/08sOpItUKm6c94Fn2bYYJ7VI9xbe6qrTQnXzmvuD2F3e0ArAOvIE 2INo1C1b2Ky8odRfgPR6tvPP9k+FpeidXIm5n5kNm/yprJ76UETTS32XGwcO3fVDoFmGtPjq9fW nzxKp0nXHmqq8BrQf+RLIRYWnRjzpmB4XuhAfAAsTK3B6ib0x0oX0nFWUPk8+GOrnEfDhlNh9ep CsuBUXl5x3yrcyq7mCOBEYNuzZwxHLJtTsO1ycz90dn42DAfEfAw8HA7pI7dZ4zPXoRetBRsoUw F8ELxr+1c3uiHRADNWr0nN7b23n92tdEiOAINa+JakitVe3c9j3MS5jLOQCb6KBQfuu8bstQ0De BtJ6FehLCTXpwLQ== 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 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs index bd6da02c7ab8..6fab67704294 100644 --- a/rust/kernel/alloc/kbox.rs +++ b/rust/kernel/alloc/kbox.rs @@ -188,6 +188,15 @@ 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`. + #[inline] + pub fn into_non_null(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 Mon Jun 8 07:21:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.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 DE44D3D8907; Thu, 4 Jun 2026 20:13:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780603998; cv=none; b=IFF0ihZvIzhHd2Z4aB2EQkAn9qcCXbQaA8sGn3rDJjflUpsKMCS++nfWFxH2V1KKSqUSN4/QsS7VMPLabh9WCYJchpO3IorRSD1dk0/ce4ey4AF/vgdfl8PtePbrIT36AqDGaU/kazsR0g2F5oThiapcKTn9jQhMx22+6vxBsMM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780603998; c=relaxed/simple; bh=1O8hcxxp/kMcvtu9yjMVb2lB/y685VrmQp32UNfHOYw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EhSng2Kv51OuGtMs41pxXmevrJI7gszt7CqSxNyBZq6lAXC4zyyUnUAbfZrDKl66nCnfJxPrFpBZ/vutDtDIZd7GnjmcLUxuTl6245O4S67d4/pZlQsyUSk2cd/VtKWDQLRO+xvJCXwOH8BBqEGnerYyKXfaNN9spQ7LHdibp4s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=d7+DGx4k; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="d7+DGx4k" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B489B1F00893; Thu, 4 Jun 2026 20:13:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780603994; bh=FyqbifIs0gEb+brR0HRbFPYYe8b52/vPAxEVwbskZ2U=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=d7+DGx4kRvBF22JK7YfD6UvK3MZe3cZ/G1pHGIQ/3H8UfQSOg7Ieg0mx1bvLq8xYE stPU76+2J+5djPEJUrJ1IJm9wxEsW9K1zFRweb/+eze4ZwWaK8HxgXzLBfo8ZCB7ex E6JVc6TzkG/cwill6Ag6itwfXLT+HjIzQS4e2j4JAEXcKLJ1ea2ES/Y2Aixk+6YMcV +zPKqF7gU8duISScX8HUFNycYk6Q9tClZy4tbVRZfiMySzFe/DI/+aarw/vw5bQ+zy sK5VJR26InjGBY29wYKn90akDlQ9bsTfZNRrgTc8VLd0dHkUdyQeYrz3ziSwEvPitl Du+Cpa9aaWiug== From: Andreas Hindborg Date: Thu, 04 Jun 2026 22:11:14 +0200 Subject: [PATCH v17 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: <20260604-unique-ref-v17-2-7b4c3d2930b9@kernel.org> References: <20260604-unique-ref-v17-0-7b4c3d2930b9@kernel.org> In-Reply-To: <20260604-unique-ref-v17-0-7b4c3d2930b9@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 , Daniel Almeida , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Uladzislau Rezki , Lorenzo Stoakes , Vlastimil Babka , "Liam R. Howlett" , Igor Korotin , Pavel Tikhomirov , Boqun Feng , Igor Korotin , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka 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 , driver-core@lists.linux.dev, Asahi Lina , Oliver Mangold X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=10553; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=ofZDFIhDjpLPpUbpvtXo6zWuRmODfjHMDH0JWHuSFdY=; b=owEBbQKS/ZANAwAKAfpQKQiqxb3QAcsmYgBqIdvofKBkFboGfACnM0viGjPeiixT1NxDQcbNU MsW74xazMuJAjMEAAEKAB0WIQRXitnI2WZ2JirAaob6UCkIqsW90AUCaiHb6AAKCRD6UCkIqsW9 0DEkD/4gf7Ho/vS4edp6caiLITOv/bLkSQN5bDrgSo/Dqw6VjWYilBwVVAiLblnteDI9tSnZAz4 evcQDaMvY7IrsQilUAtM8OixDbWtvlR+x/eslY/TZ3XhvbZhSLsMnQ8UkkHAOto8tCBTvl53I5a G8FmcHac+ptW26zaW0XNDXoedp4ZU4w/MElpuhCWopnNx578V/5+/Kd0++KK9AJdewxigY+O09R XKMuyGtiteZwpDtUCDrndWu6LUELJFBk8DlTERSF7P+OV3b/Z3bb9nsbkjC2dNa6SG0WmIUu3OP QeyC4cPcKPSTzIGcS8ecFZzwJp5ChQN+O3DEGMwV9NTEV9WrrGRGEeqcW05Jd8akGmDILrPT9uw 7PPhGLGSGJvPJ94joJDKzhWeGGQKN4Ypt7eKVQMrFp9Ydul9sXRxfanYsRd7xUsVCJsXHe0qRhw axz+zRqxcYG96KESp5w1DAN0DXXjeDg5Tip6/Di/vvvoZrcnl66TJxO8IaBQoKUir/7KAjhvDKh 6sAopNMKeJY/bAeb+sNVhiaT50U9xhsI6ME1e6JBNS2dFoe68qSHt4tpl0mNEtS+P2FRcWnIkw8 9wvr6lwo2ivn1lb6ppIFBpmHrqozyBAsxUj/60/7Ugd0+pXRJQrGpGnYAMRg8JMKgAIEIQN+hgo Di9hhF085JUUMWg== 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 | 187 +++++++++++++++++++++++++++++++++++++++++++= ++++ rust/kernel/sync/aref.rs | 5 ++ rust/kernel/types.rs | 11 +++ 4 files changed, 204 insertions(+) diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index b72b2fbe046d..d07759eec799 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -100,6 +100,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 000000000000..456e239e906e --- /dev/null +++ b/rust/kernel/owned.rs @@ -0,0 +1,187 @@ +// 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_non_null(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`. + #[inline] + pub unsafe fn from_raw(ptr: NonNull) -> Self { + // INVARIANT: By function 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. + #[inline] + pub fn into_raw(me: Self) -> NonNull { + ManuallyDrop::new(me).ptr + } + + /// Get a pinned mutable reference to the data owned by this `Owned= `. + #[inline] + 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; + + #[inline] + fn deref(&self) -> &Self::Target { + // SAFETY: The type invariants guarantee that the object is valid. + unsafe { self.ptr.as_ref() } + } +} + +impl DerefMut for Owned { + #[inline] + 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 { + #[inline] + 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 9989f56d0605..4ee5fac0e0b6 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 4329d3c2c2e5..4aec7b699269 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -11,6 +11,17 @@ }; use pin_init::{PinInit, Wrapper, Zeroable}; =20 +pub use crate::{ + owned::{ + Ownable, + Owned, // + }, + sync::aref::{ + ARef, + AlwaysRefCounted, // + }, // +}; + /// Used to transfer ownership to and from foreign (non-Rust) languages. /// /// Ownership is transferred from Rust to a foreign language by calling [`= Self::into_foreign`] and --=20 2.51.2 From nobody Mon Jun 8 07:21:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.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 4616F1E3DDE; Thu, 4 Jun 2026 20:14:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604086; cv=none; b=Ofkkn5sHIw6H+3W8XKoAENoV/nTS7O2DexL8jlYyWL0lbkFGDO7MaTqI1L7Nk+Dpq/2dRrnyhH0lNgG552DXBm/FFbMCoxlWOWpsm/7Y+GUyTxMOgWzB5ZATsM+whB8uFLDy7UG9QXSwPLHaSN1Ja3JhMD96qa7/dz/vfalHNr0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604086; c=relaxed/simple; bh=wiR/tjsjZUc/szwoZmoCjaXgIOvvjFpABHNna2O4ox0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tSHGMwYyUUdGKlI71vZvP4VYpTeN1CwR6FdmJ55m8osWGWeL+0TG9glBhpiPL49gLj7eIg61oWrTA0CFRh2VqbeS76Zz7MmCQ6k0I+EoWHwLOe8WgtFcqurXGtB0YfNRZymi/X0r29+HECbJcQKHdVv28NVSfkjYKd801TSJ+hA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=L1KhBYKa; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="L1KhBYKa" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DEAAD1F00893; Thu, 4 Jun 2026 20:14:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780604085; bh=hN3l3BdGf/2AYaP03yQUTPwUIONO7SBS5tD05SJ/lgU=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=L1KhBYKardL4WLZ1hxlsOwhksTaRQTGI+GRdaf7u+5MQLYeqW4lEoJFDK5PY8udEi OgD8pgWy26+xr++oM7Eas5xkaFfFQVWQF0gfnE/F5TPP3XfvNea3Mz2VTe3tTpDBeP 1bxU43ejnz6I/o5682xm0l7UOqZ79U5PkaIjHZv+CUzCOAngWwGH0ZvEcQGeYsQjKK 0F4rK27NUH9tegKW2KFdA132RgpjWZg1P1S53KoP6Z/MZy+yzc98gRrwDxVmDTiYFe kDSJcR75jkiLmb+QjuR21BLBIU9xRGCNr3KPvMstFAKl8aKJzXXN6D8QTD5Zg2oVcn fIEFQRiqEI/Pg== From: Andreas Hindborg Date: Thu, 04 Jun 2026 22:11:15 +0200 Subject: [PATCH v17 03/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: <20260604-unique-ref-v17-3-7b4c3d2930b9@kernel.org> References: <20260604-unique-ref-v17-0-7b4c3d2930b9@kernel.org> In-Reply-To: <20260604-unique-ref-v17-0-7b4c3d2930b9@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 , Daniel Almeida , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Uladzislau Rezki , Lorenzo Stoakes , Vlastimil Babka , "Liam R. Howlett" , Igor Korotin , Pavel Tikhomirov , Boqun Feng , Igor Korotin , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka 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 , driver-core@lists.linux.dev X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=2733; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=wiR/tjsjZUc/szwoZmoCjaXgIOvvjFpABHNna2O4ox0=; b=owEBbQKS/ZANAwAKAfpQKQiqxb3QAcsmYgBqIdvojMJS3KEQLaRggiy/IympJ139LRe+De2u3 A92SMSRv/eJAjMEAAEKAB0WIQRXitnI2WZ2JirAaob6UCkIqsW90AUCaiHb6AAKCRD6UCkIqsW9 0EKxD/40KjICAkhQszkmSwLgDHYHvBdMURq9hW/tlw+Ez08KtTHqNDPCkZkXsfpdsApuKNQ52UY heVYe2Yx5rTJP9GY1T2tzh/4qCJcYe5U8yfWfpDPvYLgePHgSOnQbWO1MSJV4IDC2qfkuecSU6i ClrnIWqCB5Yd9DMGk36B2kktJPrDCXH+brMTD93I6IMz/2J87PsQRvQ4qubjvCa84SEGjlPd578 KvK0wji01jfUpXS0QX8ccaXUELffUfenAKI38ilen48Wvfx28oqWGJoEDbtq/65D5iYOo+9DHMp GIgDlOzszni4/tUFObbPb6jT6bBa4E8O9wKm8UjQflIOdHbF8QetJbsVaDkoPOq1qcIO8LKJ003 nl+kT+DMCM7PUpWagcDVIcAqrL4U/t7j5koXNEGeIa8UEQa2Z8aYquOZuof61j4uCgyGCzy1jZE 7XDIK/8L+icsgpd8LLw7wUA5Amh0VcC28HvhGDK2yNUqIiMCXJuknR487j5nUawXyETew8AdwWn GfykSQUfGIUCawqJiakE4IQbS/kIXDbCQAdcBUxxEG/nv/4Zj2NUTuEk5Ld4CXZ1i2kkBir5Rbn EatZvAMk+OKzHVMWpEI4lfthHa377Jq6ytw19hLZoMHp/i2Ja1l19oLBy5I/y9Ko0JM50AxQWaj Gkz2Qjxyvb6xu+g== 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 | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs index 456e239e906e..5eacdf327d12 100644 --- a/rust/kernel/owned.rs +++ b/rust/kernel/owned.rs @@ -15,6 +15,8 @@ ptr::NonNull, // }; =20 +use kernel::types::ForeignOwnable; + /// Types that specify their own way of performing allocation and destruct= ion. Typically, this trait /// is implemented on types from the C side. /// @@ -108,6 +110,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, } @@ -185,3 +188,46 @@ fn drop(&mut self) { unsafe { T::release(self.ptr.as_mut()) }; } } + +// 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>; + + #[inline] + fn into_foreign(self) -> *mut kernel::ffi::c_void { + let ptr =3D self.ptr.as_ptr().cast(); + core::mem::forget(self); + ptr + } + + #[inline] + 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()) }, + } + } + + #[inline] + 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() } + } + + #[inline] + 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) } + } +} --=20 2.51.2 From nobody Mon Jun 8 07:21:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.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 EEE883DC4B9; Thu, 4 Jun 2026 20:14:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604068; cv=none; b=cOTp3c6SIWpjduCYinIa9xBydBOc8sQvC+hwKENevBcc6DBqp2yWs9orbH+8kf8n2H900HtDlU8b/4TiN+3fX1G8o4V0AwW9FNpo2QLHHexuGQPcBKKjWlWUOO8dZsca9MQJKwmO3Djvky46a9BVVDKOuVJBeos2lCGy+xqMtNc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604068; c=relaxed/simple; bh=4RyZCw8fL1vZdiYtCKnYPrhKo0dFDXqsJU7kpadSv3Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IzVAWm3SYPwuNCzNhRBte3oVLC5Qs9LqDO7kUqGw+51ZCYjjezi8zFLGPrz5+mtRqbXeKismahH4c5Rcw+GD0sNabxD27zkVWYPlj+kjXB4f3uDUKxT+Ppjtw+2jOFrEzQbhYrsB2jKfpFIIM7FsyN0hQbDS7K5V9cUzkmMZQI8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HUSWvnjj; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HUSWvnjj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 411F81F00893; Thu, 4 Jun 2026 20:14:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780604055; bh=UDKImhxSIS/fNprfWQIRF9/bFD0CG+MEzEYu4ZjZLR0=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=HUSWvnjjP2E25THnS10KhqGscgSWfXPY9OTuEU2lXvu8sGjibTgS2hJh1c7sVR233 ZsSMfrGf5wan4J4lQaBQPFxwxHEfkZB+SyslGH0qiD3tupaMJGOF+xfVCXrdCa2nop bfZ4DrP5VtkcSumcTB7mPODx29giM+ghh+FTkROTaLEuAE6mh6otpO2xPVgZt2DqVC XWOJbv6sA3Uf/sptnzfc7WprUW0qPW12ITimONL3qIMyuoyGZsERZkyT7yyp4AoXjJ JSPLPuTZtHSv89xBRY2E+XCGkG/WIy0HPLdmYvkNEYRY8uN7duiAc2vqNKEQ6Rg+2N 1E1gmpx/gdZhQ== From: Andreas Hindborg Date: Thu, 04 Jun 2026 22:11:16 +0200 Subject: [PATCH v17 04/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: <20260604-unique-ref-v17-4-7b4c3d2930b9@kernel.org> References: <20260604-unique-ref-v17-0-7b4c3d2930b9@kernel.org> In-Reply-To: <20260604-unique-ref-v17-0-7b4c3d2930b9@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 , Daniel Almeida , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Uladzislau Rezki , Lorenzo Stoakes , Vlastimil Babka , "Liam R. Howlett" , Igor Korotin , Pavel Tikhomirov , Boqun Feng , Igor Korotin , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka 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 , driver-core@lists.linux.dev X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=908; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=4RyZCw8fL1vZdiYtCKnYPrhKo0dFDXqsJU7kpadSv3Q=; b=owEBbQKS/ZANAwAKAfpQKQiqxb3QAcsmYgBqIdvpNRczTi1MEzbEqRlUSeyXZWfTU4TEqBFL8 dQ624Rhe9eJAjMEAAEKAB0WIQRXitnI2WZ2JirAaob6UCkIqsW90AUCaiHb6QAKCRD6UCkIqsW9 0GdUD/4yqmBAhNqMpqX2A7JxCA0GG24Vbr11LAL40KqFhbTCAdt3gGkUa/a9Rz9aqi3vkCbe/ST FnkQd+bp2YQxM1v4HvkNdYl6bMHsOvU18ZPZoCGKvZQdn0lKxUF293/3c9nt0kC71fWAfWL4wUP uy/AgLXJiQ/bVHs8H1//ZL7q//UZyzTjudKIDdn/EdREN8oXJP4QpPMHfnIzWC61sddwm6SZq1X 7VkKcUzxtOBs75BHWPMXfiC3Xg8KePSbkgSlhLUO70BrcXgRRSLmRRKacG6XS26Yz0me2pRnu7b cbjUrbadHMO3LNeUwdHuQjW+WEvIrm1sTyrM0G+4DxAuLLKNhoeiHC192iqOdYproBsGzIdxZ/W CcTR5LugyvvJIpEIvAXhvq2C8XTPF3dR/lAhBfHr4vph7dFDwfsiucAQpcXJSOtQ7coI+ZX7Rct JvnjdjshEue1W9UTO9m5UWjnXARSegihnwosgjfAX5rft8kqmQ8bOKDDpcHvHZ3qVnJWK/be+Oe aq7VqUaKnUOsvjxnxfFEc0jDhigeUxIZUPxZrJeTV1ak7jdJAjZNBIC+vvQ72+hBMXRMIclDCVe vviPbhfux8KOliVlfgAoDzFODyHymtIfsJkBJBNpxpvX3P3KI581baQQA6LqlsWWHywfzYv01nt XV4VKoWPUlCeb/g== 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 adecb200c654..3bdcee0e16a8 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 Mon Jun 8 07:21:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.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 113293DCD86; Thu, 4 Jun 2026 20:14:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604051; cv=none; b=LYpBSAGaR7gZU4YB3g0kZNS+29lRiKYkV9Z2Wz8cP6b9VKVV/xGFB8gyiRPxGCsdUH85XFfVtEDnNTdAO7btmjhiyVNqzBkgVzRAcRfUGxE0vDznInaJVG1tdx+sNk3AvfUg1BIl7++bN4qdsiG9M343mCKv13yVUBw2Sx+KmSI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604051; c=relaxed/simple; bh=BpVwvgHRorqwRk1iUS3Rm6A27U+vM9fhuJ9ZcXJgMZI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mEQCPbVs6UWZfRvK7ANZLDg8w4Pa/Z3ZMZmNpHDIV7vxOiEXS0bgCimF/JMnHTJrxBnM0zIUWFdz8gFtNHpT29vEaE40ByMBowBQiPO6an4/+NuKUvn+c86vwdnG4evWh+q/l0VzYaNwqvUU7+m2TEoO0Hvdb9RaEEUoVE/81VQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mosbAMrt; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mosbAMrt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0AF801F00898; Thu, 4 Jun 2026 20:13:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780604045; bh=ggqzvyh9uUTse6J1YdoRnT592sarnIvZOvO6Wa4kRj8=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=mosbAMrt0jG/xwYtdddVY5gYoUg9wgN+ozIsSOGkb00aJo2V5TW1V46BLxB++Cg+H 0rNUlnojJwS954L3LqDM8Nt36WFjTCbu9FJ04Vi/r28HzCtgwAzhPVLn2k9abRFge2 IkQylc9PHxvlb9O3dgj0BiGX8E0hTYwHjcPkxhBqcOGjRZV37J8xOPwxExoD0tW3y/ b71NSSfft8LE7/lHE/rvbgZrHYHDvvzTU4jmRlTbYX1jHHauOny6TTpusfBCyVZYlf dMlSEmvqx2/jhl4GiNKzN4kzIWAEWxHIhpyR49eMKRAhlAZLU0Ol9o5Le7U3D0R/EB XWD6EH2BagOHQ== From: Andreas Hindborg Date: Thu, 04 Jun 2026 22:11:17 +0200 Subject: [PATCH v17 05/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: <20260604-unique-ref-v17-5-7b4c3d2930b9@kernel.org> References: <20260604-unique-ref-v17-0-7b4c3d2930b9@kernel.org> In-Reply-To: <20260604-unique-ref-v17-0-7b4c3d2930b9@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 , Daniel Almeida , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Uladzislau Rezki , Lorenzo Stoakes , Vlastimil Babka , "Liam R. Howlett" , Igor Korotin , Pavel Tikhomirov , Boqun Feng , Igor Korotin , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka 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 , driver-core@lists.linux.dev, Asahi Lina X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=4419; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=Rg2v6tz0XwCXNwaYk5oY+uEcooXMgwXc01B3VEHvrOM=; b=owEBbQKS/ZANAwAKAfpQKQiqxb3QAcsmYgBqIdvqHYkB8MyfIOoBDF1dSU61Fxib1oa4Dt9RG PgIQ0wtLluJAjMEAAEKAB0WIQRXitnI2WZ2JirAaob6UCkIqsW90AUCaiHb6gAKCRD6UCkIqsW9 0IqcD/sFotgaGhMKDajo2vE0qEhGdVZ65uCHkiTMoKJrdcB+u/EW3F8VpV/IBvLFdHjNpsvogco E6hiRlSOOQyWBKf6qLQT3kNcckJUFca2rKOfxiHDoyO0g3ZhjKdB36WHeMksAohI3e5393Ar7A3 JMomk1USO6WVyn0G69K23Cfa5gxuU0ODBR7cKy8U9dnlAnseoKo790PpO1ndbKqIm1XmJflmg9Z BamGGuMTLke1RIf510z6jyUIfdP8QxBXpXDELofQVg1il1vgaiS/tSkjhE5CLPJMkfVAEgul4hZ LyLB4oVXmjIOosFVwOx3BIagjIV19MAkiMIAY6wM0ovnXQCt55Qi6Py+KJy0cAsokL+xT//Xdjn p9iM3+z839r8nvxM97PFts/FKYW1cByF4oDNG+l4W250i9L/Nj9I1xyNMaA7e73/W4sG9ez0aNK snOob3lVbaC6MC/UYTey2mtt+QzOsF4BIfH2cvKEVRwH8aAKqChai103IF19OccUq7xLqyRQYf3 gEGpIVah68briyXNnatyiyC9YSJJr2dVfLa6atP8DrONRO67JJ0tvEyiDWHoO3VvaZ/WV5fXj1c kYW2Iclhgcq7FVDvpyhKjFxoQ2h6IAQD0233nnJeT/ZRmTs6tk4ymr07hr22Hg8IOkv612sntSB qvL9y8ZQV0udSbA== 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 3bdcee0e16a8..844c75e54134 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::{ @@ -105,7 +110,7 @@ pub const fn page_align(addr: usize) -> Option { /// /// [`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= `. @@ -115,7 +120,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`. @@ -127,7 +134,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 @@ -148,8 +156,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 @@ -183,19 +192,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. @@ -370,10 +380,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 Mon Jun 8 07:21:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.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 3D7143DA5D9; Thu, 4 Jun 2026 20:13:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604010; cv=none; b=AD2nqQeeUHTNlGX5Y+zbkKRevwQ0ePERGujqmg2YEhO78CYngPUgy897Tm39CvSA1yiuY5tO/vmw+WJvELcqUMZ3MQFDmQMIxI/x+dGwfx6ekNLcb7T1Mccm4k3R4v2U31foWwFfqe9c7Kc4sGC8KYY65vYW/Gn/86fg1tJ+swQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604010; c=relaxed/simple; bh=KZI821jCYwAlNEM8F+VgChXooOwtVc75TRXvBIP5mYU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uu5m71rPc0ftN8FLa+vPFinFia6jcfPSQiN5pG4p0srE6HVdtLiRouMZzo0kUiqaawHXgeuN2tLQ1NkuUqdqstv8GpJ0ml02zzc5Jqyh0w4jiNjwrnB4svSo0wolfaHabPtGtA0OAUzgoV/RVO2kmDuw+asexyYMXHTy5Ru1GhY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VRIkboba; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VRIkboba" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D6FAB1F00898; Thu, 4 Jun 2026 20:13:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780604004; bh=JJhJELyOPXSQq8UHfkijKrUFykDpNArMVIBDqRCSDBk=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=VRIkbobaAr9Tvr/LAjf2l1rvmR/ZiO2YxIV4t682uHMzRWiALP1IZXokoJBcOloT1 Or71+h4vazMIfxWurjCgsWfNJUmmSpeB9v6xvlQzaH/plwyltqhDjSP6fEijMzSN6A lHyVBbNDN6KUOTRZ2jPZT7eqDxv/ycg9Q/TC0MkokwYxRiKcpbDE5zB/u2uzj2NUuA LTXJcIfhaWmNjPnyhW9uaBXLgwb+ZpTZjiJSpvpNsE5gR0reYKGT+izJFb9SC5KuAR jntQ+3UCQnKChQH7wMkLjf2hdggkgylWTxpEPESNxNSTlB6bnGys6t265+JJevmGwg mFwBmxZ90ZjAg== From: Andreas Hindborg Date: Thu, 04 Jun 2026 22:11:18 +0200 Subject: [PATCH v17 06/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: <20260604-unique-ref-v17-6-7b4c3d2930b9@kernel.org> References: <20260604-unique-ref-v17-0-7b4c3d2930b9@kernel.org> In-Reply-To: <20260604-unique-ref-v17-0-7b4c3d2930b9@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 , Daniel Almeida , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Uladzislau Rezki , Lorenzo Stoakes , Vlastimil Babka , "Liam R. Howlett" , Igor Korotin , Pavel Tikhomirov , Boqun Feng , Igor Korotin , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka 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 , driver-core@lists.linux.dev, Oliver Mangold , Viresh Kumar X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=35062; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=vsLTWGJQlTArMQSB/3JY/GTrzdDUXcFWfohN952re70=; b=owEBbQKS/ZANAwAKAfpQKQiqxb3QAcsmYgBqIdvrPR64zgPbGaLah3DFrW0PlrQLGxOZQdIoK wJ5RBmrhZGJAjMEAAEKAB0WIQRXitnI2WZ2JirAaob6UCkIqsW90AUCaiHb6wAKCRD6UCkIqsW9 0JaBEACjGXyVUfZAk6I9+XfF3wKRVWMXOBNsu9hT6TZkyGgUHv9A8nV1odHO5I4U4NwVPmkKgxe ywE6TSqqkEHDTfalGD90oGto7lAIRWnbEmYzFVOfhNpU+HK5E6JWAixBSH5OL4pms47d/ANrtUc GvT5etR9yB2NidAUpjkyBOJzTU4qDlRumdL+RLIiTe1e4AETBr2jEaeNl8WVCwnPAGIPU32qt3D uofQ8gOIBp2AvhwSgJ6Vi/I8RW50Lf3FseeAmyu0p7rc7V8UulZ9ihR/MImzy7WmWI+qJUYPqjq 6BVQkwOUQa+CvwqXqU70v6fPBbCCtjJjArhIiuRvAX4103O/cjrRJkPtC69/8DRgCp6HvS7n+YM 0uqCcCDdEIOOeTO185gMK0BfgnW86qHPlmVAVt6XGhfIeXsYpYiRRqwmd9VhFtpfH06CqJGTO13 gmu/C3v/geAw1o/3K5BdWJMwC/LdhnNuxcHXJZslBaHQDzGyCY06sfM0f9/QOemIyFOhHOGMDud C2Oi/mkdimmvjiYjko/hv8LTdfq3xcrpazJfllBZjuGF896O520/r2eq30B9Pix1uzovnsbJukt K6ksvaxr+wuK/faCwhurMLRQRxbdchhaIafsQXY/druZrro9W4wbYeMoA72J4G70gbZpt6nIVdQ hZBmVuUjj1hSbJQ== 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 | 12 ++++++++-- rust/kernel/device/property.rs | 11 +++++++-- rust/kernel/drm/device.rs | 9 ++++++-- rust/kernel/drm/gem/mod.rs | 16 ++++++++++---- rust/kernel/fs/file.rs | 16 ++++++++++---- rust/kernel/i2c.rs | 13 ++++++++--- 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 | 49 ++++++++++++++++++++++++++-----------= ---- rust/kernel/task.rs | 13 +++++++++-- rust/kernel/types.rs | 3 ++- rust/kernel/usb.rs | 17 +++++++++++--- 20 files changed, 195 insertions(+), 64 deletions(-) diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index 93c0db1f6655..49f07740f657 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -19,6 +19,7 @@ to_result, // }, prelude::*, + sync::aref::{AlwaysRefCounted, RefCounted}, types::Opaque, ThisModule, // }; @@ -289,7 +290,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()) }; @@ -308,6 +309,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 ce3e30c81cb5..cf013b9e2cac 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 ffa156b9df37..20ef0144094b 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 6d5396a43ebe..efdf33617d12 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -8,8 +8,12 @@ bindings, fmt, prelude::*, - sync::aref::ARef, + sync::aref::{ + ARef, + RefCounted, // + }, types::{ + AlwaysRefCounted, ForeignOwnable, Opaque, // }, // @@ -508,7 +512,7 @@ pub fn name(&self) -> &CStr { 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()) }; @@ -520,6 +524,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 5aead835fbbc..cee7e2501368 100644 --- a/rust/kernel/device/property.rs +++ b/rust/kernel/device/property.rs @@ -14,7 +14,10 @@ fmt, prelude::*, str::{CStr, CString}, - sync::aref::ARef, + sync::aref::{ + ARef, + AlwaysRefCounted, // + }, types::Opaque, }; =20 @@ -360,7 +363,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Resul= t { } =20 // SAFETY: Instances of `FwNode` are always reference-counted. -unsafe impl crate::sync::aref::AlwaysRefCounted for FwNode { +unsafe impl crate::sync::aref::RefCounted for FwNode { fn inc_ref(&self) { // SAFETY: The existence of a shared reference guarantees that the // refcount is non-zero. @@ -374,6 +377,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 adbafe8db54d..a5a040266aae 100644 --- a/rust/kernel/drm/device.rs +++ b/rust/kernel/drm/device.rs @@ -15,7 +15,8 @@ prelude::*, sync::aref::{ ARef, - AlwaysRefCounted, // + AlwaysRefCounted, + RefCounted, // }, types::Opaque, workqueue::{ @@ -217,7 +218,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()) }; @@ -232,6 +233,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 75acda7ba500..f8cc2a0ff4c7 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -17,7 +17,7 @@ prelude::*, sync::aref::{ ARef, - AlwaysRefCounted, // + RefCounted, // }, types::Opaque, }; @@ -29,7 +29,7 @@ #[cfg(CONFIG_RUST_DRM_GEM_SHMEM_HELPER)] pub mod shmem; =20 -/// A macro for implementing [`AlwaysRefCounted`] for any GEM object type. +/// A macro for implementing [`RefCounted`] for any GEM object type. /// /// Since all GEM objects use the same refcounting scheme. #[macro_export] @@ -42,7 +42,7 @@ impl $( <$( $tparam_id:ident ),+> )? for $type:ty )? ) =3D> { // SAFETY: All GEM objects are refcounted. - unsafe impl $( <$( $tparam_id ),+> )? $crate::sync::aref::AlwaysRe= fCounted for $type + unsafe impl $( <$( $tparam_id ),+> )? $crate::sync::aref::RefCount= ed for $type where Self: IntoGEMObject, $( $( $bind_param : $bind_trait ),+ )? @@ -61,6 +61,14 @@ unsafe fn dec_ref(obj: core::ptr::NonNull) { unsafe { bindings::drm_gem_object_put(obj) }; } } + + // SAFETY: We do not implement `Ownable`, thus it is okay to obtai= n an `ARef<$type>` from a + // `&$type`. + unsafe impl $( <$( $tparam_id ),+> )? $crate::sync::aref::AlwaysRe= fCounted for $type + where + Self: IntoGEMObject, + $( $( $bind_param : $bind_trait ),+ )? + {} }; } #[cfg_attr(not(CONFIG_RUST_DRM_GEM_SHMEM_HELPER), allow(unused))] @@ -98,7 +106,7 @@ fn close(_obj: &::Object, _= file: &DriverFile) } =20 /// Trait that represents a GEM object subtype -pub trait IntoGEMObject: Sized + super::private::Sealed + AlwaysRefCounted= { +pub trait IntoGEMObject: Sized + super::private::Sealed + RefCounted { /// Returns a reference to the raw `drm_gem_object` structure, which m= ust be valid as long as /// this owning object is valid. fn as_raw(&self) -> *mut bindings::drm_gem_object; diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 23ee689bd240..06e457d62a93 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 7b908f0c5a58..56791c1d63d7 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -18,7 +18,8 @@ prelude::*, sync::aref::{ ARef, - AlwaysRefCounted, // + AlwaysRefCounted, + RefCounted, // }, types::Opaque, // }; @@ -415,7 +416,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 AlwaysRefCounted for I2cAdapter { +unsafe impl 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()) }; @@ -426,6 +427,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 /// @@ -491,7 +495,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 4764d7b68f2a..dd9e3969e720 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 b8d2f051225c..aba4ce675c86 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 a760fac28765..06fe2ca776a4 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 5eacdf327d12..bedd4fef84fa 100644 --- a/rust/kernel/owned.rs +++ b/rust/kernel/owned.rs @@ -27,7 +27,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 af74ddff6114..acf7384fea02 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, // }; @@ -474,7 +478,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()) }; @@ -486,6 +490,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 979a9718f153..4f6a94540e33 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 8917d4ee499f..3c35aa94e319 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -27,6 +27,7 @@ }, of, prelude::*, + sync::aref::{AlwaysRefCounted, RefCounted}, types::Opaque, ThisModule, // }; @@ -512,7 +513,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()) }; @@ -524,6 +525,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 4ee5fac0e0b6..2d656f672b97 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,19 +92,19 @@ 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 // Even if `T` is pinned, pointers to `T` can still move. -impl Unpin for ARef {} +impl Unpin 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. @@ -120,12 +133,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) {} /// } @@ -143,7 +156,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. @@ -151,7 +164,7 @@ fn clone(&self) -> Self { } } =20 -impl Deref for ARef { +impl Deref for ARef { type Target =3D T; =20 fn deref(&self) -> &Self::Target { @@ -168,7 +181,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 38273f4eedb5..6259430b0ca3 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -10,7 +10,12 @@ pid_namespace::PidNamespace, prelude::*, sync::aref::ARef, - types::{NotThreadSafe, Opaque}, + types::{ + AlwaysRefCounted, + NotThreadSafe, + Opaque, + RefCounted, // + }, }; use core::{ ops::Deref, @@ -347,7 +352,7 @@ pub fn group_leader(&self) -> &Task { } =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. @@ -361,6 +366,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 PartialEq for Task { #[inline] fn eq(&self, other: &Self) -> bool { diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index 4aec7b699269..9b96aa2ebdb7 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 9c17a672cd27..90b13e65cc82 100644 --- a/rust/kernel/usb.rs +++ b/rust/kernel/usb.rs @@ -18,7 +18,10 @@ to_result, // }, prelude::*, - sync::aref::AlwaysRefCounted, + sync::aref::{ + AlwaysRefCounted, + RefCounted, // + }, types::Opaque, ThisModule, // }; @@ -381,7 +384,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 @@ -395,6 +398,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 @@ -432,7 +439,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 @@ -446,6 +453,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 Mon Jun 8 07:21:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.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 3C2963DA5CC; Thu, 4 Jun 2026 20:13:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604027; cv=none; b=a3Tvp4841bTE/0B+rGxaGsn0xU3/eynzq2GdsYN1g2/6WYNJpcEbvQp/VNOpx8v9a//opwqafja9sxTYinA49Elvq0MuTfrk9Z7Xtlc6weTYmKrXvte9OMjKznRMf7pAAMvEOSAu9s4jOPPv3TE7D+/XAbSNuD3Dz51ws+d1qho= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604027; c=relaxed/simple; bh=gEuAmHDRag4Ff03a/NCEXwn9RGkd0DQ3o5YrrmNIq6w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BCv0vkgF6HKXywFOc/IWFw/4zkeNCLmo9TzqoIahqpN9LLKgsuhqA44TV/nPtJmjGpg5pRI2vLWyww/uVqjqaBeJw8qMIZP6wj0Rez13+fghFZCSy192z1Mh0ERqHyPAWTOLWxYjRONHgWOi7TRiMU67liijrfoAVYa4FOb1MIY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VkUM5l+n; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VkUM5l+n" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2F4AD1F00898; Thu, 4 Jun 2026 20:13:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780604024; bh=ae09fXAF8LItvvmTTJY28TqpTPDPI0l185oWGkC0Czc=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=VkUM5l+n76eAck1/5L8AuHjDCJQ3zxzdGbIdQNsGNkp9tgvla8OKmviv9XxvDfYxh T5CXiuhoOdul1geAz+UtttAtacasQmLMt+dkZ5upH0R+SLnVIpNgsESP8vA5lskv2e 2eBuAPxWq7RvriIrOBlOS/tkItqOMwkcqthsWouvOY3aTbe8W7fmY79L/SQfGO5PvH x3TwFW7uWZC5lmZvv9zPCkT/Jz+dklERyIEaoUevYb6HL61n9X++xzKiYJ6N7oOvaW SnNqXruCFaiUzzbufT/a7XLIAx71EwVG4L6EJ5BrJMPgAbd3pWQowvHnrQlrVyNZaf aaQMqqE8DhqCw== From: Andreas Hindborg Date: Thu, 04 Jun 2026 22:11:19 +0200 Subject: [PATCH v17 07/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: <20260604-unique-ref-v17-7-7b4c3d2930b9@kernel.org> References: <20260604-unique-ref-v17-0-7b4c3d2930b9@kernel.org> In-Reply-To: <20260604-unique-ref-v17-0-7b4c3d2930b9@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 , Daniel Almeida , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Uladzislau Rezki , Lorenzo Stoakes , Vlastimil Babka , "Liam R. Howlett" , Igor Korotin , Pavel Tikhomirov , Boqun Feng , Igor Korotin , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka 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 , driver-core@lists.linux.dev, Oliver Mangold X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1543; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=5/8RAK1i9EEm+Mr/ISUqH0yYzAzf/u+vK09Vq8P7sDc=; b=owEBbQKS/ZANAwAKAfpQKQiqxb3QAcsmYgBqIdvsYbmmhUSA1BFXpd4LxLHnLV9ib9fde7UdH 17um7HAPqGJAjMEAAEKAB0WIQRXitnI2WZ2JirAaob6UCkIqsW90AUCaiHb7AAKCRD6UCkIqsW9 0Nt5EACgOkQIjNes+0YwsSd6rxBD9/YOWxQW20hXwPtAoLhwpn9RDoSA+h4PnOESKPOVrLhGp0Q 6nSJOo2SKyh4+tb4v+lBXt6nuxEXrO7wpnde2auyMfZz635i27etmDlT/litVdyj0fSGXksN3NU oiyshGS1QUb8aHjU+kneBTLgmTBDnsJpS0ZlmB1Z4WUSNySQyXwFBfwMKfd9RBFG2M3Hny10mYK J6tGLqG2IivsvXrJ0IAvzvy9hKmvFdeSr/joWbzooS1g7zHZQ0mRDaZBZecMAicHVmk9w7D7/ZU cYZ1rVnvZ57bH0MzQrNsigGiRaBVDDoxi2TCGz9xjcIBueLMvIB/LcVTuxc123pQr2cZS8FBsQw kDHh1pYRSgAz/5VjCSdNSYCUj4u/isGJptd5igW2nIB62BWy2GG5bCJ3rFJW5srwVKjnG4LA99E YnqqS+eO4npLOjXAJPhZDAIJsXWRFKFOktzb8KVF2raNweS5bB13ZZqG6zk8tKJQ4nr99xNBt+x 4LXjcKQLat/vBvT0r+sOGoTSqyYVlFU+fkky0pdmtCXHib7JSaML7g2b5cGgB6nKrIGZPJcsM17 fG8VC8R/HCyJwRk/mISYKNh/sCTlIPi6mIi6d+TAC4q1mH4JQR93mRCahJTE/AG72ip4nEwjfHy MQA6YfVG5t59F1A== 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 2d656f672b97..7491382bcf29 100644 --- a/rust/kernel/sync/aref.rs +++ b/rust/kernel/sync/aref.rs @@ -137,7 +137,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) {} @@ -145,7 +147,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 Mon Jun 8 07:21:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.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 3A4793DC4D3; Thu, 4 Jun 2026 20:13:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604017; cv=none; b=FeVQ89kSMeljA75twT90aoEeJ4RKZ7qhd33n5dwGcHQjkbEjGaK6Upp6EKN1i0XCWbGoPxu63myqgl4M8tpZFfxoX3ENvJFBoYoWoc8Rqs8THJkIvxTxSCjtVAdwkTLVAt1WVwviGPhuVvE9jcL6jwe2dPSlxUypoRWPMs+ysE8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604017; c=relaxed/simple; bh=l5c0q5tDqBvfUKptiUH9ujhgGaCW4zeIf26teZmhjjI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=C30DZH43EkKCTOKgJstCNASJIxcbIbyQcvqCwfU+BxLODurac5D10E3YEHAMtpNHiZOC+pF7bLbazj6i9CNshX15STvipgeB9mV8IaC+HpgcJgVnG12FI/Mc9GIbGfI/vwZUZTy/fd4MEE2U+T9SwscQidF1tlyJHESh5BJfjJc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NMaDa3T3; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NMaDa3T3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 34EDF1F00893; Thu, 4 Jun 2026 20:13:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780604014; bh=NPcZxJix8R8ASgeYRVdWoUpgDuVO0mdlMhZYBbXxkJg=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=NMaDa3T3vyLRFmymA/V52rXGwDjbP7qMQN4Wc6U9T7dNibSv9rS4yWTPxKF0xFzfN dFZOd0Y8wfML/F5N2JdyfxqQMOrT524BxyBbUKRKu4/typQSBoh7ZOcQC5MdBLbD5r C9zJAYfKCjEVkzTKSipsvwoebejBXmrm2+xD/6QwEn4TFfc2wN8StX1Sz9WdD8podp spMPdFZLO9/8wFf7L+vHYI9bVVvTww+5hLMn9V3TZzZQohZXAxPSqm0SM6NfrnEkOK pX49PkQ8gXFAS4hFTKiK9du8Dtl/oCH7bqwbLMSjbXowqz9mGLhnspH9Kps2IJKiI9 ZKCEb3I8LC1ew== From: Andreas Hindborg Date: Thu, 04 Jun 2026 22:11:20 +0200 Subject: [PATCH v17 08/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: <20260604-unique-ref-v17-8-7b4c3d2930b9@kernel.org> References: <20260604-unique-ref-v17-0-7b4c3d2930b9@kernel.org> In-Reply-To: <20260604-unique-ref-v17-0-7b4c3d2930b9@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 , Daniel Almeida , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Uladzislau Rezki , Lorenzo Stoakes , Vlastimil Babka , "Liam R. Howlett" , Igor Korotin , Pavel Tikhomirov , Boqun Feng , Igor Korotin , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka 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 , driver-core@lists.linux.dev X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=751; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=l5c0q5tDqBvfUKptiUH9ujhgGaCW4zeIf26teZmhjjI=; b=owEBbQKS/ZANAwAKAfpQKQiqxb3QAcsmYgBqIdvtLrwkUygT4paQMSlPzGAJcExHlfQf51liz OCOSDABPJiJAjMEAAEKAB0WIQRXitnI2WZ2JirAaob6UCkIqsW90AUCaiHb7QAKCRD6UCkIqsW9 0J6WD/0Z8lBgQ1MuPW0rDHqnrcon/KFXZUwq3cjDwyiCbtTXQiqqqEQxzoFn4yoVsgCmwPqmeOm Cx8DTKkFZa72O2fudXulQnzc7oh1qvTtZL2jIN9XCKwsrlO7B397BRIbW6DZDciF5UEjT2f2RKq 5zYNXCH8IfEgUZMKL78lTl39Rcp6XKKbUoW5PEVlEm73+SKiXHxwzFfJDkH9jcjGprTlztQ0T/4 DBj4iiOWhCKUfv8pxas1yPG0xsvkuhy2jH2bpT51pe1X9kWG7qV62tbl60SpN/1r4D6NS08pgtE /jtE3A+Q+2Ai7gLh+sEwFFLBptTVRkjy+rFiBivZDSkpYmEh4Z3a+FqILoLdN/dcb0zMcUra4a4 vdzb2MagQbOIERyflkW4Apz1YcbHDkL/895OLyzPFZKeEu6BACgcnvSr7JOca+rn3dccghtl9vs 5lbeD662E/jwmvKHa9r6/35yJ0BcM4EZcPeAFvpbHFJjgNA2CYXmZLjWWEuw3bS7+DPTVPSN1s9 kZ8uc2TYKagptlINpzFfIOqH2ojTx4awhCIuHNDv2K7rqJve7fI+WZewsteU15iOq9AfRec34+u Tdpn/pMgwdni2r7UW1vly0W0TNj1enYARL7mXpTRJR0J0On5QpNOeJfBJypkxp5AS6MB1G61dMu wuM844VmxxYXIDA== 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 7491382bcf29..818c84fa923a 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 Mon Jun 8 07:21:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.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 7D2C13D9048; Thu, 4 Jun 2026 20:14:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604067; cv=none; b=d2cc4lLg9qLEdu0BG/uNY4IjPJ5C/pM3PZJjcLnOxmZNNiAvL8P4ciW7mjpkB/S9hR7Y6KTgkM4NGJo8oYa8hOEQ4cry2/LytR8+dVzU8MTTuvycXlJEniLl2XOqTe0fsrjPpjbIX2jvZ5GsN2xAn5qJK4MNU43WS1dHPj1xphs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604067; c=relaxed/simple; bh=Hg680IEqr7v0RXM8wFbgsXk2c2pTY227EWWpn05Z3d4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rQPcHkKRFQh4FYLSqGIXvWth2HMIHtND/6w6H+MWtZCzlGxKchNhVOI1AvZeAUtpD27Fn6NCnrClVokL42ED2NvbRg01pzNXSN3TIyKQfSnAvjScW/dJC0ORXzeDuETox2NXD54dWzii7yolKsRXp8X/rdSejC0rLJEVphxUDM0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lqm/CGit; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lqm/CGit" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 296BE1F00898; Thu, 4 Jun 2026 20:14:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780604065; bh=wHDP8KrP4ENQIKP1t0z9YatTAObeBB7wKfKH68vjOXA=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=lqm/CGitNYnPbP6Mqjym4bObZ0Xd7TttuPt4yzN9DyK1s7pzp5bDS4Ut6WmWsgcW7 Br9DqJJwCbM6kHoi7+G7XAihST+dc047ZlQpOuVS6BtW10FN+Efa+3byBcu0udW3O7 8MCZ8i0bL1mj/vhtwE0+cEmvQHwt1V6C5YojYGeqTgNWEv6CNDljcpTZx1XLALQXDT O4YqJ7dEPYsbbWGOTEWNk5vbMQXJO9GZIqjOFskKbDwtpV5VeAkJlF8zC5Mj5o8XhW XQB5Hq91xaT9+2dToC3YfbxtBRAOuGJOdctWiEU+zGSdqu7YG2YSXisrHgxSs+2REo lGoLkhmILZBtQ== From: Andreas Hindborg Date: Thu, 04 Jun 2026 22:11:21 +0200 Subject: [PATCH v17 09/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: <20260604-unique-ref-v17-9-7b4c3d2930b9@kernel.org> References: <20260604-unique-ref-v17-0-7b4c3d2930b9@kernel.org> In-Reply-To: <20260604-unique-ref-v17-0-7b4c3d2930b9@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 , Daniel Almeida , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Uladzislau Rezki , Lorenzo Stoakes , Vlastimil Babka , "Liam R. Howlett" , Igor Korotin , Pavel Tikhomirov , Boqun Feng , Igor Korotin , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka 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 , driver-core@lists.linux.dev, Oliver Mangold X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=9300; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=B2PMU7iUM8MeGMk4qqOCmUPfmlEfQ1FXjOI3V19ZFVo=; b=owEBbQKS/ZANAwAKAfpQKQiqxb3QAcsmYgBqIdvuCHC8F7WwT17RsGVrQwmcDjE9XnhTBl5G0 /UWl8J5lDSJAjMEAAEKAB0WIQRXitnI2WZ2JirAaob6UCkIqsW90AUCaiHb7gAKCRD6UCkIqsW9 0D94D/9rqndYQ7hbvG1gd74fmkjYs06Zjp+poWTO4HjCKos3yChMUlBeMbHFGVvmwafHT4tZTov 0H5EQLKYbEQrGgkUHwGakY0pEheF7j0jD8/QNAy7TfqO8/tchPgbLX5CHbJ85xb2FbwsXcKbxkN RkQOtSIfRIgqRmCnz+IbfPrgB9o8qcBQQwBccLtqYXmo0FpjvugCZPV3iF2Sag0UHGZcj9SgYk0 ih99KJwjnvABG1ii0lxsCyYY7sKKvACJdiaT/qRQ6HcaZj61Hz1fwiepkf/NzgYAemwK077dczz Q9bIlWGdcqUmHglB/+KjHpJqt6ZFGvn4nfZEJ3BdxU0bnQbYNVD2EupHjMODL0hlCKbRY/084lL KZe723EfoB2xv7sv2KkpwxdjAlmGUAgOads3JTdMqZ8YOpoeCzHRsXqCNKq0Id+PZJyWRky7kn1 TXzUWPse1ZM93uIhD5P67ls6gLGxVRLhfOLHCIbVmYlE3stV56uw+h8Ql2IGF9IbaVbM9vv5hVW mbw6w73Whj5Fr/0Ced2Ma5ZEXI5za+Ar5kgQl327xaiDiE2wSGhBV+5DO/HjHlCR+8+rs/kAtja N3RfqM+1Y5sHe363U0OHL9yZ5oVDor+Rwz2MbZkI2Z+TjDVkDJDxcDIWmdqJoriU1Xu9NondLEh 7iuqE6PRbIZj7CA== 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 | 138 +++++++++++++++++++++++++++++++++++++++++++= ++-- rust/kernel/sync/aref.rs | 16 +++++- rust/kernel/types.rs | 1 + 3 files changed, 149 insertions(+), 6 deletions(-) diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs index bedd4fef84fa..9db0daab2225 100644 --- a/rust/kernel/owned.rs +++ b/rust/kernel/owned.rs @@ -14,20 +14,26 @@ pin::Pin, ptr::NonNull, // }; +use kernel::{ + sync::aref::ARef, + types::RefCounted, // +}; =20 use kernel::types::ForeignOwnable; =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 /// @@ -231,3 +237,125 @@ unsafe fn borrow_mut<'a>(ptr: *mut kernel::ffi::c_voi= d) -> Self::BorrowedMut<'a> unsafe { Pin::new_unchecked(inner) } } } + +/// 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_non_null(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`]. + #[inline] + 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. + #[inline] + 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 818c84fa923a..68d31f43e674 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 /// @@ -188,6 +195,13 @@ fn from(b: &T) -> Self { } } =20 +impl From> for ARef { + #[inline] + 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 9b96aa2ebdb7..f43c091eeb8b 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 Mon Jun 8 07:21:46 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.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 A9A5B4A2E22; Thu, 4 Jun 2026 20:14:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604099; cv=none; b=alLoDP2x03ZYEXuT9eMI2Q12NoBgacbaU5Yx2xjUW9gC20+Wda2AdOTk+lmKb6TM+UGcbFgZZ/jBdeO6Y8cdr+NwLjbep+fipQ9tCrVHZ5bTedpwOEgqejKE6SpyOhMlxG+1Pgj34Rd92usN4j/Rq7yRxCcRvqVVnikQ3yTxiZk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604099; c=relaxed/simple; bh=Yk6QSotN2tq3Mqa2udN0WeFejqVXfRoesEZYyBbnFJ8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gaPt8Wb/ILejREQmFoy8H+KUrilO5ZYtopbazn5r78gu4L6eC8bO3+cmI+z7eKsM33mmg/H5rRJuYjblDJkMPufUEiRZx77n+ATWs+VJa4dKtXJiVJ3BdvAb2AW4bDi6/95cZ1SKu7nQbP4O3IOLLd3HQYj/HT9gFeCs4SlLO5Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=emyi1bE3; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="emyi1bE3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 946FA1F00898; Thu, 4 Jun 2026 20:14:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780604095; bh=t4H8eqNZN4/mIO1u313XVeuHkqdUneIpioBG/gGEBMQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=emyi1bE3lT84UiMs0H/e5sWLBpipKD8aP4rx9nCFc5ww2rHWzTrNroixBU1R1eW3k VvDyq+Y9/EKTN5YutDxaS2ya7aaz09ocK8otk3HD4GePbWSC8Nq3UzR3jpHPJsKnlW D+G1ixqQ2oKb5RLaZIvJKK62Ge4aMEzL6NR04y47K5UJ14jmX8IhLAu4hN5UEpcV0p QeUQfwkvgeuV7wWv1oUW5AiTbIKO9lPOEnLAnAOPOPK8bI7//XDk5clHDilppzR/TY GZxIkL2upvxl1wSbQAKqhnKfs+Sb4dtPjK9uSDcEaZPvRLUc9O84wyUuh3WcYXZw+B dXBq+GQKoz+hA== From: Andreas Hindborg Date: Thu, 04 Jun 2026 22:11:22 +0200 Subject: [PATCH v17 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: <20260604-unique-ref-v17-10-7b4c3d2930b9@kernel.org> References: <20260604-unique-ref-v17-0-7b4c3d2930b9@kernel.org> In-Reply-To: <20260604-unique-ref-v17-0-7b4c3d2930b9@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 , Daniel Almeida , Viresh Kumar , Nishanth Menon , Stephen Boyd , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Boqun Feng , Uladzislau Rezki , Lorenzo Stoakes , Vlastimil Babka , "Liam R. Howlett" , Igor Korotin , Pavel Tikhomirov , Boqun Feng , Igor Korotin , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka 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 , driver-core@lists.linux.dev, Andreas Hindborg X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1098; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=MTxQNyPl556p/37N9iYrjSR5gCSkwSCTZpMY90B8pEY=; b=owEBbQKS/ZANAwAKAfpQKQiqxb3QAcsmYgBqIdvvpNub7j04mvxMdRLdPaAd/MQZCqnEQ9G7x 6NHPMMF+bKJAjMEAAEKAB0WIQRXitnI2WZ2JirAaob6UCkIqsW90AUCaiHb7wAKCRD6UCkIqsW9 0MI+D/0QPO+RBFAbjZRXC9pKgYwjFXnKxpO8ZzAKgdud2wdZcrmS6XnxjFCuPYPaFQ93AhOYZJa 4HV8ITv5TB34RklZib+C1ex0+Q7HyqZjU22svIR16LfDNFX/PzVeBvcMhmc1WvMZxfKE72VeYMD lG1FuQHv/rWnofDymriWJ1qTmmIh7KcWTZTBWOBoRgKjjYMflJitin0NXq39YIxXu1MqcEGW20v ceF6r4JVyWfA1qLVdGeuXR56Z/tP/9demSf0WEz4n/JNfPwSO2fQGqgHU5Wl5QkOeyepnUg4nCf V7AX9lwpje33yM15jdHfXun61mNZa7LYV/QZyVny/IV39nPfxrEMJMFFzFZhx3H9v6+wmG7Rl7h cOtjeMyzfmUxEJ95Tx/gR6H9Lv9v03K0ZTh/L5YdaCZvaNDy0gi0KOnWUL1eP93qbY2kiyZmE5f t+Xfj7TX4TebKhIwyEuO/uBVPqXJyZTHt2mkjJ2wP+OAjZlc3btrRL3brJE0UGHxHzedtn8XHk8 TyidsBvAMRGQ+VtyZO8Vi+OXdrfsKfO4XV4jyBjM1uPFGEafgzam59BvvN/aO0sZQB62OEFCXKc SQoUbEQRjie1O1BooUeWFUAPW1OpcbGv5nlsQmCDSxE49cATUzyJjv+bd3ihJjA8yLKgc8vmC5j m2qAWViBmLjYVlA== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 From: Andreas Hindborg Add a method to `Page` that allows construction of an instance from `struct page` pointer. Signed-off-by: Andreas Hindborg --- rust/kernel/page.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs index 844c75e54134..d56ae597f692 100644 --- a/rust/kernel/page.rs +++ b/rust/kernel/page.rs @@ -214,6 +214,18 @@ 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`. + #[inline] + 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