mirror of
https://github.com/S3NEO/android_kernel_samsung_msm8226.git
synced 2024-11-07 03:47:13 +00:00
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: Ying Han <yinghan@google.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Minchan Kim <minchan.kim@gmail.com> Acked-by: Pavel Emelyanov <xemul@openvz.org> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Mel Gorman <mel@csn.ul.ie> Acked-by: Rik 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: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
a09ed5e000
commit
1495f230fa
21 changed files with 95 additions and 61 deletions
|
@ -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,
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
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)
|
||||||
/**
|
/**
|
||||||
* 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;
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
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);
|
||||||
*
|
*
|
||||||
* 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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@
|
||||||
|
|
||||||
#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);
|
||||||
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)
|
||||||
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 @@
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
* 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,
|
||||||
|
|
10
fs/mbcache.c
10
fs/mbcache.c
|
@ -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 @@ forget:
|
||||||
* 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
|
|
||||||
/* 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)
|
||||||
* 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 @@ restart:
|
||||||
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(
|
||||||
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 *);
|
||||||
|
|
||||||
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(
|
||||||
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)
|
||||||
* 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 {
|
||||||
* 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);
|
||||||
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)
|
||||||
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);
|
||||||
|
|
34
mm/vmscan.c
34
mm/vmscan.c
|
@ -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);
|
||||||
* 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,
|
||||||
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,
|
||||||
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,
|
||||||
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 @@ loop_again:
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
* 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;
|
||||||
|
|
Loading…
Reference in a new issue