Skip to content

Commit 20c96ed

Browse files
author
Danilo Krummrich
committed
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: 76c01de ("rust: add devres abstraction") Reviewed-by: Benno Lossin <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Danilo Krummrich <[email protected]>
1 parent f744201 commit 20c96ed

File tree

1 file changed

+16
-11
lines changed

1 file changed

+16
-11
lines changed

rust/kernel/devres.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@ use crate::{
1212
error::{Error, Result},
1313
ffi::c_void,
1414
prelude::*,
15-
revocable::Revocable,
16-
sync::{Arc, Completion},
15+
revocable::{Revocable, RevocableGuard},
16+
sync::{rcu, Arc, Completion},
1717
types::ARef,
1818
};
1919

20-
use core::ops::Deref;
21-
2220
#[pin_data]
2321
struct DevresInner<T> {
2422
dev: ARef<Device>,
@@ -230,23 +228,30 @@ impl<T> Devres<T> {
230228
// SAFETY: `dev` being the same device as the device this `Devres` has been created for
231229
// proves that `self.0.data` hasn't been revoked and is guaranteed to not be revoked as
232230
// long as `dev` lives; `dev` lives at least as long as `self`.
233-
Ok(unsafe { self.deref().access() })
231+
Ok(unsafe { self.0.data.access() })
234232
}
235-
}
236233

237-
impl<T> Deref for Devres<T> {
238-
type Target = Revocable<T>;
234+
/// [`Devres`] accessor for [`Revocable::try_access`].
235+
pub fn try_access(&self) -> Option<RevocableGuard<'_, T>> {
236+
self.0.data.try_access()
237+
}
238+
239+
/// [`Devres`] accessor for [`Revocable::try_access_with`].
240+
pub fn try_access_with<R, F: FnOnce(&T) -> R>(&self, f: F) -> Option<R> {
241+
self.0.data.try_access_with(f)
242+
}
239243

240-
fn deref(&self) -> &Self::Target {
241-
&self.0.data
244+
/// [`Devres`] accessor for [`Revocable::try_access_with_guard`].
245+
pub fn try_access_with_guard<'a>(&'a self, guard: &'a rcu::Guard) -> Option<&'a T> {
246+
self.0.data.try_access_with_guard(guard)
242247
}
243248
}
244249

245250
impl<T> Drop for Devres<T> {
246251
fn drop(&mut self) {
247252
// SAFETY: When `drop` runs, it is guaranteed that nobody is accessing the revocable data
248253
// anymore, hence it is safe not to wait for the grace period to finish.
249-
if unsafe { self.revoke_nosync() } {
254+
if unsafe { self.0.data.revoke_nosync() } {
250255
// We revoked `self.0.data` before the devres action did, hence try to remove it.
251256
if !DevresInner::remove_action(&self.0) {
252257
// We could not remove the devres action, which means that it now runs concurrently,

0 commit comments

Comments
 (0)