super: fix calculation of shrinkable objects for small numbers
authorGlauber Costa <glommer@openvz.org>
Wed, 28 Aug 2013 00:17:53 +0000 (10:17 +1000)
committerAl Viro <viro@zeniv.linux.org.uk>
Tue, 10 Sep 2013 22:56:29 +0000 (18:56 -0400)
The sysctl knob sysctl_vfs_cache_pressure is used to determine which
percentage of the shrinkable objects in our cache we should actively try
to shrink.

It works great in situations in which we have many objects (at least more
than 100), because the aproximation errors will be negligible.  But if
this is not the case, specially when total_objects < 100, we may end up
concluding that we have no objects at all (total / 100 = 0, if total <
100).

This is certainly not the biggest killer in the world, but may matter in
very low kernel memory situations.

Signed-off-by: Glauber Costa <glommer@openvz.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Acked-by: Mel Gorman <mgorman@suse.de>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
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>
fs/gfs2/glock.c
fs/gfs2/quota.c
fs/mbcache.c
fs/nfs/dir.c
fs/quota/dquot.c
fs/super.c
fs/xfs/xfs_qm.c
include/linux/dcache.h

index 722329cac98fc9afb1f323ba8cf6a6306068457c..b782bb56085da3cc974ef2702871f408f984ad50 100644 (file)
@@ -1462,7 +1462,7 @@ static int gfs2_shrink_glock_memory(struct shrinker *shrink,
                gfs2_scan_glock_lru(sc->nr_to_scan);
        }
 
-       return (atomic_read(&lru_count) / 100) * sysctl_vfs_cache_pressure;
+       return vfs_pressure_ratio(atomic_read(&lru_count));
 }
 
 static struct shrinker glock_shrinker = {
index 3768c2f40e43350f3586769e9b40974ac9138a74..d550a5d6a05f263187842ea0aa6f4e2a4d70fa0a 100644 (file)
@@ -114,7 +114,7 @@ int gfs2_shrink_qd_memory(struct shrinker *shrink, struct shrink_control *sc)
        spin_unlock(&qd_lru_lock);
 
 out:
-       return (atomic_read(&qd_lru_count) * sysctl_vfs_cache_pressure) / 100;
+       return vfs_pressure_ratio(atomic_read(&qd_lru_count));
 }
 
 static u64 qd2index(struct gfs2_quota_data *qd)
index 8c32ef3ba88e7ac25a197866a38c4590836f12be..5eb04767cb29c0cd7c9be618a2aa29d595995671 100644 (file)
@@ -189,7 +189,7 @@ mb_cache_shrink_fn(struct shrinker *shrink, struct shrink_control *sc)
        list_for_each_entry_safe(entry, tmp, &free_list, e_lru_list) {
                __mb_cache_entry_forget(entry, gfp_mask);
        }
-       return (count / 100) * sysctl_vfs_cache_pressure;
+       return vfs_pressure_ratio(count);
 }
 
 
index e79bc6ce828e79b8cd3f4f6795de20f2c3ceb675..813ef257154582c1776473eb8c6ad01df05da30d 100644 (file)
@@ -2046,7 +2046,7 @@ remove_lru_entry:
        }
        spin_unlock(&nfs_access_lru_lock);
        nfs_access_free_list(&head);
-       return (atomic_long_read(&nfs_access_nr_entries) / 100) * sysctl_vfs_cache_pressure;
+       return vfs_pressure_ratio(atomic_long_read(&nfs_access_nr_entries));
 }
 
 static void __nfs_access_zap_cache(struct nfs_inode *nfsi, struct list_head *head)
index 9a702e1935383d1e8deda7678e529426262a8636..13eee847605cad84e096d1d905c92f727b6a67f9 100644 (file)
@@ -719,9 +719,8 @@ static int shrink_dqcache_memory(struct shrinker *shrink,
                prune_dqcache(nr);
                spin_unlock(&dq_list_lock);
        }
-       return ((unsigned)
-               percpu_counter_read_positive(&dqstats.counter[DQST_FREE_DQUOTS])
-               /100) * sysctl_vfs_cache_pressure;
+       return vfs_pressure_ratio(
+       percpu_counter_read_positive(&dqstats.counter[DQST_FREE_DQUOTS]));
 }
 
 static struct shrinker dqcache_shrinker = {
index f6961ea84c56c7dfa3963626d041d0004d509cbf..63b6863bac7b0bf2e7736c7d05f96df02501d849 100644 (file)
@@ -82,13 +82,13 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
                int     inodes;
 
                /* proportion the scan between the caches */
-               dentries = (sc->nr_to_scan * sb->s_nr_dentry_unused) /
-                                                       total_objects;
-               inodes = (sc->nr_to_scan * sb->s_nr_inodes_unused) /
-                                                       total_objects;
+               dentries = mult_frac(sc->nr_to_scan, sb->s_nr_dentry_unused,
+                                                       total_objects);
+               inodes = mult_frac(sc->nr_to_scan, sb->s_nr_inodes_unused,
+                                                       total_objects);
                if (fs_objects)
-                       fs_objects = (sc->nr_to_scan * fs_objects) /
-                                                       total_objects;
+                       fs_objects = mult_frac(sc->nr_to_scan, fs_objects,
+                                                       total_objects);
                /*
                 * prune the dcache first as the icache is pinned by it, then
                 * prune the icache, followed by the filesystem specific caches
@@ -104,7 +104,7 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
                                sb->s_nr_inodes_unused + fs_objects;
        }
 
-       total_objects = (total_objects / 100) * sysctl_vfs_cache_pressure;
+       total_objects = vfs_pressure_ratio(total_objects);
        drop_super(sb);
        return total_objects;
 }
index 6218a0aeeeea88449c4a1e29e54c0297ae8de6fb..956da2e1c7af6dd4ea4083c44fe3559a79cb077b 100644 (file)
@@ -1722,7 +1722,7 @@ xfs_qm_shake(
        }
 
 out:
-       return (qi->qi_lru_count / 100) * sysctl_vfs_cache_pressure;
+       return vfs_pressure_ratio(qi->qi_lru_count);
 }
 
 /*
index 844a1ef387e46da67ba4575b1603c1a7a17ac95a..59066e0b4ff134fde5679d582246e942df9f86fc 100644 (file)
@@ -395,4 +395,8 @@ static inline bool d_mountpoint(const struct dentry *dentry)
 
 extern int sysctl_vfs_cache_pressure;
 
+static inline unsigned long vfs_pressure_ratio(unsigned long val)
+{
+       return mult_frac(val, sysctl_vfs_cache_pressure, 100);
+}
 #endif /* __LINUX_DCACHE_H */