Skip to content

Commit 5806165

Browse files
Dave Chinnerdjwong
authored andcommitted
xfs: factor inode lookup from xfs_ifree_cluster
There's lots of indent in this code which makes it a bit hard to follow. We are also going to completely rework the inode lookup code as part of the inode reclaim rework, so factor out the inode lookup code from the inode cluster freeing code. Based on prototype code from Christoph Hellwig. Signed-off-by: Dave Chinner <[email protected]> Reviewed-by: Brian Foster <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Signed-off-by: Darrick J. Wong <[email protected]>
1 parent 8eb807b commit 5806165

File tree

1 file changed

+84
-68
lines changed

1 file changed

+84
-68
lines changed

fs/xfs/xfs_inode.c

Lines changed: 84 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2503,6 +2503,88 @@ xfs_iunlink_remove(
25032503
return error;
25042504
}
25052505

2506+
/*
2507+
* Look up the inode number specified and mark it stale if it is found. If it is
2508+
* dirty, return the inode so it can be attached to the cluster buffer so it can
2509+
* be processed appropriately when the cluster free transaction completes.
2510+
*/
2511+
static struct xfs_inode *
2512+
xfs_ifree_get_one_inode(
2513+
struct xfs_perag *pag,
2514+
struct xfs_inode *free_ip,
2515+
int inum)
2516+
{
2517+
struct xfs_mount *mp = pag->pag_mount;
2518+
struct xfs_inode *ip;
2519+
2520+
retry:
2521+
rcu_read_lock();
2522+
ip = radix_tree_lookup(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, inum));
2523+
2524+
/* Inode not in memory, nothing to do */
2525+
if (!ip)
2526+
goto out_rcu_unlock;
2527+
2528+
/*
2529+
* because this is an RCU protected lookup, we could find a recently
2530+
* freed or even reallocated inode during the lookup. We need to check
2531+
* under the i_flags_lock for a valid inode here. Skip it if it is not
2532+
* valid, the wrong inode or stale.
2533+
*/
2534+
spin_lock(&ip->i_flags_lock);
2535+
if (ip->i_ino != inum || __xfs_iflags_test(ip, XFS_ISTALE)) {
2536+
spin_unlock(&ip->i_flags_lock);
2537+
goto out_rcu_unlock;
2538+
}
2539+
spin_unlock(&ip->i_flags_lock);
2540+
2541+
/*
2542+
* Don't try to lock/unlock the current inode, but we _cannot_ skip the
2543+
* other inodes that we did not find in the list attached to the buffer
2544+
* and are not already marked stale. If we can't lock it, back off and
2545+
* retry.
2546+
*/
2547+
if (ip != free_ip) {
2548+
if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
2549+
rcu_read_unlock();
2550+
delay(1);
2551+
goto retry;
2552+
}
2553+
2554+
/*
2555+
* Check the inode number again in case we're racing with
2556+
* freeing in xfs_reclaim_inode(). See the comments in that
2557+
* function for more information as to why the initial check is
2558+
* not sufficient.
2559+
*/
2560+
if (ip->i_ino != inum) {
2561+
xfs_iunlock(ip, XFS_ILOCK_EXCL);
2562+
goto out_rcu_unlock;
2563+
}
2564+
}
2565+
rcu_read_unlock();
2566+
2567+
xfs_iflock(ip);
2568+
xfs_iflags_set(ip, XFS_ISTALE);
2569+
2570+
/*
2571+
* We don't need to attach clean inodes or those only with unlogged
2572+
* changes (which we throw away, anyway).
2573+
*/
2574+
if (!ip->i_itemp || xfs_inode_clean(ip)) {
2575+
ASSERT(ip != free_ip);
2576+
xfs_ifunlock(ip);
2577+
xfs_iunlock(ip, XFS_ILOCK_EXCL);
2578+
goto out_no_inode;
2579+
}
2580+
return ip;
2581+
2582+
out_rcu_unlock:
2583+
rcu_read_unlock();
2584+
out_no_inode:
2585+
return NULL;
2586+
}
2587+
25062588
/*
25072589
* A big issue when freeing the inode cluster is that we _cannot_ skip any
25082590
* inodes that are in memory - they all must be marked stale and attached to
@@ -2603,77 +2685,11 @@ xfs_ifree_cluster(
26032685
* even trying to lock them.
26042686
*/
26052687
for (i = 0; i < igeo->inodes_per_cluster; i++) {
2606-
retry:
2607-
rcu_read_lock();
2608-
ip = radix_tree_lookup(&pag->pag_ici_root,
2609-
XFS_INO_TO_AGINO(mp, (inum + i)));
2610-
2611-
/* Inode not in memory, nothing to do */
2612-
if (!ip) {
2613-
rcu_read_unlock();
2688+
ip = xfs_ifree_get_one_inode(pag, free_ip, inum + i);
2689+
if (!ip)
26142690
continue;
2615-
}
2616-
2617-
/*
2618-
* because this is an RCU protected lookup, we could
2619-
* find a recently freed or even reallocated inode
2620-
* during the lookup. We need to check under the
2621-
* i_flags_lock for a valid inode here. Skip it if it
2622-
* is not valid, the wrong inode or stale.
2623-
*/
2624-
spin_lock(&ip->i_flags_lock);
2625-
if (ip->i_ino != inum + i ||
2626-
__xfs_iflags_test(ip, XFS_ISTALE)) {
2627-
spin_unlock(&ip->i_flags_lock);
2628-
rcu_read_unlock();
2629-
continue;
2630-
}
2631-
spin_unlock(&ip->i_flags_lock);
2632-
2633-
/*
2634-
* Don't try to lock/unlock the current inode, but we
2635-
* _cannot_ skip the other inodes that we did not find
2636-
* in the list attached to the buffer and are not
2637-
* already marked stale. If we can't lock it, back off
2638-
* and retry.
2639-
*/
2640-
if (ip != free_ip) {
2641-
if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
2642-
rcu_read_unlock();
2643-
delay(1);
2644-
goto retry;
2645-
}
2646-
2647-
/*
2648-
* Check the inode number again in case we're
2649-
* racing with freeing in xfs_reclaim_inode().
2650-
* See the comments in that function for more
2651-
* information as to why the initial check is
2652-
* not sufficient.
2653-
*/
2654-
if (ip->i_ino != inum + i) {
2655-
xfs_iunlock(ip, XFS_ILOCK_EXCL);
2656-
rcu_read_unlock();
2657-
continue;
2658-
}
2659-
}
2660-
rcu_read_unlock();
26612691

2662-
xfs_iflock(ip);
2663-
xfs_iflags_set(ip, XFS_ISTALE);
2664-
2665-
/*
2666-
* we don't need to attach clean inodes or those only
2667-
* with unlogged changes (which we throw away, anyway).
2668-
*/
26692692
iip = ip->i_itemp;
2670-
if (!iip || xfs_inode_clean(ip)) {
2671-
ASSERT(ip != free_ip);
2672-
xfs_ifunlock(ip);
2673-
xfs_iunlock(ip, XFS_ILOCK_EXCL);
2674-
continue;
2675-
}
2676-
26772693
iip->ili_last_fields = iip->ili_fields;
26782694
iip->ili_fields = 0;
26792695
iip->ili_fsync_fields = 0;

0 commit comments

Comments
 (0)