Skip to content

Commit

Permalink
vmscan: change shrinker API by passing shrink_control struct
Browse files Browse the repository at this point in the history
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.

[[email protected]: fix build]
[[email protected]: fix warning]
[[email protected]: fix up new shrinker API]
[[email protected]: fix xfs warning]
[[email protected]: update gfs2]
Signed-off-by: Ying Han <[email protected]>
Cc: KOSAKI Motohiro <[email protected]>
Cc: Minchan Kim <[email protected]>
Acked-by: Pavel Emelyanov <[email protected]>
Cc: KAMEZAWA Hiroyuki <[email protected]>
Cc: Mel Gorman <[email protected]>
Acked-by: Rik van Riel <[email protected]>
Cc: Johannes Weiner <[email protected]>
Cc: Hugh Dickins <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: Steven Whitehouse <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
yinghan authored and torvalds committed May 25, 2011
1 parent a09ed5e commit 1495f23
Show file tree
Hide file tree
Showing 21 changed files with 95 additions and 61 deletions.
3 changes: 2 additions & 1 deletion arch/x86/kvm/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

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_freed = NULL;
int nr_to_scan = sc->nr_to_scan;

if (nr_to_scan == 0)
goto out;
Expand Down
9 changes: 3 additions & 6 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 int i915_gem_inactive_shrink(struct shrinker *shrinker,
int nr_to_scan,
gfp_t gfp_mask);

struct shrink_control *sc);

/* some bookkeeping */
static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv,
Expand Down Expand Up @@ -4092,16 +4090,15 @@ i915_gpu_is_active(struct drm_device *dev)
}

static int
i915_gem_inactive_shrink(struct shrinker *shrinker,
int nr_to_scan,
gfp_t gfp_mask)
i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
{
struct drm_i915_private *dev_priv =
container_of(shrinker,
struct drm_i915_private,
mm.inactive_shrinker);
struct drm_device *dev = dev_priv->dev;
struct drm_i915_gem_object *obj, *next;
int nr_to_scan = sc->nr_to_scan;
int cnt;

if (!mutex_trylock(&dev->struct_mutex))
Expand Down
4 changes: 3 additions & 1 deletion drivers/gpu/drm/ttm/ttm_page_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
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);
unsigned i;
unsigned pool_offset = atomic_add_return(1, &start_pool);
struct ttm_page_pool *pool;
int shrink_pages = sc->nr_to_scan;

pool_offset = pool_offset % NUM_POOLS;
/* select start pool in round robin fashion */
Expand Down
5 changes: 4 additions & 1 deletion drivers/staging/zcache/zcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1181,9 +1181,12 @@ static bool zcache_freeze;
/*
* 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 nr = sc->nr_to_scan;
gfp_t gfp_mask = sc->gfp_mask;

if (nr >= 0) {
if (!(gfp_mask & __GFP_FS))
Expand Down
8 changes: 6 additions & 2 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1220,7 +1220,7 @@ void shrink_dcache_parent(struct dentry * 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
* GFP_NOFS allocation attempt. One example deadlock is:
Expand All @@ -1231,8 +1231,12 @@ EXPORT_SYMBOL(shrink_dcache_parent);
*
* 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 (!(gfp_mask & __GFP_FS))
return -1;
Expand Down
3 changes: 1 addition & 2 deletions fs/drop_caches.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,10 @@ static void drop_slab(void)
int nr_objects;
struct shrink_control shrink = {
.gfp_mask = GFP_KERNEL,
.nr_scanned = 1000,
};

do {
nr_objects = shrink_slab(&shrink, 1000);
nr_objects = shrink_slab(&shrink, 1000, 1000);
} while (nr_objects > 10);
}

Expand Down
5 changes: 4 additions & 1 deletion fs/gfs2/glock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
int may_demote;
int nr_skipped = 0;
int nr = sc->nr_to_scan;
gfp_t gfp_mask = sc->gfp_mask;
LIST_HEAD(skipped);

if (nr == 0)
Expand Down
12 changes: 7 additions & 5 deletions fs/gfs2/quota.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/buffer_head.h>
Expand Down Expand Up @@ -77,19 +78,20 @@ static LIST_HEAD(qd_lru_list);
static atomic_t qd_lru_count = ATOMIC_INIT(0);
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_sbd *sdp;
int nr_to_scan = sc->nr_to_scan;

if (nr == 0)
if (nr_to_scan == 0)
goto out;

if (!(gfp_mask & __GFP_FS))
if (!(sc->gfp_mask & __GFP_FS))
return -1;

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,
struct gfs2_quota_data, qd_reclaim);
sdp = qd->qd_gl->gl_sbd;
Expand All @@ -110,7 +112,7 @@ int gfs2_shrink_qd_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask)
spin_unlock(&qd_lru_lock);
kmem_cache_free(gfs2_quotad_cachep, qd);
spin_lock(&qd_lru_lock);
nr--;
nr_to_scan--;
}
spin_unlock(&qd_lru_lock);

Expand Down
4 changes: 3 additions & 1 deletion fs/gfs2/quota.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

struct gfs2_inode;
struct gfs2_sbd;
struct shrink_control;

#define NO_QUOTA_CHANGE ((u32)-1)

Expand Down Expand Up @@ -51,7 +52,8 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
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;

#endif /* __QUOTA_DOT_H__ */
6 changes: 5 additions & 1 deletion fs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
* 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) {
/*
* Nasty deadlock avoidance. We may hold various FS locks,
Expand Down
10 changes: 6 additions & 4 deletions fs/mbcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ static DEFINE_SPINLOCK(mb_cache_spinlock);
* 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 = {
.shrink = mb_cache_shrink_fn,
Expand Down Expand Up @@ -156,18 +157,19 @@ __mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
* gets low.
*
* @shrink: (ignored)
* @nr_to_scan: Number of objects to scan
* @gfp_mask: (ignored)
* @sc: shrink_control passed from reclaim
*
* Returns the number of objects which are present in the cache.
*/
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);
struct mb_cache *cache;
struct mb_cache_entry *entry, *tmp;
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);
spin_lock(&mb_cache_spinlock);
Expand Down
5 changes: 4 additions & 1 deletion fs/nfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
struct nfs_inode *nfsi, *next;
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)
return (nr_to_scan == 0) ? 0 : -1;
Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ extern int nfs_init_client(struct nfs_client *clp,

/* dir.c */
extern int nfs_access_cache_shrinker(struct shrinker *shrink,
int nr_to_scan, gfp_t gfp_mask);
struct shrink_control *sc);

