Skip to content

Commit 229f135

Browse files
committed
Merge tag 'driver-core-6.16-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core
Pull driver core fixes from Danilo Krummrich: - Fix a race condition in Devres::drop(). This depends on two other patches: - (Minimal) Rust abstractions for struct completion - Let Revocable indicate whether its data is already being revoked - Fix Devres to avoid exposing the internal Revocable - Add .mailmap entry for Danilo Krummrich - Add Madhavan Srinivasan to embargoed-hardware-issues.rst * tag 'driver-core-6.16-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core: Documentation: embargoed-hardware-issues.rst: Add myself for Power mailmap: add entry for Danilo Krummrich rust: devres: do not dereference to the internal Revocable rust: devres: fix race in Devres::drop() rust: revocable: indicate whether `data` has been revoked already rust: completion: implement initial abstraction
2 parents 74b4cc9 + eab9dcb commit 229f135

File tree

9 files changed

+183
-21
lines changed

9 files changed

+183
-21
lines changed

.mailmap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ Daniel Borkmann <[email protected]> <[email protected]>
197197
198198
199199
200+
200201
David Brownell <[email protected]>
201202
202203

Documentation/process/embargoed-hardware-issues.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ an involved disclosed party. The current ambassadors list:
290290
AMD Tom Lendacky <[email protected]>
291291
Ampere Darren Hart <[email protected]>
292292
ARM Catalin Marinas <[email protected]>
293+
IBM Power Madhavan Srinivasan <[email protected]>
293294
IBM Z Christian Borntraeger <[email protected]>
294295
Intel Tony Luck <[email protected]>
295296
Qualcomm Trilok Soni <[email protected]>

rust/bindings/bindings_helper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <linux/blk_types.h>
4040
#include <linux/blkdev.h>
4141
#include <linux/clk.h>
42+
#include <linux/completion.h>
4243
#include <linux/configfs.h>
4344
#include <linux/cpu.h>
4445
#include <linux/cpufreq.h>

rust/helpers/completion.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/completion.h>
4+
5+
void rust_helper_init_completion(struct completion *x)
6+
{
7+
init_completion(x);
8+
}

rust/helpers/helpers.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "build_assert.c"
1414
#include "build_bug.c"
1515
#include "clk.c"
16+
#include "completion.c"
1617
#include "cpu.c"
1718
#include "cpufreq.c"
1819
#include "cpumask.c"

rust/kernel/devres.rs

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,28 @@ use crate::{
1212
error::{Error, Result},
1313
ffi::c_void,
1414
prelude::*,
15-
revocable::Revocable,
16-
sync::Arc,
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>,
2523
callback: unsafe extern "C" fn(*mut c_void),
2624
#[pin]
2725
data: Revocable<T>,
26+
#[pin]
27+
revoke: Completion,
2828
}
2929

3030
/// This abstraction is meant to be used by subsystems to containerize [`Device`] bound resources to
3131
/// manage their lifetime.
3232
///
3333
/// [`Device`] bound resources should be freed when either the resource goes out of scope or the
34-
/// [`Device`] is unbound respectively, depending on what happens first.
34+
/// [`Device`] is unbound respectively, depending on what happens first. In any case, it is always
35+
/// guaranteed that revoking the device resource is completed before the corresponding [`Device`]
36+
/// is unbound.
3537
///
3638
/// To achieve that [`Devres`] registers a devres callback on creation, which is called once the
3739
/// [`Device`] is unbound, revoking access to the encapsulated resource (see also [`Revocable`]).
@@ -102,6 +104,7 @@ impl<T> DevresInner<T> {
102104
dev: dev.into(),
103105
callback: Self::devres_callback,
104106
data <- Revocable::new(data),
107+
revoke <- Completion::new(),
105108
}),
106109
flags,
107110
)?;
@@ -130,26 +133,28 @@ impl<T> DevresInner<T> {
130133
self as _
131134
}
132135

133-
fn remove_action(this: &Arc<Self>) {
136+
fn remove_action(this: &Arc<Self>) -> bool {
134137
// SAFETY:
135138
// - `self.inner.dev` is a valid `Device`,
136139
// - the `action` and `data` pointers are the exact same ones as given to devm_add_action()
137140
// previously,
138141
// - `self` is always valid, even if the action has been released already.
139-
let ret = unsafe {
142+
let success = unsafe {
140143
bindings::devm_remove_action_nowarn(
141144
this.dev.as_raw(),
142145
Some(this.callback),
143146
this.as_ptr() as _,
144147
)
145-
};
148+
} == 0;
146149

147-
if ret == 0 {
150+
if success {
148151
// SAFETY: We leaked an `Arc` reference to devm_add_action() in `DevresInner::new`; if
149152
// devm_remove_action_nowarn() was successful we can (and have to) claim back ownership
150153
// of this reference.
151154
let _ = unsafe { Arc::from_raw(this.as_ptr()) };
152155
}
156+
157+
success
153158
}
154159

155160
#[allow(clippy::missing_safety_doc)]
@@ -161,7 +166,12 @@ impl<T> DevresInner<T> {
161166
// `DevresInner::new`.
162167
let inner = unsafe { Arc::from_raw(ptr) };
163168

164-
inner.data.revoke();
169+
if !inner.data.revoke() {
170+
// If `revoke()` returns false, it means that `Devres::drop` already started revoking
171+
// `inner.data` for us. Hence we have to wait until `Devres::drop()` signals that it
172+
// completed revoking `inner.data`.
173+
inner.revoke.wait_for_completion();
174+
}
165175
}
166176
}
167177

@@ -218,20 +228,36 @@ impl<T> Devres<T> {
218228
// SAFETY: `dev` being the same device as the device this `Devres` has been created for
219229
// proves that `self.0.data` hasn't been revoked and is guaranteed to not be revoked as
220230
// long as `dev` lives; `dev` lives at least as long as `self`.
221-
Ok(unsafe { self.deref().access() })
231+
Ok(unsafe { self.0.data.access() })
222232
}
223-
}
224233

225-
impl<T> Deref for Devres<T> {
226-
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+
}
227243

228-
fn deref(&self) -> &Self::Target {
229-
&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)
230247
}
231248
}
232249

233250
impl<T> Drop for Devres<T> {
234251
fn drop(&mut self) {
235-
DevresInner::remove_action(&self.0);
252+
// SAFETY: When `drop` runs, it is guaranteed that nobody is accessing the revocable data
253+
// anymore, hence it is safe not to wait for the grace period to finish.
254+
if unsafe { self.0.data.revoke_nosync() } {
255+
// We revoked `self.0.data` before the devres action did, hence try to remove it.
256+
if !DevresInner::remove_action(&self.0) {
257+
// We could not remove the devres action, which means that it now runs concurrently,
258+
// hence signal that `self.0.data` has been revoked successfully.
259+
self.0.revoke.complete_all();
260+
}
261+
}
236262
}
237263
}

