@@ -80,6 +80,7 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
if (sc->nr_to_scan) {
int dentries;
int inodes;
+ int fs_to_scan = 0;
/* proportion the scan between the caches */
dentries = (sc->nr_to_scan * sb->s_nr_dentry_unused) /
@@ -87,7 +88,7 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
inodes = (sc->nr_to_scan * sb->s_nr_inodes_unused) /
total_objects;
if (fs_objects)
- fs_objects = (sc->nr_to_scan * fs_objects) /
+ fs_to_scan = (sc->nr_to_scan * fs_objects) /
total_objects;
/*
* prune the dcache first as the icache is pinned by it, then
@@ -96,8 +97,23 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
prune_dcache_sb(sb, dentries);
prune_icache_sb(sb, inodes);
- if (fs_objects && sb->s_op->free_cached_objects) {
- sb->s_op->free_cached_objects(sb, fs_objects);
+ /*
+ * If as a result of pruning the icache, we released some
+ * of the fs_objects, give credit to the fact and
+ * reduce the number of fs objects that we should try
+ * to release.
+ */
+ if (fs_to_scan) {
+ int fs_objects_now = sb->s_op->nr_cached_objects(sb);
+
+ if (fs_objects_now < fs_objects)
+ fs_to_scan -= fs_objects - fs_objects_now;
+ if (fs_to_scan < 0)
+ fs_to_scan = 0;
+ }
+
+ if (fs_to_scan && sb->s_op->free_cached_objects) {
+ sb->s_op->free_cached_objects(sb, fs_to_scan);
fs_objects = sb->s_op->nr_cached_objects(sb);
}
total_objects = sb->s_nr_dentry_unused +