Re: [PATCH 12/19] bcache: update bucket_in_use periodically

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

 



On 2017/7/1 上午4:43, bcache@xxxxxxxxxxxxxxxxxx wrote:
> From: Tang Junhui <tang.junhui@xxxxxxxxxx>
> 
> bucket_in_use is updated in gc thread which triggered by invalidating or
> writing sectors_to_gc dirty data, It's been too long, Therefore, when we
> use it to compare with the threshold, it is often not timely, which leads
> to inaccurate judgment and often results in bucket depletion.
> 
> Signed-off-by: Tang Junhui <tang.junhui@xxxxxxxxxx>
> ---
>  drivers/md/bcache/btree.c | 29 +++++++++++++++++++++++++++--
>  1 file changed, 27 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
> index 866dcf7..77aa20b 100644
> --- a/drivers/md/bcache/btree.c
> +++ b/drivers/md/bcache/btree.c
> @@ -90,6 +90,8 @@
>  #define MAX_NEED_GC		64
>  #define MAX_SAVE_PRIO		72
>  
> +#define GC_THREAD_TIMEOUT_MS	(30 * 1000)
> +
>  #define PTR_DIRTY_BIT		(((uint64_t) 1 << 36))
>  
>  #define PTR_HASH(c, k)							\
> @@ -1760,6 +1762,23 @@ static void bch_btree_gc(struct cache_set *c)
>  	bch_moving_gc(c);
>  }
>  
> +void bch_update_bucket_in_use(struct cache_set *c)
> +{
> +	struct cache *ca;
> +	struct bucket *b;
> +	unsigned i;
> +	size_t available = 0;
> +
> +	for_each_cache(ca, c, i) {
> +		for_each_bucket(b, ca) {
> +			if (!GC_MARK(b) || GC_MARK(b) == GC_MARK_RECLAIMABLE)
> +				available++;
> +		}
> +	}
> +

bucket_lock of cache set should be held before accessing buckets.


> +	c->gc_stats.in_use = (c->nbuckets - available) * 100 / c->nbuckets;
> +}
> +
>  static bool gc_should_run(struct cache_set *c)
>  {
>  	struct cache *ca;
> @@ -1778,10 +1797,16 @@ static bool gc_should_run(struct cache_set *c)
>  static int bch_gc_thread(void *arg)
>  {
>  	struct cache_set *c = arg;
> +	long  ret;
> +	unsigned long timeout = msecs_to_jiffies(GC_THREAD_TIMEOUT_MS);
>  
>  	while (1) {
> -		wait_event_interruptible(c->gc_wait,
> -			   kthread_should_stop() || gc_should_run(c));
> +		ret = wait_event_interruptible_timeout(c->gc_wait,
> +			   kthread_should_stop() || gc_should_run(c), timeout);
> +		if (!ret) {
> +			bch_update_bucket_in_use(c);
> +			continue;

A continue here will ignore status returned from kthread_should_stop(),
which might not be expected behavior.


> +		}
>  
>  		if (kthread_should_stop())
>  			break;
> 

Iterating all buckets from the cache set requires bucket_lock to be
held. Waiting for bucket_lock may take quite a long time for either
bucket allocating code or bch_gc_thread(). What I concern is, this patch
may introduce bucket allocation delay in period of GC_THREAD_TIMEOUT_MS.

We need to find out a way to avoid such a performance regression.

-- 
Coly Li



[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