Re: [PATCH 3/4] bcache: notify allocator to prepare for GC

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

 



On 2018/4/12 2:38 PM, tang.junhui@xxxxxxxxxx wrote:
> From: Tang Junhui <tang.junhui@xxxxxxxxxx>
> 
> Since no new bucket can be allocated during GC, and front side I/Os would
> run out of all the buckets, so notify allocator to pack the free_inc queue
> full of buckets before GC, then we could have enough buckets for front side
> I/Os during GC period.
> 
> Signed-off-by: Tang Junhui <tang.junhui@xxxxxxxxxx>

Hi Junhui,

This method is complicated IMHO. Why not in bch_allocator_thread()
simple call wake_up_gc(ca->set) after invalidate_buckets() ?

Thanks.

Coly Li

> ---
>  drivers/md/bcache/alloc.c  | 11 +++++++-
>  drivers/md/bcache/bcache.h |  2 ++
>  drivers/md/bcache/btree.c  | 69 ++++++++++++++++++++++++++++++++++++++++++++--
>  drivers/md/bcache/btree.h  |  4 +++
>  4 files changed, 83 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c
> index a0cc1bc..85020cc 100644
> --- a/drivers/md/bcache/alloc.c
> +++ b/drivers/md/bcache/alloc.c
> @@ -323,7 +323,8 @@ static int bch_allocator_thread(void *arg)
>  		 * possibly issue discards to them, then we add the bucket to
>  		 * the free list:
>  		 */
> -		while (!fifo_empty(&ca->free_inc)) {
> +		while (!fifo_empty(&ca->free_inc) &&
> +		       ca->prepare_gc != GC_PREPARING) {
>  			long bucket;
>  
>  			fifo_pop(&ca->free_inc, bucket);
> @@ -353,6 +354,14 @@ static int bch_allocator_thread(void *arg)
>  		invalidate_buckets(ca);
>  
>  		/*
> +		 * Let GC continue
> +		 */
> +		if (ca->prepare_gc == GC_PREPARING) {
> +			ca->prepare_gc = GC_PREPARED;
> +			wake_up_gc(ca->set);
> +		}
> +
> +		/*
>  		 * Now, we write their new gens to disk so we can start writing
>  		 * new stuff to them:
>  		 */
> diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
> index ab4c9ca..61a6ff2 100644
> --- a/drivers/md/bcache/bcache.h
> +++ b/drivers/md/bcache/bcache.h
> @@ -428,6 +428,8 @@ struct cache {
>  	 * cpu
>  	 */
>  	unsigned		invalidate_needs_gc;
> +	/* used to notify allocator to prepare GC*/
> +	unsigned int		prepare_gc;
>  
>  	bool			discard; /* Get rid of? */
>  
> diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
> index 10f967e..aba0700 100644
> --- a/drivers/md/bcache/btree.c
> +++ b/drivers/md/bcache/btree.c
> @@ -1805,6 +1805,46 @@ static void bch_btree_gc(struct cache_set *c)
>  	bch_moving_gc(c);
>  }
>  
> +static bool cache_gc_prepare_none(struct cache_set *c)
> +{
> +	struct cache *ca;
> +	unsigned int i;
> +
> +	for_each_cache(ca, c, i)
> +		if (ca->prepare_gc != GC_PREPARE_NONE)
> +			return false;
> +	return true;
> +}
> +
> +static bool cache_gc_prepare_ok(struct cache_set *c)
> +{
> +	struct cache *ca;
> +	unsigned int i;
> +
> +	for_each_cache(ca, c, i)
> +		if (ca->prepare_gc != GC_PREPARED)
> +			return false;
> +	return true;
> +}
> +
> +static void set_cache_gc_prepare_none(struct cache_set *c)
> +{
> +	struct cache *ca;
> +	unsigned int i;
> +
> +	for_each_cache(ca, c, i)
> +		ca->prepare_gc = GC_PREPARE_NONE;
> +}
> +
> +static void set_cache_gc_preparing(struct cache_set *c)
> +{
> +	struct cache *ca;
> +	unsigned int i;
> +
> +	for_each_cache(ca, c, i)
> +		ca->prepare_gc = GC_PREPARING;
> +}
> +
>  static bool gc_should_run(struct cache_set *c)
>  {
>  	struct cache *ca;
> @@ -1814,8 +1854,33 @@ static bool gc_should_run(struct cache_set *c)
>  		if (ca->invalidate_needs_gc)
>  			return true;
>  
> -	if (atomic_read(&c->sectors_to_gc) < 0)
> -		return true;
> +	if (atomic_read(&c->sectors_to_gc) < 0) {
> +		mutex_lock(&c->bucket_lock);
> +		if (cache_gc_prepare_none(c)) {
> +			/*
> +			 * notify allocator thread to prepare for GC
> +			 */
> +			set_cache_gc_preparing(c);
> +			mutex_unlock(&c->bucket_lock);
> +			pr_info("gc preparing");
> +			return false;
> +		} else if (cache_gc_prepare_ok(c)) {
> +			/*
> +			 * alloc thread finished preparing,
> +			 * and continue to GC
> +			 */
> +			set_cache_gc_prepare_none(c);
> +			mutex_unlock(&c->bucket_lock);
> +			pr_info("gc prepared ok");
> +			return true;
> +		} else {
> +			/*
> +			 * waitting allocator finishing prepareing
> +			 */
> +			mutex_unlock(&c->bucket_lock);
> +			return false;
> +		}
> +	}
>  
>  	return false;
>  }
> diff --git a/drivers/md/bcache/btree.h b/drivers/md/bcache/btree.h
> index d211e2c..e60bd7a 100644
> --- a/drivers/md/bcache/btree.h
> +++ b/drivers/md/bcache/btree.h
> @@ -102,6 +102,10 @@
>  #include "bset.h"
>  #include "debug.h"
>  
> +#define GC_PREPARE_NONE		0
> +#define GC_PREPARING		1
> +#define GC_PREPARED		2
> +
>  struct btree_write {
>  	atomic_t		*journal;
>  
> 




[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux