* [PATCH v5] rust: aref: make `AlwaysRefCounted::inc_ref` an associated function
@ 2026-06-28 9:28 Trevor Chan
2026-06-28 9:37 ` sashiko-bot
0 siblings, 1 reply; 2+ messages in thread
From: Trevor Chan @ 2026-06-28 9:28 UTC (permalink / raw)
To: gregkh, rafael, dakr, ojeda, a.hindborg, paul, airlied, simona,
aliceryhl, viro, brauner, igor.korotin, boqun, gary, axboe,
daniel.almeida, shankari.ak0208, lyude, j, akpm, acourbot
Cc: david.m.ertman, iweiny, leon, bjorn3_gh, lossin, tmgross, tamird,
work, sergeh, jack, ljs, liam, bhelgaas, kwilczynski, ptikhomirov,
elle, rust-for-linux, driver-core, linux-kernel, linux-block,
linux-security-module, dri-devel, linux-fsdevel, linux-mm,
linux-pci
`AlwaysRefCounted::inc_ref` is a function that shouldn't be called lightly.
To prevent accidentally calling it, change `inc_ref` to be an associated function.
Modify all `AlwaysRefCounted` implementors to work with this change.
Suggested-by: Benno Lossin <lossin@kernel.org>
Link: https://github.com/Rust-for-Linux/linux/issues/1177
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Trevor Chan <trev@trevrosa.dev>
---
Changes in v2:
- Don't word wrap the patch
Changes in v3:
- Make argument name of `Empty::inc_ref` consistent with `Empty::dec_ref`
Changes in v4:
- Rebase to new rust-next, change new implementors
- Reword explanation for change in `AlwaysRefCounted::inc_ref` doc comment
Changes in v5:
- Change commit message to be imperative
---
rust/kernel/auxiliary.rs | 4 ++--
rust/kernel/block/mq/request.rs | 4 ++--
rust/kernel/cred.rs | 4 ++--
rust/kernel/device.rs | 4 ++--
rust/kernel/device/property.rs | 4 ++--
rust/kernel/drm/device.rs | 4 ++--
rust/kernel/drm/gem/mod.rs | 4 ++--
rust/kernel/fs/file.rs | 8 ++++----
rust/kernel/i2c.rs | 8 ++++----
rust/kernel/mm.rs | 8 ++++----
rust/kernel/mm/mmput_async.rs | 4 ++--
rust/kernel/pci.rs | 4 ++--
rust/kernel/pid_namespace.rs | 4 ++--
rust/kernel/platform.rs | 4 ++--
rust/kernel/sync/aref.rs | 9 ++++++---
rust/kernel/task.rs | 4 ++--
rust/kernel/usb.rs | 8 ++++----
17 files changed, 46 insertions(+), 43 deletions(-)
diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs
index c42928d5a239..75a61b51cf79 100644
--- a/rust/kernel/auxiliary.rs
+++ b/rust/kernel/auxiliary.rs
@@ -345,9 +345,9 @@ unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for Device<Ctx>
// SAFETY: Instances of `Device` are always reference-counted.
unsafe impl crate::sync::aref::AlwaysRefCounted for Device {
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
- unsafe { bindings::get_device(self.as_ref().as_raw()) };
+ unsafe { bindings::get_device(obj.as_ref().as_raw()) };
}
unsafe fn dec_ref(obj: NonNull<Self>) {
diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request.rs
index ce3e30c81cb5..f41d01ea4595 100644
--- a/rust/kernel/block/mq/request.rs
+++ b/rust/kernel/block/mq/request.rs
@@ -234,8 +234,8 @@ unsafe impl<T: Operations> Sync for Request<T> {}
// keeps the object alive in memory at least until a matching reference count
// decrement is executed.
unsafe impl<T: Operations> AlwaysRefCounted for Request<T> {
- fn inc_ref(&self) {
- self.wrapper_ref().refcount().inc();
+ fn inc_ref(obj: &Self) {
+ obj.wrapper_ref().refcount().inc();
}
unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) {
diff --git a/rust/kernel/cred.rs b/rust/kernel/cred.rs
index ffa156b9df37..d53cbc792fa3 100644
--- a/rust/kernel/cred.rs
+++ b/rust/kernel/cred.rs
@@ -78,9 +78,9 @@ pub fn euid(&self) -> Kuid {
// SAFETY: The type invariants guarantee that `Credential` is always ref-counted.
unsafe impl AlwaysRefCounted for Credential {
#[inline]
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
- unsafe { bindings::get_cred(self.0.get()) };
+ unsafe { bindings::get_cred(obj.0.get()) };
}
#[inline]
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index 645afc49a27d..ec44dcc405d5 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -449,9 +449,9 @@ pub fn name(&self) -> &CStr {
// SAFETY: Instances of `Device` are always reference-counted.
unsafe impl crate::sync::aref::AlwaysRefCounted for Device {
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
- unsafe { bindings::get_device(self.as_raw()) };
+ unsafe { bindings::get_device(obj.as_raw()) };
}
unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
diff --git a/rust/kernel/device/property.rs b/rust/kernel/device/property.rs
index 5aead835fbbc..c39ccc1458b9 100644
--- a/rust/kernel/device/property.rs
+++ b/rust/kernel/device/property.rs
@@ -361,10 +361,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// SAFETY: Instances of `FwNode` are always reference-counted.
unsafe impl crate::sync::aref::AlwaysRefCounted for FwNode {
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The existence of a shared reference guarantees that the
// refcount is non-zero.
- unsafe { bindings::fwnode_handle_get(self.as_raw()) };
+ unsafe { bindings::fwnode_handle_get(obj.as_raw()) };
}
unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 477cf771fb10..0c70ec010bd9 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -363,9 +363,9 @@ fn deref(&self) -> &Self::Target {
// SAFETY: DRM device objects are always reference counted and the get/put functions
// satisfy the requirements.
unsafe impl<T: drm::Driver, C: DeviceContext> AlwaysRefCounted for Device<T, C> {
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
- unsafe { bindings::drm_dev_get(self.as_raw()) };
+ unsafe { bindings::drm_dev_get(obj.as_raw()) };
}
unsafe fn dec_ref(obj: NonNull<Self>) {
diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
index c8b66d816871..ee9e412066ab 100644
--- a/rust/kernel/drm/gem/mod.rs
+++ b/rust/kernel/drm/gem/mod.rs
@@ -52,10 +52,10 @@ unsafe impl $( <$( $tparam_id ),+> )? $crate::sync::aref::AlwaysRefCounted for $
Self: IntoGEMObject,
$( $( $bind_param : $bind_trait ),+ )?
{
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is
// non-zero.
- unsafe { bindings::drm_gem_object_get(self.as_raw()) };
+ unsafe { bindings::drm_gem_object_get(obj.as_raw()) };
}
unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) {
diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs
index 23ee689bd240..8e5967afcd11 100644
--- a/rust/kernel/fs/file.rs
+++ b/rust/kernel/fs/file.rs
@@ -199,9 +199,9 @@ unsafe impl Sync for File {}
// makes `ARef<File>` own a normal refcount.
unsafe impl AlwaysRefCounted for File {
#[inline]
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
- unsafe { bindings::get_file(self.as_ptr()) };
+ unsafe { bindings::get_file(obj.as_ptr()) };
}
#[inline]
@@ -235,9 +235,9 @@ pub struct LocalFile {
// makes `ARef<LocalFile>` own a normal refcount.
unsafe impl AlwaysRefCounted for LocalFile {
#[inline]
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
- unsafe { bindings::get_file(self.as_ptr()) };
+ unsafe { bindings::get_file(obj.as_ptr()) };
}
#[inline]
diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs
index 624b971ca8b0..1a9882a64c4b 100644
--- a/rust/kernel/i2c.rs
+++ b/rust/kernel/i2c.rs
@@ -425,9 +425,9 @@ pub fn get(index: i32) -> Result<ARef<Self>> {
// SAFETY: Instances of `I2cAdapter` are always reference-counted.
unsafe impl AlwaysRefCounted for I2cAdapter {
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
- unsafe { bindings::i2c_get_adapter(self.index()) };
+ unsafe { bindings::i2c_get_adapter(obj.index()) };
}
unsafe fn dec_ref(obj: NonNull<Self>) {
@@ -501,9 +501,9 @@ unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for I2cClient<C
// SAFETY: Instances of `I2cClient` are always reference-counted.
unsafe impl AlwaysRefCounted for I2cClient {
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
- unsafe { bindings::get_device(self.as_ref().as_raw()) };
+ unsafe { bindings::get_device(obj.as_ref().as_raw()) };
}
unsafe fn dec_ref(obj: NonNull<Self>) {
diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs
index 4764d7b68f2a..c955cbd884b8 100644
--- a/rust/kernel/mm.rs
+++ b/rust/kernel/mm.rs
@@ -57,9 +57,9 @@ unsafe impl Sync for Mm {}
// SAFETY: By the type invariants, this type is always refcounted.
unsafe impl AlwaysRefCounted for Mm {
#[inline]
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The pointer is valid since self is a reference.
- unsafe { bindings::mmgrab(self.as_raw()) };
+ unsafe { bindings::mmgrab(obj.as_raw()) };
}
#[inline]
@@ -93,9 +93,9 @@ unsafe impl Sync for MmWithUser {}
// SAFETY: By the type invariants, this type is always refcounted.
unsafe impl AlwaysRefCounted for MmWithUser {
#[inline]
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The pointer is valid since self is a reference.
- unsafe { bindings::mmget(self.as_raw()) };
+ unsafe { bindings::mmget(obj.as_raw()) };
}
#[inline]
diff --git a/rust/kernel/mm/mmput_async.rs b/rust/kernel/mm/mmput_async.rs
index b8d2f051225c..7df40777654c 100644
--- a/rust/kernel/mm/mmput_async.rs
+++ b/rust/kernel/mm/mmput_async.rs
@@ -36,9 +36,9 @@ unsafe impl Sync for MmWithUserAsync {}
// SAFETY: By the type invariants, this type is always refcounted.
unsafe impl AlwaysRefCounted for MmWithUserAsync {
#[inline]
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The pointer is valid since self is a reference.
- unsafe { bindings::mmget(self.as_raw()) };
+ unsafe { bindings::mmget(obj.as_raw()) };
}
#[inline]
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 5071cae6543f..0f16cf0da3d7 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -482,9 +482,9 @@ impl<'a> crate::dma::Device<'a> for Device<device::Core<'a>> {}
// SAFETY: Instances of `Device` are always reference-counted.
unsafe impl crate::sync::aref::AlwaysRefCounted for Device {
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
- unsafe { bindings::pci_dev_get(self.as_raw()) };
+ unsafe { bindings::pci_dev_get(obj.as_raw()) };
}
unsafe fn dec_ref(obj: NonNull<Self>) {
diff --git a/rust/kernel/pid_namespace.rs b/rust/kernel/pid_namespace.rs
index 979a9718f153..381c9f980b1f 100644
--- a/rust/kernel/pid_namespace.rs
+++ b/rust/kernel/pid_namespace.rs
@@ -43,9 +43,9 @@ pub unsafe fn from_ptr<'a>(ptr: *const bindings::pid_namespace) -> &'a Self {
// SAFETY: Instances of `PidNamespace` are always reference-counted.
unsafe impl AlwaysRefCounted for PidNamespace {
#[inline]
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
- unsafe { bindings::get_pid_ns(self.as_ptr()) };
+ unsafe { bindings::get_pid_ns(obj.as_ptr()) };
}
#[inline]
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index 9b362e0495d3..85068ae5a405 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -519,9 +519,9 @@ impl<'a> crate::dma::Device<'a> for Device<device::Core<'a>> {}
// SAFETY: Instances of `Device` are always reference-counted.
unsafe impl crate::sync::aref::AlwaysRefCounted for Device {
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
- unsafe { bindings::get_device(self.as_ref().as_raw()) };
+ unsafe { bindings::get_device(obj.as_ref().as_raw()) };
}
unsafe fn dec_ref(obj: NonNull<Self>) {
diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs
index b721b2e00b98..2ae2130d5bb1 100644
--- a/rust/kernel/sync/aref.rs
+++ b/rust/kernel/sync/aref.rs
@@ -44,7 +44,10 @@
/// alive.)
pub unsafe trait AlwaysRefCounted {
/// Increments the reference count on the object.
- fn inc_ref(&self);
+ ///
+ /// This function should not be called accidentally; a type might declare their own `inc_ref`
+ /// function and it shouldn't be confused with this one.
+ fn inc_ref(obj: &Self);
/// Decrements the reference count on the object.
///
@@ -145,7 +148,7 @@ pub fn into_raw(me: Self) -> NonNull<T> {
impl<T: AlwaysRefCounted> Clone for ARef<T> {
fn clone(&self) -> Self {
- self.inc_ref();
+ T::inc_ref(self);
// SAFETY: We just incremented the refcount above.
unsafe { Self::from_raw(self.ptr) }
}
@@ -162,7 +165,7 @@ fn deref(&self) -> &Self::Target {
impl<T: AlwaysRefCounted> From<&T> for ARef<T> {
fn from(b: &T) -> Self {
- b.inc_ref();
+ T::inc_ref(b);
// SAFETY: We just incremented the refcount above.
unsafe { Self::from_raw(NonNull::from(b)) }
}
diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
index 38273f4eedb5..a7711e1558c2 100644
--- a/rust/kernel/task.rs
+++ b/rust/kernel/task.rs
@@ -349,9 +349,9 @@ pub fn group_leader(&self) -> &Task {
// SAFETY: The type invariants guarantee that `Task` is always refcounted.
unsafe impl crate::sync::aref::AlwaysRefCounted for Task {
#[inline]
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
- unsafe { bindings::get_task_struct(self.as_ptr()) };
+ unsafe { bindings::get_task_struct(obj.as_ptr()) };
}
#[inline]
diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs
index 7aff0c82d0af..c039059c1891 100644
--- a/rust/kernel/usb.rs
+++ b/rust/kernel/usb.rs
@@ -393,11 +393,11 @@ fn as_ref(&self) -> &Device {
// SAFETY: Instances of `Interface` are always reference-counted.
unsafe impl AlwaysRefCounted for Interface {
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The invariants of `Interface` guarantee that `self.as_raw()`
// returns a valid `struct usb_interface` pointer, for which we will
// acquire a new refcount.
- unsafe { bindings::usb_get_intf(self.as_raw()) };
+ unsafe { bindings::usb_get_intf(obj.as_raw()) };
}
unsafe fn dec_ref(obj: NonNull<Self>) {
@@ -444,11 +444,11 @@ fn as_raw(&self) -> *mut bindings::usb_device {
// SAFETY: Instances of `Device` are always reference-counted.
unsafe impl AlwaysRefCounted for Device {
- fn inc_ref(&self) {
+ fn inc_ref(obj: &Self) {
// SAFETY: The invariants of `Device` guarantee that `self.as_raw()`
// returns a valid `struct usb_device` pointer, for which we will
// acquire a new refcount.
- unsafe { bindings::usb_get_dev(self.as_raw()) };
+ unsafe { bindings::usb_get_dev(obj.as_raw()) };
}
unsafe fn dec_ref(obj: NonNull<Self>) {
--
2.47.3
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v5] rust: aref: make `AlwaysRefCounted::inc_ref` an associated function
2026-06-28 9:28 [PATCH v5] rust: aref: make `AlwaysRefCounted::inc_ref` an associated function Trevor Chan
@ 2026-06-28 9:37 ` sashiko-bot
0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-06-28 9:37 UTC (permalink / raw)
To: Trevor Chan; +Cc: linux-pci, ojeda, dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Un-updated AlwaysRefCounted trait implementations cause conditional compilation and rustdoc test errors.
--
commit 5db284043a909f35f9aed5c1467a5f9cf863972d
Author: Trevor Chan <trev@trevrosa.dev>
rust: aref: make `AlwaysRefCounted::inc_ref` an associated function
This commit changes the AlwaysRefCounted::inc_ref function from a method
to an associated function to prevent accidental calls. It updates the
implementors of this trait to reflect this change.
Link: https://github.com/Rust-for-Linux/linux/issues/1177
> diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs
> index b721b2e00b986..2ae2130d5bb1d 100644
> --- a/rust/kernel/sync/aref.rs
> +++ b/rust/kernel/sync/aref.rs
> @@ -44,7 +44,10 @@
> /// alive.)
> pub unsafe trait AlwaysRefCounted {
> /// Increments the reference count on the object.
> - fn inc_ref(&self);
> + ///
> + /// This function should not be called accidentally; a type might declare their own `inc_ref`
> + /// function and it shouldn't be confused with this one.
> + fn inc_ref(obj: &Self);
[Severity: Low]
Will this change break the build for conditionally compiled modules and
rustdoc tests that still use the old method signature?
When compiling with CONFIG_RUST_DRM_GPUVM, CONFIG_PM_OPP, or
CONFIG_RUST_PWM_ABSTRACTIONS enabled, it appears this will result in
compiler error E0185 because the following implementations were not updated:
rust/kernel/drm/gpuvm/mod.rs:
unsafe impl<T: DriverGpuVm> AlwaysRefCounted for GpuVm<T> {
fn inc_ref(&self) {
rust/kernel/drm/gpuvm/vm_bo.rs:
unsafe impl<T: DriverGpuVm> AlwaysRefCounted for GpuVmBo<T> {
fn inc_ref(&self) {
rust/kernel/opp.rs:
unsafe impl AlwaysRefCounted for OPP {
#[inline]
fn inc_ref(&self) {
rust/kernel/pwm.rs:
unsafe impl<T: PwmOps> AlwaysRefCounted for Chip<T> {
#[inline]
fn inc_ref(&self) {
Additionally, a rustdoc test in rust/kernel/sync/aref.rs for ARef::into_raw
still implements it using the old signature:
/// unsafe impl AlwaysRefCounted for Empty {
/// fn inc_ref(&self) {}
Should these implementations be updated to use fn inc_ref(obj: &Self) to
match the new trait definition?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260628092853.16550-1-trev@trevrosa.dev?part=1
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-06-28 9:37 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-28 9:28 [PATCH v5] rust: aref: make `AlwaysRefCounted::inc_ref` an associated function Trevor Chan
2026-06-28 9:37 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.