From: Johannes Weiner Date: Fri, 1 Oct 2010 07:43:54 +0000 (+0000) Subject: xfs: properly account for reclaimed inodes X-Git-Tag: v2.6.34.12~114 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=edca0bf3bbff8dc94ac9a7b1e05d656167cebb15;p=karo-tx-linux.git xfs: properly account for reclaimed inodes 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. [PG: upstream has xfs_reclaim_inode in fs/xfs/linux-2.6/xfs_sync.c but in 34 baseline, it is xfs_ireclaim in fs/xfs/xfs_iget.c so drop the STATIC and add a prototype for it. ] Signed-off-by: Johannes Weiner Reviewed-by: Dave Chinner Signed-off-by: Alex Elder Signed-off-by: Paul Gortmaker --- diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index a427c638d909..c5a69a435421 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c @@ -706,6 +706,14 @@ xfs_inode_set_reclaim_tag( xfs_perag_put(pag); } +void +__xfs_inode_clear_reclaim( + xfs_perag_t *pag, + xfs_inode_t *ip) +{ + pag->pag_ici_reclaimable--; +} + void __xfs_inode_clear_reclaim_tag( xfs_mount_t *mp, @@ -714,7 +722,7 @@ __xfs_inode_clear_reclaim_tag( { radix_tree_tag_clear(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); - pag->pag_ici_reclaimable--; + __xfs_inode_clear_reclaim(pag, ip); } /* diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h index cdcbaaca9880..bf82419f818e 100644 --- a/fs/xfs/linux-2.6/xfs_sync.h +++ b/fs/xfs/linux-2.6/xfs_sync.h @@ -49,6 +49,8 @@ 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_tag(struct xfs_mount *mp, struct xfs_perag *pag, struct xfs_inode *ip); +void __xfs_inode_clear_reclaim(struct xfs_perag *pag, struct xfs_inode *ip); + int xfs_sync_inode_valid(struct xfs_inode *ip, struct xfs_perag *pag); int xfs_inode_ag_iterator(struct xfs_mount *mp, diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 5ac3be018856..14364c4f74b0 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -495,6 +495,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_perag_put(pag);