On Sat, Feb 17, 2024 at 03:23:40PM -0500, Chuck Lever wrote: > From: Chuck Lever <chuck.lever@xxxxxxxxxx> > > Liam and Matthew say that once the RCU read lock is released, > xa_state is not safe to re-use for the next xas_find() call. But the > RCU read lock must be released on each loop iteration so that > dput(), which might_sleep(), can be called safely. Fwiw, functions like this: static struct dentry *offset_find_next(struct xa_state *xas) { struct dentry *child, *found = NULL; rcu_read_lock(); child = xas_next_entry(xas, U32_MAX); if (!child) goto out; spin_lock(&child->d_lock); if (simple_positive(child)) found = dget_dlock(child); spin_unlock(&child->d_lock); out: rcu_read_unlock(); return found; } should use the new guard feature going forward imho. IOW, in the future such helpers should be written as: static struct dentry *offset_find_next(struct xa_state *xas) { struct dentry *child, *found = NULL; guard(rcu)(); child = xas_next_entry(xas, U32_MAX); if (!child) return NULL; spin_lock(&child->d_lock); if (simple_positive(child)) found = dget_dlock(child); spin_unlock(&child->d_lock); return found; } which allows you to eliminate the goto and to have the guarantee that the rcu lock is released when you return. This also works for other locks btw.