xfs: make use of new shrinker callout for the inode cache
authorDave Chinner <dchinner@redhat.com>
Fri, 8 Jul 2011 04:14:46 +0000 (14:14 +1000)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 21 Jul 2011 00:47:42 +0000 (20:47 -0400)
Convert the inode reclaim shrinker to use the new per-sb shrinker
operations. This allows much bigger reclaim batches to be used, and
allows the XFS inode cache to be shrunk in proportion with the VFS
dentry and inode caches. This avoids the problem of the VFS caches
being shrunk significantly before the XFS inode cache is shrunk
resulting in imbalances in the caches during reclaim.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/linux-2.6/xfs_sync.c
fs/xfs/linux-2.6/xfs_sync.h

index a1a881e68a9aa86a1aa76c27931e02202a57a08d..a9c6ccff7b485588c14fea00374c0e7070cca64a 100644 (file)
@@ -1025,11 +1025,6 @@ xfs_fs_put_super(
 {
        struct xfs_mount        *mp = XFS_M(sb);
 
-       /*
-        * Unregister the memory shrinker before we tear down the mount
-        * structure so we don't have memory reclaim racing with us here.
-        */
-       xfs_inode_shrinker_unregister(mp);
        xfs_syncd_stop(mp);
 
        /*
@@ -1416,8 +1411,6 @@ xfs_fs_fill_super(
        if (error)
                goto out_filestream_unmount;
 
-       xfs_inode_shrinker_register(mp);
-
        error = xfs_mountfs(mp);
        if (error)
                goto out_syncd_stop;
@@ -1440,7 +1433,6 @@ xfs_fs_fill_super(
        return 0;
 
  out_syncd_stop:
-       xfs_inode_shrinker_unregister(mp);
        xfs_syncd_stop(mp);
  out_filestream_unmount:
        xfs_filestream_unmount(mp);
@@ -1465,7 +1457,6 @@ xfs_fs_fill_super(
        }
 
  fail_unmount:
-       xfs_inode_shrinker_unregister(mp);
        xfs_syncd_stop(mp);
 
        /*
@@ -1491,6 +1482,21 @@ xfs_fs_mount(
        return mount_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super);
 }
 
+static int
+xfs_fs_nr_cached_objects(
+       struct super_block      *sb)
+{
+       return xfs_reclaim_inodes_count(XFS_M(sb));
+}
+
+static void
+xfs_fs_free_cached_objects(
+       struct super_block      *sb,
+       int                     nr_to_scan)
+{
+       xfs_reclaim_inodes_nr(XFS_M(sb), nr_to_scan);
+}
+
 static const struct super_operations xfs_super_operations = {
        .alloc_inode            = xfs_fs_alloc_inode,
        .destroy_inode          = xfs_fs_destroy_inode,
@@ -1504,6 +1510,8 @@ static const struct super_operations xfs_super_operations = {
        .statfs                 = xfs_fs_statfs,
        .remount_fs             = xfs_fs_remount,
        .show_options           = xfs_fs_show_options,
+       .nr_cached_objects      = xfs_fs_nr_cached_objects,
+       .free_cached_objects    = xfs_fs_free_cached_objects,
 };
 
 static struct file_system_type xfs_fs_type = {
index 8ecad5ff9f9b0e0bdb5a4f76dd97b694147a5a55..9bd7e895a4e28433750979b4f705c795e4b4878f 100644 (file)
@@ -179,6 +179,8 @@ restart:
                if (error == EFSCORRUPTED)
                        break;
 
+               cond_resched();
+
        } while (nr_found && !done);
 
        if (skipped) {
@@ -986,6 +988,8 @@ restart:
 
                        *nr_to_scan -= XFS_LOOKUP_BATCH;
 
+                       cond_resched();
+
                } while (nr_found && !done && *nr_to_scan > 0);
 
                if (trylock && !done)
@@ -1003,7 +1007,7 @@ restart:
         * ensure that when we get more reclaimers than AGs we block rather
         * than spin trying to execute reclaim.
         */
-       if (trylock && skipped && *nr_to_scan > 0) {
+       if (skipped && (flags & SYNC_WAIT) && *nr_to_scan > 0) {
                trylock = 0;
                goto restart;
        }
@@ -1021,44 +1025,38 @@ xfs_reclaim_inodes(
 }
 
 /*
- * Inode cache shrinker.
+ * Scan a certain number of inodes for reclaim.
  *
  * When called we make sure that there is a background (fast) inode reclaim in
- * progress, while we will throttle the speed of reclaim via doiing synchronous
+ * progress, while we will throttle the speed of reclaim via doing synchronous
  * reclaim of inodes. That means if we come across dirty inodes, we wait for
  * them to be cleaned, which we hope will not be very long due to the
  * background walker having already kicked the IO off on those dirty inodes.
  */
-static int
-xfs_reclaim_inode_shrink(
-       struct shrinker *shrink,
-       struct shrink_control *sc)
+void
+xfs_reclaim_inodes_nr(
+       struct xfs_mount        *mp,
+       int                     nr_to_scan)
 {
-       struct xfs_mount *mp;
-       struct xfs_perag *pag;
-       xfs_agnumber_t  ag;
-       int             reclaimable;
-       int nr_to_scan = sc->nr_to_scan;
-       gfp_t gfp_mask = sc->gfp_mask;
-
-       mp = container_of(shrink, struct xfs_mount, m_inode_shrink);
-       if (nr_to_scan) {
-               /* kick background reclaimer and push the AIL */
-               xfs_syncd_queue_reclaim(mp);
-               xfs_ail_push_all(mp->m_ail);
+       /* kick background reclaimer and push the AIL */
+       xfs_syncd_queue_reclaim(mp);
+       xfs_ail_push_all(mp->m_ail);
 
-               if (!(gfp_mask & __GFP_FS))
-                       return -1;
+       xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, &nr_to_scan);
+}
 
-               xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT,
-                                       &nr_to_scan);
-               /* terminate if we don't exhaust the scan */
-               if (nr_to_scan > 0)
-                       return -1;
-       }
+/*
+ * Return the number of reclaimable inodes in the filesystem for
+ * the shrinker to determine how much to reclaim.
+ */
+int
+xfs_reclaim_inodes_count(
+       struct xfs_mount        *mp)
+{
+       struct xfs_perag        *pag;
+       xfs_agnumber_t          ag = 0;
+       int                     reclaimable = 0;
 
-       reclaimable = 0;
-       ag = 0;
        while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) {
                ag = pag->pag_agno + 1;
                reclaimable += pag->pag_ici_reclaimable;
@@ -1067,18 +1065,3 @@ xfs_reclaim_inode_shrink(
        return reclaimable;
 }
 
-void
-xfs_inode_shrinker_register(
-       struct xfs_mount        *mp)
-{
-       mp->m_inode_shrink.shrink = xfs_reclaim_inode_shrink;
-       mp->m_inode_shrink.seeks = DEFAULT_SEEKS;
-       register_shrinker(&mp->m_inode_shrink);
-}
-
-void
-xfs_inode_shrinker_unregister(
-       struct xfs_mount        *mp)
-{
-       unregister_shrinker(&mp->m_inode_shrink);
-}
index e3a6ad27415f77c07484941e1b6a79b07d2a3a34..2e15685977646109ba0c02e48732d93463bf7e5c 100644 (file)
@@ -43,6 +43,8 @@ void xfs_quiesce_attr(struct xfs_mount *mp);
 void xfs_flush_inodes(struct xfs_inode *ip);
 
 int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
+int xfs_reclaim_inodes_count(struct xfs_mount *mp);
+void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
 
 void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
 void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip);
@@ -54,7 +56,4 @@ int xfs_inode_ag_iterator(struct xfs_mount *mp,
        int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),
        int flags);
 
-void xfs_inode_shrinker_register(struct xfs_mount *mp);
-void xfs_inode_shrinker_unregister(struct xfs_mount *mp);
-
 #endif
This page took 0.030563 seconds and 5 git commands to generate.