Commit 1495f230 authored by Ying Han's avatar Ying Han Committed by Linus Torvalds

vmscan: change shrinker API by passing shrink_control struct

Change each shrinker's API by consolidating the existing parameters into
shrink_control struct.  This will simplify any further features added w/o
touching each file of shrinker.

[akpm@linux-foundation.org: fix build]
[akpm@linux-foundation.org: fix warning]
[kosaki.motohiro@jp.fujitsu.com: fix up new shrinker API]
[akpm@linux-foundation.org: fix xfs warning]
[akpm@linux-foundation.org: update gfs2]
Signed-off-by: default avatarYing Han <yinghan@google.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Minchan Kim <minchan.kim@gmail.com>
Acked-by: default avatarPavel Emelyanov <xemul@openvz.org>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Mel Gorman <mel@csn.ul.ie>
Acked-by: default avatarRik van Riel <riel@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Hugh Dickins <hughd@google.com>
Cc: Dave Hansen <dave@linux.vnet.ibm.com>
Cc: Steven Whitehouse <swhiteho@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent a09ed5e0
...@@ -3545,10 +3545,11 @@ static int kvm_mmu_remove_some_alloc_mmu_pages(struct kvm *kvm, ...@@ -3545,10 +3545,11 @@ static int kvm_mmu_remove_some_alloc_mmu_pages(struct kvm *kvm,
return kvm_mmu_prepare_zap_page(kvm, page, invalid_list); return kvm_mmu_prepare_zap_page(kvm, page, invalid_list);
} }
static int mmu_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) static int mmu_shrink(struct shrinker *shrink, struct shrink_control *sc)
{ {
struct kvm *kvm; struct kvm *kvm;
struct kvm *kvm_freed = NULL; struct kvm *kvm_freed = NULL;
int nr_to_scan = sc->nr_to_scan;
if (nr_to_scan == 0) if (nr_to_scan == 0)
goto out; goto out;
......
...@@ -56,9 +56,7 @@ static int i915_gem_phys_pwrite(struct drm_device *dev, ...@@ -56,9 +56,7 @@ static int i915_gem_phys_pwrite(struct drm_device *dev,
static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj); static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj);
static int i915_gem_inactive_shrink(struct shrinker *shrinker, static int i915_gem_inactive_shrink(struct shrinker *shrinker,
int nr_to_scan, struct shrink_control *sc);
gfp_t gfp_mask);
/* some bookkeeping */ /* some bookkeeping */
static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv, static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv,
...@@ -4092,9 +4090,7 @@ i915_gpu_is_active(struct drm_device *dev) ...@@ -4092,9 +4090,7 @@ i915_gpu_is_active(struct drm_device *dev)
} }
static int static int
i915_gem_inactive_shrink(struct shrinker *shrinker, i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
int nr_to_scan,
gfp_t gfp_mask)
{ {
struct drm_i915_private *dev_priv = struct drm_i915_private *dev_priv =
container_of(shrinker, container_of(shrinker,
...@@ -4102,6 +4098,7 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, ...@@ -4102,6 +4098,7 @@ i915_gem_inactive_shrink(struct shrinker *shrinker,
mm.inactive_shrinker); mm.inactive_shrinker);
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
struct drm_i915_gem_object *obj, *next; struct drm_i915_gem_object *obj, *next;
int nr_to_scan = sc->nr_to_scan;
int cnt; int cnt;
if (!mutex_trylock(&dev->struct_mutex)) if (!mutex_trylock(&dev->struct_mutex))
......
...@@ -395,12 +395,14 @@ static int ttm_pool_get_num_unused_pages(void) ...@@ -395,12 +395,14 @@ static int ttm_pool_get_num_unused_pages(void)
/** /**
* Callback for mm to request pool to reduce number of page held. * Callback for mm to request pool to reduce number of page held.
*/ */
static int ttm_pool_mm_shrink(struct shrinker *shrink, int shrink_pages, gfp_t gfp_mask) static int ttm_pool_mm_shrink(struct shrinker *shrink,
struct shrink_control *sc)
{ {
static atomic_t start_pool = ATOMIC_INIT(0); static atomic_t start_pool = ATOMIC_INIT(0);
unsigned i; unsigned i;
unsigned pool_offset = atomic_add_return(1, &start_pool); unsigned pool_offset = atomic_add_return(1, &start_pool);
struct ttm_page_pool *pool; struct ttm_page_pool *pool;
int shrink_pages = sc->nr_to_scan;
pool_offset = pool_offset % NUM_POOLS; pool_offset = pool_offset % NUM_POOLS;
/* select start pool in round robin fashion */ /* select start pool in round robin fashion */
......
...@@ -1181,9 +1181,12 @@ static bool zcache_freeze; ...@@ -1181,9 +1181,12 @@ static bool zcache_freeze;
/* /*
* zcache shrinker interface (only useful for ephemeral pages, so zbud only) * zcache shrinker interface (only useful for ephemeral pages, so zbud only)
*/ */
static int shrink_zcache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) static int shrink_zcache_memory(struct shrinker *shrink,
struct shrink_control *sc)
{ {
int ret = -1; int ret = -1;
int nr = sc->nr_to_scan;
gfp_t gfp_mask = sc->gfp_mask;
if (nr >= 0) { if (nr >= 0) {
if (!(gfp_mask & __GFP_FS)) if (!(gfp_mask & __GFP_FS))
......
...@@ -1220,7 +1220,7 @@ void shrink_dcache_parent(struct dentry * parent) ...@@ -1220,7 +1220,7 @@ void shrink_dcache_parent(struct dentry * parent)
EXPORT_SYMBOL(shrink_dcache_parent); EXPORT_SYMBOL(shrink_dcache_parent);
/* /*
* Scan `nr' dentries and return the number which remain. * Scan `sc->nr_slab_to_reclaim' dentries and return the number which remain.
* *
* We need to avoid reentering the filesystem if the caller is performing a * We need to avoid reentering the filesystem if the caller is performing a
* GFP_NOFS allocation attempt. One example deadlock is: * GFP_NOFS allocation attempt. One example deadlock is:
...@@ -1231,8 +1231,12 @@ EXPORT_SYMBOL(shrink_dcache_parent); ...@@ -1231,8 +1231,12 @@ EXPORT_SYMBOL(shrink_dcache_parent);
* *
* In this case we return -1 to tell the caller that we baled. * In this case we return -1 to tell the caller that we baled.
*/ */
static int shrink_dcache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) static int shrink_dcache_memory(struct shrinker *shrink,
struct shrink_control *sc)
{ {
int nr = sc->nr_to_scan;
gfp_t gfp_mask = sc->gfp_mask;
if (nr) { if (nr) {
if (!(gfp_mask & __GFP_FS)) if (!(gfp_mask & __GFP_FS))
return -1; return -1;
......
...@@ -42,11 +42,10 @@ static void drop_slab(void) ...@@ -42,11 +42,10 @@ static void drop_slab(void)
int nr_objects; int nr_objects;
struct shrink_control shrink = { struct shrink_control shrink = {
.gfp_mask = GFP_KERNEL, .gfp_mask = GFP_KERNEL,
.nr_scanned = 1000,
}; };
do { do {
nr_objects = shrink_slab(&shrink, 1000); nr_objects = shrink_slab(&shrink, 1000, 1000);
} while (nr_objects > 10); } while (nr_objects > 10);
} }
......
...@@ -1346,11 +1346,14 @@ void gfs2_glock_complete(struct gfs2_glock *gl, int ret) ...@@ -1346,11 +1346,14 @@ void gfs2_glock_complete(struct gfs2_glock *gl, int ret)
} }
static int gfs2_shrink_glock_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) static int gfs2_shrink_glock_memory(struct shrinker *shrink,
struct shrink_control *sc)
{ {
struct gfs2_glock *gl; struct gfs2_glock *gl;
int may_demote; int may_demote;
int nr_skipped = 0; int nr_skipped = 0;
int nr = sc->nr_to_scan;
gfp_t gfp_mask = sc->gfp_mask;
LIST_HEAD(skipped); LIST_HEAD(skipped);
if (nr == 0) if (nr == 0)
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mm.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
...@@ -77,19 +78,20 @@ static LIST_HEAD(qd_lru_list); ...@@ -77,19 +78,20 @@ static LIST_HEAD(qd_lru_list);
static atomic_t qd_lru_count = ATOMIC_INIT(0); static atomic_t qd_lru_count = ATOMIC_INIT(0);
static DEFINE_SPINLOCK(qd_lru_lock); static DEFINE_SPINLOCK(qd_lru_lock);
int gfs2_shrink_qd_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) int gfs2_shrink_qd_memory(struct shrinker *shrink, struct shrink_control *sc)
{ {
struct gfs2_quota_data *qd; struct gfs2_quota_data *qd;
struct gfs2_sbd *sdp; struct gfs2_sbd *sdp;
int nr_to_scan = sc->nr_to_scan;
if (nr == 0) if (nr_to_scan == 0)
goto out; goto out;
if (!(gfp_mask & __GFP_FS)) if (!(sc->gfp_mask & __GFP_FS))
return -1; return -1;
spin_lock(&qd_lru_lock); spin_lock(&qd_lru_lock);
while (nr && !list_empty(&qd_lru_list)) { while (nr_to_scan && !list_empty(&qd_lru_list)) {
qd = list_entry(qd_lru_list.next, qd = list_entry(qd_lru_list.next,
struct gfs2_quota_data, qd_reclaim); struct gfs2_quota_data, qd_reclaim);
sdp = qd->qd_gl->gl_sbd; sdp = qd->qd_gl->gl_sbd;
...@@ -110,7 +112,7 @@ int gfs2_shrink_qd_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) ...@@ -110,7 +112,7 @@ int gfs2_shrink_qd_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask)
spin_unlock(&qd_lru_lock); spin_unlock(&qd_lru_lock);
kmem_cache_free(gfs2_quotad_cachep, qd); kmem_cache_free(gfs2_quotad_cachep, qd);
spin_lock(&qd_lru_lock); spin_lock(&qd_lru_lock);
nr--; nr_to_scan--;
} }
spin_unlock(&qd_lru_lock); spin_unlock(&qd_lru_lock);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
struct gfs2_inode; struct gfs2_inode;
struct gfs2_sbd; struct gfs2_sbd;
struct shrink_control;
#define NO_QUOTA_CHANGE ((u32)-1) #define NO_QUOTA_CHANGE ((u32)-1)
...@@ -51,7 +52,8 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip) ...@@ -51,7 +52,8 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
return ret; return ret;
} }
extern int gfs2_shrink_qd_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask); extern int gfs2_shrink_qd_memory(struct shrinker *shrink,
struct shrink_control *sc);
extern const struct quotactl_ops gfs2_quotactl_ops; extern const struct quotactl_ops gfs2_quotactl_ops;
#endif /* __QUOTA_DOT_H__ */ #endif /* __QUOTA_DOT_H__ */
...@@ -751,8 +751,12 @@ static void prune_icache(int nr_to_scan) ...@@ -751,8 +751,12 @@ static void prune_icache(int nr_to_scan)
* This function is passed the number of inodes to scan, and it returns the * This function is passed the number of inodes to scan, and it returns the
* total number of remaining possibly-reclaimable inodes. * total number of remaining possibly-reclaimable inodes.
*/ */
static int shrink_icache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) static int shrink_icache_memory(struct shrinker *shrink,
struct shrink_control *sc)
{ {
int nr = sc->nr_to_scan;
gfp_t gfp_mask = sc->gfp_mask;
if (nr) { if (nr) {
/* /*
* Nasty deadlock avoidance. We may hold various FS locks, * Nasty deadlock avoidance. We may hold various FS locks,
......
...@@ -90,7 +90,8 @@ static DEFINE_SPINLOCK(mb_cache_spinlock); ...@@ -90,7 +90,8 @@ static DEFINE_SPINLOCK(mb_cache_spinlock);
* What the mbcache registers as to get shrunk dynamically. * What the mbcache registers as to get shrunk dynamically.
*/ */
static int mb_cache_shrink_fn(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask); static int mb_cache_shrink_fn(struct shrinker *shrink,
struct shrink_control *sc);
static struct shrinker mb_cache_shrinker = { static struct shrinker mb_cache_shrinker = {
.shrink = mb_cache_shrink_fn, .shrink = mb_cache_shrink_fn,
...@@ -156,18 +157,19 @@ __mb_cache_entry_release_unlock(struct mb_cache_entry *ce) ...@@ -156,18 +157,19 @@ __mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
* gets low. * gets low.
* *
* @shrink: (ignored) * @shrink: (ignored)
* @nr_to_scan: Number of objects to scan * @sc: shrink_control passed from reclaim
* @gfp_mask: (ignored)
* *
* Returns the number of objects which are present in the cache. * Returns the number of objects which are present in the cache.
*/ */
static int static int
mb_cache_shrink_fn(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) mb_cache_shrink_fn(struct shrinker *shrink, struct shrink_control *sc)
{ {
LIST_HEAD(free_list); LIST_HEAD(free_list);
struct mb_cache *cache; struct mb_cache *cache;
struct mb_cache_entry *entry, *tmp; struct mb_cache_entry *entry, *tmp;
int count = 0; int count = 0;
int nr_to_scan = sc->nr_to_scan;
gfp_t gfp_mask = sc->gfp_mask;
mb_debug("trying to free %d entries", nr_to_scan); mb_debug("trying to free %d entries", nr_to_scan);
spin_lock(&mb_cache_spinlock); spin_lock(&mb_cache_spinlock);
......
...@@ -2042,11 +2042,14 @@ static void nfs_access_free_list(struct list_head *head) ...@@ -2042,11 +2042,14 @@ static void nfs_access_free_list(struct list_head *head)
} }
} }
int nfs_access_cache_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) int nfs_access_cache_shrinker(struct shrinker *shrink,
struct shrink_control *sc)
{ {
LIST_HEAD(head); LIST_HEAD(head);
struct nfs_inode *nfsi, *next; struct nfs_inode *nfsi, *next;
struct nfs_access_entry *cache; struct nfs_access_entry *cache;
int nr_to_scan = sc->nr_to_scan;
gfp_t gfp_mask = sc->gfp_mask;
if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL) if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL)
return (nr_to_scan == 0) ? 0 : -1; return (nr_to_scan == 0) ? 0 : -1;
......
...@@ -234,7 +234,7 @@ extern int nfs_init_client(struct nfs_client *clp, ...@@ -234,7 +234,7 @@ extern int nfs_init_client(struct nfs_client *clp,
/* dir.c */ /* dir.c */
extern int nfs_access_cache_shrinker(struct shrinker *shrink, extern int nfs_access_cache_shrinker(struct shrinker *shrink,
int nr_to_scan, gfp_t gfp_mask); struct shrink_control *sc);
/* inode.c */ /* inode.c */
extern struct workqueue_struct *nfsiod_workqueue; extern struct workqueue_struct *nfsiod_workqueue;
......
...@@ -691,8 +691,11 @@ static void prune_dqcache(int count) ...@@ -691,8 +691,11 @@ static void prune_dqcache(int count)
* This is called from kswapd when we think we need some * This is called from kswapd when we think we need some
* more memory * more memory
*/ */
static int shrink_dqcache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) static int shrink_dqcache_memory(struct shrinker *shrink,
struct shrink_control *sc)
{ {
int nr = sc->nr_to_scan;
if (nr) { if (nr) {
spin_lock(&dq_list_lock); spin_lock(&dq_list_lock);
prune_dqcache(nr); prune_dqcache(nr);
......
...@@ -1422,12 +1422,12 @@ xfs_wait_buftarg( ...@@ -1422,12 +1422,12 @@ xfs_wait_buftarg(
int int
xfs_buftarg_shrink( xfs_buftarg_shrink(
struct shrinker *shrink, struct shrinker *shrink,
int nr_to_scan, struct shrink_control *sc)
gfp_t mask)
{ {
struct xfs_buftarg *btp = container_of(shrink, struct xfs_buftarg *btp = container_of(shrink,
struct xfs_buftarg, bt_shrinker); struct xfs_buftarg, bt_shrinker);
struct xfs_buf *bp; struct xfs_buf *bp;
int nr_to_scan = sc->nr_to_scan;
LIST_HEAD(dispose); LIST_HEAD(dispose);
if (!nr_to_scan) if (!nr_to_scan)
......
...@@ -1032,13 +1032,14 @@ xfs_reclaim_inodes( ...@@ -1032,13 +1032,14 @@ xfs_reclaim_inodes(
static int static int
xfs_reclaim_inode_shrink( xfs_reclaim_inode_shrink(
struct shrinker *shrink, struct shrinker *shrink,
int nr_to_scan, struct shrink_control *sc)
gfp_t gfp_mask)
{ {
struct xfs_mount *mp; struct xfs_mount *mp;
struct xfs_perag *pag; struct xfs_perag *pag;
xfs_agnumber_t ag; xfs_agnumber_t ag;
int reclaimable; int reclaimable;
int nr_to_scan = sc->nr_to_scan;
gfp_t gfp_mask = sc->gfp_mask;
mp = container_of(shrink, struct xfs_mount, m_inode_shrink); mp = container_of(shrink, struct xfs_mount, m_inode_shrink);
if (nr_to_scan) { if (nr_to_scan) {
......
...@@ -60,7 +60,7 @@ STATIC void xfs_qm_list_destroy(xfs_dqlist_t *); ...@@ -60,7 +60,7 @@ STATIC void xfs_qm_list_destroy(xfs_dqlist_t *);
STATIC int xfs_qm_init_quotainos(xfs_mount_t *); STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
STATIC int xfs_qm_shake(struct shrinker *, int, gfp_t); STATIC int xfs_qm_shake(struct shrinker *, struct shrink_control *);
static struct shrinker xfs_qm_shaker = { static struct shrinker xfs_qm_shaker = {
.shrink = xfs_qm_shake, .shrink = xfs_qm_shake,
...@@ -2009,10 +2009,10 @@ xfs_qm_shake_freelist( ...@@ -2009,10 +2009,10 @@ xfs_qm_shake_freelist(
STATIC int STATIC int
xfs_qm_shake( xfs_qm_shake(
struct shrinker *shrink, struct shrinker *shrink,
int nr_to_scan, struct shrink_control *sc)
gfp_t gfp_mask)
{ {
int ndqused, nfree, n; int ndqused, nfree, n;
gfp_t gfp_mask = sc->gfp_mask;
if (!kmem_shake_allow(gfp_mask)) if (!kmem_shake_allow(gfp_mask))
return 0; return 0;
......
...@@ -1166,18 +1166,20 @@ static inline void sync_mm_rss(struct task_struct *task, struct mm_struct *mm) ...@@ -1166,18 +1166,20 @@ static inline void sync_mm_rss(struct task_struct *task, struct mm_struct *mm)
* We consolidate the values for easier extention later. * We consolidate the values for easier extention later.
*/ */
struct shrink_control { struct shrink_control {
unsigned long nr_scanned;
gfp_t gfp_mask; gfp_t gfp_mask;
/* How many slab objects shrinker() should scan and try to reclaim */
unsigned long nr_to_scan;
}; };
/* /*
* A callback you can register to apply pressure to ageable caches. * A callback you can register to apply pressure to ageable caches.
* *
* 'shrink' is passed a count 'nr_to_scan' and a 'gfpmask'. It should * 'sc' is passed shrink_control which includes a count 'nr_to_scan'
* look through the least-recently-used 'nr_to_scan' entries and * and a 'gfpmask'. It should look through the least-recently-used
* attempt to free them up. It should return the number of objects * 'nr_to_scan' entries and attempt to free them up. It should return
* which remain in the cache. If it returns -1, it means it cannot do * the number of objects which remain in the cache. If it returns -1, it means
* any scanning at this time (eg. there is a risk of deadlock). * it cannot do any scanning at this time (eg. there is a risk of deadlock).
* *
* The 'gfpmask' refers to the allocation we are currently trying to * The 'gfpmask' refers to the allocation we are currently trying to
* fulfil. * fulfil.
...@@ -1186,7 +1188,7 @@ struct shrink_control { ...@@ -1186,7 +1188,7 @@ struct shrink_control {
* querying the cache size, so a fastpath for that case is appropriate. * querying the cache size, so a fastpath for that case is appropriate.
*/ */
struct shrinker { struct shrinker {
int (*shrink)(struct shrinker *, int nr_to_scan, gfp_t gfp_mask); int (*shrink)(struct shrinker *, struct shrink_control *sc);
int seeks; /* seeks to recreate an obj */ int seeks; /* seeks to recreate an obj */
/* These are for internal use */ /* These are for internal use */
...@@ -1640,7 +1642,8 @@ int in_gate_area_no_mm(unsigned long addr); ...@@ -1640,7 +1642,8 @@ int in_gate_area_no_mm(unsigned long addr);
int drop_caches_sysctl_handler(struct ctl_table *, int, int drop_caches_sysctl_handler(struct ctl_table *, int,
void __user *, size_t *, loff_t *); void __user *, size_t *, loff_t *);
unsigned long shrink_slab(struct shrink_control *shrink, unsigned long shrink_slab(struct shrink_control *shrink,
unsigned long lru_pages); unsigned long nr_pages_scanned,
unsigned long lru_pages);
#ifndef CONFIG_MMU #ifndef CONFIG_MMU
#define randomize_va_space 0 #define randomize_va_space 0
......
...@@ -241,10 +241,9 @@ void shake_page(struct page *p, int access) ...@@ -241,10 +241,9 @@ void shake_page(struct page *p, int access)
do { do {
struct shrink_control shrink = { struct shrink_control shrink = {
.gfp_mask = GFP_KERNEL, .gfp_mask = GFP_KERNEL,
.nr_scanned = 1000,
}; };
nr = shrink_slab(&shrink, 1000); nr = shrink_slab(&shrink, 1000, 1000);
if (page_count(p) == 1) if (page_count(p) == 1)
break; break;
} while (nr > 10); } while (nr > 10);
......
...@@ -202,6 +202,14 @@ void unregister_shrinker(struct shrinker *shrinker) ...@@ -202,6 +202,14 @@ void unregister_shrinker(struct shrinker *shrinker)
} }
EXPORT_SYMBOL(unregister_shrinker); EXPORT_SYMBOL(unregister_shrinker);
static inline int do_shrinker_shrink(struct shrinker *shrinker,
struct shrink_control *sc,
unsigned long nr_to_scan)
{
sc->nr_to_scan = nr_to_scan;
return (*shrinker->shrink)(shrinker, sc);
}
#define SHRINK_BATCH 128 #define SHRINK_BATCH 128
/* /*
* Call the shrink functions to age shrinkable caches * Call the shrink functions to age shrinkable caches
...@@ -223,15 +231,14 @@ EXPORT_SYMBOL(unregister_shrinker); ...@@ -223,15 +231,14 @@ EXPORT_SYMBOL(unregister_shrinker);
* Returns the number of slab objects which we shrunk. * Returns the number of slab objects which we shrunk.
*/ */
unsigned long shrink_slab(struct shrink_control *shrink, unsigned long shrink_slab(struct shrink_control *shrink,
unsigned long nr_pages_scanned,
unsigned long lru_pages) unsigned long lru_pages)
{ {
struct shrinker *shrinker; struct shrinker *shrinker;
unsigned long ret = 0; unsigned long ret = 0;
unsigned long scanned = shrink->nr_scanned;
gfp_t gfp_mask = shrink->gfp_mask;
if (scanned == 0) if (nr_pages_scanned == 0)
scanned = SWAP_CLUSTER_MAX; nr_pages_scanned = SWAP_CLUSTER_MAX;
if (!down_read_trylock(&shrinker_rwsem)) { if (!down_read_trylock(&shrinker_rwsem)) {
/* Assume we'll be able to shrink next time */ /* Assume we'll be able to shrink next time */
...@@ -244,8 +251,8 @@ unsigned long shrink_slab(struct shrink_control *shrink, ...@@ -244,8 +251,8 @@ unsigned long shrink_slab(struct shrink_control *shrink,
unsigned long total_scan; unsigned long total_scan;
unsigned long max_pass; unsigned long max_pass;
max_pass = (*shrinker->shrink)(shrinker, 0, gfp_mask); max_pass = do_shrinker_shrink(shrinker, shrink, 0);
delta = (4 * scanned) / shrinker->seeks; delta = (4 * nr_pages_scanned) / shrinker->seeks;
delta *= max_pass; delta *= max_pass;
do_div(delta, lru_pages + 1); do_div(delta, lru_pages + 1);
shrinker->nr += delta; shrinker->nr += delta;
...@@ -272,9 +279,9 @@ unsigned long shrink_slab(struct shrink_control *shrink, ...@@ -272,9 +279,9 @@ unsigned long shrink_slab(struct shrink_control *shrink,
int shrink_ret; int shrink_ret;
int nr_before; int nr_before;
nr_before = (*shrinker->shrink)(shrinker, 0, gfp_mask); nr_before = do_shrinker_shrink(shrinker, shrink, 0);
shrink_ret = (*shrinker->shrink)(shrinker, this_scan, shrink_ret = do_shrinker_shrink(shrinker, shrink,
gfp_mask); this_scan);
if (shrink_ret == -1) if (shrink_ret == -1)
break; break;
if (shrink_ret < nr_before) if (shrink_ret < nr_before)
...@@ -2072,8 +2079,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, ...@@ -2072,8 +2079,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
lru_pages += zone_reclaimable_pages(zone); lru_pages += zone_reclaimable_pages(zone);
} }
shrink->nr_scanned = sc->nr_scanned; shrink_slab(shrink, sc->nr_scanned, lru_pages);
shrink_slab(shrink, lru_pages);
if (reclaim_state) { if (reclaim_state) {
sc->nr_reclaimed += reclaim_state->reclaimed_slab; sc->nr_reclaimed += reclaim_state->reclaimed_slab;
reclaim_state->reclaimed_slab = 0; reclaim_state->reclaimed_slab = 0;
...@@ -2456,8 +2462,7 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order, ...@@ -2456,8 +2462,7 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order,
end_zone, 0)) end_zone, 0))
shrink_zone(priority, zone, &sc); shrink_zone(priority, zone, &sc);
reclaim_state->reclaimed_slab = 0; reclaim_state->reclaimed_slab = 0;
shrink.nr_scanned = sc.nr_scanned; nr_slab = shrink_slab(&shrink, sc.nr_scanned, lru_pages);
nr_slab = shrink_slab(&shrink, lru_pages);
sc.nr_reclaimed += reclaim_state->reclaimed_slab; sc.nr_reclaimed += reclaim_state->reclaimed_slab;
total_scanned += sc.nr_scanned; total_scanned += sc.nr_scanned;
...@@ -3025,7 +3030,6 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) ...@@ -3025,7 +3030,6 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
} }
nr_slab_pages0 = zone_page_state(zone, NR_SLAB_RECLAIMABLE); nr_slab_pages0 = zone_page_state(zone, NR_SLAB_RECLAIMABLE);
shrink.nr_scanned = sc.nr_scanned;
if (nr_slab_pages0 > zone->min_slab_pages) { if (nr_slab_pages0 > zone->min_slab_pages) {
/* /*
* shrink_slab() does not currently allow us to determine how * shrink_slab() does not currently allow us to determine how
...@@ -3041,7 +3045,7 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) ...@@ -3041,7 +3045,7 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
unsigned long lru_pages = zone_reclaimable_pages(zone); unsigned long lru_pages = zone_reclaimable_pages(zone);
/* No reclaimable slab or very low memory pressure */ /* No reclaimable slab or very low memory pressure */
if (!shrink_slab(&shrink, lru_pages)) if (!shrink_slab(&shrink, sc.nr_scanned, lru_pages))
break; break;
/* Freed enough memory */ /* Freed enough memory */
......
...@@ -326,10 +326,12 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan) ...@@ -326,10 +326,12 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
* Run memory cache shrinker. * Run memory cache shrinker.
*/ */
static int static int
rpcauth_cache_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) rpcauth_cache_shrinker(struct shrinker *shrink, struct shrink_control *sc)
{ {
LIST_HEAD(free); LIST_HEAD(free);
int res; int res;
int nr_to_scan = sc->nr_to_scan;
gfp_t gfp_mask = sc->gfp_mask;
if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL) if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL)
return (nr_to_scan == 0) ? 0 : -1; return (nr_to_scan == 0) ? 0 : -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment