On Tue, Apr 30, 2013 at 10:53:55PM +0100, Mel Gorman wrote:
> On Sat, Apr 27, 2013 at 03:19:13AM +0400, Glauber Costa wrote:
> > diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
> > index 03e44c1..8b9c1a6 100644
> > --- a/drivers/md/bcache/btree.c
> > +++ b/drivers/md/bcache/btree.c
> > @@ -599,11 +599,12 @@ static int mca_reap(struct btree *b, struct closure 
> > *cl, unsigned min_order)
> >     return 0;
> >  }
> >  
> > -static int bch_mca_shrink(struct shrinker *shrink, struct shrink_control 
> > *sc)
> > +static long bch_mca_scan(struct shrinker *shrink, struct shrink_control 
> > *sc)
> >  {
> >     struct cache_set *c = container_of(shrink, struct cache_set, shrink);
> >     struct btree *b, *t;
> >     unsigned long i, nr = sc->nr_to_scan;
> > +   long freed = 0;
> >  
> >     if (c->shrinker_disabled)
> >             return 0;
> 
> -1 if shrinker disabled?
> 
> Otherwise if the shrinker is disabled we ultimately hit this loop in
> shrink_slab_one()

My memory is very hazy on this stuff, but I recall there being another
loop that'd just spin if we always returned -1.

(It might've been /proc/sys/vm/drop_caches, or maybe that was another
bug..)

But 0 should certainly be safe - if we're always returning 0, then we're
claiming we don't have anything to shrink.

> do {
>       ret = shrinker->scan_objects(shrinker, sc);
>       if (ret == -1)
>               break
>       ....
>         count_vm_events(SLABS_SCANNED, batch_size);
>         total_scan -= batch_size;
> 
>         cond_resched();
> } while (total_scan >= batch_size);
> 
> which won't break as such but we busy loop until total_scan drops and
> account for SLABS_SCANNED incorrectly.
> 
> More using of mutex_lock in here which means that multiple direct reclaimers
> will contend on each other. bch_mca_shrink() checks for __GFP_WAIT but an
> atomic caller does not direct reclaim so it'll always try and contend.
> 
> > @@ -611,12 +612,6 @@ static int bch_mca_shrink(struct shrinker *shrink, 
> > struct shrink_control *sc)
> >     if (c->try_harder)
> >             return 0;
> >  
> > -   /*
> > -    * If nr == 0, we're supposed to return the number of items we have
> > -    * cached. Not allowed to return -1.
> > -    */
> > -   if (!nr)
> > -           return mca_can_free(c) * c->btree_pages;
> >  
> >     /* Return -1 if we can't do anything right now */
> >     if (sc->gfp_mask & __GFP_WAIT)
> > @@ -629,14 +624,14 @@ static int bch_mca_shrink(struct shrinker *shrink, 
> > struct shrink_control *sc)
> >  
> >     i = 0;
> >     list_for_each_entry_safe(b, t, &c->btree_cache_freeable, list) {
> > -           if (!nr)
> > +           if (freed >= nr)
> >                     break;
> >  
> >             if (++i > 3 &&
> >                 !mca_reap(b, NULL, 0)) {
> >                     mca_data_free(b);
> >                     rw_unlock(true, b);
> > -                   --nr;
> > +                   freed++;
> >             }
> >     }
> >  
> > @@ -647,7 +642,7 @@ static int bch_mca_shrink(struct shrinker *shrink, 
> > struct shrink_control *sc)
> >     if (list_empty(&c->btree_cache))
> >             goto out;
> >  
> > -   for (i = 0; nr && i < c->bucket_cache_used; i++) {
> > +   for (i = 0; i < c->bucket_cache_used; i++) {
> >             b = list_first_entry(&c->btree_cache, struct btree, list);
> >             list_rotate_left(&c->btree_cache);
> >  
> > @@ -656,14 +651,20 @@ static int bch_mca_shrink(struct shrinker *shrink, 
> > struct shrink_control *sc)
> >                     mca_bucket_free(b);
> >                     mca_data_free(b);
> >                     rw_unlock(true, b);
> > -                   --nr;
> > +                   freed++;
> >             } else
> >                     b->accessed = 0;
> >     }
> >  out:
> > -   nr = mca_can_free(c) * c->btree_pages;
> >     mutex_unlock(&c->bucket_lock);
> > -   return nr;
> > +   return freed;
> > +}
> > +
> > +static long bch_mca_count(struct shrinker *shrink, struct shrink_control 
> > *sc)
> > +{
> > +   struct cache_set *c = container_of(shrink, struct cache_set, shrink);
> > +
> > +   return mca_can_free(c) * c->btree_pages;
> >  }
> >  
> >  void bch_btree_cache_free(struct cache_set *c)
> > @@ -732,7 +733,8 @@ int bch_btree_cache_alloc(struct cache_set *c)
> >             c->verify_data = NULL;
> >  #endif
> >  
> > -   c->shrink.shrink = bch_mca_shrink;
> > +   c->shrink.count_objects = bch_mca_count;
> > +   c->shrink.scan_objects = bch_mca_scan;
> >     c->shrink.seeks = 4;
> >     c->shrink.batch = c->btree_pages * 2;
> >     register_shrinker(&c->shrink);
> > diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c
> > index 4d9cca4..fa8d048 100644
> > --- a/drivers/md/bcache/sysfs.c
> > +++ b/drivers/md/bcache/sysfs.c
> > @@ -535,7 +535,7 @@ STORE(__bch_cache_set)
> >             struct shrink_control sc;
> >             sc.gfp_mask = GFP_KERNEL;
> >             sc.nr_to_scan = strtoul_or_return(buf);
> > -           c->shrink.shrink(&c->shrink, &sc);
> > +           c->shrink.scan_objects(&c->shrink, &sc);
> >     }
> >  
> >     sysfs_strtoul(congested_read_threshold_us,
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to