summaryrefslogtreecommitdiff
path: root/rust
diff options
context:
space:
mode:
authorDanilo Krummrich <dakr@kernel.org>2025-06-11 19:48:25 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-07-06 11:04:25 +0200
commit5640e62e85082a7abc1aca83a3a7ad9f0b2c3a60 (patch)
tree7c1090a66182ef27cafce95a8b89061aa36b56c2 /rust
parent8b60b1dd7b5a8129c2a83cc1b38cc2b0485a8347 (diff)
downloadlinux-5640e62e85082a7abc1aca83a3a7ad9f0b2c3a60.tar.gz
linux-5640e62e85082a7abc1aca83a3a7ad9f0b2c3a60.tar.bz2
linux-5640e62e85082a7abc1aca83a3a7ad9f0b2c3a60.zip
rust: devres: do not dereference to the internal Revocable
commit 20c96ed278e362ae4e324ed7d8c69fb48c508d3c upstream. We can't expose direct access to the internal Revocable, since this allows users to directly revoke the internal Revocable without Devres having the chance to synchronize with the devres callback -- we have to guarantee that the internal Revocable has been fully revoked before the device is fully unbound. Hence, remove the corresponding Deref implementation and, instead, provide indirect accessors for the internal Revocable. Note that we can still support Devres::revoke() by implementing the required synchronization (which would be almost identical to the synchronization in Devres::drop()). Fixes: 76c01ded724b ("rust: add devres abstraction") Reviewed-by: Benno Lossin <lossin@kernel.org> Link: https://lore.kernel.org/r/20250611174827.380555-1-dakr@kernel.org Signed-off-by: Danilo Krummrich <dakr@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'rust')
-rw-r--r--rust/kernel/devres.rs20
1 files changed, 10 insertions, 10 deletions
diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs
index f3a4e3383b8d..dc6ea014ee60 100644
--- a/rust/kernel/devres.rs
+++ b/rust/kernel/devres.rs
@@ -12,13 +12,11 @@ use crate::{
error::{Error, Result},
ffi::c_void,
prelude::*,
- revocable::Revocable,
- sync::{Arc, Completion},
+ revocable::{Revocable, RevocableGuard},
+ sync::{rcu, Arc, Completion},
types::ARef,
};
-use core::ops::Deref;
-
#[pin_data]
struct DevresInner<T> {
dev: ARef<Device>,
@@ -196,13 +194,15 @@ impl<T> Devres<T> {
Ok(())
}
-}
-impl<T> Deref for Devres<T> {
- type Target = Revocable<T>;
+ /// [`Devres`] accessor for [`Revocable::try_access`].
+ pub fn try_access(&self) -> Option<RevocableGuard<'_, T>> {
+ self.0.data.try_access()
+ }
- fn deref(&self) -> &Self::Target {
- &self.0.data
+ /// [`Devres`] accessor for [`Revocable::try_access_with_guard`].
+ pub fn try_access_with_guard<'a>(&'a self, guard: &'a rcu::Guard) -> Option<&'a T> {
+ self.0.data.try_access_with_guard(guard)
}
}
@@ -210,7 +210,7 @@ impl<T> Drop for Devres<T> {
fn drop(&mut self) {
// SAFETY: When `drop` runs, it is guaranteed that nobody is accessing the revocable data
// anymore, hence it is safe not to wait for the grace period to finish.
- if unsafe { self.revoke_nosync() } {
+ if unsafe { self.0.data.revoke_nosync() } {
// We revoked `self.0.data` before the devres action did, hence try to remove it.
if !DevresInner::remove_action(&self.0) {
// We could not remove the devres action, which means that it now runs concurrently,