Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Dave Chinner and committed by
Al Viro
8daaa831 8ab47664

+46 -56
+17 -9
fs/xfs/linux-2.6/xfs_super.c
··· 1025 1025 { 1026 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 1028 xfs_syncd_stop(mp); 1034 1029 1035 1030 /* ··· 1411 1416 if (error) 1412 1417 goto out_filestream_unmount; 1413 1418 1414 - xfs_inode_shrinker_register(mp); 1415 - 1416 1419 error = xfs_mountfs(mp); 1417 1420 if (error) 1418 1421 goto out_syncd_stop; ··· 1433 1440 return 0; 1434 1441 1435 1442 out_syncd_stop: 1436 - xfs_inode_shrinker_unregister(mp); 1437 1443 xfs_syncd_stop(mp); 1438 1444 out_filestream_unmount: 1439 1445 xfs_filestream_unmount(mp); ··· 1457 1465 } 1458 1466 1459 1467 fail_unmount: 1460 - xfs_inode_shrinker_unregister(mp); 1461 1468 xfs_syncd_stop(mp); 1462 1469 1463 1470 /* ··· 1482 1491 return mount_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super); 1483 1492 } 1484 1493 1494 + static int 1495 + xfs_fs_nr_cached_objects( 1496 + struct super_block *sb) 1497 + { 1498 + return xfs_reclaim_inodes_count(XFS_M(sb)); 1499 + } 1500 + 1501 + static void 1502 + xfs_fs_free_cached_objects( 1503 + struct super_block *sb, 1504 + int nr_to_scan) 1505 + { 1506 + xfs_reclaim_inodes_nr(XFS_M(sb), nr_to_scan); 1507 + } 1508 + 1485 1509 static const struct super_operations xfs_super_operations = { 1486 1510 .alloc_inode = xfs_fs_alloc_inode, 1487 1511 .destroy_inode = xfs_fs_destroy_inode, ··· 1510 1504 .statfs = xfs_fs_statfs, 1511 1505 .remount_fs = xfs_fs_remount, 1512 1506 .show_options = xfs_fs_show_options, 1507 + .nr_cached_objects = xfs_fs_nr_cached_objects, 1508 + .free_cached_objects = xfs_fs_free_cached_objects, 1513 1509 }; 1514 1510 1515 1511 static struct file_system_type xfs_fs_type = {
+27 -44
fs/xfs/linux-2.6/xfs_sync.c
··· 179 179 if (error == EFSCORRUPTED) 180 180 break; 181 181 182 + cond_resched(); 183 + 182 184 } while (nr_found && !done); 183 185 184 186 if (skipped) { ··· 988 986 989 987 *nr_to_scan -= XFS_LOOKUP_BATCH; 990 988 989 + cond_resched(); 990 + 991 991 } while (nr_found && !done && *nr_to_scan > 0); 992 992 993 993 if (trylock && !done) ··· 1007 1003 * ensure that when we get more reclaimers than AGs we block rather 1008 1004 * than spin trying to execute reclaim. 1009 1005 */ 1010 - if (trylock && skipped && *nr_to_scan > 0) { 1006 + if (skipped && (flags & SYNC_WAIT) && *nr_to_scan > 0) { 1011 1007 trylock = 0; 1012 1008 goto restart; 1013 1009 } ··· 1025 1021 } 1026 1022 1027 1023 /* 1028 - * Inode cache shrinker. 1024 + * Scan a certain number of inodes for reclaim. 1029 1025 * 1030 1026 * When called we make sure that there is a background (fast) inode reclaim in 1031 - * progress, while we will throttle the speed of reclaim via doiing synchronous 1027 + * progress, while we will throttle the speed of reclaim via doing synchronous 1032 1028 * reclaim of inodes. That means if we come across dirty inodes, we wait for 1033 1029 * them to be cleaned, which we hope will not be very long due to the 1034 1030 * background walker having already kicked the IO off on those dirty inodes. 1035 1031 */ 1036 - static int 1037 - xfs_reclaim_inode_shrink( 1038 - struct shrinker *shrink, 1039 - struct shrink_control *sc) 1032 + void 1033 + xfs_reclaim_inodes_nr( 1034 + struct xfs_mount *mp, 1035 + int nr_to_scan) 1040 1036 { 1041 - struct xfs_mount *mp; 1042 - struct xfs_perag *pag; 1043 - xfs_agnumber_t ag; 1044 - int reclaimable; 1045 - int nr_to_scan = sc->nr_to_scan; 1046 - gfp_t gfp_mask = sc->gfp_mask; 1037 + /* kick background reclaimer and push the AIL */ 1038 + xfs_syncd_queue_reclaim(mp); 1039 + xfs_ail_push_all(mp->m_ail); 1047 1040 1048 - mp = container_of(shrink, struct xfs_mount, m_inode_shrink); 1049 - if (nr_to_scan) { 1050 - /* kick background reclaimer and push the AIL */ 1051 - xfs_syncd_queue_reclaim(mp); 1052 - xfs_ail_push_all(mp->m_ail); 1041 + xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, &nr_to_scan); 1042 + } 1053 1043 1054 - if (!(gfp_mask & __GFP_FS)) 1055 - return -1; 1044 + /* 1045 + * Return the number of reclaimable inodes in the filesystem for 1046 + * the shrinker to determine how much to reclaim. 1047 + */ 1048 + int 1049 + xfs_reclaim_inodes_count( 1050 + struct xfs_mount *mp) 1051 + { 1052 + struct xfs_perag *pag; 1053 + xfs_agnumber_t ag = 0; 1054 + int reclaimable = 0; 1056 1055 1057 - xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, 1058 - &nr_to_scan); 1059 - /* terminate if we don't exhaust the scan */ 1060 - if (nr_to_scan > 0) 1061 - return -1; 1062 - } 1063 - 1064 - reclaimable = 0; 1065 - ag = 0; 1066 1056 while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) { 1067 1057 ag = pag->pag_agno + 1; 1068 1058 reclaimable += pag->pag_ici_reclaimable; ··· 1065 1067 return reclaimable; 1066 1068 } 1067 1069 1068 - void 1069 - xfs_inode_shrinker_register( 1070 - struct xfs_mount *mp) 1071 - { 1072 - mp->m_inode_shrink.shrink = xfs_reclaim_inode_shrink; 1073 - mp->m_inode_shrink.seeks = DEFAULT_SEEKS; 1074 - register_shrinker(&mp->m_inode_shrink); 1075 - } 1076 - 1077 - void 1078 - xfs_inode_shrinker_unregister( 1079 - struct xfs_mount *mp) 1080 - { 1081 - unregister_shrinker(&mp->m_inode_shrink); 1082 - }
+2 -3
fs/xfs/linux-2.6/xfs_sync.h
··· 43 43 void xfs_flush_inodes(struct xfs_inode *ip); 44 44 45 45 int xfs_reclaim_inodes(struct xfs_mount *mp, int mode); 46 + int xfs_reclaim_inodes_count(struct xfs_mount *mp); 47 + void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan); 46 48 47 49 void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); 48 50 void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip); ··· 55 53 int xfs_inode_ag_iterator(struct xfs_mount *mp, 56 54 int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags), 57 55 int flags); 58 - 59 - void xfs_inode_shrinker_register(struct xfs_mount *mp); 60 - void xfs_inode_shrinker_unregister(struct xfs_mount *mp); 61 56 62 57 #endif