From: Glauber Costa <glommer-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
To: Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
Cc: Glauber Costa <glommer-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Mel Gorman <mgorman-l3A5Bk7waGM@public.gmane.org>,
Dave Chinner <david-FqsqvQoI3Ljby3iVrkZq2A@public.gmane.org>,
linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org,
cgroups-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A@public.gmane.org,
Michal Hocko <mhocko-AlSwsSmVLrQ@public.gmane.org>,
Johannes Weiner <hannes-druUgvl0LCNAfugRpC6u6w@public.gmane.org>,
hughd-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
Greg Thelen <gthelen-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>,
Dave Chinner <dchinner-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Subject: Re: [PATCH v10 06/35] mm: new shrinker API
Date: Thu, 6 Jun 2013 11:58:04 +0400 [thread overview]
Message-ID: <51B0410C.9030908@parallels.com> (raw)
In-Reply-To: <20130605160751.499f0ebb35e89a80dd7931f2-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
On 06/06/2013 03:07 AM, Andrew Morton wrote:
> On Mon, 3 Jun 2013 23:29:35 +0400 Glauber Costa <glommer-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org> wrote:
>
>> From: Dave Chinner <dchinner-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>>
>> The current shrinker callout API uses an a single shrinker call for
>> multiple functions. To determine the function, a special magical
>> value is passed in a parameter to change the behaviour. This
>> complicates the implementation and return value specification for
>> the different behaviours.
>>
>> Separate the two different behaviours into separate operations, one
>> to return a count of freeable objects in the cache, and another to
>> scan a certain number of objects in the cache for freeing. In
>> defining these new operations, ensure the return values and
>> resultant behaviours are clearly defined and documented.
>>
>> Modify shrink_slab() to use the new API and implement the callouts
>> for all the existing shrinkers.
>>
>> ...
>>
>> --- a/include/linux/shrinker.h
>> +++ b/include/linux/shrinker.h
>> @@ -4,31 +4,47 @@
>> /*
>> * This struct is used to pass information from page reclaim to the shrinkers.
>> * We consolidate the values for easier extention later.
>> + *
>> + * The 'gfpmask' refers to the allocation we are currently trying to
>> + * fulfil.
>> + *
>> + * Note that 'shrink' will be passed nr_to_scan == 0 when the VM is
>> + * querying the cache size, so a fastpath for that case is appropriate.
>> */
>> struct shrink_control {
>> gfp_t gfp_mask;
>>
>> /* How many slab objects shrinker() should scan and try to reclaim */
>> - unsigned long nr_to_scan;
>> + long nr_to_scan;
>
> Why this change?
>
> (I might have asked this before, but because the changelog wasn't
> updated, you get to answer it again!)
>
There were various reasons to have a signed quantity for nr_to_scan, I
believe I fixed all of them by now. We still want the lru nr_items to be
a signed quantity, but this one can go. I will make sure of that, and
shout if there is any impediment still.
>> };
>>
>> /*
>> * A callback you can register to apply pressure to ageable caches.
>> *
>> - * 'sc' is passed shrink_control which includes a count 'nr_to_scan'
>> - * and a 'gfpmask'. It should look through the least-recently-used
>> - * 'nr_to_scan' entries and attempt to free them up. It should return
>> - * the number of objects which remain in the cache. If it returns -1, it means
>> - * it cannot do any scanning at this time (eg. there is a risk of deadlock).
>> + * @shrink() should look through the least-recently-used 'nr_to_scan' entries
>> + * and attempt to free them up. It should return the number of objects which
>> + * remain in the cache. If it returns -1, it means it cannot do any scanning at
>> + * this time (eg. there is a risk of deadlock).
>> *
>> - * The 'gfpmask' refers to the allocation we are currently trying to
>> - * fulfil.
>> + * @count_objects should return the number of freeable items in the cache. If
>> + * there are no objects to free or the number of freeable items cannot be
>> + * determined, it should return 0. No deadlock checks should be done during the
>> + * count callback - the shrinker relies on aggregating scan counts that couldn't
>> + * be executed due to potential deadlocks to be run at a later call when the
>> + * deadlock condition is no longer pending.
>> *
>> - * Note that 'shrink' will be passed nr_to_scan == 0 when the VM is
>> - * querying the cache size, so a fastpath for that case is appropriate.
>> + * @scan_objects will only be called if @count_objects returned a positive
>> + * value for the number of freeable objects.
>
> Saying "positive value" implies to me that count_objects() can return a
> negative code, but such a thing is not documented here. If
> count_objects() *doesn't* return a -ve code then s/positive/non-zero/
> here would clear up confusion.
>
Ok, I will update.
>> The callout should scan the cache
>> + * and attempt to free items from the cache. It should then return the number of
>> + * objects freed during the scan, or -1 if progress cannot be made due to
>> + * potential deadlocks. If -1 is returned, then no further attempts to call the
>> + * @scan_objects will be made from the current reclaim context.
>> */
>> struct shrinker {
>> int (*shrink)(struct shrinker *, struct shrink_control *sc);
>> + long (*count_objects)(struct shrinker *, struct shrink_control *sc);
>> + long (*scan_objects)(struct shrinker *, struct shrink_control *sc);
>
> As these both return counts-of-things, one would expect the return type
> to be unsigned.
>
> I assume that scan_objects was made signed for the "return -1" thing,
> although that might not have been the best decision - it could return
> ~0UL, for example.
>
Ok. By using long we are already limiting the amount of scanned objects
to half the size of an int anyway, so separating a special value won't hurt.
> It's unclear why count_objects() returns a signed quantity.
>
>
I can only guess, but I believe Dave originally just wanted them
symmetrical, for it was a slightly mechanical conversion.
The only benefit that can come from count_objects returning -1, is
catching conversion bugs. We had already caught one like this. Like a
shrinker is returning count < 0 because it was mistakenly converted, and
the "return -1" that existed before ended up in count and scan.
Since this have already proved useful once, how about we leave it like
this, give it some time in linux-next (I have audited Dave's conversion,
but very honestly I obviously haven't stressed tested all possible
drivers that have shrinkers).
vmscan have a WARN_ON() testing for that, so we'll know. I can provide
another patch to fix that after a while.
Would that work for you ?
>> int seeks; /* seeks to recreate an obj */
>> long batch; /* reclaim batch size, 0 = default */
>>
>> diff --git a/mm/vmscan.c b/mm/vmscan.c
>> index b1b38ad..6ac3ec2 100644
>> --- a/mm/vmscan.c
>> +++ b/mm/vmscan.c
>> @@ -205,19 +205,19 @@ static inline int do_shrinker_shrink(struct shrinker *shrinker,
>> *
>> * Returns the number of slab objects which we shrunk.
>> */
>> -unsigned long shrink_slab(struct shrink_control *shrink,
>> +unsigned long shrink_slab(struct shrink_control *shrinkctl,
>> unsigned long nr_pages_scanned,
>> unsigned long lru_pages)
>> {
>> struct shrinker *shrinker;
>> - unsigned long ret = 0;
>> + unsigned long freed = 0;
>>
>> if (nr_pages_scanned == 0)
>> nr_pages_scanned = SWAP_CLUSTER_MAX;
>>
>> if (!down_read_trylock(&shrinker_rwsem)) {
>> /* Assume we'll be able to shrink next time */
>> - ret = 1;
>> + freed = 1;
>
> That's odd - it didn't free anything? Needs a comment to avoid
> mystifying other readers.
>
This is because a return value of zero would make us stop trying. There
is a comment saying that: "Assume we'll be able to shrink next time",
but admittedly it is not saying much. I confess that I still remember
the first time I looked into this code, and it took me a while to figure
out this was the reason.
>> goto out;
>> }
>>
>> @@ -225,13 +225,16 @@ unsigned long shrink_slab(struct shrink_control *shrink,
>> unsigned long long delta;
>> long total_scan;
>> long max_pass;
>> - int shrink_ret = 0;
>> long nr;
>> long new_nr;
>> long batch_size = shrinker->batch ? shrinker->batch
>> : SHRINK_BATCH;
>>
>> - max_pass = do_shrinker_shrink(shrinker, shrink, 0);
>> + if (shrinker->scan_objects) {
>
> Did you mean to test ->scan_objects here? Or ->count_objects?
> ->scan_objects makes sense but I wanna know if it was a copy-n-paste
> bug.
>
It doesn't really matter, because:
1) This is temporary and will go away.
2) No shrinker is half-converted.
>> + max_pass = shrinker->count_objects(shrinker, shrinkctl);
>> + WARN_ON(max_pass < 0);
>
> OK so from that I see that ->count_objects() doesn't return negative.
>
> I this warning ever triggers, I expect it will trigger *a lot*.
> WARN_ON_ONCE would be more prudent. Or just nuke it.
>
I can change it to WARN_ON_ONCE. As I have suggested, we could leave it
like this (with WARN_ON_ONCE) for some time in linux-next until we are
more or less confident that this was stressed enough.
>> + } else
>> + max_pass = do_shrinker_shrink(shrinker, shrinkctl, 0);
>> if (max_pass <= 0)
>> continue;
>>
>> @@ -248,8 +251,8 @@ unsigned long shrink_slab(struct shrink_control *shrink,
>> do_div(delta, lru_pages + 1);
>> total_scan += delta;
>> if (total_scan < 0) {
>> - printk(KERN_ERR "shrink_slab: %pF negative objects to "
>> - "delete nr=%ld\n",
>> + printk(KERN_ERR
>> + "shrink_slab: %pF negative objects to delete nr=%ld\n",
>> shrinker->shrink, total_scan);
>> total_scan = max_pass;
>> }
>> @@ -277,20 +280,31 @@ unsigned long shrink_slab(struct shrink_control *shrink,
>> if (total_scan > max_pass * 2)
>> total_scan = max_pass * 2;
>>
>> - trace_mm_shrink_slab_start(shrinker, shrink, nr,
>> + trace_mm_shrink_slab_start(shrinker, shrinkctl, nr,
>> nr_pages_scanned, lru_pages,
>> max_pass, delta, total_scan);
>>
>> while (total_scan >= batch_size) {
>> - int nr_before;
>> + long ret;
>> +
>> + if (shrinker->scan_objects) {
>> + shrinkctl->nr_to_scan = batch_size;
>> + ret = shrinker->scan_objects(shrinker, shrinkctl);
>> +
>> + if (ret == -1)
>> + break;
>> + freed += ret;
>> + } else {
>> + int nr_before;
>> + nr_before = do_shrinker_shrink(shrinker, shrinkctl, 0);
>> + ret = do_shrinker_shrink(shrinker, shrinkctl,
>> + batch_size);
>> + if (ret == -1)
>> + break;
>> + if (ret < nr_before)
>
> This test seems unnecessary.
>
Everything within the "else" is going away in a couple of patches. This
is just to keep the tree working while we convert everybody. And since
this is just moving the code below inside a conditional, I would prefer
leaving it this way to make sure that this is actually just the same
code going to a different place.
>> + freed += nr_before - ret;
>> + }
>>
>> - nr_before = do_shrinker_shrink(shrinker, shrink, 0);
>> - shrink_ret = do_shrinker_shrink(shrinker, shrink,
>> - batch_size);
>> - if (shrink_ret == -1)
>> - break;
>> - if (shrink_ret < nr_before)
>> - ret += nr_before - shrink_ret;
>> count_vm_events(SLABS_SCANNED, batch_size);
>> total_scan -= batch_size;
>>
>> @@ -308,12 +322,12 @@ unsigned long shrink_slab(struct shrink_control *shrink,
>> else
>> new_nr = atomic_long_read(&shrinker->nr_in_batch);
>>
>> - trace_mm_shrink_slab_end(shrinker, shrink_ret, nr, new_nr);
>> + trace_mm_shrink_slab_end(shrinker, freed, nr, new_nr);
>> }
>> up_read(&shrinker_rwsem);
>> out:
>> cond_resched();
>> - return ret;
>> + return freed;
>> }
>>
>> static inline int is_page_cache_freeable(struct page *page)
>
> shrink_slab() has a long, long history of exhibiting various overflows
> - both multiplicative and over-incrementing. I looked, and can't see
> any introduction of such problems here, but please do check it
> carefully. Expect the impossible :(
>
Yes, cap'n. Will do that.
WARNING: multiple messages have this Message-ID (diff)
From: Glauber Costa <glommer-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
To: Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
Cc: Glauber Costa <glommer-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>,
<linux-fsdevel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
Mel Gorman <mgorman-l3A5Bk7waGM@public.gmane.org>,
Dave Chinner <david-FqsqvQoI3Ljby3iVrkZq2A@public.gmane.org>,
<linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org>,
<cgroups-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
<kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A@public.gmane.org>,
Michal Hocko <mhocko-AlSwsSmVLrQ@public.gmane.org>,
Johannes Weiner <hannes-druUgvl0LCNAfugRpC6u6w@public.gmane.org>,
<hughd-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>,
Greg Thelen <gthelen-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>,
Dave Chinner <dchinner-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Subject: Re: [PATCH v10 06/35] mm: new shrinker API
Date: Thu, 6 Jun 2013 11:58:04 +0400 [thread overview]
Message-ID: <51B0410C.9030908@parallels.com> (raw)
In-Reply-To: <20130605160751.499f0ebb35e89a80dd7931f2-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
On 06/06/2013 03:07 AM, Andrew Morton wrote:
> On Mon, 3 Jun 2013 23:29:35 +0400 Glauber Costa <glommer-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org> wrote:
>
>> From: Dave Chinner <dchinner-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>>
>> The current shrinker callout API uses an a single shrinker call for
>> multiple functions. To determine the function, a special magical
>> value is passed in a parameter to change the behaviour. This
>> complicates the implementation and return value specification for
>> the different behaviours.
>>
>> Separate the two different behaviours into separate operations, one
>> to return a count of freeable objects in the cache, and another to
>> scan a certain number of objects in the cache for freeing. In
>> defining these new operations, ensure the return values and
>> resultant behaviours are clearly defined and documented.
>>
>> Modify shrink_slab() to use the new API and implement the callouts
>> for all the existing shrinkers.
>>
>> ...
>>
>> --- a/include/linux/shrinker.h
>> +++ b/include/linux/shrinker.h
>> @@ -4,31 +4,47 @@
>> /*
>> * This struct is used to pass information from page reclaim to the shrinkers.
>> * We consolidate the values for easier extention later.
>> + *
>> + * The 'gfpmask' refers to the allocation we are currently trying to
>> + * fulfil.
>> + *
>> + * Note that 'shrink' will be passed nr_to_scan == 0 when the VM is
>> + * querying the cache size, so a fastpath for that case is appropriate.
>> */
>> struct shrink_control {
>> gfp_t gfp_mask;
>>
>> /* How many slab objects shrinker() should scan and try to reclaim */
>> - unsigned long nr_to_scan;
>> + long nr_to_scan;
>
> Why this change?
>
> (I might have asked this before, but because the changelog wasn't
> updated, you get to answer it again!)
>
There were various reasons to have a signed quantity for nr_to_scan, I
believe I fixed all of them by now. We still want the lru nr_items to be
a signed quantity, but this one can go. I will make sure of that, and
shout if there is any impediment still.
>> };
>>
>> /*
>> * A callback you can register to apply pressure to ageable caches.
>> *
>> - * 'sc' is passed shrink_control which includes a count 'nr_to_scan'
>> - * and a 'gfpmask'. It should look through the least-recently-used
>> - * 'nr_to_scan' entries and attempt to free them up. It should return
>> - * the number of objects which remain in the cache. If it returns -1, it means
>> - * it cannot do any scanning at this time (eg. there is a risk of deadlock).
>> + * @shrink() should look through the least-recently-used 'nr_to_scan' entries
>> + * and attempt to free them up. It should return the number of objects which
>> + * remain in the cache. If it returns -1, it means it cannot do any scanning at
>> + * this time (eg. there is a risk of deadlock).
>> *
>> - * The 'gfpmask' refers to the allocation we are currently trying to
>> - * fulfil.
>> + * @count_objects should return the number of freeable items in the cache. If
>> + * there are no objects to free or the number of freeable items cannot be
>> + * determined, it should return 0. No deadlock checks should be done during the
>> + * count callback - the shrinker relies on aggregating scan counts that couldn't
>> + * be executed due to potential deadlocks to be run at a later call when the
>> + * deadlock condition is no longer pending.
>> *
>> - * Note that 'shrink' will be passed nr_to_scan == 0 when the VM is
>> - * querying the cache size, so a fastpath for that case is appropriate.
>> + * @scan_objects will only be called if @count_objects returned a positive
>> + * value for the number of freeable objects.
>
> Saying "positive value" implies to me that count_objects() can return a
> negative code, but such a thing is not documented here. If
> count_objects() *doesn't* return a -ve code then s/positive/non-zero/
> here would clear up confusion.
>
Ok, I will update.
>> The callout should scan the cache
>> + * and attempt to free items from the cache. It should then return the number of
>> + * objects freed during the scan, or -1 if progress cannot be made due to
>> + * potential deadlocks. If -1 is returned, then no further attempts to call the
>> + * @scan_objects will be made from the current reclaim context.
>> */
>> struct shrinker {
>> int (*shrink)(struct shrinker *, struct shrink_control *sc);
>> + long (*count_objects)(struct shrinker *, struct shrink_control *sc);
>> + long (*scan_objects)(struct shrinker *, struct shrink_control *sc);
>
> As these both return counts-of-things, one would expect the return type
> to be unsigned.
>
> I assume that scan_objects was made signed for the "return -1" thing,
> although that might not have been the best decision - it could return
> ~0UL, for example.
>
Ok. By using long we are already limiting the amount of scanned objects
to half the size of an int anyway, so separating a special value won't hurt.
> It's unclear why count_objects() returns a signed quantity.
>
>
I can only guess, but I believe Dave originally just wanted them
symmetrical, for it was a slightly mechanical conversion.
The only benefit that can come from count_objects returning -1, is
catching conversion bugs. We had already caught one like this. Like a
shrinker is returning count < 0 because it was mistakenly converted, and
the "return -1" that existed before ended up in count and scan.
Since this have already proved useful once, how about we leave it like
this, give it some time in linux-next (I have audited Dave's conversion,
but very honestly I obviously haven't stressed tested all possible
drivers that have shrinkers).
vmscan have a WARN_ON() testing for that, so we'll know. I can provide
another patch to fix that after a while.
Would that work for you ?
>> int seeks; /* seeks to recreate an obj */
>> long batch; /* reclaim batch size, 0 = default */
>>
>> diff --git a/mm/vmscan.c b/mm/vmscan.c
>> index b1b38ad..6ac3ec2 100644
>> --- a/mm/vmscan.c
>> +++ b/mm/vmscan.c
>> @@ -205,19 +205,19 @@ static inline int do_shrinker_shrink(struct shrinker *shrinker,
>> *
>> * Returns the number of slab objects which we shrunk.
>> */
>> -unsigned long shrink_slab(struct shrink_control *shrink,
>> +unsigned long shrink_slab(struct shrink_control *shrinkctl,
>> unsigned long nr_pages_scanned,
>> unsigned long lru_pages)
>> {
>> struct shrinker *shrinker;
>> - unsigned long ret = 0;
>> + unsigned long freed = 0;
>>
>> if (nr_pages_scanned == 0)
>> nr_pages_scanned = SWAP_CLUSTER_MAX;
>>
>> if (!down_read_trylock(&shrinker_rwsem)) {
>> /* Assume we'll be able to shrink next time */
>> - ret = 1;
>> + freed = 1;
>
> That's odd - it didn't free anything? Needs a comment to avoid
> mystifying other readers.
>
This is because a return value of zero would make us stop trying. There
is a comment saying that: "Assume we'll be able to shrink next time",
but admittedly it is not saying much. I confess that I still remember
the first time I looked into this code, and it took me a while to figure
out this was the reason.
>> goto out;
>> }
>>
>> @@ -225,13 +225,16 @@ unsigned long shrink_slab(struct shrink_control *shrink,
>> unsigned long long delta;
>> long total_scan;
>> long max_pass;
>> - int shrink_ret = 0;
>> long nr;
>> long new_nr;
>> long batch_size = shrinker->batch ? shrinker->batch
>> : SHRINK_BATCH;
>>
>> - max_pass = do_shrinker_shrink(shrinker, shrink, 0);
>> + if (shrinker->scan_objects) {
>
> Did you mean to test ->scan_objects here? Or ->count_objects?
> ->scan_objects makes sense but I wanna know if it was a copy-n-paste
> bug.
>
It doesn't really matter, because:
1) This is temporary and will go away.
2) No shrinker is half-converted.
>> + max_pass = shrinker->count_objects(shrinker, shrinkctl);
>> + WARN_ON(max_pass < 0);
>
> OK so from that I see that ->count_objects() doesn't return negative.
>
> I this warning ever triggers, I expect it will trigger *a lot*.
> WARN_ON_ONCE would be more prudent. Or just nuke it.
>
I can change it to WARN_ON_ONCE. As I have suggested, we could leave it
like this (with WARN_ON_ONCE) for some time in linux-next until we are
more or less confident that this was stressed enough.
>> + } else
>> + max_pass = do_shrinker_shrink(shrinker, shrinkctl, 0);
>> if (max_pass <= 0)
>> continue;
>>
>> @@ -248,8 +251,8 @@ unsigned long shrink_slab(struct shrink_control *shrink,
>> do_div(delta, lru_pages + 1);
>> total_scan += delta;
>> if (total_scan < 0) {
>> - printk(KERN_ERR "shrink_slab: %pF negative objects to "
>> - "delete nr=%ld\n",
>> + printk(KERN_ERR
>> + "shrink_slab: %pF negative objects to delete nr=%ld\n",
>> shrinker->shrink, total_scan);
>> total_scan = max_pass;
>> }
>> @@ -277,20 +280,31 @@ unsigned long shrink_slab(struct shrink_control *shrink,
>> if (total_scan > max_pass * 2)
>> total_scan = max_pass * 2;
>>
>> - trace_mm_shrink_slab_start(shrinker, shrink, nr,
>> + trace_mm_shrink_slab_start(shrinker, shrinkctl, nr,
>> nr_pages_scanned, lru_pages,
>> max_pass, delta, total_scan);
>>
>> while (total_scan >= batch_size) {
>> - int nr_before;
>> + long ret;
>> +
>> + if (shrinker->scan_objects) {
>> + shrinkctl->nr_to_scan = batch_size;
>> + ret = shrinker->scan_objects(shrinker, shrinkctl);
>> +
>> + if (ret == -1)
>> + break;
>> + freed += ret;
>> + } else {
>> + int nr_before;
>> + nr_before = do_shrinker_shrink(shrinker, shrinkctl, 0);
>> + ret = do_shrinker_shrink(shrinker, shrinkctl,
>> + batch_size);
>> + if (ret == -1)
>> + break;
>> + if (ret < nr_before)
>
> This test seems unnecessary.
>
Everything within the "else" is going away in a couple of patches. This
is just to keep the tree working while we convert everybody. And since
this is just moving the code below inside a conditional, I would prefer
leaving it this way to make sure that this is actually just the same
code going to a different place.
>> + freed += nr_before - ret;
>> + }
>>
>> - nr_before = do_shrinker_shrink(shrinker, shrink, 0);
>> - shrink_ret = do_shrinker_shrink(shrinker, shrink,
>> - batch_size);
>> - if (shrink_ret == -1)
>> - break;
>> - if (shrink_ret < nr_before)
>> - ret += nr_before - shrink_ret;
>> count_vm_events(SLABS_SCANNED, batch_size);
>> total_scan -= batch_size;
>>
>> @@ -308,12 +322,12 @@ unsigned long shrink_slab(struct shrink_control *shrink,
>> else
>> new_nr = atomic_long_read(&shrinker->nr_in_batch);
>>
>> - trace_mm_shrink_slab_end(shrinker, shrink_ret, nr, new_nr);
>> + trace_mm_shrink_slab_end(shrinker, freed, nr, new_nr);
>> }
>> up_read(&shrinker_rwsem);
>> out:
>> cond_resched();
>> - return ret;
>> + return freed;
>> }
>>
>> static inline int is_page_cache_freeable(struct page *page)
>
> shrink_slab() has a long, long history of exhibiting various overflows
> - both multiplicative and over-incrementing. I looked, and can't see
> any introduction of such problems here, but please do check it
> carefully. Expect the impossible :(
>
Yes, cap'n. Will do that.
WARNING: multiple messages have this Message-ID (diff)
From: Glauber Costa <glommer@parallels.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Glauber Costa <glommer@openvz.org>,
linux-fsdevel@vger.kernel.org, Mel Gorman <mgorman@suse.de>,
Dave Chinner <david@fromorbit.com>,
linux-mm@kvack.org, cgroups@vger.kernel.org,
kamezawa.hiroyu@jp.fujitsu.com, Michal Hocko <mhocko@suse.cz>,
Johannes Weiner <hannes@cmpxchg.org>,
hughd@google.com, Greg Thelen <gthelen@google.com>,
Dave Chinner <dchinner@redhat.com>
Subject: Re: [PATCH v10 06/35] mm: new shrinker API
Date: Thu, 6 Jun 2013 11:58:04 +0400 [thread overview]
Message-ID: <51B0410C.9030908@parallels.com> (raw)
In-Reply-To: <20130605160751.499f0ebb35e89a80dd7931f2@linux-foundation.org>
On 06/06/2013 03:07 AM, Andrew Morton wrote:
> On Mon, 3 Jun 2013 23:29:35 +0400 Glauber Costa <glommer@openvz.org> wrote:
>
>> From: Dave Chinner <dchinner@redhat.com>
>>
>> The current shrinker callout API uses an a single shrinker call for
>> multiple functions. To determine the function, a special magical
>> value is passed in a parameter to change the behaviour. This
>> complicates the implementation and return value specification for
>> the different behaviours.
>>
>> Separate the two different behaviours into separate operations, one
>> to return a count of freeable objects in the cache, and another to
>> scan a certain number of objects in the cache for freeing. In
>> defining these new operations, ensure the return values and
>> resultant behaviours are clearly defined and documented.
>>
>> Modify shrink_slab() to use the new API and implement the callouts
>> for all the existing shrinkers.
>>
>> ...
>>
>> --- a/include/linux/shrinker.h
>> +++ b/include/linux/shrinker.h
>> @@ -4,31 +4,47 @@
>> /*
>> * This struct is used to pass information from page reclaim to the shrinkers.
>> * We consolidate the values for easier extention later.
>> + *
>> + * The 'gfpmask' refers to the allocation we are currently trying to
>> + * fulfil.
>> + *
>> + * Note that 'shrink' will be passed nr_to_scan == 0 when the VM is
>> + * querying the cache size, so a fastpath for that case is appropriate.
>> */
>> struct shrink_control {
>> gfp_t gfp_mask;
>>
>> /* How many slab objects shrinker() should scan and try to reclaim */
>> - unsigned long nr_to_scan;
>> + long nr_to_scan;
>
> Why this change?
>
> (I might have asked this before, but because the changelog wasn't
> updated, you get to answer it again!)
>
There were various reasons to have a signed quantity for nr_to_scan, I
believe I fixed all of them by now. We still want the lru nr_items to be
a signed quantity, but this one can go. I will make sure of that, and
shout if there is any impediment still.
>> };
>>
>> /*
>> * A callback you can register to apply pressure to ageable caches.
>> *
>> - * 'sc' is passed shrink_control which includes a count 'nr_to_scan'
>> - * and a 'gfpmask'. It should look through the least-recently-used
>> - * 'nr_to_scan' entries and attempt to free them up. It should return
>> - * the number of objects which remain in the cache. If it returns -1, it means
>> - * it cannot do any scanning at this time (eg. there is a risk of deadlock).
>> + * @shrink() should look through the least-recently-used 'nr_to_scan' entries
>> + * and attempt to free them up. It should return the number of objects which
>> + * remain in the cache. If it returns -1, it means it cannot do any scanning at
>> + * this time (eg. there is a risk of deadlock).
>> *
>> - * The 'gfpmask' refers to the allocation we are currently trying to
>> - * fulfil.
>> + * @count_objects should return the number of freeable items in the cache. If
>> + * there are no objects to free or the number of freeable items cannot be
>> + * determined, it should return 0. No deadlock checks should be done during the
>> + * count callback - the shrinker relies on aggregating scan counts that couldn't
>> + * be executed due to potential deadlocks to be run at a later call when the
>> + * deadlock condition is no longer pending.
>> *
>> - * Note that 'shrink' will be passed nr_to_scan == 0 when the VM is
>> - * querying the cache size, so a fastpath for that case is appropriate.
>> + * @scan_objects will only be called if @count_objects returned a positive
>> + * value for the number of freeable objects.
>
> Saying "positive value" implies to me that count_objects() can return a
> negative code, but such a thing is not documented here. If
> count_objects() *doesn't* return a -ve code then s/positive/non-zero/
> here would clear up confusion.
>
Ok, I will update.
>> The callout should scan the cache
>> + * and attempt to free items from the cache. It should then return the number of
>> + * objects freed during the scan, or -1 if progress cannot be made due to
>> + * potential deadlocks. If -1 is returned, then no further attempts to call the
>> + * @scan_objects will be made from the current reclaim context.
>> */
>> struct shrinker {
>> int (*shrink)(struct shrinker *, struct shrink_control *sc);
>> + long (*count_objects)(struct shrinker *, struct shrink_control *sc);
>> + long (*scan_objects)(struct shrinker *, struct shrink_control *sc);
>
> As these both return counts-of-things, one would expect the return type
> to be unsigned.
>
> I assume that scan_objects was made signed for the "return -1" thing,
> although that might not have been the best decision - it could return
> ~0UL, for example.
>
Ok. By using long we are already limiting the amount of scanned objects
to half the size of an int anyway, so separating a special value won't hurt.
> It's unclear why count_objects() returns a signed quantity.
>
>
I can only guess, but I believe Dave originally just wanted them
symmetrical, for it was a slightly mechanical conversion.
The only benefit that can come from count_objects returning -1, is
catching conversion bugs. We had already caught one like this. Like a
shrinker is returning count < 0 because it was mistakenly converted, and
the "return -1" that existed before ended up in count and scan.
Since this have already proved useful once, how about we leave it like
this, give it some time in linux-next (I have audited Dave's conversion,
but very honestly I obviously haven't stressed tested all possible
drivers that have shrinkers).
vmscan have a WARN_ON() testing for that, so we'll know. I can provide
another patch to fix that after a while.
Would that work for you ?
>> int seeks; /* seeks to recreate an obj */
>> long batch; /* reclaim batch size, 0 = default */
>>
>> diff --git a/mm/vmscan.c b/mm/vmscan.c
>> index b1b38ad..6ac3ec2 100644
>> --- a/mm/vmscan.c
>> +++ b/mm/vmscan.c
>> @@ -205,19 +205,19 @@ static inline int do_shrinker_shrink(struct shrinker *shrinker,
>> *
>> * Returns the number of slab objects which we shrunk.
>> */
>> -unsigned long shrink_slab(struct shrink_control *shrink,
>> +unsigned long shrink_slab(struct shrink_control *shrinkctl,
>> unsigned long nr_pages_scanned,
>> unsigned long lru_pages)
>> {
>> struct shrinker *shrinker;
>> - unsigned long ret = 0;
>> + unsigned long freed = 0;
>>
>> if (nr_pages_scanned == 0)
>> nr_pages_scanned = SWAP_CLUSTER_MAX;
>>
>> if (!down_read_trylock(&shrinker_rwsem)) {
>> /* Assume we'll be able to shrink next time */
>> - ret = 1;
>> + freed = 1;
>
> That's odd - it didn't free anything? Needs a comment to avoid
> mystifying other readers.
>
This is because a return value of zero would make us stop trying. There
is a comment saying that: "Assume we'll be able to shrink next time",
but admittedly it is not saying much. I confess that I still remember
the first time I looked into this code, and it took me a while to figure
out this was the reason.
>> goto out;
>> }
>>
>> @@ -225,13 +225,16 @@ unsigned long shrink_slab(struct shrink_control *shrink,
>> unsigned long long delta;
>> long total_scan;
>> long max_pass;
>> - int shrink_ret = 0;
>> long nr;
>> long new_nr;
>> long batch_size = shrinker->batch ? shrinker->batch
>> : SHRINK_BATCH;
>>
>> - max_pass = do_shrinker_shrink(shrinker, shrink, 0);
>> + if (shrinker->scan_objects) {
>
> Did you mean to test ->scan_objects here? Or ->count_objects?
> ->scan_objects makes sense but I wanna know if it was a copy-n-paste
> bug.
>
It doesn't really matter, because:
1) This is temporary and will go away.
2) No shrinker is half-converted.
>> + max_pass = shrinker->count_objects(shrinker, shrinkctl);
>> + WARN_ON(max_pass < 0);
>
> OK so from that I see that ->count_objects() doesn't return negative.
>
> I this warning ever triggers, I expect it will trigger *a lot*.
> WARN_ON_ONCE would be more prudent. Or just nuke it.
>
I can change it to WARN_ON_ONCE. As I have suggested, we could leave it
like this (with WARN_ON_ONCE) for some time in linux-next until we are
more or less confident that this was stressed enough.
>> + } else
>> + max_pass = do_shrinker_shrink(shrinker, shrinkctl, 0);
>> if (max_pass <= 0)
>> continue;
>>
>> @@ -248,8 +251,8 @@ unsigned long shrink_slab(struct shrink_control *shrink,
>> do_div(delta, lru_pages + 1);
>> total_scan += delta;
>> if (total_scan < 0) {
>> - printk(KERN_ERR "shrink_slab: %pF negative objects to "
>> - "delete nr=%ld\n",
>> + printk(KERN_ERR
>> + "shrink_slab: %pF negative objects to delete nr=%ld\n",
>> shrinker->shrink, total_scan);
>> total_scan = max_pass;
>> }
>> @@ -277,20 +280,31 @@ unsigned long shrink_slab(struct shrink_control *shrink,
>> if (total_scan > max_pass * 2)
>> total_scan = max_pass * 2;
>>
>> - trace_mm_shrink_slab_start(shrinker, shrink, nr,
>> + trace_mm_shrink_slab_start(shrinker, shrinkctl, nr,
>> nr_pages_scanned, lru_pages,
>> max_pass, delta, total_scan);
>>
>> while (total_scan >= batch_size) {
>> - int nr_before;
>> + long ret;
>> +
>> + if (shrinker->scan_objects) {
>> + shrinkctl->nr_to_scan = batch_size;
>> + ret = shrinker->scan_objects(shrinker, shrinkctl);
>> +
>> + if (ret == -1)
>> + break;
>> + freed += ret;
>> + } else {
>> + int nr_before;
>> + nr_before = do_shrinker_shrink(shrinker, shrinkctl, 0);
>> + ret = do_shrinker_shrink(shrinker, shrinkctl,
>> + batch_size);
>> + if (ret == -1)
>> + break;
>> + if (ret < nr_before)
>
> This test seems unnecessary.
>
Everything within the "else" is going away in a couple of patches. This
is just to keep the tree working while we convert everybody. And since
this is just moving the code below inside a conditional, I would prefer
leaving it this way to make sure that this is actually just the same
code going to a different place.
>> + freed += nr_before - ret;
>> + }
>>
>> - nr_before = do_shrinker_shrink(shrinker, shrink, 0);
>> - shrink_ret = do_shrinker_shrink(shrinker, shrink,
>> - batch_size);
>> - if (shrink_ret == -1)
>> - break;
>> - if (shrink_ret < nr_before)
>> - ret += nr_before - shrink_ret;
>> count_vm_events(SLABS_SCANNED, batch_size);
>> total_scan -= batch_size;
>>
>> @@ -308,12 +322,12 @@ unsigned long shrink_slab(struct shrink_control *shrink,
>> else
>> new_nr = atomic_long_read(&shrinker->nr_in_batch);
>>
>> - trace_mm_shrink_slab_end(shrinker, shrink_ret, nr, new_nr);
>> + trace_mm_shrink_slab_end(shrinker, freed, nr, new_nr);
>> }
>> up_read(&shrinker_rwsem);
>> out:
>> cond_resched();
>> - return ret;
>> + return freed;
>> }
>>
>> static inline int is_page_cache_freeable(struct page *page)
>
> shrink_slab() has a long, long history of exhibiting various overflows
> - both multiplicative and over-incrementing. I looked, and can't see
> any introduction of such problems here, but please do check it
> carefully. Expect the impossible :(
>
Yes, cap'n. Will do that.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2013-06-06 7:58 UTC|newest]
Thread overview: 248+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-03 19:29 [PATCH v10 00/35] kmemcg shrinkers Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 02/35] super: fix calculation of shrinkable objects for small numbers Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 05/35] dcache: remove dentries from LRU before putting on dispose list Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-05 23:07 ` Andrew Morton
2013-06-05 23:07 ` Andrew Morton
2013-06-06 8:04 ` Glauber Costa
2013-06-06 8:04 ` Glauber Costa
[not found] ` <1370287804-3481-1-git-send-email-glommer-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2013-06-03 19:29 ` [PATCH v10 01/35] fs: bump inode and dentry counters to long Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 03/35] dcache: convert dentry_stat.nr_unused to per-cpu counters Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-05 23:07 ` Andrew Morton
2013-06-05 23:07 ` Andrew Morton
2013-06-06 1:45 ` Dave Chinner
2013-06-06 2:48 ` Andrew Morton
2013-06-06 4:02 ` Dave Chinner
2013-06-06 12:40 ` Glauber Costa
2013-06-06 12:40 ` Glauber Costa
2013-06-06 22:25 ` Andrew Morton
2013-06-06 22:25 ` Andrew Morton
[not found] ` <20130606152546.52f614d852da32d28a0b460f-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2013-06-06 23:42 ` Dave Chinner
2013-06-06 23:42 ` Dave Chinner
2013-06-07 6:03 ` Glauber Costa
2013-06-07 6:03 ` Glauber Costa
2013-06-07 6:03 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 04/35] dentry: move to per-sb LRU locks Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-05 23:07 ` Andrew Morton
2013-06-05 23:07 ` Andrew Morton
2013-06-06 1:56 ` Dave Chinner
2013-06-06 8:03 ` Glauber Costa
2013-06-06 8:03 ` Glauber Costa
2013-06-06 12:51 ` Glauber Costa
2013-06-06 12:51 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 06/35] mm: new shrinker API Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-05 23:07 ` Andrew Morton
2013-06-05 23:07 ` Andrew Morton
[not found] ` <20130605160751.499f0ebb35e89a80dd7931f2-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2013-06-06 7:58 ` Glauber Costa [this message]
2013-06-06 7:58 ` Glauber Costa
2013-06-06 7:58 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 07/35] shrinker: convert superblock shrinkers to new API Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 08/35] list: add a new LRU list type Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
[not found] ` <1370287804-3481-9-git-send-email-glommer-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2013-06-05 23:07 ` Andrew Morton
2013-06-05 23:07 ` Andrew Morton
2013-06-05 23:07 ` Andrew Morton
2013-06-06 2:49 ` Dave Chinner
2013-06-06 2:49 ` Dave Chinner
2013-06-06 3:05 ` Andrew Morton
[not found] ` <20130605200554.d4dae16f.akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2013-06-06 4:44 ` Dave Chinner
2013-06-06 4:44 ` Dave Chinner
2013-06-06 7:04 ` Andrew Morton
2013-06-06 9:03 ` Glauber Costa
2013-06-06 9:03 ` Glauber Costa
2013-06-06 9:55 ` Andrew Morton
2013-06-06 9:55 ` Andrew Morton
[not found] ` <20130606025517.8400c279.akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2013-06-06 11:47 ` Glauber Costa
2013-06-06 11:47 ` Glauber Costa
2013-06-06 11:47 ` Glauber Costa
2013-06-06 14:28 ` Glauber Costa
2013-06-06 14:28 ` Glauber Costa
2013-06-06 14:28 ` Glauber Costa
2013-06-06 8:10 ` Glauber Costa
2013-06-06 8:10 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 09/35] inode: convert inode lru list to generic lru list code Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 10/35] dcache: convert to use new lru list infrastructure Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 11/35] list_lru: per-node " Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-05 23:08 ` Andrew Morton
2013-06-05 23:08 ` Andrew Morton
2013-06-06 3:21 ` Dave Chinner
2013-06-06 3:51 ` Andrew Morton
2013-06-06 3:51 ` Andrew Morton
2013-06-06 8:21 ` Glauber Costa
2013-06-06 8:21 ` Glauber Costa
2013-06-06 8:21 ` Glauber Costa
2013-06-06 16:15 ` Glauber Costa
2013-06-06 16:15 ` Glauber Costa
2013-06-06 16:48 ` Andrew Morton
2013-06-06 16:48 ` Andrew Morton
2013-06-06 16:48 ` Andrew Morton
2013-06-03 19:29 ` [PATCH v10 12/35] shrinker: add node awareness Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-05 23:08 ` Andrew Morton
2013-06-05 23:08 ` Andrew Morton
2013-06-06 3:26 ` Dave Chinner
2013-06-06 3:54 ` Andrew Morton
[not found] ` <20130605160810.5b203c3368b9df7d087ee3b1-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2013-06-06 8:23 ` Glauber Costa
2013-06-06 8:23 ` Glauber Costa
2013-06-06 8:23 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 13/35] vmscan: per-node deferred work Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-05 23:08 ` Andrew Morton
2013-06-05 23:08 ` Andrew Morton
2013-06-06 3:37 ` Dave Chinner
2013-06-06 4:59 ` Dave Chinner
2013-06-06 7:12 ` Andrew Morton
2013-06-06 7:12 ` Andrew Morton
[not found] ` <20130605160815.fb69f7d4d1736455727fc669-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2013-06-06 9:00 ` Glauber Costa
2013-06-06 9:00 ` Glauber Costa
2013-06-06 9:00 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 14/35] list_lru: per-node API Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 15/35] fs: convert inode and dentry shrinking to be node aware Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 16/35] xfs: convert buftarg LRU to generic code Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 17/35] xfs: rework buffer dispose list tracking Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 18/35] xfs: convert dquot cache lru to list_lru Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 19/35] fs: convert fs shrinkers to new scan/count API Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 21/35] i915: bail out earlier when shrinker cannot acquire mutex Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 22/35] shrinker: convert remaining shrinkers to count/scan API Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-05 23:08 ` Andrew Morton
2013-06-05 23:08 ` Andrew Morton
[not found] ` <20130605160821.59adf9ad4efe48144fd9e237-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2013-06-06 3:41 ` Dave Chinner
2013-06-06 3:41 ` Dave Chinner
2013-06-06 8:27 ` Glauber Costa
2013-06-06 8:27 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 23/35] hugepage: convert huge zero page shrinker to new shrinker API Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 24/35] shrinker: Kill old ->shrink API Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 25/35] vmscan: also shrink slab in memcg pressure Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 26/35] memcg,list_lru: duplicate LRUs upon kmemcg creation Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-05 23:08 ` Andrew Morton
2013-06-05 23:08 ` Andrew Morton
2013-06-05 23:08 ` Andrew Morton
[not found] ` <20130605160828.1ec9f3538258d9a6d6c74083-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2013-06-06 8:52 ` Glauber Costa
2013-06-06 8:52 ` Glauber Costa
2013-06-06 8:52 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 27/35] lru: add an element to a memcg list Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-05 23:08 ` Andrew Morton
2013-06-05 23:08 ` Andrew Morton
2013-06-05 23:08 ` Andrew Morton
2013-06-06 8:44 ` Glauber Costa
2013-06-06 8:44 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 28/35] list_lru: per-memcg walks Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-05 23:08 ` Andrew Morton
2013-06-05 23:08 ` Andrew Morton
[not found] ` <20130605160837.0d0a35fbd4b32d7ad02f7136-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2013-06-06 8:37 ` Glauber Costa
2013-06-06 8:37 ` Glauber Costa
2013-06-06 8:37 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 29/35] memcg: per-memcg kmem shrinking Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-05 23:08 ` Andrew Morton
2013-06-05 23:08 ` Andrew Morton
[not found] ` <20130605160841.909420c06bfde62039489d2e-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2013-06-06 8:35 ` Glauber Costa
2013-06-06 8:35 ` Glauber Costa
2013-06-06 8:35 ` Glauber Costa
2013-06-06 9:49 ` Andrew Morton
2013-06-06 9:49 ` Andrew Morton
[not found] ` <20130606024906.e5b85b28.akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2013-06-06 12:09 ` Glauber Costa
2013-06-06 12:09 ` Glauber Costa
2013-06-06 12:09 ` Glauber Costa
[not found] ` <51B07BEC.9010205-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
2013-06-06 22:23 ` Andrew Morton
2013-06-06 22:23 ` Andrew Morton
2013-06-06 22:23 ` Andrew Morton
2013-06-07 6:10 ` Glauber Costa
2013-06-07 6:10 ` Glauber Costa
2013-06-07 6:10 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 30/35] memcg: scan cache objects hierarchically Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-05 23:08 ` Andrew Morton
2013-06-05 23:08 ` Andrew Morton
2013-06-03 19:30 ` [PATCH v10 32/35] super: targeted memcg reclaim Glauber Costa
2013-06-03 19:30 ` Glauber Costa
2013-06-03 19:30 ` Glauber Costa
2013-06-03 19:30 ` [PATCH v10 33/35] memcg: move initialization to memcg creation Glauber Costa
2013-06-03 19:30 ` Glauber Costa
2013-06-03 19:30 ` Glauber Costa
2013-06-03 19:30 ` [PATCH v10 34/35] vmpressure: in-kernel notifications Glauber Costa
2013-06-03 19:30 ` Glauber Costa
2013-06-03 19:30 ` Glauber Costa
2013-06-03 19:30 ` [PATCH v10 35/35] memcg: reap dead memcgs upon global memory pressure Glauber Costa
2013-06-03 19:30 ` Glauber Costa
2013-06-03 19:30 ` Glauber Costa
2013-06-05 23:09 ` Andrew Morton
2013-06-05 23:09 ` Andrew Morton
2013-06-06 8:33 ` Glauber Costa
2013-06-06 8:33 ` Glauber Costa
2013-06-06 8:33 ` Glauber Costa
2013-06-03 19:29 ` [PATCH v10 20/35] drivers: convert shrinkers to new count/scan API Glauber Costa
2013-06-03 19:29 ` Glauber Costa
2013-06-03 19:30 ` [PATCH v10 31/35] vmscan: take at least one pass with shrinkers Glauber Costa
2013-06-03 19:30 ` Glauber Costa
2013-06-05 23:07 ` [PATCH v10 00/35] kmemcg shrinkers Andrew Morton
2013-06-05 23:07 ` Andrew Morton
2013-06-06 3:44 ` Dave Chinner
2013-06-06 5:51 ` Glauber Costa
2013-06-06 5:51 ` Glauber Costa
2013-06-06 5:51 ` Glauber Costa
[not found] ` <51B02347.60809-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
2013-06-06 7:18 ` Andrew Morton
2013-06-06 7:18 ` Andrew Morton
2013-06-06 7:18 ` Andrew Morton
[not found] ` <20130606001855.48d9da2e.akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2013-06-06 7:37 ` Glauber Costa
2013-06-06 7:37 ` Glauber Costa
2013-06-06 7:37 ` Glauber Costa
2013-06-06 7:47 ` Andrew Morton
2013-06-06 7:47 ` Andrew Morton
2013-06-06 7:59 ` Glauber Costa
2013-06-06 7:59 ` Glauber Costa
2013-06-06 7:59 ` Glauber Costa
[not found] ` <20130605160721.da995af82eb247ccf8f8537f-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2013-06-07 14:15 ` Michal Hocko
2013-06-07 14:15 ` Michal Hocko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51B0410C.9030908@parallels.com \
--to=glommer-bzqdu9zft3wakbo8gow8eq@public.gmane.org \
--cc=akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org \
--cc=cgroups-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=david-FqsqvQoI3Ljby3iVrkZq2A@public.gmane.org \
--cc=dchinner-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
--cc=glommer-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org \
--cc=gthelen-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
--cc=hannes-druUgvl0LCNAfugRpC6u6w@public.gmane.org \
--cc=hughd-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
--cc=kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A@public.gmane.org \
--cc=linux-fsdevel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org \
--cc=mgorman-l3A5Bk7waGM@public.gmane.org \
--cc=mhocko-AlSwsSmVLrQ@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.