aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2013-08-27 20:17:57 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-09-10 18:56:30 -0400
commit0a234c6dcb79a270803f5c9773ed650b78730962 (patch)
tree8f93bd04d5c01a32dc78617c04dc770dc4b86883 /fs
parent24f7c6b981fb70084757382da464ea85d72af300 (diff)
shrinker: convert superblock shrinkers to new API
Convert superblock shrinker to use the new count/scan API, and propagate the API changes through to the filesystem callouts. The filesystem callouts already use a count/scan API, so it's just changing counters to longs to match the VM API. This requires the dentry and inode shrinker callouts to be converted to the count/scan API. This is mainly a mechanical change. [glommer@openvz.org: use mult_frac for fractional proportions, build fixes] Signed-off-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Glauber Costa <glommer@openvz.org> Acked-by: Mel Gorman <mgorman@suse.de> Cc: "Theodore Ts'o" <tytso@mit.edu> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Cc: Arve Hjønnevåg <arve@android.com> Cc: Carlos Maiolino <cmaiolino@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Chuck Lever <chuck.lever@oracle.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: David Rientjes <rientjes@google.com> Cc: Gleb Natapov <gleb@redhat.com> Cc: Greg Thelen <gthelen@google.com> Cc: J. Bruce Fields <bfields@redhat.com> Cc: Jan Kara <jack@suse.cz> Cc: Jerome Glisse <jglisse@redhat.com> Cc: John Stultz <john.stultz@linaro.org> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Kent Overstreet <koverstreet@google.com> Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Marcelo Tosatti <mtosatti@redhat.com> Cc: Mel Gorman <mgorman@suse.de> Cc: Steven Whitehouse <swhiteho@redhat.com> Cc: Thomas Hellstrom <thellstrom@vmware.com> Cc: Trond Myklebust <Trond.Myklebust@netapp.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/dcache.c7
-rw-r--r--fs/inode.c7
-rw-r--r--fs/internal.h2
-rw-r--r--fs/super.c80
-rw-r--r--fs/xfs/xfs_icache.c4
-rw-r--r--fs/xfs/xfs_icache.h2
-rw-r--r--fs/xfs/xfs_super.c8
7 files changed, 68 insertions, 42 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 509b49410943..77d466b13fef 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -913,11 +913,12 @@ static void shrink_dentry_list(struct list_head *list)
913 * This function may fail to free any resources if all the dentries are in 913 * This function may fail to free any resources if all the dentries are in
914 * use. 914 * use.
915 */ 915 */
916void prune_dcache_sb(struct super_block *sb, int count) 916long prune_dcache_sb(struct super_block *sb, unsigned long nr_to_scan)
917{ 917{
918 struct dentry *dentry; 918 struct dentry *dentry;
919 LIST_HEAD(referenced); 919 LIST_HEAD(referenced);
920 LIST_HEAD(tmp); 920 LIST_HEAD(tmp);
921 long freed = 0;
921 922
922relock: 923relock:
923 spin_lock(&sb->s_dentry_lru_lock); 924 spin_lock(&sb->s_dentry_lru_lock);
@@ -942,7 +943,8 @@ relock:
942 this_cpu_dec(nr_dentry_unused); 943 this_cpu_dec(nr_dentry_unused);
943 sb->s_nr_dentry_unused--; 944 sb->s_nr_dentry_unused--;
944 spin_unlock(&dentry->d_lock); 945 spin_unlock(&dentry->d_lock);
945 if (!--count) 946 freed++;
947 if (!--nr_to_scan)
946 break; 948 break;
947 } 949 }
948 cond_resched_lock(&sb->s_dentry_lru_lock); 950 cond_resched_lock(&sb->s_dentry_lru_lock);
@@ -952,6 +954,7 @@ relock:
952 spin_unlock(&sb->s_dentry_lru_lock); 954 spin_unlock(&sb->s_dentry_lru_lock);
953 955
954 shrink_dentry_list(&tmp); 956 shrink_dentry_list(&tmp);
957 return freed;
955} 958}
956 959
957/* 960/*
diff --git a/fs/inode.c b/fs/inode.c
index 2a3c37ea823d..021d64768a55 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -706,10 +706,11 @@ static int can_unuse(struct inode *inode)
706 * LRU does not have strict ordering. Hence we don't want to reclaim inodes 706 * LRU does not have strict ordering. Hence we don't want to reclaim inodes
707 * with this flag set because they are the inodes that are out of order. 707 * with this flag set because they are the inodes that are out of order.
708 */ 708 */
709void prune_icache_sb(struct super_block *sb, int nr_to_scan) 709long prune_icache_sb(struct super_block *sb, unsigned long nr_to_scan)
710{ 710{
711 LIST_HEAD(freeable); 711 LIST_HEAD(freeable);
712 int nr_scanned; 712 long nr_scanned;
713 long freed = 0;
713 unsigned long reap = 0; 714 unsigned long reap = 0;
714 715
715 spin_lock(&sb->s_inode_lru_lock); 716 spin_lock(&sb->s_inode_lru_lock);
@@ -779,6 +780,7 @@ void prune_icache_sb(struct super_block *sb, int nr_to_scan)
779 list_move(&inode->i_lru, &freeable); 780 list_move(&inode->i_lru, &freeable);
780 sb->s_nr_inodes_unused--; 781 sb->s_nr_inodes_unused--;
781 this_cpu_dec(nr_unused); 782 this_cpu_dec(nr_unused);
783 freed++;
782 } 784 }
783 if (current_is_kswapd()) 785 if (current_is_kswapd())
784 __count_vm_events(KSWAPD_INODESTEAL, reap); 786 __count_vm_events(KSWAPD_INODESTEAL, reap);
@@ -789,6 +791,7 @@ void prune_icache_sb(struct super_block *sb, int nr_to_scan)
789 current->reclaim_state->reclaimed_slab += reap; 791 current->reclaim_state->reclaimed_slab += reap;
790 792
791 dispose_list(&freeable); 793 dispose_list(&freeable);
794 return freed;
792} 795}
793 796
794static void __wait_on_freeing_inode(struct inode *inode); 797static void __wait_on_freeing_inode(struct inode *inode);
diff --git a/fs/internal.h b/fs/internal.h
index b6495659d6e8..cb83a3417a68 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -114,6 +114,7 @@ extern int open_check_o_direct(struct file *f);
114 * inode.c 114 * inode.c
115 */ 115 */
116extern spinlock_t inode_sb_list_lock; 116extern spinlock_t inode_sb_list_lock;
117extern long prune_icache_sb(struct super_block *sb, unsigned long nr_to_scan);
117extern void inode_add_lru(struct inode *inode); 118extern void inode_add_lru(struct inode *inode);
118 119
119/* 120/*
@@ -130,6 +131,7 @@ extern int invalidate_inodes(struct super_block *, bool);
130 */ 131 */
131extern struct dentry *__d_alloc(struct super_block *, const struct qstr *); 132extern struct dentry *__d_alloc(struct super_block *, const struct qstr *);
132extern int d_set_mounted(struct dentry *dentry); 133extern int d_set_mounted(struct dentry *dentry);
134extern long prune_dcache_sb(struct super_block *sb, unsigned long nr_to_scan);
133 135
134/* 136/*
135 * read_write.c 137 * read_write.c
diff --git a/fs/super.c b/fs/super.c
index 3c5318694ccd..8aa2660642b9 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -53,11 +53,15 @@ static char *sb_writers_name[SB_FREEZE_LEVELS] = {
53 * shrinker path and that leads to deadlock on the shrinker_rwsem. Hence we 53 * shrinker path and that leads to deadlock on the shrinker_rwsem. Hence we
54 * take a passive reference to the superblock to avoid this from occurring. 54 * take a passive reference to the superblock to avoid this from occurring.
55 */ 55 */
56static int prune_super(struct shrinker *shrink, struct shrink_control *sc) 56static unsigned long super_cache_scan(struct shrinker *shrink,
57 struct shrink_control *sc)
57{ 58{
58 struct super_block *sb; 59 struct super_block *sb;
59 int fs_objects = 0; 60 long fs_objects = 0;
60 int total_objects; 61 long total_objects;
62 long freed = 0;
63 long dentries;
64 long inodes;
61 65
62 sb = container_of(shrink, struct super_block, s_shrink); 66 sb = container_of(shrink, struct super_block, s_shrink);
63 67
@@ -65,11 +69,11 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
65 * Deadlock avoidance. We may hold various FS locks, and we don't want 69 * Deadlock avoidance. We may hold various FS locks, and we don't want
66 * to recurse into the FS that called us in clear_inode() and friends.. 70 * to recurse into the FS that called us in clear_inode() and friends..
67 */ 71 */
68 if (sc->nr_to_scan && !(sc->gfp_mask & __GFP_FS)) 72 if (!(sc->gfp_mask & __GFP_FS))
69 return -1; 73 return SHRINK_STOP;
70 74
71 if (!grab_super_passive(sb)) 75 if (!grab_super_passive(sb))
72 return -1; 76 return SHRINK_STOP;
73 77
74 if (sb->s_op->nr_cached_objects) 78 if (sb->s_op->nr_cached_objects)
75 fs_objects = sb->s_op->nr_cached_objects(sb); 79 fs_objects = sb->s_op->nr_cached_objects(sb);
@@ -77,33 +81,46 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
77 total_objects = sb->s_nr_dentry_unused + 81 total_objects = sb->s_nr_dentry_unused +
78 sb->s_nr_inodes_unused + fs_objects + 1; 82 sb->s_nr_inodes_unused + fs_objects + 1;
79 83
80 if (sc->nr_to_scan) { 84 /* proportion the scan between the caches */
81 int dentries; 85 dentries = mult_frac(sc->nr_to_scan, sb->s_nr_dentry_unused,
82 int inodes; 86 total_objects);
83 87 inodes = mult_frac(sc->nr_to_scan, sb->s_nr_inodes_unused,
84 /* proportion the scan between the caches */ 88 total_objects);
85 dentries = mult_frac(sc->nr_to_scan, sb->s_nr_dentry_unused,
86 total_objects);
87 inodes = mult_frac(sc->nr_to_scan, sb->s_nr_inodes_unused,
88 total_objects);
89 if (fs_objects)
90 fs_objects = mult_frac(sc->nr_to_scan, fs_objects,
91 total_objects);
92 /*
93 * prune the dcache first as the icache is pinned by it, then
94 * prune the icache, followed by the filesystem specific caches
95 */
96 prune_dcache_sb(sb, dentries);
97 prune_icache_sb(sb, inodes);
98 89
99 if (fs_objects && sb->s_op->free_cached_objects) { 90 /*
100 sb->s_op->free_cached_objects(sb, fs_objects); 91 * prune the dcache first as the icache is pinned by it, then
101 fs_objects = sb->s_op->nr_cached_objects(sb); 92 * prune the icache, followed by the filesystem specific caches
102 } 93 */
103 total_objects = sb->s_nr_dentry_unused + 94 freed = prune_dcache_sb(sb, dentries);
104 sb->s_nr_inodes_unused + fs_objects; 95 freed += prune_icache_sb(sb, inodes);
96
97 if (fs_objects) {
98 fs_objects = mult_frac(sc->nr_to_scan, fs_objects,
99 total_objects);
100 freed += sb->s_op->free_cached_objects(sb, fs_objects);
105 } 101 }
106 102
103 drop_super(sb);
104 return freed;
105}
106
107static unsigned long super_cache_count(struct shrinker *shrink,
108 struct shrink_control *sc)
109{
110 struct super_block *sb;
111 long total_objects = 0;
112
113 sb = container_of(shrink, struct super_block, s_shrink);
114
115 if (!grab_super_passive(sb))
116 return 0;
117
118 if (sb->s_op && sb->s_op->nr_cached_objects)
119 total_objects = sb->s_op->nr_cached_objects(sb);
120
121 total_objects += sb->s_nr_dentry_unused;
122 total_objects += sb->s_nr_inodes_unused;
123
107 total_objects = vfs_pressure_ratio(total_objects); 124 total_objects = vfs_pressure_ratio(total_objects);
108 drop_super(sb); 125 drop_super(sb);
109 return total_objects; 126 return total_objects;
@@ -211,7 +228,8 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags)
211 s->cleancache_poolid = -1; 228 s->cleancache_poolid = -1;
212 229
213 s->s_shrink.seeks = DEFAULT_SEEKS; 230 s->s_shrink.seeks = DEFAULT_SEEKS;
214 s->s_shrink.shrink = prune_super; 231 s->s_shrink.scan_objects = super_cache_scan;
232 s->s_shrink.count_objects = super_cache_count;
215 s->s_shrink.batch = 1024; 233 s->s_shrink.batch = 1024;
216 } 234 }
217out: 235out:
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 16219b9c6790..73b62a24ceac 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -1167,7 +1167,7 @@ xfs_reclaim_inodes(
1167 * them to be cleaned, which we hope will not be very long due to the 1167 * them to be cleaned, which we hope will not be very long due to the
1168 * background walker having already kicked the IO off on those dirty inodes. 1168 * background walker having already kicked the IO off on those dirty inodes.
1169 */ 1169 */
1170void 1170long
1171xfs_reclaim_inodes_nr( 1171xfs_reclaim_inodes_nr(
1172 struct xfs_mount *mp, 1172 struct xfs_mount *mp,
1173 int nr_to_scan) 1173 int nr_to_scan)
@@ -1176,7 +1176,7 @@ xfs_reclaim_inodes_nr(
1176 xfs_reclaim_work_queue(mp); 1176 xfs_reclaim_work_queue(mp);
1177 xfs_ail_push_all(mp->m_ail); 1177 xfs_ail_push_all(mp->m_ail);
1178 1178
1179 xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, &nr_to_scan); 1179 return xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, &nr_to_scan);
1180} 1180}
1181 1181
1182/* 1182/*
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index 8a89f7d791bd..456f0144e1b6 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -46,7 +46,7 @@ void xfs_reclaim_worker(struct work_struct *work);
46 46
47int xfs_reclaim_inodes(struct xfs_mount *mp, int mode); 47int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
48int xfs_reclaim_inodes_count(struct xfs_mount *mp); 48int xfs_reclaim_inodes_count(struct xfs_mount *mp);
49void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan); 49long xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
50 50
51void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); 51void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
52 52
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 979a77d4b87d..71d7aaebb912 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1535,19 +1535,19 @@ xfs_fs_mount(
1535 return mount_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super); 1535 return mount_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super);
1536} 1536}
1537 1537
1538static int 1538static long
1539xfs_fs_nr_cached_objects( 1539xfs_fs_nr_cached_objects(
1540 struct super_block *sb) 1540 struct super_block *sb)
1541{ 1541{
1542 return xfs_reclaim_inodes_count(XFS_M(sb)); 1542 return xfs_reclaim_inodes_count(XFS_M(sb));
1543} 1543}
1544 1544
1545static void 1545static long
1546xfs_fs_free_cached_objects( 1546xfs_fs_free_cached_objects(
1547 struct super_block *sb, 1547 struct super_block *sb,
1548 int nr_to_scan) 1548 long nr_to_scan)
1549{ 1549{
1550 xfs_reclaim_inodes_nr(XFS_M(sb), nr_to_scan); 1550 return xfs_reclaim_inodes_nr(XFS_M(sb), nr_to_scan);
1551} 1551}
1552 1552
1553static const struct super_operations xfs_super_operations = { 1553static const struct super_operations xfs_super_operations = {