aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2010-07-19 18:07:02 -0400
committerDave Chinner <david@fromorbit.com>2010-07-19 18:07:02 -0400
commit70e60ce71516c3a9e882edb70a09f696a05961db (patch)
tree324a400f2d21d071f6c462edbb6efa789125f6f1 /fs/xfs
parent7f8275d0d660c146de6ee3017e1e2e594c49e820 (diff)
xfs: convert inode shrinker to per-filesystem contexts
Now the shrinker passes us a context, wire up a shrinker context per filesystem. This allows us to remove the global mount list and the locking problems that introduced. It also means that a shrinker call does not need to traverse clean filesystems before finding a filesystem with reclaimable inodes. This significantly reduces scanning overhead when lots of filesystems are present. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c62
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.h2
-rw-r--r--fs/xfs/xfs_mount.h2
4 files changed, 15 insertions, 53 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index f2d1718c916..80938c736c2 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -1883,7 +1883,6 @@ init_xfs_fs(void)
1883 goto out_cleanup_procfs; 1883 goto out_cleanup_procfs;
1884 1884
1885 vfs_initquota(); 1885 vfs_initquota();
1886 xfs_inode_shrinker_init();
1887 1886
1888 error = register_filesystem(&xfs_fs_type); 1887 error = register_filesystem(&xfs_fs_type);
1889 if (error) 1888 if (error)
@@ -1911,7 +1910,6 @@ exit_xfs_fs(void)
1911{ 1910{
1912 vfs_exitquota(); 1911 vfs_exitquota();
1913 unregister_filesystem(&xfs_fs_type); 1912 unregister_filesystem(&xfs_fs_type);
1914 xfs_inode_shrinker_destroy();
1915 xfs_sysctl_unregister(); 1913 xfs_sysctl_unregister();
1916 xfs_cleanup_procfs(); 1914 xfs_cleanup_procfs();
1917 xfs_buf_terminate(); 1915 xfs_buf_terminate();
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index be375827af9..f433819611c 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -828,14 +828,7 @@ xfs_reclaim_inodes(
828 828
829/* 829/*
830 * Shrinker infrastructure. 830 * Shrinker infrastructure.
831 *
832 * This is all far more complex than it needs to be. It adds a global list of
833 * mounts because the shrinkers can only call a global context. We need to make
834 * the shrinkers pass a context to avoid the need for global state.
835 */ 831 */
836static LIST_HEAD(xfs_mount_list);
837static struct rw_semaphore xfs_mount_list_lock;
838
839static int 832static int
840xfs_reclaim_inode_shrink( 833xfs_reclaim_inode_shrink(
841 struct shrinker *shrink, 834 struct shrinker *shrink,
@@ -847,65 +840,38 @@ xfs_reclaim_inode_shrink(
847 xfs_agnumber_t ag; 840 xfs_agnumber_t ag;
848 int reclaimable = 0; 841 int reclaimable = 0;
849 842
843 mp = container_of(shrink, struct xfs_mount, m_inode_shrink);
850 if (nr_to_scan) { 844 if (nr_to_scan) {
851 if (!(gfp_mask & __GFP_FS)) 845 if (!(gfp_mask & __GFP_FS))
852 return -1; 846 return -1;
853 847
854 down_read(&xfs_mount_list_lock); 848 xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0,
855 list_for_each_entry(mp, &xfs_mount_list, m_mplist) {
856 xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0,
857 XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan); 849 XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan);
858 if (nr_to_scan <= 0) 850 /* if we don't exhaust the scan, don't bother coming back */
859 break; 851 if (nr_to_scan > 0)
860 } 852 return -1;
861 up_read(&xfs_mount_list_lock); 853 }
862 }
863 854
864 down_read(&xfs_mount_list_lock); 855 for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) {
865 list_for_each_entry(mp, &xfs_mount_list, m_mplist) { 856 pag = xfs_perag_get(mp, ag);
866 for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { 857 reclaimable += pag->pag_ici_reclaimable;
867 pag = xfs_perag_get(mp, ag); 858 xfs_perag_put(pag);
868 reclaimable += pag->pag_ici_reclaimable;
869 xfs_perag_put(pag);
870 }
871 } 859 }
872 up_read(&xfs_mount_list_lock);
873 return reclaimable; 860 return reclaimable;
874} 861}
875 862
876static struct shrinker xfs_inode_shrinker = {
877 .shrink = xfs_reclaim_inode_shrink,
878 .seeks = DEFAULT_SEEKS,
879};
880
881void __init
882xfs_inode_shrinker_init(void)
883{
884 init_rwsem(&xfs_mount_list_lock);
885 register_shrinker(&xfs_inode_shrinker);
886}
887
888void
889xfs_inode_shrinker_destroy(void)
890{
891 ASSERT(list_empty(&xfs_mount_list));
892 unregister_shrinker(&xfs_inode_shrinker);
893}
894
895void 863void
896xfs_inode_shrinker_register( 864xfs_inode_shrinker_register(
897 struct xfs_mount *mp) 865 struct xfs_mount *mp)
898{ 866{
899 down_write(&xfs_mount_list_lock); 867 mp->m_inode_shrink.shrink = xfs_reclaim_inode_shrink;
900 list_add_tail(&mp->m_mplist, &xfs_mount_list); 868 mp->m_inode_shrink.seeks = DEFAULT_SEEKS;
901 up_write(&xfs_mount_list_lock); 869 register_shrinker(&mp->m_inode_shrink);
902} 870}
903 871
904void 872void
905xfs_inode_shrinker_unregister( 873xfs_inode_shrinker_unregister(
906 struct xfs_mount *mp) 874 struct xfs_mount *mp)
907{ 875{
908 down_write(&xfs_mount_list_lock); 876 unregister_shrinker(&mp->m_inode_shrink);
909 list_del(&mp->m_mplist);
910 up_write(&xfs_mount_list_lock);
911} 877}
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h
index cdcbaaca988..e28139aaa4a 100644
--- a/fs/xfs/linux-2.6/xfs_sync.h
+++ b/fs/xfs/linux-2.6/xfs_sync.h
@@ -55,8 +55,6 @@ int xfs_inode_ag_iterator(struct xfs_mount *mp,
55 int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags), 55 int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),
56 int flags, int tag, int write_lock, int *nr_to_scan); 56 int flags, int tag, int write_lock, int *nr_to_scan);
57 57
58void xfs_inode_shrinker_init(void);
59void xfs_inode_shrinker_destroy(void);
60void xfs_inode_shrinker_register(struct xfs_mount *mp); 58void xfs_inode_shrinker_register(struct xfs_mount *mp);
61void xfs_inode_shrinker_unregister(struct xfs_mount *mp); 59void xfs_inode_shrinker_unregister(struct xfs_mount *mp);
62 60
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 1d2c7eed4ed..5761087ee8e 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -259,7 +259,7 @@ typedef struct xfs_mount {
259 wait_queue_head_t m_wait_single_sync_task; 259 wait_queue_head_t m_wait_single_sync_task;
260 __int64_t m_update_flags; /* sb flags we need to update 260 __int64_t m_update_flags; /* sb flags we need to update
261 on the next remount,rw */ 261 on the next remount,rw */
262 struct list_head m_mplist; /* inode shrinker mount list */ 262 struct shrinker m_inode_shrink; /* inode reclaim shrinker */
263} xfs_mount_t; 263} xfs_mount_t;
264 264
265/* 265/*