On 2018/4/12 2:38 PM, tang.jun...@zte.com.cn wrote:
> From: Tang Junhui <tang.jun...@zte.com.cn>
> 
> 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.jun...@zte.com.cn>

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;
>  
> 

Reply via email to