]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
xfs: properly account for reclaimed inodes
authorJohannes Weiner <hannes@cmpxchg.org>
Fri, 1 Oct 2010 07:43:54 +0000 (07:43 +0000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 23 Jun 2011 22:28:42 +0000 (15:28 -0700)
commit 081003fff467ea0e727f66d5d435b4f473a789b3 upstream.

When marking an inode reclaimable, a per-AG counter is increased, the
inode is tagged reclaimable in its per-AG tree, and, when this is the
first reclaimable inode in the AG, the AG entry in the per-mount tree
is also tagged.

When an inode is finally reclaimed, however, it is only deleted from
the per-AG tree.  Neither the counter is decreased, nor is the parent
tree's AG entry untagged properly.

Since the tags in the per-mount tree are not cleared, the inode
shrinker iterates over all AGs that have had reclaimable inodes at one
point in time.

The counters on the other hand signal an increasing amount of slab
objects to reclaim.  Since "70e60ce xfs: convert inode shrinker to
per-filesystem context" this is not a real issue anymore because the
shrinker bails out after one iteration.

But the problem was observable on a machine running v2.6.34, where the
reclaimable work increased and each process going into direct reclaim
eventually got stuck on the xfs inode shrinking path, trying to scan
several million objects.

Fix this by properly unwinding the reclaimable-state tracking of an
inode when it is reclaimed.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Alex Elder <aelder@sgi.com>
Backported-by: Stefan Priebe <s.priebe@profihost.ag>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
fs/xfs/linux-2.6/xfs_sync.c
fs/xfs/linux-2.6/xfs_sync.h
fs/xfs/xfs_iget.c

index 57adf2d60dfc0dffceff1a410c94ea96a255a356..0a0245e673dca01a3f6ae2d181e72cdff0fbd520 100644 (file)
@@ -712,16 +712,24 @@ xfs_inode_set_reclaim_tag(
 }
 
 void
-__xfs_inode_clear_reclaim_tag(
-       xfs_mount_t     *mp,
+__xfs_inode_clear_reclaim(
        xfs_perag_t     *pag,
        xfs_inode_t     *ip)
 {
-       radix_tree_tag_clear(&pag->pag_ici_root,
-                       XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
        pag->pag_ici_reclaimable--;
 }
 
+void
+__xfs_inode_clear_reclaim_tag(
+       xfs_mount_t     *mp,
+       xfs_perag_t     *pag,
+       xfs_inode_t     *ip)
+{
+       radix_tree_tag_clear(&pag->pag_ici_root,
+                       XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
+       __xfs_inode_clear_reclaim(pag, ip);
+}
+
 STATIC int
 xfs_reclaim_inode(
        struct xfs_inode        *ip,
index 0b28c13bdf9455a6a406b57d4785554e90bdb7c3..81dd3bcb8d96c8434b6c06a6fa828538b6193b19 100644 (file)
@@ -48,6 +48,7 @@ int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
 
 void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
 void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip);
+void __xfs_inode_clear_reclaim(struct xfs_perag *pag, struct xfs_inode *ip);
 void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag,
                                struct xfs_inode *ip);
 
index fd21160a6238d7a994b2c49f25c7e1fb0801904b..788b72e5dbccfab2521c757139ddcf46038c43cb 100644 (file)
@@ -499,6 +499,7 @@ xfs_ireclaim(
        write_lock(&pag->pag_ici_lock);
        if (!radix_tree_delete(&pag->pag_ici_root, agino))
                ASSERT(0);
+       __xfs_inode_clear_reclaim(pag, ip);
        write_unlock(&pag->pag_ici_lock);
        xfs_put_perag(mp, pag);