Re: [PATCH v6 15/31] fs: convert fs shrinkers to new scan/count API

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun 12-05-13 22:13:36, Glauber Costa wrote:
> From: Dave Chinner <dchinner@xxxxxxxxxx>
> 
> Convert the filesystem shrinkers to use the new API, and standardise
> some of the behaviours of the shrinkers at the same time. For
> example, nr_to_scan means the number of objects to scan, not the
> number of objects to free.
> 
> I refactored the CIFS idmap shrinker a little - it really needs to
> be broken up into a shrinker per tree and keep an item count with
> the tree root so that we don't need to walk the tree every time the
> shrinker needs to count the number of objects in the tree (i.e.
> all the time under memory pressure).
> 
> [ glommer: fixes for ext4, ubifs, nfs, cifs and glock. Fixes are
>   needed mainly due to new code merged in the tree ]
> Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx>
> Signed-off-by: Glauber Costa <glommer@xxxxxxxxxx>
> Acked-by: Mel Gorman <mgorman@xxxxxxx>
> CC: Steven Whitehouse <swhiteho@xxxxxxxxxx>
> CC: Artem Bityutskiy <dedekind1@xxxxxxxxx>
> CC: Adrian Hunter <adrian.hunter@xxxxxxxxx>
> CC: Jan Kara <jack@xxxxxxx>
  Acked-by: Jan Kara <jack@xxxxxxx>

for ext4, quota, and mbcache parts...

								Honza

