[PATCH 1/2] rust: workqueue: add SAFETY comments for Pin<KBox<T>> impls

From: Moayad Salloum

Date: Sun May 17 2026 - 21:39:46 EST


Fill in the two SAFETY: TODO placeholders for the WorkItemPointer<ID>
and RawWorkItem<ID> implementations of Pin<KBox<T>>.

For WorkItemPointer: __enqueue uses a work_struct initialized with this
trait's run function because Work::new stores T::Pointer::run via
init_work_with_key, and the ID const generic ensures the correct Work
field and WorkItemPointer impl are selected.

For RawWorkItem: the work_struct pointer remains valid for the closure's
duration because KBox::into_raw leaks the allocation without dropping it.
If queue_work_on returns true, the memory is only reclaimed in
WorkItemPointer::run via KBox::from_raw. queue_work_on cannot return
false because Pin<KBox<T>> provides exclusive ownership, so the item
cannot already be in a workqueue.

Signed-off-by: Moayad Salloum <salloummoayad4@xxxxxxxxx>
---
rust/kernel/workqueue.rs | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index 7e253b6f2..6d665418b 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -881,7 +881,15 @@ unsafe impl<T, const ID: u64> RawDelayedWorkItem<ID> for Arc<T>
{
}

-// SAFETY: TODO.
+// SAFETY: The `__enqueue` implementation in `RawWorkItem` uses a `work_struct` initialized with
+// the `run` method of this trait as the function pointer because:
+// - `__enqueue` gets the `work_struct` from the `Work` field, using `T::raw_get_work`.
+// - The only safe way to create a `Work` object is through `Work::new`.
+// - `Work::new` makes sure that `T::Pointer::run` is passed to `init_work_with_key`.
+// - Finally, `Work` and `RawWorkItem` guarantee that the correct `Work` field will be used
+// because of the ID const generic bound. This ensures that `T::raw_get_work` uses the correct
+// offset for the `Work` field, and `Work::new` picks the correct implementation of
+// `WorkItemPointer` for `Pin<KBox<T>>`.
unsafe impl<T, const ID: u64> WorkItemPointer<ID> for Pin<KBox<T>>
where
T: WorkItem<ID, Pointer = Self>,
@@ -901,7 +909,14 @@ unsafe impl<T, const ID: u64> WorkItemPointer<ID> for Pin<KBox<T>>
}
}

-// SAFETY: TODO.
+// SAFETY: The `work_struct` raw pointer is guaranteed to be valid for the duration of the call to
+// the closure because we call `KBox::into_raw` before the closure, which leaks the allocation
+// without dropping it, so the pointer remains live. If `queue_work_on` returns true, it is further
+// guaranteed to be valid until a call to the function pointer in the `work_struct` because the
+// leaked memory is only reclaimed in `WorkItemPointer::run` (via `KBox::from_raw`), which is what
+// the function pointer in the `work_struct` must be pointing to, according to the safety
+// requirements of `WorkItemPointer`. Note that `queue_work_on` can never return false here:
+// `Pin<KBox<T>>` provides exclusive ownership, so the work item cannot already be in a workqueue.
unsafe impl<T, const ID: u64> RawWorkItem<ID> for Pin<KBox<T>>
where
T: WorkItem<ID, Pointer = Self>,
--
2.43.0