Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: devres: do not dereference to the internal Revocable

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>

+16 -11
+16 -11
rust/kernel/devres.rs
··· 12 12 error::{Error, Result}, 13 13 ffi::c_void, 14 14 prelude::*, 15 - revocable::Revocable, 16 - sync::{Arc, Completion}, 15 + revocable::{Revocable, RevocableGuard}, 16 + sync::{rcu, Arc, Completion}, 17 17 types::ARef, 18 18 }; 19 - 20 - use core::ops::Deref; 21 19 22 20 #[pin_data] 23 21 struct DevresInner<T> { ··· 228 230 // SAFETY: `dev` being the same device as the device this `Devres` has been created for 229 231 // proves that `self.0.data` hasn't been revoked and is guaranteed to not be revoked as 230 232 // long as `dev` lives; `dev` lives at least as long as `self`. 231 - Ok(unsafe { self.deref().access() }) 233 + Ok(unsafe { self.0.data.access() }) 232 234 } 233 - } 234 235 235 - impl<T> Deref for Devres<T> { 236 - type Target = Revocable<T>; 236 + /// [`Devres`] accessor for [`Revocable::try_access`]. 237 + pub fn try_access(&self) -> Option<RevocableGuard<'_, T>> { 238 + self.0.data.try_access() 239 + } 237 240 238 - fn deref(&self) -> &Self::Target { 239 - &self.0.data 241 + /// [`Devres`] accessor for [`Revocable::try_access_with`]. 242 + pub fn try_access_with<R, F: FnOnce(&T) -> R>(&self, f: F) -> Option<R> { 243 + self.0.data.try_access_with(f) 244 + } 245 + 246 + /// [`Devres`] accessor for [`Revocable::try_access_with_guard`]. 247 + pub fn try_access_with_guard<'a>(&'a self, guard: &'a rcu::Guard) -> Option<&'a T> { 248 + self.0.data.try_access_with_guard(guard) 240 249 } 241 250 } 242 251 ··· 251 246 fn drop(&mut self) { 252 247 // SAFETY: When `drop` runs, it is guaranteed that nobody is accessing the revocable data 253 248 // anymore, hence it is safe not to wait for the grace period to finish. 254 - if unsafe { self.revoke_nosync() } { 249 + if unsafe { self.0.data.revoke_nosync() } { 255 250 // We revoked `self.0.data` before the devres action did, hence try to remove it. 256 251 if !DevresInner::remove_action(&self.0) { 257 252 // We could not remove the devres action, which means that it now runs concurrently,