Add `XArrayState` as internal state for XArray iteration and entry operations. This struct wraps the C `xa_state` structure and holds a reference to a `Guard` to ensure exclusive access to the XArray for the lifetime of the state object. The `XAS_RESTART` constant is also exposed through the bindings helper to properly initialize the `xa_node` field. The struct and its constructor are marked with `#[expect(dead_code)]` as there are no users yet. We will remove this annotation in a later patch. Signed-off-by: Andreas Hindborg --- rust/bindings/bindings_helper.h | 1 + rust/kernel/xarray.rs | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index a067038b4b422..58605c32e8102 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -117,6 +117,7 @@ const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT; const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC = XA_FLAGS_ALLOC; const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC1 = XA_FLAGS_ALLOC1; +const size_t RUST_CONST_HELPER_XAS_RESTART = (size_t)XAS_RESTART; const vm_flags_t RUST_CONST_HELPER_VM_MERGEABLE = VM_MERGEABLE; const vm_flags_t RUST_CONST_HELPER_VM_READ = VM_READ; diff --git a/rust/kernel/xarray.rs b/rust/kernel/xarray.rs index ede48b5e1dba3..d1246ec114898 100644 --- a/rust/kernel/xarray.rs +++ b/rust/kernel/xarray.rs @@ -8,7 +8,10 @@ iter, marker::PhantomData, pin::Pin, - ptr::NonNull, // + ptr::{ + null_mut, + NonNull, // + }, }; use kernel::{ alloc, @@ -319,6 +322,42 @@ pub fn store( } } +/// Internal state for XArray iteration and entry operations. +/// +/// # Invariants +/// +/// - `state` is always a valid `bindings::xa_state`. +#[expect(dead_code)] +pub(crate) struct XArrayState<'a, 'b, T: ForeignOwnable> { + /// Holds a reference to the lock guard to ensure the lock is not dropped + /// while `Self` is live. + _access: PhantomData<&'b Guard<'a, T>>, + state: bindings::xa_state, +} + +impl<'a, 'b, T: ForeignOwnable> XArrayState<'a, 'b, T> { + #[expect(dead_code)] + fn new(access: &'b Guard<'a, T>, index: usize) -> Self { + let ptr = access.xa.xa.get(); + // INVARIANT: We initialize `self.state` to a valid value below. + Self { + _access: PhantomData, + state: bindings::xa_state { + xa: ptr, + xa_index: index, + xa_shift: 0, + xa_sibs: 0, + xa_offset: 0, + xa_pad: 0, + xa_node: bindings::XAS_RESTART as *mut bindings::xa_node, + xa_alloc: null_mut(), + xa_update: None, + xa_lru: null_mut(), + }, + } + } +} + // SAFETY: `XArray` has no shared mutable state so it is `Send` iff `T` is `Send`. unsafe impl Send for XArray {} -- 2.51.2