rust/kernel/revocable.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,10 @@ impl<T> Revocable<T> {
154154
/// # Safety
155155
///
156156
/// Callers must ensure that there are no more concurrent users of the revocable object.
157-
unsafe fn revoke_internal<const SYNC: bool>(&self) {
158-
if self.is_available.swap(false, Ordering::Relaxed) {
157+
unsafe fn revoke_internal<const SYNC: bool>(&self) -> bool {
158+
let revoke = self.is_available.swap(false, Ordering::Relaxed);
159+
160+
if revoke {
159161
if SYNC {
160162
// SAFETY: Just an FFI call, there are no further requirements.
161163
unsafe { bindings::synchronize_rcu() };
@@ -165,17 +167,22 @@ impl<T> Revocable<T> {
165167
// `compare_exchange` above that takes `is_available` from `true` to `false`.
166168
unsafe { drop_in_place(self.data.get()) };
167169
}
170+
171+
revoke
168172
}
169173

170174
/// Revokes access to and drops the wrapped object.
171175
///
172176
/// Access to the object is revoked immediately to new callers of [`Revocable::try_access`],
173177
/// expecting that there are no concurrent users of the object.
174178
///
179+
/// Returns `true` if `&self` has been revoked with this call, `false` if it was revoked
180+
/// already.
181+
///
175182
/// # Safety
176183
///
177184
/// Callers must ensure that there are no more concurrent users of the revocable object.
178-
pub unsafe fn revoke_nosync(&self) {
185+
pub unsafe fn revoke_nosync(&self) -> bool {
179186
// SAFETY: By the safety requirement of this function, the caller ensures that nobody is
180187
// accessing the data anymore and hence we don't have to wait for the grace period to
181188
// finish.
@@ -189,7 +196,10 @@ impl<T> Revocable<T> {
189196
/// If there are concurrent users of the object (i.e., ones that called
190197
/// [`Revocable::try_access`] beforehand and still haven't dropped the returned guard), this
191198
/// function waits for the concurrent access to complete before dropping the wrapped object.
192-
pub fn revoke(&self) {
199+
///
200+
/// Returns `true` if `&self` has been revoked with this call, `false` if it was revoked
201+
/// already.
202+
pub fn revoke(&self) -> bool {
193203
// SAFETY: By passing `true` we ask `revoke_internal` to wait for the grace period to
194204
// finish.
195205
unsafe { self.revoke_internal::<true>() }

rust/kernel/sync.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ use crate::types::Opaque;
1010
use pin_init;
1111

1212
mod arc;
13+
pub mod completion;
1314
mod condvar;
1415
pub mod lock;
1516
mod locked_by;
1617
pub mod poll;
1718
pub mod rcu;
1819

1920
pub use arc::{Arc, ArcBorrow, UniqueArc};
21+
pub use completion::Completion;
2022
pub use condvar::{new_condvar, CondVar, CondVarTimeoutResult};
2123
pub use lock::global::{global_lock, GlobalGuard, GlobalLock, GlobalLockBackend, GlobalLockedBy};
2224
pub use lock::mutex::{new_mutex, Mutex, MutexGuard};

rust/kernel/sync/completion.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Completion support.
4+
//!
5+
//! Reference: <https://docs.kernel.org/scheduler/completion.html>
6+
//!
7+
//! C header: [`include/linux/completion.h`](srctree/include/linux/completion.h)
8+
9+
use crate::{bindings, prelude::*, types::Opaque};
10+
11+
/// Synchronization primitive to signal when a certain task has been completed.
12+
///
13+
/// The [`Completion`] synchronization primitive signals when a certain task has been completed by
14+
/// waking up other tasks that have been queued up to wait for the [`Completion`] to be completed.
15+
///
16+
/// # Examples
17+
///
18+
/// ```
19+
/// use kernel::sync::{Arc, Completion};
20+
/// use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem};
21+
///
22+
/// #[pin_data]
23+
/// struct MyTask {
24+
/// #[pin]
25+
/// work: Work<MyTask>,
26+
/// #[pin]
27+
/// done: Completion,
28+
/// }
29+
///
30+
/// impl_has_work! {
31+
/// impl HasWork<Self> for MyTask { self.work }
32+
/// }
33+
///
34+
/// impl MyTask {
35+
/// fn new() -> Result<Arc<Self>> {
36+
/// let this = Arc::pin_init(pin_init!(MyTask {
37+
/// work <- new_work!("MyTask::work"),
38+
/// done <- Completion::new(),
39+
/// }), GFP_KERNEL)?;
40+
///
41+
/// let _ = workqueue::system().enqueue(this.clone());
42+
///
43+
/// Ok(this)
44+
/// }
45+
///
46+
/// fn wait_for_completion(&self) {
47+
/// self.done.wait_for_completion();
48+
///
49+
/// pr_info!("Completion: task complete\n");
50+
/// }
51+
/// }
52+
///
53+
/// impl WorkItem for MyTask {
54+
/// type Pointer = Arc<MyTask>;
55+
///
56+
/// fn run(this: Arc<MyTask>) {
57+
/// // process this task
58+
/// this.done.complete_all();
59+
/// }
60+
/// }
61+
///
62+
/// let task = MyTask::new()?;
63+
/// task.wait_for_completion();
64+
/// # Ok::<(), Error>(())
65+
/// ```
66+
#[pin_data]
67+
pub struct Completion {
68+
#[pin]
69+
inner: Opaque<bindings::completion>,
70+
}
71+
72+
// SAFETY: `Completion` is safe to be send to any task.
73+
unsafe impl Send for Completion {}
74+
75+
// SAFETY: `Completion` is safe to be accessed concurrently.
76+
unsafe impl Sync for Completion {}
77+
78+
impl Completion {
79+
/// Create an initializer for a new [`Completion`].
80+
pub fn new() -> impl PinInit<Self> {
81+
pin_init!(Self {
82+
inner <- Opaque::ffi_init(|slot: *mut bindings::completion| {
83+
// SAFETY: `slot` is a valid pointer to an uninitialized `struct completion`.
84+
unsafe { bindings::init_completion(slot) };
85+
}),
86+
})
87+
}
88+
89+
fn as_raw(&self) -> *mut bindings::completion {
90+
self.inner.get()
91+
}
92+
93+
/// Signal all tasks waiting on this completion.
94+
///
95+
/// This method wakes up all tasks waiting on this completion; after this operation the
96+
/// completion is permanently done, i.e. signals all current and future waiters.
97+
pub fn complete_all(&self) {
98+
// SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`.
99+
unsafe { bindings::complete_all(self.as_raw()) };
100+
}
101+
102+
/// Wait for completion of a task.
103+
///
104+
/// This method waits for the completion of a task; it is not interruptible and there is no
105+
/// timeout.
106+
///
107+
/// See also [`Completion::complete_all`].
108+
pub fn wait_for_completion(&self) {
109+
// SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`.
110+
unsafe { bindings::wait_for_completion(self.as_raw()) };
111+
}
112+
}

0 commit comments

Comments
 (0)