On Fri, 2026-07-03 at 09:31 +0200, Philipp Stanner wrote:
+// Necessary to guarantee that `inner` always comes first and can be freed by C. +// Also useful for using casts instead of container_of(). +#[repr(C)] +#[pin_data] +struct DriverFenceData<'a, T: Send + Sync + FenceCtxOps> { + #[pin] + /// The inner fence. + // Must always be the first member so that unsafe casting works; but also + // necessary so that the C backend can free the allocation (coming from our + // Rust code) with kfree_rcu(). + inner: Fence, + /// Callback head for dropping this in a deferred manner through RCU. + rcu_head: bindings::callback_head, + /// Reference to access the FenceCtx. Useful for obtaining name parameters. + fctx: &'a FenceCtx<T>, + /// The API user's data. This must either not need drop, or must delay its + /// drop by a grace period. It is essential that the data only performs + /// operations legal in atomic context in its [`Drop`] implementation. + #[pin] + data: T::FenceDataType, +}
+pub struct DriverFence<'a, T: Send + Sync + FenceCtxOps> { + /// The actual content of the fence. Lives in a raw pointer so that its + /// memory can be managed independently. Valid until both the [`DriverFence`] + /// and all associated [`Fence`]s have disappeared. + data: NonNull<DriverFenceData<'a, T>>, +}
+/// A pre-prepared DMA fence, carrying the user's data and the memory it and the +/// fence reside in. Only useful for creating a [`DriverFence`]. Splitting +/// allocation and full initialization is necessary because fences cannot be +/// allocated dynamically in some circumstances (deadlock). +pub struct DriverFenceAllocation<'a, T: Send + Sync + FenceCtxOps> { + /// The memory for the actual content of the fence. + /// Handed over to a [`DriverFence`], or deallocated once the + /// [`DriverFenceAllocation`] drops. + data: KBox<DriverFenceData<'a, T>>, +}
One issue that I'm only discovering just now is that the request of deriving the DriverFence's generic through the FenceCtx's generic causes issues like this:
struct DriverFoo { f: DriverFence<()>, // error: must implement FenceCtxOps }
IOW, all DriverFence::data now must implement the trait. Which is obviously not what we want.
But I cannot get easily get rid of it. See DriverFenceData.
@Boris: Do you have a suggestion? Otherwise I'd want to default back to PhantomData, which I still believe is cleaner.
P.