[PATCH v5 12/12] rust: xarray: document `Guard` lock drop semantics

From: Andreas Hindborg

Date: Wed Sep 02 2026 - 10:57:20 EST


`Guard::store` calls `__xa_store`, which drops the xarray lock to
allocate memory when called with blocking allocation flags and
reacquires it afterwards. A Rust lock guard is normally expected to
provide continuous mutual exclusion for its entire lifetime, so this
behavior can surprise users: a check-then-act sequence spanning a
blocking `store` call is not atomic.

Document the behavior on `Guard` and expand the `store` docs,
pointing to the entry API with preallocated memory as the way to
modify the array without dropping the lock.

Suggested-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Assisted-by: LLM
Signed-off-by: Andreas Hindborg <a.hindborg@xxxxxxxxxx>
---
rust/kernel/xarray.rs | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/xarray.rs b/rust/kernel/xarray.rs
index 87123ab96a92..a11472acc661 100644
--- a/rust/kernel/xarray.rs
+++ b/rust/kernel/xarray.rs
@@ -242,6 +242,21 @@ pub fn lock(&self) -> Guard<'_, T> {
/// A lock guard.
///
/// The lock is unlocked when the guard goes out of scope.
+///
+/// # Temporary lock drops
+///
+/// Unlike a typical Rust lock guard, holding a `Guard` does not guarantee
+/// continuous mutual exclusion for its entire lifetime: [`store`] may drop and
+/// reacquire the lock to allocate memory when called with blocking allocation
+/// flags. Other threads may lock and modify the array in that window, so a
+/// sequence of operations on the guard that spans such a call is not atomic.
+///
+/// To modify the array without dropping the lock, use the entry API with
+/// preallocated memory, see [`entry`] and [`insert_entry`].
+///
+/// [`store`]: Guard::store
+/// [`entry`]: Guard::entry
+/// [`insert_entry`]: Guard::insert_entry
#[must_use = "the lock unlocks immediately when the guard is unused"]
pub struct Guard<'a, T: ForeignOwnable> {
xa: &'a XArray<T>,
@@ -485,7 +500,12 @@ pub fn remove(&mut self, index: usize) -> Option<T> {

/// Stores an element at the given index.
///
- /// May drop the lock if needed to allocate memory, and then reacquire it afterwards.
+ /// If `gfp` contains blocking allocation flags, this method may drop the
+ /// lock to allocate memory and reacquire it afterwards. Other threads may
+ /// lock and modify the array in that window, so callers must not rely on
+ /// this method being atomic with respect to other operations on the
+ /// guard. To store without dropping the lock, use [`Guard::insert_entry`]
+ /// with preallocated memory.
///
/// On success, returns the element which was previously at the given index.
///

--
2.51.2