[PATCH 1/2] xfs: fix handling of RCU freed inodes from other AGs in xfs_icwalk_ag

Christoph Hellwig
2024-08-12T05:24:02Z

When xfs_icwalk_ag skips an inode because it was RCU freed from another
AG, the slot for the inode in the batch array needs to be zeroed. We
also really shouldn't try to grab the inode in that case (or at very
least undo the grab), so move the call to xfs_icwalk_ag after this sanity
check.

Fixes: 1a3e8f3da09c ("xfs: convert inode cache lookups to use RCU locking")
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/xfs_icache.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index ae3c049fd3a216..3ee92d3d1770db 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -1701,9 +1701,6 @@ xfs_icwalk_ag(
for (i = 0; i < nr_found; i++) {
struct xfs_inode *ip = batch[i];

- if (done || !xfs_icwalk_igrab(goal, ip, icw))
- batch[i] = NULL;
-
/*
* Update the index for the next lookup. Catch
* overflows into the next AG range which can occur if
@@ -1716,8 +1713,14 @@ xfs_icwalk_ag(
* us to see this inode, so another lookup from the
* same index will not find it again.
*/
- if (XFS_INO_TO_AGNO(mp, ip->i_ino) != pag->pag_agno)
+ if (XFS_INO_TO_AGNO(mp, ip->i_ino) != pag->pag_agno) {
+ batch[i] = NULL;
continue;
+ }
+
+ if (done || !xfs_icwalk_igrab(goal, ip, icw))
+ batch[i] = NULL;
+
first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
done = true;
--
2.43.0