/* inode.c */
extern struct workqueue_struct *nfsiod_workqueue;
Expand Down
5 changes: 4 additions & 1 deletion fs/quota/dquot.c
Original file line number Diff line number Diff line change
Expand Up @@ -691,8 +691,11 @@ static void prune_dqcache(int count)
* This is called from kswapd when we think we need some
* 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) {
spin_lock(&dq_list_lock);
prune_dqcache(nr);
Expand Down
4 changes: 2 additions & 2 deletions fs/xfs/linux-2.6/xfs_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1422,12 +1422,12 @@ xfs_wait_buftarg(
int
xfs_buftarg_shrink(
struct shrinker *shrink,
int nr_to_scan,
gfp_t mask)
struct shrink_control *sc)
{
struct xfs_buftarg *btp = container_of(shrink,
struct xfs_buftarg, bt_shrinker);
struct xfs_buf *bp;
int nr_to_scan = sc->nr_to_scan;
LIST_HEAD(dispose);

if (!nr_to_scan)
Expand Down
5 changes: 3 additions & 2 deletions fs/xfs/linux-2.6/xfs_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -1032,13 +1032,14 @@ xfs_reclaim_inodes(
static int
xfs_reclaim_inode_shrink(
struct shrinker *shrink,
int nr_to_scan,
gfp_t gfp_mask)
struct shrink_control *sc)
{
struct xfs_mount *mp;
struct xfs_perag *pag;
xfs_agnumber_t ag;
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);
if (nr_to_scan) {
Expand Down
6 changes: 3 additions & 3 deletions fs/xfs/quota/xfs_qm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_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 = {
.shrink = xfs_qm_shake,
Expand Down Expand Up @@ -2009,10 +2009,10 @@ xfs_qm_shake_freelist(
STATIC int
xfs_qm_shake(
struct shrinker *shrink,
int nr_to_scan,
gfp_t gfp_mask)
struct shrink_control *sc)
{
int ndqused, nfree, n;
gfp_t gfp_mask = sc->gfp_mask;

if (!kmem_shake_allow(gfp_mask))
return 0;
Expand Down
19 changes: 11 additions & 8 deletions include/linux/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
struct shrink_control {
unsigned long nr_scanned;
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.
*
* 'shrink' is passed a count 'nr_to_scan' and a 'gfpmask'. It should
* look through the least-recently-used 'nr_to_scan' entries and
* attempt to free them up. It should return the number of objects
* which remain in the cache. If it returns -1, it means it cannot do
* any scanning at this time (eg. there is a risk of deadlock).
* 'sc' is passed shrink_control which includes a count 'nr_to_scan'
* and a 'gfpmask'. It should look through the least-recently-used
* 'nr_to_scan' entries and attempt to free them up. It should return
* the number of objects which remain in the cache. If it returns -1, it means
* 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
* fulfil.
Expand All @@ -1186,7 +1188,7 @@ struct shrink_control {
* querying the cache size, so a fastpath for that case is appropriate.
*/
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 */

/* These are for internal use */
Expand Down Expand Up @@ -1640,7 +1642,8 @@ int in_gate_area_no_mm(unsigned long addr);
int drop_caches_sysctl_handler(struct ctl_table *, int,
void __user *, size_t *, loff_t *);
unsigned long shrink_slab(struct shrink_control *shrink,
unsigned long lru_pages);
unsigned long nr_pages_scanned,
unsigned long lru_pages);

#ifndef CONFIG_MMU
#define randomize_va_space 0
Expand Down
3 changes: 1 addition & 2 deletions mm/memory-failure.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,9 @@ void shake_page(struct page *p, int access)
do {
struct shrink_control shrink = {
.gfp_mask = GFP_KERNEL,
.nr_scanned = 1000,
};

nr = shrink_slab(&shrink, 1000);
nr = shrink_slab(&shrink, 1000, 1000);
if (page_count(p) == 1)
break;
} while (nr > 10);
Expand Down
Loading

0 comments on commit 1495f23

Please sign in to comment.