aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-07-08 00:14:46 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2011-07-20 20:47:42 -0400
commit8daaa83145ef1f0a146680618328dbbd0fa76939 (patch)
tree8ca49f03ed2fc4dada7283a6e109b13e3fb5501e /fs/xfs
parent8ab47664d51a69ea79fe70bb07ca80664f74f76b (diff)
xfs: make use of new shrinker callout for the inode cache
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>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c26
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c71
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.h5
3 files changed, 46 insertions, 56 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index a1a881e68a9a..a9c6ccff7b48 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -1025,11 +1025,6 @@ xfs_fs_put_super(
1025{ 1025{
1026 struct xfs_mount *mp = XFS_M(sb); 1026 struct xfs_mount *mp = XFS_M(sb);
1027 1027
1028 /*
1029 * Unregister the memory shrinker before we tear down the mount
1030 * structure so we don't have memory reclaim racing with us here.
1031 */
1032 xfs_inode_shrinker_unregister(mp);
1033 xfs_syncd_stop(mp); 1028 xfs_syncd_stop(mp);
1034 1029
1035 /* 1030 /*
@@ -1416,8 +1411,6 @@ xfs_fs_fill_super(
1416 if (error) 1411 if (error)
1417 goto out_filestream_unmount; 1412 goto out_filestream_unmount;
1418 1413
1419 xfs_inode_shrinker_register(mp);
1420
1421 error = xfs_mountfs(mp); 1414 error = xfs_mountfs(mp);
1422 if (error) 1415 if (error)
1423 goto out_syncd_stop; 1416 goto out_syncd_stop;
@@ -1440,7 +1433,6 @@ xfs_fs_fill_super(
1440 return 0; 1433 return 0;
1441 1434
1442 out_syncd_stop: 1435 out_syncd_stop:
1443 xfs_inode_shrinker_unregister(mp);
1444 xfs_syncd_stop(mp); 1436 xfs_syncd_stop(mp);
1445 out_filestream_unmount: 1437 out_filestream_unmount:
1446 xfs_filestream_unmount(mp); 1438 xfs_filestream_unmount(mp);
@@ -1465,7 +1457,6 @@ xfs_fs_fill_super(
1465 } 1457 }
1466 1458
1467 fail_unmount: 1459 fail_unmount:
1468 xfs_inode_shrinker_unregister(mp);
1469 xfs_syncd_stop(mp); 1460 xfs_syncd_stop(mp);
1470 1461
1471 /* 1462 /*
@@ -1491,6 +1482,21 @@ xfs_fs_mount(
1491 return mount_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super); 1482 return mount_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super);
1492} 1483}
1493 1484
1485static int
1486xfs_fs_nr_cached_objects(
1487 struct super_block *sb)
1488{
1489 return xfs_reclaim_inodes_count(XFS_M(sb));
1490}
1491
1492static void
1493xfs_fs_free_cached_objects(
1494 struct super_block *sb,
1495 int nr_to_scan)
1496{
1497 xfs_reclaim_inodes_nr(XFS_M(sb), nr_to_scan);
1498}
1499
1494static const struct super_operations xfs_super_operations = { 1500static const struct super_operations xfs_super_operations = {
1495 .alloc_inode = xfs_fs_alloc_inode, 1501 .alloc_inode = xfs_fs_alloc_inode,
1496 .destroy_inode = xfs_fs_destroy_inode, 1502 .destroy_inode = xfs_fs_destroy_inode,
@@ -1504,6 +1510,8 @@ static const struct super_operations xfs_super_operations = {
1504 .statfs = xfs_fs_statfs, 1510 .statfs = xfs_fs_statfs,
1505 .remount_fs = xfs_fs_remount, 1511 .remount_fs = xfs_fs_remount,
1506 .show_options = xfs_fs_show_options, 1512 .show_options = xfs_fs_show_options,
1513 .nr_cached_objects = xfs_fs_nr_cached_objects,
1514 .free_cached_objects = xfs_fs_free_cached_objects,
1507}; 1515};
1508 1516
1509static struct file_system_type xfs_fs_type = { 1517static struct file_system_type xfs_fs_type = {
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index 8ecad5ff9f9b..9bd7e895a4e2 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -179,6 +179,8 @@ restart:
179 if (error == EFSCORRUPTED) 179 if (error == EFSCORRUPTED)
180 break; 180 break;
181 181
182 cond_resched();
183
182 } while (nr_found && !done); 184 } while (nr_found && !done);
183 185
184 if (skipped) { 186 if (skipped) {
@@ -986,6 +988,8 @@ restart:
986 988
987 *nr_to_scan -= XFS_LOOKUP_BATCH; 989 *nr_to_scan -= XFS_LOOKUP_BATCH;
988 990
991 cond_resched();
992
989 } while (nr_found && !done && *nr_to_scan > 0); 993 } while (nr_found && !done && *nr_to_scan > 0);
990 994
991 if (trylock && !done) 995 if (trylock && !done)
@@ -1003,7 +1007,7 @@ restart:
1003 * ensure that when we get more reclaimers than AGs we block rather 1007 * ensure that when we get more reclaimers than AGs we block rather
1004 * than spin trying to execute reclaim. 1008 * than spin trying to execute reclaim.
1005 */ 1009 */
1006 if (trylock && skipped && *nr_to_scan > 0) { 1010 if (skipped && (flags & SYNC_WAIT) && *nr_to_scan > 0) {
1007 trylock = 0; 1011 trylock = 0;
1008 goto restart; 1012 goto restart;
1009 } 1013 }
@@ -1021,44 +1025,38 @@ xfs_reclaim_inodes(
1021} 1025}
1022 1026
1023/* 1027/*
1024 * Inode cache shrinker. 1028 * Scan a certain number of inodes for reclaim.
1025 * 1029 *
1026 * When called we make sure that there is a background (fast) inode reclaim in 1030 * When called we make sure that there is a background (fast) inode reclaim in
1027 * progress, while we will throttle the speed of reclaim via doiing synchronous 1031 * progress, while we will throttle the speed of reclaim via doing synchronous
1028 * reclaim of inodes. That means if we come across dirty inodes, we wait for 1032 * reclaim of inodes. That means if we come across dirty inodes, we wait for
1029 * them to be cleaned, which we hope will not be very long due to the 1033 * them to be cleaned, which we hope will not be very long due to the
1030 * background walker having already kicked the IO off on those dirty inodes. 1034 * background walker having already kicked the IO off on those dirty inodes.
1031 */ 1035 */
1032static int 1036void
1033xfs_reclaim_inode_shrink( 1037xfs_reclaim_inodes_nr(
1034 struct shrinker *shrink, 1038 struct xfs_mount *mp,
1035 struct shrink_control *sc) 1039 int nr_to_scan)
1036{ 1040{
1037 struct xfs_mount *mp; 1041 /* kick background reclaimer and push the AIL */
1038 struct xfs_perag *pag; 1042 xfs_syncd_queue_reclaim(mp);
1039 xfs_agnumber_t ag; 1043 xfs_ail_push_all(mp->m_ail);
1040 int reclaimable;
1041 int nr_to_scan = sc->nr_to_scan;
1042 gfp_t gfp_mask = sc->gfp_mask;
1043
1044 mp = container_of(shrink, struct xfs_mount, m_inode_shrink);
1045 if (nr_to_scan) {
1046 /* kick background reclaimer and push the AIL */
1047 xfs_syncd_queue_reclaim(mp);
1048 xfs_ail_push_all(mp->m_ail);
1049 1044
1050 if (!(gfp_mask & __GFP_FS)) 1045 xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, &nr_to_scan);
1051 return -1; 1046}
1052 1047
1053 xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, 1048/*
1054 &nr_to_scan); 1049 * Return the number of reclaimable inodes in the filesystem for
1055 /* terminate if we don't exhaust the scan */ 1050 * the shrinker to determine how much to reclaim.
1056 if (nr_to_scan > 0) 1051 */
1057 return -1; 1052int
1058 } 1053xfs_reclaim_inodes_count(
1054 struct xfs_mount *mp)
1055{
1056 struct xfs_perag *pag;
1057 xfs_agnumber_t ag = 0;
1058 int reclaimable = 0;
1059 1059
1060 reclaimable = 0;
1061 ag = 0;
1062 while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) { 1060 while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) {
1063 ag = pag->pag_agno + 1; 1061 ag = pag->pag_agno + 1;
1064 reclaimable += pag->pag_ici_reclaimable; 1062 reclaimable += pag->pag_ici_reclaimable;
@@ -1067,18 +1065,3 @@ xfs_reclaim_inode_shrink(
1067 return reclaimable; 1065 return reclaimable;
1068} 1066}
1069 1067
1070void
1071xfs_inode_shrinker_register(
1072 struct xfs_mount *mp)
1073{
1074 mp->m_inode_shrink.shrink = xfs_reclaim_inode_shrink;
1075 mp->m_inode_shrink.seeks = DEFAULT_SEEKS;
1076 register_shrinker(&mp->m_inode_shrink);
1077}
1078
1079void
1080xfs_inode_shrinker_unregister(
1081 struct xfs_mount *mp)
1082{
1083 unregister_shrinker(&mp->m_inode_shrink);
1084}
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h
index e3a6ad27415f..2e1568597764 100644
--- a/fs/xfs/linux-2.6/xfs_sync.h
+++ b/fs/xfs/linux-2.6/xfs_sync.h
@@ -43,6 +43,8 @@ void xfs_quiesce_attr(struct xfs_mount *mp);
43void xfs_flush_inodes(struct xfs_inode *ip); 43void xfs_flush_inodes(struct xfs_inode *ip);
44 44
45int xfs_reclaim_inodes(struct xfs_mount *mp, int mode); 45int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
46int xfs_reclaim_inodes_count(struct xfs_mount *mp);
47void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
46 48
47void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); 49void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
48void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip); 50void __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,
54 int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags), 56 int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),
55 int flags); 57 int flags);
56 58
57void xfs_inode_shrinker_register(struct xfs_mount *mp);
58void xfs_inode_shrinker_unregister(struct xfs_mount *mp);
59
60#endif 59#endif