> ---
>  fs/ext4/extents_status.c | 30 ++++++++++++++++------------
>  fs/gfs2/glock.c          | 28 +++++++++++++++-----------
>  fs/gfs2/main.c           |  3 ++-
>  fs/gfs2/quota.c          | 12 +++++++-----
>  fs/gfs2/quota.h          |  4 +++-
>  fs/mbcache.c             | 51 ++++++++++++++++++++++++++++--------------------
>  fs/nfs/dir.c             | 18 ++++++++++++++---
>  fs/nfs/internal.h        |  4 +++-
>  fs/nfs/super.c           |  3 ++-
>  fs/nfsd/nfscache.c       | 31 ++++++++++++++++++++---------
>  fs/quota/dquot.c         | 34 +++++++++++++++-----------------
>  fs/ubifs/shrinker.c      | 20 +++++++++++--------
>  fs/ubifs/super.c         |  3 ++-
>  fs/ubifs/ubifs.h         |  3 ++-
>  14 files changed, 151 insertions(+), 93 deletions(-)
> 
> diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
> index e6941e6..4bce4f0 100644
> --- a/fs/ext4/extents_status.c
> +++ b/fs/ext4/extents_status.c
> @@ -878,20 +878,26 @@ int ext4_es_zeroout(struct inode *inode, struct ext4_extent *ex)
>  				     EXTENT_STATUS_WRITTEN);
>  }
>  
> -static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
> +
> +static long ext4_es_count(struct shrinker *shrink, struct shrink_control *sc)
> +{
> +	long nr;
> +	struct ext4_sb_info *sbi = container_of(shrink,
> +					struct ext4_sb_info, s_es_shrinker);
> +
> +	nr = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
> +	trace_ext4_es_shrink_enter(sbi->s_sb, sc->nr_to_scan, nr);
> +	return nr;
> +}
> +
> +static long ext4_es_scan(struct shrinker *shrink, struct shrink_control *sc)
>  {
>  	struct ext4_sb_info *sbi = container_of(shrink,
>  					struct ext4_sb_info, s_es_shrinker);
>  	struct ext4_inode_info *ei;
>  	struct list_head *cur, *tmp, scanned;
>  	int nr_to_scan = sc->nr_to_scan;
> -	int ret, nr_shrunk = 0;
> -
> -	ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
> -	trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret);
> -
> -	if (!nr_to_scan)
> -		return ret;
> +	int ret = 0, nr_shrunk = 0;
>  
>  	INIT_LIST_HEAD(&scanned);
>  
> @@ -920,9 +926,8 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
>  	list_splice_tail(&scanned, &sbi->s_es_lru);
>  	spin_unlock(&sbi->s_es_lru_lock);
>  
> -	ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
>  	trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret);
> -	return ret;
> +	return nr_shrunk;
>  }
>  
>  void ext4_es_register_shrinker(struct super_block *sb)
> @@ -932,7 +937,8 @@ void ext4_es_register_shrinker(struct super_block *sb)
>  	sbi = EXT4_SB(sb);
>  	INIT_LIST_HEAD(&sbi->s_es_lru);
>  	spin_lock_init(&sbi->s_es_lru_lock);
> -	sbi->s_es_shrinker.shrink = ext4_es_shrink;
> +	sbi->s_es_shrinker.scan_objects = ext4_es_scan;
> +	sbi->s_es_shrinker.count_objects = ext4_es_count;
>  	sbi->s_es_shrinker.seeks = DEFAULT_SEEKS;
>  	register_shrinker(&sbi->s_es_shrinker);
>  }
> @@ -973,7 +979,7 @@ static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei,
>  	struct ext4_es_tree *tree = &ei->i_es_tree;
>  	struct rb_node *node;
>  	struct extent_status *es;
> -	int nr_shrunk = 0;
> +	long nr_shrunk = 0;
>  
>  	if (ei->i_es_lru_nr == 0)
>  		return 0;
> diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
> index 3bd2748..4ddbccb 100644
> --- a/fs/gfs2/glock.c
> +++ b/fs/gfs2/glock.c
> @@ -1428,21 +1428,22 @@ __acquires(&lru_lock)
>   * gfs2_dispose_glock_lru() above.
>   */
>  
> -static void gfs2_scan_glock_lru(int nr)
> +static long gfs2_scan_glock_lru(int nr)
>  {
>  	struct gfs2_glock *gl;
>  	LIST_HEAD(skipped);
>  	LIST_HEAD(dispose);
> +	long freed = 0;
>  
>  	spin_lock(&lru_lock);
> -	while(nr && !list_empty(&lru_list)) {
> +	while ((nr-- >= 0) && !list_empty(&lru_list)) {
>  		gl = list_entry(lru_list.next, struct gfs2_glock, gl_lru);
>  
>  		/* Test for being demotable */
>  		if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
>  			list_move(&gl->gl_lru, &dispose);
>  			atomic_dec(&lru_count);
> -			nr--;
> +			freed++;
>  			continue;
>  		}
>  
> @@ -1452,23 +1453,28 @@ static void gfs2_scan_glock_lru(int nr)
>  	if (!list_empty(&dispose))
>  		gfs2_dispose_glock_lru(&dispose);
>  	spin_unlock(&lru_lock);
> +
> +	return freed;
>  }
>  
> -static int gfs2_shrink_glock_memory(struct shrinker *shrink,
> -				    struct shrink_control *sc)
> +static long gfs2_glock_shrink_scan(struct shrinker *shrink,
> +				   struct shrink_control *sc)
>  {
> -	if (sc->nr_to_scan) {
> -		if (!(sc->gfp_mask & __GFP_FS))
> -			return -1;
> -		gfs2_scan_glock_lru(sc->nr_to_scan);
> -	}
> +	if (!(sc->gfp_mask & __GFP_FS))
> +		return -1;
> +	return gfs2_scan_glock_lru(sc->nr_to_scan);
> +}
>  
> +static long gfs2_glock_shrink_count(struct shrinker *shrink,
> +				    struct shrink_control *sc)
> +{
>  	return vfs_pressure_ratio(atomic_read(&lru_count));
>  }
>  
>  static struct shrinker glock_shrinker = {
> -	.shrink = gfs2_shrink_glock_memory,
>  	.seeks = DEFAULT_SEEKS,
> +	.count_objects = gfs2_glock_shrink_count,
> +	.scan_objects = gfs2_glock_shrink_scan,
>  };
>  
>  /**
> diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
> index e04d0e0..a105d84 100644
> --- a/fs/gfs2/main.c
> +++ b/fs/gfs2/main.c
> @@ -32,7 +32,8 @@
>  struct workqueue_struct *gfs2_control_wq;
>  
>  static struct shrinker qd_shrinker = {
> -	.shrink = gfs2_shrink_qd_memory,
> +	.count_objects = gfs2_qd_shrink_count,
> +	.scan_objects = gfs2_qd_shrink_scan,
>  	.seeks = DEFAULT_SEEKS,
>  };
>  
> diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
> index 5c14206..77b82f6 100644
> --- a/fs/gfs2/quota.c
> +++ b/fs/gfs2/quota.c
> @@ -75,14 +75,12 @@ 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, struct shrink_control *sc)
> +long gfs2_qd_shrink_scan(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_to_scan == 0)
> -		goto out;
> +	long freed = 0;
>  
>  	if (!(sc->gfp_mask & __GFP_FS))
>  		return -1;
> @@ -110,10 +108,14 @@ int gfs2_shrink_qd_memory(struct shrinker *shrink, struct shrink_control *sc)
>  		kmem_cache_free(gfs2_quotad_cachep, qd);
>  		spin_lock(&qd_lru_lock);
>  		nr_to_scan--;
> +		freed++;
>  	}
>  	spin_unlock(&qd_lru_lock);
> +	return freed;
> +}
>  
> -out:
> +long gfs2_qd_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
> +{
>  	return vfs_pressure_ratio(atomic_read(&qd_lru_count));
>  }
>  
> diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h
> index 4f5e6e4..4f61708 100644
> --- a/fs/gfs2/quota.h
> +++ b/fs/gfs2/quota.h
> @@ -53,7 +53,9 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
>  	return ret;
>  }
>  
> -extern int gfs2_shrink_qd_memory(struct shrinker *shrink,
> +extern long gfs2_qd_shrink_count(struct shrinker *shrink,
> +				 struct shrink_control *sc);
> +extern long gfs2_qd_shrink_scan(struct shrinker *shrink,
>  				 struct shrink_control *sc);
>  extern const struct quotactl_ops gfs2_quotactl_ops;
>  
> diff --git a/fs/mbcache.c b/fs/mbcache.c
> index 5eb0476..009a463 100644
> --- a/fs/mbcache.c
> +++ b/fs/mbcache.c
> @@ -86,18 +86,6 @@ static LIST_HEAD(mb_cache_list);
>  static LIST_HEAD(mb_cache_lru_list);
>  static DEFINE_SPINLOCK(mb_cache_spinlock);
>  
> -/*
> - * What the mbcache registers as to get shrunk dynamically.
> - */
> -
> -static int mb_cache_shrink_fn(struct shrinker *shrink,
> -			      struct shrink_control *sc);
> -
> -static struct shrinker mb_cache_shrinker = {
> -	.shrink = mb_cache_shrink_fn,
> -	.seeks = DEFAULT_SEEKS,
> -};
> -
>  static inline int
>  __mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
>  {
> @@ -151,7 +139,7 @@ forget:
>  
>  
>  /*
> - * mb_cache_shrink_fn()  memory pressure callback
> + * mb_cache_shrink_scan()  memory pressure callback
>   *
>   * This function is called by the kernel memory management when memory
>   * gets low.
> @@ -159,17 +147,18 @@ forget:
>   * @shrink: (ignored)
>   * @sc: shrink_control passed from reclaim
>   *
> - * Returns the number of objects which are present in the cache.
> + * Returns the number of objects freed.
>   */
> -static int
> -mb_cache_shrink_fn(struct shrinker *shrink, struct shrink_control *sc)
> +static long
> +mb_cache_shrink_scan(
> +	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;
> +	long freed = 0;
>  
>  	mb_debug("trying to free %d entries", nr_to_scan);
>  	spin_lock(&mb_cache_spinlock);
> @@ -179,19 +168,39 @@ mb_cache_shrink_fn(struct shrinker *shrink, struct shrink_control *sc)
>  				   struct mb_cache_entry, e_lru_list);
>  		list_move_tail(&ce->e_lru_list, &free_list);
>  		__mb_cache_entry_unhash(ce);
> +		freed++;
> +	}
> +	spin_unlock(&mb_cache_spinlock);
> +	list_for_each_entry_safe(entry, tmp, &free_list, e_lru_list) {
> +		__mb_cache_entry_forget(entry, gfp_mask);
>  	}
> +	return freed;
> +}
> +
> +static long
> +mb_cache_shrink_count(
> +	struct shrinker		*shrink,
> +	struct shrink_control	*sc)
> +{
> +	struct mb_cache *cache;
> +	long count = 0;
> +
> +	spin_lock(&mb_cache_spinlock);
>  	list_for_each_entry(cache, &mb_cache_list, c_cache_list) {
>  		mb_debug("cache %s (%d)", cache->c_name,
>  			  atomic_read(&cache->c_entry_count));
>  		count += atomic_read(&cache->c_entry_count);
>  	}
>  	spin_unlock(&mb_cache_spinlock);
> -	list_for_each_entry_safe(entry, tmp, &free_list, e_lru_list) {
> -		__mb_cache_entry_forget(entry, gfp_mask);
> -	}
> +
>  	return vfs_pressure_ratio(count);
>  }
>  
> +static struct shrinker mb_cache_shrinker = {
> +	.count_objects = mb_cache_shrink_count,
> +	.scan_objects = mb_cache_shrink_scan,
> +	.seeks = DEFAULT_SEEKS,
> +};
>  
>  /*
>   * mb_cache_create()  create a new cache
> diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
> index 54d7c47..b355905 100644
> --- a/fs/nfs/dir.c
> +++ b/fs/nfs/dir.c
> @@ -1958,17 +1958,20 @@ static void nfs_access_free_list(struct list_head *head)
>  	}
>  }
>  
> -int nfs_access_cache_shrinker(struct shrinker *shrink,
> -			      struct shrink_control *sc)
> +long
> +nfs_access_cache_scan(
> +	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;
> +	long freed = 0;
>  
>  	if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL)
> -		return (nr_to_scan == 0) ? 0 : -1;
> +		return -1;
>  
>  	spin_lock(&nfs_access_lru_lock);
>  	list_for_each_entry_safe(nfsi, next, &nfs_access_lru_list, access_cache_inode_lru) {
> @@ -1984,6 +1987,7 @@ int nfs_access_cache_shrinker(struct shrinker *shrink,
>  				struct nfs_access_entry, lru);
>  		list_move(&cache->lru, &head);
>  		rb_erase(&cache->rb_node, &nfsi->access_cache);
> +		freed++;
>  		if (!list_empty(&nfsi->access_cache_entry_lru))
>  			list_move_tail(&nfsi->access_cache_inode_lru,
>  					&nfs_access_lru_list);
> @@ -1998,6 +2002,14 @@ remove_lru_entry:
>  	}
>  	spin_unlock(&nfs_access_lru_lock);
>  	nfs_access_free_list(&head);
> +	return freed;
> +}
> +
> +long
> +nfs_access_cache_count(
> +	struct shrinker		*shrink,
> +	struct shrink_control	*sc)
> +{
>  	return vfs_pressure_ratio(atomic_long_read(&nfs_access_nr_entries));
>  }
>  
> diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
> index 91e59a3..9651e20 100644
> --- a/fs/nfs/internal.h
> +++ b/fs/nfs/internal.h
> @@ -269,7 +269,9 @@ extern struct nfs_client *nfs_init_client(struct nfs_client *clp,
>  			   const char *ip_addr, rpc_authflavor_t authflavour);
>  
>  /* dir.c */
> -extern int nfs_access_cache_shrinker(struct shrinker *shrink,
> +extern long nfs_access_cache_count(struct shrinker *shrink,
> +					struct shrink_control *sc);
> +extern long nfs_access_cache_scan(struct shrinker *shrink,
>  					struct shrink_control *sc);
>  struct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int);
>  int nfs_create(struct inode *, struct dentry *, umode_t, bool);
> diff --git a/fs/nfs/super.c b/fs/nfs/super.c
> index a366107..2fed70f 100644
> --- a/fs/nfs/super.c
> +++ b/fs/nfs/super.c
> @@ -359,7 +359,8 @@ static void unregister_nfs4_fs(void)
>  #endif
>  
>  static struct shrinker acl_shrinker = {
> -	.shrink		= nfs_access_cache_shrinker,
> +	.count_objects	= nfs_access_cache_count,
> +	.scan_objects	= nfs_access_cache_scan,
>  	.seeks		= DEFAULT_SEEKS,
>  };
>  
> diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
> index e76244e..5564c38 100644
> --- a/fs/nfsd/nfscache.c
> +++ b/fs/nfsd/nfscache.c
> @@ -59,11 +59,14 @@ static unsigned int		longest_chain_cachesize;
>  
>  static int	nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec);
>  static void	cache_cleaner_func(struct work_struct *unused);
> -static int 	nfsd_reply_cache_shrink(struct shrinker *shrink,
> -					struct shrink_control *sc);
> +static long	nfsd_reply_cache_count(struct shrinker *shrink,
> +				       struct shrink_control *sc);
> +static long	nfsd_reply_cache_scan(struct shrinker *shrink,
> +				      struct shrink_control *sc);
>  
>  static struct shrinker nfsd_reply_cache_shrinker = {
> -	.shrink	= nfsd_reply_cache_shrink,
> +	.scan_objects = nfsd_reply_cache_scan,
> +	.count_objects = nfsd_reply_cache_count,
>  	.seeks	= 1,
>  };
>  
> @@ -232,16 +235,18 @@ nfsd_cache_entry_expired(struct svc_cacherep *rp)
>   * Walk the LRU list and prune off entries that are older than RC_EXPIRE.
>   * Also prune the oldest ones when the total exceeds the max number of entries.
>   */
> -static void
> +static long
>  prune_cache_entries(void)
>  {
>  	struct svc_cacherep *rp, *tmp;
> +	long freed = 0;
>  
>  	list_for_each_entry_safe(rp, tmp, &lru_head, c_lru) {
>  		if (!nfsd_cache_entry_expired(rp) &&
>  		    num_drc_entries <= max_drc_entries)
>  			break;
>  		nfsd_reply_cache_free_locked(rp);
> +		freed++;
>  	}
>  
>  	/*
> @@ -254,6 +259,7 @@ prune_cache_entries(void)
>  		cancel_delayed_work(&cache_cleaner);
>  	else
>  		mod_delayed_work(system_wq, &cache_cleaner, RC_EXPIRE);
> +	return freed;
>  }
>  
>  static void
> @@ -264,20 +270,27 @@ cache_cleaner_func(struct work_struct *unused)
>  	spin_unlock(&cache_lock);
>  }
>  
> -static int
> -nfsd_reply_cache_shrink(struct shrinker *shrink, struct shrink_control *sc)
> +static long
> +nfsd_reply_cache_count(struct shrinker *shrink, struct shrink_control *sc)
>  {
> -	unsigned int num;
> +	long num;
>  
>  	spin_lock(&cache_lock);
> -	if (sc->nr_to_scan)
> -		prune_cache_entries();
>  	num = num_drc_entries;
>  	spin_unlock(&cache_lock);
>  
>  	return num;
>  }
>  
> +static long
> +nfsd_reply_cache_scan(struct shrinker *shrink, struct shrink_control *sc)
> +{
> +	long freed;
> +	spin_lock(&cache_lock);
> +	freed = prune_cache_entries();
> +	spin_unlock(&cache_lock);
> +	return freed;
> +}
>  /*
>   * Walk an xdr_buf and get a CRC for at most the first RC_CSUMLEN bytes
>   */
> diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
> index 762b09c..fd6b762 100644
> --- a/fs/quota/dquot.c
> +++ b/fs/quota/dquot.c
> @@ -687,44 +687,42 @@ int dquot_quota_sync(struct super_block *sb, int type)
>  }
>  EXPORT_SYMBOL(dquot_quota_sync);
>  
> -/* Free unused dquots from cache */
> -static void prune_dqcache(int count)
> +static long
> +dqcache_shrink_scan(
> +	struct shrinker		*shrink,
> +	struct shrink_control	*sc)
>  {
>  	struct list_head *head;
>  	struct dquot *dquot;
> +	long freed = 0;
>  
>  	head = free_dquots.prev;
> -	while (head != &free_dquots && count) {
> +	while (head != &free_dquots && sc->nr_to_scan) {
>  		dquot = list_entry(head, struct dquot, dq_free);
>  		remove_dquot_hash(dquot);
>  		remove_free_dquot(dquot);
>  		remove_inuse(dquot);
>  		do_destroy_dquot(dquot);
> -		count--;
> +		sc->nr_to_scan--;
> +		freed++;
>  		head = free_dquots.prev;
>  	}
> +	return freed;
>  }
>  
> -/*
> - * This is called from kswapd when we think we need some
> - * more memory
> - */
> -static int shrink_dqcache_memory(struct shrinker *shrink,
> -				 struct shrink_control *sc)
> -{
> -	int nr = sc->nr_to_scan;
> +static long
> +dqcache_shrink_count(
> +	struct shrinker		*shrink,
> +	struct shrink_control	*sc)
>  
> -	if (nr) {
> -		spin_lock(&dq_list_lock);
> -		prune_dqcache(nr);
> -		spin_unlock(&dq_list_lock);
> -	}
> +{
>  	return vfs_pressure_ratio(
>  	percpu_counter_read_positive(&dqstats.counter[DQST_FREE_DQUOTS]));
>  }
>  
>  static struct shrinker dqcache_shrinker = {
> -	.shrink = shrink_dqcache_memory,
> +	.count_objects = dqcache_shrink_count,
> +	.scan_objects = dqcache_shrink_scan,
>  	.seeks = DEFAULT_SEEKS,
>  };
>  
> diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c
> index 9e1d056..669d8c0 100644
> --- a/fs/ubifs/shrinker.c
> +++ b/fs/ubifs/shrinker.c
> @@ -277,19 +277,23 @@ static int kick_a_thread(void)
>  	return 0;
>  }
>  
> -int ubifs_shrinker(struct shrinker *shrink, struct shrink_control *sc)
> +long ubifs_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
> +{
> +	long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt);
> +
> +	/*
> +	 * Due to the way UBIFS updates the clean znode counter it may
> +	 * temporarily be negative.
> +	 */
> +	return clean_zn_cnt >= 0 ? clean_zn_cnt : 1;
> +}
> +
> +long ubifs_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
>  {
>  	int nr = sc->nr_to_scan;
>  	int freed, contention = 0;
>  	long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt);
>  
> -	if (nr == 0)
> -		/*
> -		 * Due to the way UBIFS updates the clean znode counter it may
> -		 * temporarily be negative.
> -		 */
> -		return clean_zn_cnt >= 0 ? clean_zn_cnt : 1;
> -
>  	if (!clean_zn_cnt) {
>  		/*
>  		 * No clean znodes, nothing to reap. All we can do in this case
> diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
> index f21acf0..ff357e0 100644
> --- a/fs/ubifs/super.c
> +++ b/fs/ubifs/super.c
> @@ -49,7 +49,8 @@ struct kmem_cache *ubifs_inode_slab;
>  
>  /* UBIFS TNC shrinker description */
>  static struct shrinker ubifs_shrinker_info = {
> -	.shrink = ubifs_shrinker,
> +	.scan_objects = ubifs_shrink_scan,
> +	.count_objects = ubifs_shrink_count,
>  	.seeks = DEFAULT_SEEKS,
>  };
>  
> diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
> index b2babce..bcdafcc 100644
> --- a/fs/ubifs/ubifs.h
> +++ b/fs/ubifs/ubifs.h
> @@ -1624,7 +1624,8 @@ int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot);
>  int ubifs_tnc_end_commit(struct ubifs_info *c);
>  
>  /* shrinker.c */
> -int ubifs_shrinker(struct shrinker *shrink, struct shrink_control *sc);
> +long ubifs_shrink_scan(struct shrinker *shrink, struct shrink_control *sc);
> +long ubifs_shrink_count(struct shrinker *shrink, struct shrink_control *sc);
>  
>  /* commit.c */
>  int ubifs_bg_thread(void *info);
> -- 
> 1.8.1.4
> 
-- 
Jan Kara <jack@xxxxxxx>
SUSE Labs, CR
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux