memcg: disable swap cgroup allocation at swapon
Subsystems (5)
v2 cover memcg: disable swap cgroup allocation at swapon
Hello,
Here is the v2 patch set for disabling swap_cgroup structures allocation per swapon.
In the initial version, one big issue is that I have missed the swap tracking for the root memcg, thanks Michal pointing it out. :)
In order to solve it, the easiest approach I can think out is to bypass the root memcg swap accounting during the business and figure it out with some global stats, which means that we always return 0 per root memcg swap charge/uncharge stage, and this is inspired by another proposal from Zhengju:
"memcg: Don't account root memcg page statistics -- https://lkml.org/lkml/2013/1/2/71"
Besides that, another major fix is deallocate swap accounting structures on the last non-root memcg remove after all references to it are gone rather than doing it on mem_cgroup_destroy().
Any comment are welcome!
v1->v2:
- Refactor swap_cgroup_swapon()/swap_cgroup_prepare(), to make the later can be used for allocating buffers per the first non-root memcg creation.
- Bypass root memcg swap statistics, using the global stats to figure it out instead.
- Export nr_swap_files which would be used when creating/freeing swap_cgroup
- Deallocate swap accounting structures on the last non-root memcg removal
Old patch set:
v1:
http://marc.info/?l=linux-mm&m=135461016823964&w=2
Thanks,
-Jeff
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 14 lines · Jeff Liu
Hello,
Here is the v2 patch set for disabling
swap_cgroupstructures allocation per swapon.In the initial version, one big issue is that I have missed the swap tracking for the root memcg, thanks Michal pointing it out. :)
In order to solve it, the easiest approach I can think out is to bypass the root memcg swap accounting during the business and figure it out with some global stats, which means that we always return 0 per root memcg swap charge/uncharge stage, and this is inspired by another proposal from Zhengju:
"memcg: Don't account root memcg page statistics -- https://lkml.org/lkml/2013/1/2/71"
Quoted 5 lines
Besides that, another major fix is deallocate swap accounting structures on the last non-root memcg remove after all references to it are gone rather than doing it on
mem_cgroup_destroy().Any comment are welcome!
Could you also post your testing methodology and results, please? It would be also really great if you could sum up memory savings.
Anyway thanks this second version looks really promising.
Quoted 20 lines
v1->v2:
- Refactor swap_cgroup_swapon()/swap_cgroup_prepare(), to make the later can be used for allocating buffers per the first non-root memcg creation.
- Bypass root memcg swap statistics, using the global stats to figure it out instead.
- Exportnr_swap_fileswhich would be used when creating/freeingswap_cgroup
- Deallocate swap accounting structures on the last non-root memcg removalOld patch set:
v1:
http://marc.info/?l=linux-mm&m=135461016823964&w=2Thanks,
-Jeff--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected] For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Signature · 2 lines
Michal Hocko SUSE Labs
Quoted 15 lines · Michal Hocko
Quoted 14 lines · Jeff Liu
Hello,
Here is the v2 patch set for disabling
swap_cgroupstructures allocation per swapon.In the initial version, one big issue is that I have missed the swap tracking for the root memcg, thanks Michal pointing it out. :)
In order to solve it, the easiest approach I can think out is to bypass the root memcg swap accounting during the business and figure it out with some global stats, which means that we always return 0 per root memcg swap charge/uncharge stage, and this is inspired by another proposal from Zhengju:
"memcg: Don't account root memcg page statistics -- https://lkml.org/lkml/2013/1/2/71"
Quoted 8 lines
Quoted 5 lines
Besides that, another major fix is deallocate swap accounting structures on the last non-root memcg remove after all references to it are gone rather than doing it on
mem_cgroup_destroy().Any comment are welcome!
Could you also post your testing methodology and results, please? It would be also really great if you could sum up memory savings.
Sure, I'll post those info in the next try, and will revisit [PATCH v2 2/6] and answer the comments from you and Glauber since my head is not very clear now. :)
Quoted 2 lines
Anyway thanks this second version looks really promising.
Thanks for your kind review, have a nice day!
-Jeff
Quoted 13 lines
Quoted 13 lines
v1->v2:
- Refactor swap_cgroup_swapon()/swap_cgroup_prepare(), to make the later can be used for allocating buffers per the first non-root memcg creation.
- Bypass root memcg swap statistics, using the global stats to figure it out instead.
- Exportnr_swap_fileswhich would be used when creating/freeingswap_cgroup
- Deallocate swap accounting structures on the last non-root memcg removalOld patch set:
v1:
http://marc.info/?l=linux-mm&m=135461016823964&w=2
Quoted 9 lines
Quoted 8 lines
Thanks,
-Jeff--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v2 1/6 memcg: refactor swap_cgroup_swapon()
Refector swap_cgroup_swapon() to setup the number of pages only, and move the rest to swap_cgroup_prepare(), so that the later can be used for allocating buffers when creating the first non-root memcg.
--- mm/page_cgroup.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-)
mm/page_cgroup.c +6 -11
@@ -360,6 +360,9 @@ static int swap_cgroup_prepare(int type)unsigned long idx, max; ctrl = &swap_cgroup_ctrl[type]; + ctrl->map =vzalloc (ctrl->length *sizeof (void *)); +if (!ctrl->map) + goto nomem;for (idx =0 ; idx < ctrl->length; idx++) { page =alloc_page (GFP_KERNEL | __GFP_ZERO);
@@ -368,11 +371,13 @@ static int swap_cgroup_prepare(int type) ctrl->map[idx] = page; }return 0 ; + not_enough_page: max = idx;for (idx =0 ; idx < max; idx++)__free_page (ctrl->map[idx]); - + ctrl->map =NULL ; +nomem:return -ENOMEM ; }
@@ -460,8 +465,6 @@ unsigned short lookup_swap_cgroup_id(swp_entry_t ent)int swap_cgroup_swapon (int type,unsigned long max_pages) { -void *array; -unsigned long array_size;unsigned long length;struct swap_cgroup_ctrl *ctrl;
@@ -469,23 +472,15 @@ int swap_cgroup_swapon(int type, unsigned long max_pages)return 0 ; length =DIV_ROUND_UP (max_pages,SC_PER_PAGE ); - array_size = length *sizeof (void *); - - array =vzalloc (array_size); -if (!array) - goto nomem; ctrl = &swap_cgroup_ctrl[type];mutex_lock (&swap_cgroup_mutex); ctrl->length = length; - ctrl->map = array;spin_lock_init (&ctrl->lock);if (swap_cgroup_prepare (type)) {/* memory shortage */ - ctrl->map =NULL ; ctrl->length =0 ;mutex_unlock (&swap_cgroup_mutex); -vfree (array); goto nomem; }mutex_unlock (&swap_cgroup_mutex);
Signature · 7 lines
1.7.9.5 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 1/6] memcg: refactor swap_cgroup_swapon()
Quoted 4 lines · Jeff Liu
Refector
swap_cgroup_swapon()to setup the number of pages only, and move the rest toswap_cgroup_prepare(), so that the later can be used for allocating buffers when creating the first non-root memcg.
Quoted 9 lines
Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <[email protected]>CC Sha Zhengju <[email protected]>
In itself seems just like a healthy reshuffling to me
So looks good.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 1/6] memcg: refactor swap_cgroup_swapon()
In reply to Jeff LiuQuoted 4 lines · Jeff Liu
Refector
swap_cgroup_swapon()to setup the number of pages only, and move the rest toswap_cgroup_prepare(), so that the later can be used for allocating buffers when creating the first non-root memcg.
Quoted 8 lines
Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <akpm-de/[email protected]>CC Sha Zhengju <[email protected]>
Makes sense and it even saves some lines.
Quoted 75 lines
--- mm/page_cgroup.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-)mm/page_cgroup.c +6
-11@@ -360,6 +360,9 @@ static int swap_cgroup_prepare(int type)unsigned long idx, max; ctrl = &swap_cgroup_ctrl[type]; + ctrl->map =vzalloc (ctrl->length *sizeof (void *)); +if (!ctrl->map) + goto nomem;for (idx =0 ; idx < ctrl->length; idx++) { page =alloc_page (GFP_KERNEL | __GFP_ZERO);@@ -368,11 +371,13 @@ static int swap_cgroup_prepare(int type) ctrl->map[idx] = page; }return 0 ; + not_enough_page: max = idx;for (idx =0 ; idx < max; idx++)__free_page (ctrl->map[idx]); - + ctrl->map =NULL ; +nomem:return -ENOMEM ; }@@ -460,8 +465,6 @@ unsigned short lookup_swap_cgroup_id(swp_entry_t ent)int swap_cgroup_swapon (int type,unsigned long max_pages) { -void *array; -unsigned long array_size;unsigned long length;struct swap_cgroup_ctrl *ctrl;@@ -469,23 +472,15 @@ int swap_cgroup_swapon(int type, unsigned long max_pages)return 0 ; length =DIV_ROUND_UP (max_pages,SC_PER_PAGE ); - array_size = length *sizeof (void *); - - array =vzalloc (array_size); -if (!array) - goto nomem; ctrl = &swap_cgroup_ctrl[type];mutex_lock (&swap_cgroup_mutex); ctrl->length = length; - ctrl->map = array;spin_lock_init (&ctrl->lock);if (swap_cgroup_prepare (type)) {/* memory shortage */ - ctrl->map =NULL ; ctrl->length =0 ;mutex_unlock (&swap_cgroup_mutex); -vfree (array); goto nomem; }mutex_unlock (&swap_cgroup_mutex);Signature · 7 lines
1.7.9.5 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected] For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Signature · 2 lines
Michal Hocko SUSE Labs
PATCH v2 2/6 memcg: bypass swap accounting for the root memcg
Root memcg with swap cgroup is special since we only do tracking but can not set limits against it. In order to facilitate the implementation of the coming swap cgroup structures delay allocation mechanism, we can bypass the default swap statistics upon the root memcg and figure it out through the global stats instead as below:
root_memcg_swap_stat: total_swap_pages - nr_swap_pages - used_swap_pages_of_all_memcgsmemcg_total_swap_stats: root_memcg_swap_stat + other_memcg_swap_stats
In this way, we'll return an invalid CSS_ID(generally, it's 0) at swap cgroup related tracking infrastructures if only the root memcg is alive. That is to say, we have not yet allocate swap cgroup structures. As a result, the per pages swapin/swapout stats number agains the root memcg shoud be ZERO.
--- mm/memcontrol.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-)
mm/memcontrol.c +30 -5
@@ -5231,12 +5231,34 @@ static int memcg_stat_show(struct cgroup *cont, struct cftype *cft,struct mem_cgroup *memcg =mem_cgroup_from_cont (cont);struct mem_cgroup *mi;unsigned int i; +long long root_swap_stat =0 ;for (i =0 ; i <MEM_CGROUP_STAT_NSTATS ; i++) { -if (i ==MEM_CGROUP_STAT_SWAP && !do_swap_account) -continue ; +long val =0 ; + +if (i !=MEM_CGROUP_STAT_SWAP ) + val =mem_cgroup_read_stat (memcg, i); +else { +if (!do_swap_account) +continue ; +if (!mem_cgroup_is_root (memcg)) + val =mem_cgroup_read_stat (memcg, i); +else { +/* +* The corresponding stat number of swap for +* root_mem_cgroup is 0 since we don't account +* it in any case. Instead, we can fake the +* root number via: total_swap_pages - +* nr_swap_pages - total_swap_pages_of_all_memcg +*/ +for_each_mem_cgroup (mi) + val +=mem_cgroup_read_stat (mi, i); + val = root_swap_stat = (total_swap_pages - + nr_swap_pages - val); + } + }seq_printf (m,"%s %ld\n" , mem_cgroup_stat_names[i], -mem_cgroup_read_stat (memcg, i) *PAGE_SIZE ); + val *PAGE_SIZE ); }for (i =0 ; i <MEM_CGROUP_EVENTS_NSTATS ; i++)
@@ -5260,8 +5282,11 @@ static int memcg_stat_show(struct cgroup *cont, struct cftype *cft,for (i =0 ; i <MEM_CGROUP_STAT_NSTATS ; i++) {long long val =0 ; -if (i ==MEM_CGROUP_STAT_SWAP && !do_swap_account) -continue ; +if (i ==MEM_CGROUP_STAT_SWAP ) { +if (!do_swap_account) +continue ; + val += root_swap_stat *PAGE_SIZE ; + }for_each_mem_cgroup_tree (mi, memcg) val +=mem_cgroup_read_stat (mi, i) *PAGE_SIZE ;seq_printf (m,"total_%s %lld\n" , mem_cgroup_stat_names[i], val);
Signature · 7 lines
1.7.9.5 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 2/6] memcg: bypass swap accounting for the root memcg
Quoted 6 lines · Jeff Liu
Root memcg with swap cgroup is special since we only do tracking but can not set limits against it. In order to facilitate the implementation of the coming swap cgroup structures delay allocation mechanism, we can bypass the default swap statistics upon the root memcg and figure it out through the global stats instead as below:
I am sorry if this is was already discussed before, but:
Quoted 3 lines
root_memcg_swap_stat:total_swap_pages-nr_swap_pages-used_swap_pages_of_all_memcgsmemcg_total_swap_stats:root_memcg_swap_stat+other_memcg_swap_stats
Shouldn't it *at least* be dependent on use_hierarchy?
I don't see why root_memcg won't be always total_swap_pages - nr_swap_pages, since the root memcg is always viewed as a superset of the others, AFAIR.
Even if it is not the general case (which again, I really believe it is), it certainly is the case for hierarchy enabled setups.
Also, I truly don't understand what is the business of root_memcg_swap_stat in non-root memcgs.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 2/6] memcg: bypass swap accounting for the root memcg
Hi Glauber,
Sorry for my late response!
Quoted 7 lines · Lord Glauber Costa of Sealand
Quoted 6 lines · Jeff Liu
Root memcg with swap cgroup is special since we only do tracking but can not set limits against it. In order to facilitate the implementation of the coming swap cgroup structures delay allocation mechanism, we can bypass the default swap statistics upon the root memcg and figure it out through the global stats instead as below:
Quoted 6 lines
I am sorry if this is was already discussed before, but:
Quoted 3 lines
root_memcg_swap_stat:total_swap_pages-nr_swap_pages-used_swap_pages_of_all_memcgsmemcg_total_swap_stats:root_memcg_swap_stat+other_memcg_swap_statsShouldn't it *at least* be dependent on
use_hierarchy?
Yeah, actually use_hierarchy only affects the total swap numbers. While computing memcg_total_swap_stats, it's original for_each_mem_cgroup_tree() way already handle the stuff about hierarchy and here we do not change its behavior. What we do is adding the root's local swap stat to total (since the root statistics are not accounting anymore, the per cpu data is ZERO).
Quoted 7 lines
I don't see why
root_memcgwon't be alwaystotal_swap_pages-nr_swap_pages, since the root memcg is always viewed as a superset of the others, AFAIR.Even if it is not the general case (which again, I really believe it is), it certainly is the case for hierarchy enabled setups.
I'm also confused a little by hierarchy recently especially the corresponding behavior of root is different... But we may have to do some modification just based on the current implementation as the plan of getting rid of hierarchy is slow as Michal mentioned.
Quoted 3 lines
Also, I truly don't understand what is the business of
root_memcg_swap_statin non-root memcgs.
root_memcg_swap_stat represents swap numbers belonging to the root mem cgroup. As its stats is 0 now, we need to fake it by the help of other memcgs, that is: global_used_swap - swaps_used_by_other_memcgs(non-root memcgs).
Thanks,
-Jeff
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 2/6] memcg: bypass swap accounting for the root memcg
In reply to Jeff LiuQuoted 7 lines · Jeff Liu
Root memcg with swap cgroup is special since we only do tracking but can not set limits against it. In order to facilitate the implementation of the coming swap cgroup structures delay allocation mechanism, we can bypass the default swap statistics upon the root memcg and figure it out through the global stats instead as below:
root_memcg_swap_stat:total_swap_pages-nr_swap_pages-used_swap_pages_of_all_memcgs
How do you protect from races with swap{in,out}? Or they are tolerable?
Quoted 1 line
memcg_total_swap_stats:root_memcg_swap_stat+other_memcg_swap_stats
I am not sure I understand and if I do then it is not true:
root (swap = 10M, use_hierarchy = 0/1)
\
A (swap = 1M, use_hierarchy = 1)
\
B (swap = 2M)total for A is 3M regardless of what root has "accounted" while total for root should be 10 for use_hierarchy = 0 and 13 for the other case (this is btw. broken in the tree already now because for_each_mem_cgroup_tree resp. mem_cgroup_iter doesn't honor use_hierarchy for the root cgroup - this is a separate topic though).
Quoted 46 lines
In this way, we'll return an invalid
CSS_ID(generally, it's 0)at swap cgroup related tracking infrastructures if only the root memcg is alive. That is to say, we have not yet allocate swap cgroup structures. As a result, the per pages swapin/swapout stats number agains the root memcg shoud be ZERO.Signed-off-by Jie Liu <[email protected]>Signed-off-by Sha Zhengju <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <[email protected]>--- mm/memcontrol.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-)mm/memcontrol.c +13
-2@@ -5231,12 +5231,34 @@ static int memcg_stat_show(struct cgroup *cont, struct cftype *cft,struct mem_cgroup *memcg =mem_cgroup_from_cont (cont);struct mem_cgroup *mi;unsigned int i; +long long root_swap_stat =0 ;for (i =0 ; i <MEM_CGROUP_STAT_NSTATS ; i++) { -if (i ==MEM_CGROUP_STAT_SWAP && !do_swap_account) -continue ; +long val =0 ; + +if (i !=MEM_CGROUP_STAT_SWAP ) + val =mem_cgroup_read_stat (memcg, i); +else { +if (!do_swap_account) +continue ; +if (!mem_cgroup_is_root (memcg)) + val =mem_cgroup_read_stat (memcg, i); +else { +/* +* The corresponding stat number of swap for
mm/memcontrol.c static int memcg_stat_show(struct cgroup *cont, struct cftype *cft, · line 5260
Quoted 10 lines
mm/memcontrol.c +10
-0+* root_mem_cgroup is 0 since we don't account +* it in any case. Instead, we can fake the +* root number via: total_swap_pages - +* nr_swap_pages - total_swap_pages_of_all_memcg +*/ +for_each_mem_cgroup (mi) + val +=mem_cgroup_read_stat (mi, i); + val = root_swap_stat = (total_swap_pages - + nr_swap_pages - val); + }
This calls for a helper.
Quoted 8 lines
mm/memcontrol.c +2
-1+ }seq_printf (m,"%s %ld\n" , mem_cgroup_stat_names[i], -mem_cgroup_read_stat (memcg, i) *PAGE_SIZE ); + val *PAGE_SIZE ); }mm/memcontrol.c +0
-0for (i =0 ; i <MEM_CGROUP_EVENTS_NSTATS ; i++)
mm/memcontrol.c static int memcg_stat_show(struct cgroup *cont, struct cftype *cft, · line 5289
Quoted 10 lines
mm/memcontrol.c +5
-2@@ -5260,8 +5282,11 @@ static int memcg_stat_show(struct cgroup *cont, struct cftype *cft,for (i =0 ; i <MEM_CGROUP_STAT_NSTATS ; i++) {long long val =0 ; -if (i ==MEM_CGROUP_STAT_SWAP && !do_swap_account) -continue ; +if (i ==MEM_CGROUP_STAT_SWAP ) { +if (!do_swap_account) +continue ; + val += root_swap_stat *PAGE_SIZE ; + }
This doesn't seem right because you are adding root swap amount to _all_ groups. This should be done only if (memcg == root_mem_cgroup).
Quoted 3 lines
mm/memcontrol.c +0
-0for_each_mem_cgroup_tree (mi, memcg) val +=mem_cgroup_read_stat (mi, i) *PAGE_SIZE ;seq_printf (m,"total_%s %lld\n" , mem_cgroup_stat_names[i], val);
Signature · 8 lines
Michal Hocko SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 2/6] memcg: bypass swap accounting for the root memcg
Quoted 10 lines · Michal Hocko
Quoted 7 lines · Jeff Liu
Root memcg with swap cgroup is special since we only do tracking but can not set limits against it. In order to facilitate the implementation of the coming swap cgroup structures delay allocation mechanism, we can bypass the default swap statistics upon the root memcg and figure it out through the global stats instead as below:
root_memcg_swap_stat:total_swap_pages-nr_swap_pages-used_swap_pages_of_all_memcgsHow do you protect from races with swap{in,out}? Or they are tolerable?
To be honest, I previously have not taken race with swapin/out into consideration.
Yes, this patch would cause a little error since it has to iterate each memcg which can introduce a bit overhead based on how many memcgs are configured.
However, considering our current implementation of swap statistics, we do account when swap cache is uncharged, but it is possible that the swap slot is already allocated before that. That is to say, there is a inconsistent window in swap accounting stats IMHO. As a figure shows to human, I think it can be tolerated to some extents. :)
Quoted 7 lines
Quoted 2 lines
memcg_total_swap_stats:root_memcg_swap_stat+other_memcg_swap_statsI am not sure I understand and if I do then it is not true:
root (swap = 10M,use_hierarchy= 0/1)
\
A (swap = 1M,use_hierarchy= 1)
Quoted 5 lines
\ B (swap = 2M)total for A is 3M regardless of what root has "accounted" while total for root should be 10 for
use_hierarchy= 0 and 13 for the other
I am not sure I catch your point, but I think the total for root should be 13 no matter use_hierarchy = 0 or 1, and the current patch is just doing that.
Originally, for_each_mem_cgroup_tree(iter, memcg) does statistics by iterating all those children memcgs including the memcg itself. But now, as we don't account the root memcg swap statistics anymore(hence the stats is 0), we need to add the local swap stats of root memcg itself(10M) to the memcg_total_swap_stats. So actually we don't change the way of accounting memcg_total_swap_stats.
Quoted 3 lines
case (this is btw. broken in the tree already now because
for_each_mem_cgroup_treeresp.mem_cgroup_iterdoesn't honoruse_hierarchyfor the root cgroup - this is a separate topic though).
Yes, I noticed that the for_each_mem_cgroup_tree() resp, mem_cgroup_iter() don't take the root->use_hierarchy into consideration, as it has the following logic:
if (!root->use_hierarchy && root != root_mem_cgroup) {
if (prev)
return NULL; return root; }
As i don't change the for_each_mem_cgroup_tree(), so it is in accordance with the original behavior.
Quoted 50 lines
Quoted 50 lines
In this way, we'll return an invalid
CSS_ID(generally, it's 0)at swap cgroup related tracking infrastructures if only the root memcg is alive. That is to say, we have not yet allocate swap cgroup structures. As a result, the per pages swapin/swapout stats number agains the root memcg shoud be ZERO.Signed-off-by Jie Liu <[email protected]>Signed-off-by Sha Zhengju <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <[email protected]>--- mm/memcontrol.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-)mm/memcontrol.c +17
-2@@ -5231,12 +5231,34 @@ static int memcg_stat_show(struct cgroup *cont, struct cftype *cft,struct mem_cgroup *memcg =mem_cgroup_from_cont (cont);struct mem_cgroup *mi;unsigned int i; +long long root_swap_stat =0 ;for (i =0 ; i <MEM_CGROUP_STAT_NSTATS ; i++) { -if (i ==MEM_CGROUP_STAT_SWAP && !do_swap_account) -continue ; +long val =0 ; + +if (i !=MEM_CGROUP_STAT_SWAP ) + val =mem_cgroup_read_stat (memcg, i); +else { +if (!do_swap_account) +continue ; +if (!mem_cgroup_is_root (memcg)) + val =mem_cgroup_read_stat (memcg, i); +else { +/* +* The corresponding stat number of swap for +* root_mem_cgroup is 0 since we don't account +* it in any case. Instead, we can fake the +* root number via: total_swap_pages - +* nr_swap_pages - total_swap_pages_of_all_memcg
Quoted 8 lines
mm/memcontrol.c static int memcg_stat_show(struct cgroup *cont, struct cftype *cft, · line 5258
Quoted 6 lines
mm/memcontrol.c +6
-0+*/ +for_each_mem_cgroup (mi) + val +=mem_cgroup_read_stat (mi, i); + val = root_swap_stat = (total_swap_pages - + nr_swap_pages - val); + }This calls for a helper.
Yes, Sir.
Quoted 12 lines
Quoted 12 lines
mm/memcontrol.c +2
-1+ }seq_printf (m,"%s %ld\n" , mem_cgroup_stat_names[i], -mem_cgroup_read_stat (memcg, i) *PAGE_SIZE ); + val *PAGE_SIZE ); }mm/memcontrol.c +0
-0for (i =0 ; i <MEM_CGROUP_EVENTS_NSTATS ; i++)@@ -5260,8 +5282,11 @@ static int memcg_stat_show(struct cgroup *cont, struct cftype *cft,for (i =0 ; i <MEM_CGROUP_STAT_NSTATS ; i++) {long long val =0 ;
Quoted 10 lines
mm/memcontrol.c static int memcg_stat_show(struct cgroup *cont, struct cftype *cft, · line 5289
Quoted 7 lines
mm/memcontrol.c +5
-2-if (i ==MEM_CGROUP_STAT_SWAP && !do_swap_account) -continue ; +if (i ==MEM_CGROUP_STAT_SWAP ) { +if (!do_swap_account) +continue ; + val += root_swap_stat *PAGE_SIZE ; + }This doesn't seem right because you are adding root swap amount to _all_ groups. This should be done only if (memcg ==
root_mem_cgroup).
Ah, I?m too dumb!
Thanks,
-Jeff
Quoted 4 lines
mm/memcontrol.c static int memcg_stat_show(struct cgroup *cont, struct cftype *cft, · line 5292
Quoted 4 lines
mm/memcontrol.c +0
-0for_each_mem_cgroup_tree (mi, memcg) val +=mem_cgroup_read_stat (mi, i) *PAGE_SIZE ;seq_printf (m,"total_%s %lld\n" , mem_cgroup_stat_names[i], val);
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 2/6] memcg: bypass swap accounting for the root memcg
Quoted 18 lines · Jeff Liu
Quoted 8 lines · Michal Hocko
Quoted 7 lines · Jeff Liu
Root memcg with swap cgroup is special since we only do tracking but can not set limits against it. In order to facilitate the implementation of the coming swap cgroup structures delay allocation mechanism, we can bypass the default swap statistics upon the root memcg and figure it out through the global stats instead as below:
Quoted 5 lines
Quoted 2 lines
root_memcg_swap_stat:total_swap_pages-nr_swap_pages-used_swap_pages_of_all_memcgsHow do you protect from races with swap{in,out}? Or they are tolerable?
To be honest, I previously have not taken race with swapin/out into consideration.
Quoted 7 lines
Yes, this patch would cause a little error since it has to iterate each memcg which can introduce a bit overhead based on how many memcgs are configured.
However, considering our current implementation of swap statistics, we do account when swap cache is uncharged, but it is possible that the swap slot is already allocated before that.
I am not sure I follow you here. I was merely interested in races while there is a swapping activity while the value is calculated. The errors, or let's say imprecision, shouldn't be big but it would be good to think how big it can be and how it can be reduced (e.g. what if we start accounting for root once there is another group existing - this would solve the problem of delayed allocation and the imprecision as well).
Quoted 12 lines
That is to say, there is a inconsistent window in swap accounting stats IMHO. As a figure shows to human, I think it can be tolerated to some extents. :)
Quoted 10 lines
Quoted 2 lines
memcg_total_swap_stats:root_memcg_swap_stat+other_memcg_swap_statsI am not sure I understand and if I do then it is not true:
root (swap = 10M,use_hierarchy= 0/1)
\
A (swap = 1M,use_hierarchy= 1)\ B (swap = 2M)
Quoted 7 lines
Quoted 3 lines
total for A is 3M regardless of what root has "accounted" while total for root should be 10 for
use_hierarchy= 0 and 13 for the otherI am not sure I catch your point, but I think the total for root should be 13 no matter
use_hierarchy= 0 or 1, and the current patch is just doing that.
I do not see any reason to make root different wrt. other roots of hierarchy. Anyway this is not important right now.
Quoted 6 lines
Originally,
for_each_mem_cgroup_tree(iter, memcg)does statistics by iterating all those children memcgs including the memcg itself. But now, as we don't account the root memcg swap statistics anymore(hence the stats is 0), we need to add the local swap stats of root memcg itself(10M) to thememcg_total_swap_stats. So actually we don't change the way of accountingmemcg_total_swap_stats.
I guess you are talking about tatal_ numbers. And yes, your patch doesn't change that.
Quoted 10 lines
Quoted 4 lines
case (this is btw. broken in the tree already now because
for_each_mem_cgroup_treeresp.mem_cgroup_iterdoesn't honoruse_hierarchyfor the root cgroup - this is a separate topic though).Yes, I noticed that the
for_each_mem_cgroup_tree()resp,mem_cgroup_iter()don't take theroot->use_hierarchyinto consideration, as it has the following logic:
if (!root->use_hierarchy && root !=root_mem_cgroup) {
if (prev)
Quoted 6 lines
return NULL; return root; }As i don't change the
for_each_mem_cgroup_tree(), so it is in accordance with the original behavior.
True, and I was just mentioning that as I noticed this only during the review. It wasn't meant to dispute your patch. Sorry if this wasn't clear enough. We have that behavior for ages and nobody complained so it is probably not worth fixing (especially when use_hierarchy is on the way out very sloooooowly).
[...]
Thanks
Signature · 8 lines
Michal Hocko SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 2/6] memcg: bypass swap accounting for the root memcg
Quoted 31 lines · Michal Hocko
Quoted 18 lines · Jeff Liu
Quoted 8 lines · Michal Hocko
Quoted 7 lines · Jeff Liu
Root memcg with swap cgroup is special since we only do tracking but can not set limits against it. In order to facilitate the implementation of the coming swap cgroup structures delay allocation mechanism, we can bypass the default swap statistics upon the root memcg and figure it out through the global stats instead as below:
Quoted 5 lines
Quoted 2 lines
root_memcg_swap_stat:total_swap_pages-nr_swap_pages-used_swap_pages_of_all_memcgsHow do you protect from races with swap{in,out}? Or they are tolerable?
To be honest, I previously have not taken race with swapin/out into consideration.
Quoted 7 lines
Yes, this patch would cause a little error since it has to iterate each memcg which can introduce a bit overhead based on how many memcgs are configured.
However, considering our current implementation of swap statistics, we do account when swap cache is uncharged, but it is possible that the swap slot is already allocated before that.
I am not sure I follow you here. I was merely interested in races while there is a swapping activity while the value is calculated. The errors, or let's say imprecision, shouldn't be big but it would be good to think how big it can be and how it can be reduced
...
Quoted 3 lines
(e.g. what if we start
accounting for root once there is another group existing - this would solve the problem of delayed allocation and the imprecision as well).
At first, I also tried to account for root memcg swap in this sway, i.e. return the root_memcg css_id from swap_cgroup_cmpxchg() && swap_cgroup_record() if there is no children memcg exists, however, it caused the kernel panic with deadlock...
If return 0 from both functions in this case, no panic but it's obviously that the root memcg swap accounting number is wrong, so that's why I choose the current idea to bypass it...
I need some time to dig into the details anyway.
Quoted 31 lines
Quoted 13 lines
That is to say, there is a inconsistent window in swap accounting stats IMHO. As a figure shows to human, I think it can be tolerated to some extents. :)
Quoted 10 lines
Quoted 2 lines
memcg_total_swap_stats:root_memcg_swap_stat+other_memcg_swap_statsI am not sure I understand and if I do then it is not true:
root (swap = 10M,use_hierarchy= 0/1)
\
A (swap = 1M,use_hierarchy= 1)\ B (swap = 2M)Quoted 7 lines
Quoted 3 lines
total for A is 3M regardless of what root has "accounted" while total for root should be 10 for
use_hierarchy= 0 and 13 for the otherI am not sure I catch your point, but I think the total for root should be 13 no matter
use_hierarchy= 0 or 1, and the current patch is just doing that.I do not see any reason to make root different wrt. other roots of hierarchy. Anyway this is not important right now.
Quoted 6 lines
Originally,
for_each_mem_cgroup_tree(iter, memcg)does statistics by iterating all those children memcgs including the memcg itself. But now, as we don't account the root memcg swap statistics anymore(hence the stats is 0), we need to add the local swap stats of root memcg itself(10M) to thememcg_total_swap_stats. So actually we don't change the way of accountingmemcg_total_swap_stats.
Quoted 2 lines
I guess you are talking about
tatal_numbers. And yes, your patch doesn't change that.
Yes.
Thanks you!
-Jeff
Quoted 24 lines
Quoted 11 lines
Quoted 5 lines
case (this is btw. broken in the tree already now because
for_each_mem_cgroup_treeresp.mem_cgroup_iterdoesn't honoruse_hierarchyfor the root cgroup - this is a separate topic though).Yes, I noticed that the
for_each_mem_cgroup_tree()resp,mem_cgroup_iter()don't take theroot->use_hierarchyinto consideration, as it has the following logic:
if (!root->use_hierarchy && root !=root_mem_cgroup) {
if (prev)Quoted 6 lines
return NULL; return root; }As i don't change the
for_each_mem_cgroup_tree(), so it is in accordance with the original behavior.True, and I was just mentioning that as I noticed this only during the review. It wasn't meant to dispute your patch. Sorry if this wasn't clear enough. We have that behavior for ages and nobody complained so it is probably not worth fixing (especially when
use_hierarchyis on the way out very sloooooowly).
Quoted 4 lines
[...]
Thanks
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v2 3/6 memcg: introduce memsw_accounting_users
As we don't account the swap stat number for the root_mem_cgroup anymore, here we can just return an invalid CSS ID if there is no non-root memcg is alive. Also, introduce memsw_accounting_users to track the number of active non-root memcgs.
--- mm/page_cgroup.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
mm/page_cgroup.c +15 -1
@@ -336,6 +336,8 @@ struct swap_cgroup { };#define SC_PER_PAGE (PAGE_SIZE/sizeof(struct swap_cgroup)) +static atomic_t memsw_accounting_users =ATOMIC_INIT (0 ); +/* * SwapCgroup implements "lookup" and "exchange" operations. * In typical usage, this swap_cgroup is accessed via memcg's charge/uncharge
@@ -389,6 +391,9 @@ static struct swap_cgroup *lookup_swap_cgroup(swp_entry_t ent,struct page *mappage;struct swap_cgroup *sc; +if (!atomic_read (&memsw_accounting_users)) +return NULL ; + ctrl = &swap_cgroup_ctrl[swp_type (ent)];if (ctrlp) *ctrlp = ctrl;
@@ -416,6 +421,8 @@ unsigned short swap_cgroup_cmpxchg(swp_entry_t ent,unsigned short retval; sc =lookup_swap_cgroup (ent, &ctrl); +if (!sc) +return 0 ;spin_lock_irqsave (&ctrl->lock, flags); retval = sc->id;
@@ -443,6 +450,8 @@ unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id)unsigned long flags; sc =lookup_swap_cgroup (ent, &ctrl); +if (!sc) +return 0 ;spin_lock_irqsave (&ctrl->lock, flags); old = sc->id;
@@ -460,7 +469,9 @@ unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id)*/ unsigned short lookup_swap_cgroup_id (swp_entry_t ent) { -return lookup_swap_cgroup (ent,NULL )->id; +struct swap_cgroup *sc =lookup_swap_cgroup (ent,NULL ); + +return sc ? sc->id :0 ; }int swap_cgroup_swapon (int type,unsigned long max_pages)
@@ -471,6 +482,9 @@ int swap_cgroup_swapon(int type, unsigned long max_pages)if (!do_swap_account)return 0 ; +if (!atomic_read (&memsw_accounting_users)) +return 0 ; + length =DIV_ROUND_UP (max_pages,SC_PER_PAGE ); ctrl = &swap_cgroup_ctrl[type];
Signature · 7 lines
1.7.9.5 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 3/6] memcg: introduce memsw_accounting_users
Hi,
Quoted 23 lines · Jeff Liu
As we don't account the swap stat number for the
root_mem_cgroupanymore, here we can just return an invalid CSS ID if there is no non-root memcg is alive. Also, introducememsw_accounting_usersto track the number of active non-root memcgs.Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <[email protected]>CC Sha Zhengju <[email protected]>--- mm/page_cgroup.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)mm/page_cgroup.c +0
-0
mm/page_cgroup.c struct swap_cgroup { · line 340
Quoted 5 lines
mm/page_cgroup.c +2
-0@@ -336,6 +336,8 @@ struct swap_cgroup { };#define SC_PER_PAGE (PAGE_SIZE/sizeof(struct swap_cgroup)) +static atomic_t memsw_accounting_users =ATOMIC_INIT (0 ); +
I am not seeing this being incremented or decremented. I can only guess that it comes in later patches. However, they are clearly used as a global reference counter.
This is precisely one of the use cases static branches solve very neatly. Did you consider using them?
True, they will help a lot more when we are touching hot paths, and swap is hardly a hot path.
However, since one of the main complaints about memcg has been that we inflict "death by a thousand cuts", maybe it wouldn't hurt everything else being the same.
Michal and others, do you have any feelings here?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 3/6] memcg: introduce memsw_accounting_users
Quoted 36 lines · Lord Glauber Costa of Sealand
Hi,
Quoted 23 lines · Jeff Liu
As we don't account the swap stat number for the
root_mem_cgroupanymore, here we can just return an invalid CSS ID if there is no non-root memcg is alive. Also, introducememsw_accounting_usersto track the number of active non-root memcgs.Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <[email protected]>CC Sha Zhengju <[email protected]>--- mm/page_cgroup.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)mm/page_cgroup.c +0
-0mm/page_cgroup.c struct swap_cgroup { · line 340
Quoted 5 lines
mm/page_cgroup.c +2
-0@@ -336,6 +336,8 @@ struct swap_cgroup { };#define SC_PER_PAGE (PAGE_SIZE/sizeof(struct swap_cgroup)) +static atomic_t memsw_accounting_users =ATOMIC_INIT (0 ); +I am not seeing this being incremented or decremented. I can only guess that it comes in later patches. However, they are clearly used as a global reference counter.
Quoted 2 lines
This is precisely one of the use cases static branches solve very neatly. Did you consider using them?
Yep, I'll try to replace it with the static branches if there are no objections from the others. :)
Thanks,
-Jeff
Quoted 10 lines
True, they will help a lot more when we are touching hot paths, and swap is hardly a hot path.
However, since one of the main complaints about memcg has been that we inflict "death by a thousand cuts", maybe it wouldn't hurt everything else being the same.
Michal and others, do you have any feelings here?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 3/6] memcg: introduce memsw_accounting_users
In reply to Lord Glauber Costa of SealandQuoted 39 lines · Glauber Costa
Hi,
Quoted 23 lines · Jeff Liu
As we don't account the swap stat number for the
root_mem_cgroupanymore, here we can just return an invalid CSS ID if there is no non-root memcg is alive. Also, introducememsw_accounting_usersto track the number of active non-root memcgs.Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <[email protected]>CC Sha Zhengju <[email protected]>--- mm/page_cgroup.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)mm/page_cgroup.c +0
-0mm/page_cgroup.c struct swap_cgroup { · line 340
Quoted 5 lines
mm/page_cgroup.c +2
-0@@ -336,6 +336,8 @@ struct swap_cgroup { };#define SC_PER_PAGE (PAGE_SIZE/sizeof(struct swap_cgroup)) +static atomic_t memsw_accounting_users =ATOMIC_INIT (0 ); +I am not seeing this being incremented or decremented. I can only guess that it comes in later patches. However, they are clearly used as a global reference counter.
This is precisely one of the use cases static branches solve very neatly. Did you consider using them?
Quoted 8 lines
True, they will help a lot more when we are touching hot paths, and swap is hardly a hot path.
However, since one of the main complaints about memcg has been that we inflict "death by a thousand cuts", maybe it wouldn't hurt everything else being the same.
Michal and others, do you have any feelings here?
I would leave a static branch change to a separate patch. Make it work first and only then care about how it looks.
Signature · 8 lines
Michal Hocko SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 3/6] memcg: introduce memsw_accounting_users
In reply to Jeff LiuQuoted 23 lines · Jeff Liu
As we don't account the swap stat number for the
root_mem_cgroupanymore, here we can just return an invalid CSS ID if there is no non-root memcg is alive. Also, introducememsw_accounting_usersto track the number of active non-root memcgs.Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <akpm-de/[email protected]>CC Sha Zhengju <[email protected]>--- mm/page_cgroup.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)mm/page_cgroup.c +0
-0
mm/page_cgroup.c struct swap_cgroup { · line 339
Quoted 4 lines
mm/page_cgroup.c +1
-0@@ -336,6 +336,8 @@ struct swap_cgroup { };#define SC_PER_PAGE (PAGE_SIZE/sizeof(struct swap_cgroup)) +static atomic_t memsw_accounting_users =ATOMIC_INIT (0 );
Nobody manipulates whith this number. I suspect the next patch will do but it is generally better to have also users of the introduced counters in the same patch. For one thing this patch would introduce a regression because no pages would be accounted at this stage (for example during git bisect).
Quoted 61 lines
mm/page_cgroup.c +14
-1+/* * SwapCgroup implements "lookup" and "exchange" operations. * In typical usage, this swap_cgroup is accessed via memcg's charge/uncharge @@ -389,6 +391,9 @@ static struct swap_cgroup *lookup_swap_cgroup(swp_entry_t ent,struct page *mappage;struct swap_cgroup *sc; +if (!atomic_read (&memsw_accounting_users)) +return NULL ; + ctrl = &swap_cgroup_ctrl[swp_type (ent)];if (ctrlp) *ctrlp = ctrl;@@ -416,6 +421,8 @@ unsigned short swap_cgroup_cmpxchg(swp_entry_t ent,unsigned short retval; sc =lookup_swap_cgroup (ent, &ctrl); +if (!sc) +return 0 ;spin_lock_irqsave (&ctrl->lock, flags); retval = sc->id;@@ -443,6 +450,8 @@ unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id)unsigned long flags; sc =lookup_swap_cgroup (ent, &ctrl); +if (!sc) +return 0 ;spin_lock_irqsave (&ctrl->lock, flags); old = sc->id;@@ -460,7 +469,9 @@ unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id)*/ unsigned short lookup_swap_cgroup_id (swp_entry_t ent) { -return lookup_swap_cgroup (ent,NULL )->id; +struct swap_cgroup *sc =lookup_swap_cgroup (ent,NULL ); + +return sc ? sc->id :0 ; }int swap_cgroup_swapon (int type,unsigned long max_pages)@@ -471,6 +482,9 @@ int swap_cgroup_swapon(int type, unsigned long max_pages)if (!do_swap_account)return 0 ; +if (!atomic_read (&memsw_accounting_users)) +return 0 ; + length =DIV_ROUND_UP (max_pages,SC_PER_PAGE ); ctrl = &swap_cgroup_ctrl[type];Signature · 7 lines
1.7.9.5 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected] For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Signature · 2 lines
Michal Hocko SUSE Labs
Re: [PATCH v2 3/6] memcg: introduce memsw_accounting_users
Quoted 27 lines · Michal Hocko
Quoted 26 lines · Jeff Liu
As we don't account the swap stat number for the
root_mem_cgroupanymore, here we can just return an invalid CSS ID if there is no non-root memcg is alive. Also, introducememsw_accounting_usersto track the number of active non-root memcgs.Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <[email protected]>CC Sha Zhengju <[email protected]>--- mm/page_cgroup.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)mm/page_cgroup.c +0
-0@@ -336,6 +336,8 @@ struct swap_cgroup { };#define SC_PER_PAGE (PAGE_SIZE/sizeof(struct swap_cgroup))
Quoted 7 lines
mm/page_cgroup.c struct swap_cgroup { · line 339
Quoted 1 line
mm/page_cgroup.c +1
-0+static atomic_t memsw_accounting_users =ATOMIC_INIT (0 );Nobody manipulates whith this number. I suspect the next patch will do but it is generally better to have also users of the introduced counters in the same patch. For one thing this patch would introduce a regression because no pages would be accounted at this stage (for example during git bisect).
Ah, I'll revise it accordingly.
Thanks,
-Jeff
Quoted 57 lines
Quoted 57 lines
mm/page_cgroup.c +14
-1+/* * SwapCgroup implements "lookup" and "exchange" operations. * In typical usage, this swap_cgroup is accessed via memcg's charge/uncharge @@ -389,6 +391,9 @@ static struct swap_cgroup *lookup_swap_cgroup(swp_entry_t ent,struct page *mappage;struct swap_cgroup *sc; +if (!atomic_read (&memsw_accounting_users)) +return NULL ; + ctrl = &swap_cgroup_ctrl[swp_type (ent)];if (ctrlp) *ctrlp = ctrl;@@ -416,6 +421,8 @@ unsigned short swap_cgroup_cmpxchg(swp_entry_t ent,unsigned short retval; sc =lookup_swap_cgroup (ent, &ctrl); +if (!sc) +return 0 ;spin_lock_irqsave (&ctrl->lock, flags); retval = sc->id;@@ -443,6 +450,8 @@ unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id)unsigned long flags; sc =lookup_swap_cgroup (ent, &ctrl); +if (!sc) +return 0 ;spin_lock_irqsave (&ctrl->lock, flags); old = sc->id;@@ -460,7 +469,9 @@ unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id)*/ unsigned short lookup_swap_cgroup_id (swp_entry_t ent) { -return lookup_swap_cgroup (ent,NULL )->id; +struct swap_cgroup *sc =lookup_swap_cgroup (ent,NULL ); + +return sc ? sc->id :0 ; }int swap_cgroup_swapon (int type,unsigned long max_pages)@@ -471,6 +482,9 @@ int swap_cgroup_swapon(int type, unsigned long max_pages)if (!do_swap_account)return 0 ; +if (!atomic_read (&memsw_accounting_users)) +return 0 ; + length =DIV_ROUND_UP (max_pages,SC_PER_PAGE ); ctrl = &swap_cgroup_ctrl[type];Signature · 1 line
1.7.9.5
Quoted 6 lines
Quoted 5 lines
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v2 4/6 memcg: export nr_swap_files
Export nr_swap_files which would be used for initializing and destorying swap cgroup structures in the coming patch.
--- include/linux/swap.h | 1 + mm/swapfile.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-)
include/linux/swap.h +1 -0
@@ -348,6 +348,7 @@ extern struct page *swapin_readahead(swp_entry_t, gfp_t,/* linux/mm/swapfile.c */ extern long nr_swap_pages;extern long total_swap_pages; +extern unsigned int nr_swapfiles;extern void si_swapinfo (struct sysinfo *);extern swp_entry_t get_swap_page (void );extern swp_entry_t get_swap_page_of_type (int );
mm/swapfile.c +1 -1
@@ -46,7 +46,7 @@ static void free_swap_count_continuations(struct swap_info_struct *);static sector_t map_swap_entry (swp_entry_t ,struct block_device **);DEFINE_SPINLOCK (swap_lock); -static unsigned int nr_swapfiles; +unsigned int nr_swapfiles;long nr_swap_pages;long total_swap_pages;static int least_priority;
Signature · 7 lines
1.7.9.5 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 4/6] memcg: export nr_swap_files
Quoted 12 lines · Jeff Liu
Export
nr_swap_fileswhich would be used for initializing and destorying swap cgroup structures in the coming patch.Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <[email protected]>CC Sha Zhengju <[email protected]>
Well, nothing fancy here.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 4/6] memcg: export nr_swap_files
In reply to Jeff LiuQuoted 11 lines · Jeff Liu
Export
nr_swap_fileswhich would be used for initializing and destorying swap cgroup structures in the coming patch.Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <akpm-de/[email protected]>CC Sha Zhengju <[email protected]>
You are missing definition for !CONFIG_SWAP
After this is fixed you can add my
Quoted 39 lines
--- include/linux/swap.h | 1 + mm/swapfile.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-)include/linux/swap.h +1
-0@@ -348,6 +348,7 @@ extern struct page *swapin_readahead(swp_entry_t, gfp_t,/* linux/mm/swapfile.c */ extern long nr_swap_pages;extern long total_swap_pages; +extern unsigned int nr_swapfiles;extern void si_swapinfo (struct sysinfo *);extern swp_entry_t get_swap_page (void );extern swp_entry_t get_swap_page_of_type (int );mm/swapfile.c +1
-1@@ -46,7 +46,7 @@ static void free_swap_count_continuations(struct swap_info_struct *);static sector_t map_swap_entry (swp_entry_t ,struct block_device **);DEFINE_SPINLOCK (swap_lock); -static unsigned int nr_swapfiles; +unsigned int nr_swapfiles;long nr_swap_pages;long total_swap_pages;static int least_priority;Signature · 7 lines
1.7.9.5 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected] For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Signature · 2 lines
Michal Hocko SUSE Labs
Re: [PATCH v2 4/6] memcg: export nr_swap_files
Quoted 13 lines · Michal Hocko
Quoted 11 lines · Jeff Liu
Export
nr_swap_fileswhich would be used for initializing and destorying swap cgroup structures in the coming patch.Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <[email protected]>CC Sha Zhengju <[email protected]>
Quoted 1 line
You are missing definition for !CONFIG_SWAP
Yep, I missed "#define nr_swapfiles 0U" in this case.
Thanks,
-Jeff
Quoted 38 lines
After this is fixed you can add my
Acked-by Michal Hocko <[email protected]>Quoted 34 lines
--- include/linux/swap.h | 1 + mm/swapfile.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-)include/linux/swap.h +1
-0@@ -348,6 +348,7 @@ extern struct page *swapin_readahead(swp_entry_t, gfp_t,/* linux/mm/swapfile.c */ extern long nr_swap_pages;extern long total_swap_pages; +extern unsigned int nr_swapfiles;extern void si_swapinfo (struct sysinfo *);extern swp_entry_t get_swap_page (void );extern swp_entry_t get_swap_page_of_type (int );mm/swapfile.c +1
-1@@ -46,7 +46,7 @@ static void free_swap_count_continuations(struct swap_info_struct *);static sector_t map_swap_entry (swp_entry_t ,struct block_device **);DEFINE_SPINLOCK (swap_lock); -static unsigned int nr_swapfiles; +unsigned int nr_swapfiles;long nr_swap_pages;long total_swap_pages;static int least_priority;Signature · 1 line
1.7.9.5
Quoted 6 lines
Quoted 5 lines
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v2 5/6 memcg: introduce swap_cgroup_init()/swap_cgroup_free()
Introduce swap_cgroup_init()/swap_cgroup_free() to allocate buffers when creating the first non-root memcg and deallocate buffers on the last non-root memcg is gone.
--- include/linux/page_cgroup.h | 12 +++++ mm/page_cgroup.c | 108 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 110 insertions(+), 10 deletions(-)
include/linux/page_cgroup.h +12 -0
@@ -113,6 +113,8 @@ extern unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id);extern unsigned short lookup_swap_cgroup_id (swp_entry_t ent);extern int swap_cgroup_swapon (int type,unsigned long max_pages);extern void swap_cgroup_swapoff (int type); +extern int swap_cgroup_init (void ); +extern void swap_cgroup_free (void );#else static inline
@@ -138,6 +140,16 @@ static inline void swap_cgroup_swapoff(int type)return ; } +static inline int swap_cgroup_init (void ) +{ +return 0 ; +} + +static inline void swap_cgroup_free (void ) +{ +return ; +} +#endif /* CONFIG_MEMCG_SWAP */ #endif /* !__GENERATING_BOUNDS_H */
mm/page_cgroup.c +98 -10
144 lines not on this page · raw message
Signature · 7 lines
1.7.9.5 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 5/6] memcg: introduce swap_cgroup_init()/swap_cgroup_free()
Quoted 12 lines · Jeff Liu
Introduce swap_cgroup_init()/swap_cgroup_free() to allocate buffers when creating the first non-root memcg and deallocate buffers on the last non-root memcg is gone.
Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <[email protected]>CC Sha Zhengju <[email protected]>
Looks sane.
Only:
Quoted 13 lines
#endif /* !__GENERATING_BOUNDS_H */
mm/page_cgroup.c +4
-0@@ -362,14 +362,28 @@ static int swap_cgroup_prepare(int type)unsigned long idx, max; ctrl = &swap_cgroup_ctrl[type]; +if (!ctrl->length) { +/* +* Bypass the buffer allocation if the corresponding swap +* partition/file was turned off.
mm/page_cgroup.c static int swap_cgroup_prepare(int type) · line 377
Quoted 10 lines
mm/page_cgroup.c +8
-1+*/ +pr_debug ("couldn't allocate swap_cgroup on a disabled swap " +"partition or file, index: %d\n" , type); +return 0 ; + } + ctrl->map =vzalloc (ctrl->length *sizeof (void *)); -if (!ctrl->map) +if (!ctrl->map) { + ctrl->length =0 ;
Considering moving this assignment somewhere in the exit path in the labels region.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 5/6] memcg: introduce swap_cgroup_init()/swap_cgroup_free()
Quoted 38 lines · Lord Glauber Costa of Sealand
Quoted 12 lines · Jeff Liu
Introduce swap_cgroup_init()/swap_cgroup_free() to allocate buffers when creating the first non-root memcg and deallocate buffers on the last non-root memcg is gone.
Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <[email protected]>CC Sha Zhengju <[email protected]>Looks sane.
Reviewed-by Glauber Costa <[email protected]>Only:
Quoted 18 lines
#endif /* !__GENERATING_BOUNDS_H */
mm/page_cgroup.c +9
-0@@ -362,14 +362,28 @@ static int swap_cgroup_prepare(int type)unsigned long idx, max; ctrl = &swap_cgroup_ctrl[type]; +if (!ctrl->length) { +/* +* Bypass the buffer allocation if the corresponding swap +* partition/file was turned off. +*/ +pr_debug ("couldn't allocate swap_cgroup on a disabled swap " +"partition or file, index: %d\n" , type); +return 0 ; + }
Quoted 8 lines
mm/page_cgroup.c static int swap_cgroup_prepare(int type) · line 377
Quoted 5 lines
mm/page_cgroup.c +3
-1+ ctrl->map =vzalloc (ctrl->length *sizeof (void *)); -if (!ctrl->map) +if (!ctrl->map) { + ctrl->length =0 ;Considering moving this assignment somewhere in the exit path in the labels region.
Nice point. Both "ctrl->length = 0" statements in this function should be moved down to the exit path of "nomem:" label.
Thanks,
-Jeff
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 5/6] memcg: introduce swap_cgroup_init()/swap_cgroup_free()
In reply to Jeff LiuQuoted 2 lines · Jeff Liu
Introduce swap_cgroup_init()/swap_cgroup_free() to allocate buffers when creating the first non-root memcg and deallocate buffers on the last non-root memcg is gone.
I think this deserves more words ;) At least it would be good to describe contexts from which init and free might be called. What are the locking rules.
Also swap_cgroup_destroy sounds more in pair with swap_cgroup_init.
Please add the users of those function here as well. It is much easier to review.
Quoted 49 lines
Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <akpm-de/[email protected]>CC Sha Zhengju <[email protected]>--- include/linux/page_cgroup.h | 12 +++++ mm/page_cgroup.c | 108 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 110 insertions(+), 10 deletions(-)include/linux/page_cgroup.h +12
-0@@ -113,6 +113,8 @@ extern unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id);extern unsigned short lookup_swap_cgroup_id (swp_entry_t ent);extern int swap_cgroup_swapon (int type,unsigned long max_pages);extern void swap_cgroup_swapoff (int type); +extern int swap_cgroup_init (void ); +extern void swap_cgroup_free (void );#else static inline@@ -138,6 +140,16 @@ static inline void swap_cgroup_swapoff(int type)return ; } +static inline int swap_cgroup_init (void ) +{ +return 0 ; +} + +static inline void swap_cgroup_free (void ) +{ +return ; +} +#endif /* CONFIG_MEMCG_SWAP */ #endif /* !__GENERATING_BOUNDS_H */ mm/page_cgroup.c +0
-0
mm/page_cgroup.c static int swap_cgroup_prepare(int type) · line 371
Quoted 10 lines
mm/page_cgroup.c +7
-0@@ -362,14 +362,28 @@ static int swap_cgroup_prepare(int type)unsigned long idx, max; ctrl = &swap_cgroup_ctrl[type]; +if (!ctrl->length) { +/* +* Bypass the buffer allocation if the corresponding swap +* partition/file was turned off. +*/ +pr_debug ("couldn't allocate swap_cgroup on a disabled swap " +"partition or file, index: %d\n" , type);
Do we really need to log this? I guess your scenario is:
swapon part1
swapon part2
swapon part3
swapoff part2
create first non-root cgroup
which is perfectly ok and I do not see any reason to log it.
mm/page_cgroup.c nomem:
Quoted 21 lines
mm/page_cgroup.c +9
-2+return 0 ; + } + ctrl->map =vzalloc (ctrl->length *sizeof (void *)); -if (!ctrl->map) +if (!ctrl->map) { + ctrl->length =0 ; goto nomem; + }for (idx =0 ; idx < ctrl->length; idx++) { page =alloc_page (GFP_KERNEL | __GFP_ZERO); -if (!page) +if (!page) { + ctrl->length =0 ; goto not_enough_page; + } ctrl->map[idx] = page; }return 0 ;@@ -383,6 +397,32 @@ nomem:
ctrl->length = 0 under this label would be probably nicer than keeping it at two places.
Quoted 9 lines
mm/page_cgroup.c +6
-0return -ENOMEM ; } +/* +* free buffer for swap_cgroup. +*/ +static void swap_cgroup_teardown (int type) +{ +struct page **map;
mm/page_cgroup.c nomem: · line 415
Quoted 10 lines
mm/page_cgroup.c +10
-0+unsigned long length; +struct swap_cgroup_ctrl *ctrl; + + ctrl = &swap_cgroup_ctrl[type]; + map = ctrl->map; + length = ctrl->length; + ctrl->map =NULL ; + ctrl->length =0 ; + +if (map) {
allocation path checks for ctrl->length so it would be good to unify both. They are handling the same case (gone swap).
Quoted 28 lines
mm/page_cgroup.c +21
-0+unsigned long i; +for (i =0 ; i < length; i++) { +struct page *page = map[i]; +if (page) +__free_page (page); + } +vfree (map); + } +} +static struct swap_cgroup *lookup_swap_cgroup (swp_entry_t ent,struct swap_cgroup_ctrl **ctrlp) {@@ -474,6 +514,56 @@ unsigned short lookup_swap_cgroup_id(swp_entry_t ent)return sc ? sc->id :0 ; } +/* +* Allocate swap cgroup accounting structures when the first non-root +* memcg is created. +*/ +int swap_cgroup_init (void ) +{ +unsigned int type; + +if (!do_swap_account) +return 0 ; +
mm/page_cgroup.c unsigned short lookup_swap_cgroup_id(swp_entry_t ent) · line 537
Quoted 10 lines
mm/page_cgroup.c +10
-0+if (atomic_add_return (1 , &memsw_accounting_users) !=1 ) +return 0 ; + +mutex_lock (&swap_cgroup_mutex); +for (type =0 ; type < nr_swapfiles; type++) { +if (swap_cgroup_prepare (type) <0 ) { +mutex_unlock (&swap_cgroup_mutex); + goto nomem; + } + }
You should clean up those types that were successful...
Quoted 61 lines
mm/page_cgroup.c +35
-8+mutex_unlock (&swap_cgroup_mutex); +return 0 ; + +nomem: +pr_info ("couldn't allocate enough memory for swap_cgroup " +"while creating non-root memcg.\n" ); +return -ENOMEM ; +} + +/* +* Deallocate swap cgroup accounting structures on the last non-root +* memcg removal. +*/ +void swap_cgroup_free (void ) +{ +unsigned int type; + +if (!do_swap_account) +return ; + +if (atomic_sub_return (1 , &memsw_accounting_users)) +return ; + +mutex_lock (&swap_cgroup_mutex); +for (type =0 ; type < nr_swapfiles; type++) +swap_cgroup_teardown (type); +mutex_unlock (&swap_cgroup_mutex); +} +int swap_cgroup_swapon (int type,unsigned long max_pages) {unsigned long length;@@ -482,20 +572,18 @@ int swap_cgroup_swapon(int type, unsigned long max_pages)if (!do_swap_account)return 0 ; -if (!atomic_read (&memsw_accounting_users)) -return 0 ; - length =DIV_ROUND_UP (max_pages,SC_PER_PAGE ); ctrl = &swap_cgroup_ctrl[type];mutex_lock (&swap_cgroup_mutex); ctrl->length = length;spin_lock_init (&ctrl->lock); -if (swap_cgroup_prepare (type)) { -/* memory shortage */ - ctrl->length =0 ; -mutex_unlock (&swap_cgroup_mutex); - goto nomem; +if (atomic_read (&memsw_accounting_users)) { +if (swap_cgroup_prepare (type)) { +/* memory shortage */ +mutex_unlock (&swap_cgroup_mutex); + goto nomem; + } }mutex_unlock (&swap_cgroup_mutex);Signature · 1 line
1.7.9.5
Signature · 2 lines
Michal Hocko SUSE Labs
Re: [PATCH v2 5/6] memcg: introduce swap_cgroup_init()/swap_cgroup_free()
Quoted 8 lines · Michal Hocko
Quoted 2 lines · Jeff Liu
Introduce swap_cgroup_init()/swap_cgroup_free() to allocate buffers when creating the first non-root memcg and deallocate buffers on the last non-root memcg is gone.
I think this deserves more words ;) At least it would be good to describe contexts from which init and free might be called. What are the locking rules.
Alsoswap_cgroup_destroysounds more in pair withswap_cgroup_init.
Will improve the comments log as well as fix the naming. Btw, I named it as swap_cgroup_free() because we have mem_cgroup_free() corresponding to mem_cgroup_init(). :)
Quoted 3 lines
Please add the users of those function here as well. It is much easier to review.
Sure.
Quoted 52 lines
Quoted 52 lines
Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <[email protected]>CC Sha Zhengju <[email protected]>--- include/linux/page_cgroup.h | 12 +++++ mm/page_cgroup.c | 108 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 110 insertions(+), 10 deletions(-)include/linux/page_cgroup.h +12
-0@@ -113,6 +113,8 @@ extern unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id);extern unsigned short lookup_swap_cgroup_id (swp_entry_t ent);extern int swap_cgroup_swapon (int type,unsigned long max_pages);extern void swap_cgroup_swapoff (int type); +extern int swap_cgroup_init (void ); +extern void swap_cgroup_free (void );#else static inline@@ -138,6 +140,16 @@ static inline void swap_cgroup_swapoff(int type)return ; } +static inline int swap_cgroup_init (void ) +{ +return 0 ; +} + +static inline void swap_cgroup_free (void ) +{ +return ; +} +#endif /* CONFIG_MEMCG_SWAP */ #endif /* !__GENERATING_BOUNDS_H */ mm/page_cgroup.c +0
-0@@ -362,14 +362,28 @@ static int swap_cgroup_prepare(int type)unsigned long idx, max;
Quoted 15 lines
mm/page_cgroup.c static int swap_cgroup_prepare(int type) · line 371
Quoted 8 lines
mm/page_cgroup.c +7
-0ctrl = &swap_cgroup_ctrl[type]; +if (!ctrl->length) { +/* +* Bypass the buffer allocation if the corresponding swap +* partition/file was turned off. +*/ +pr_debug ("couldn't allocate swap_cgroup on a disabled swap " +"partition or file, index: %d\n" , type);Do we really need to log this? I guess your scenario is:
swapon part1
swapon part2
swapon part3
swapoff part2
create first non-root cgroup
Yesss!!
Quoted 2 lines
which is perfectly ok and I do not see any reason to log it.
okay, I'll remove this redundant debug info.
Quoted 11 lines
Quoted 11 lines
mm/page_cgroup.c +6
-1+return 0 ; + } + ctrl->map =vzalloc (ctrl->length *sizeof (void *)); -if (!ctrl->map) +if (!ctrl->map) { + ctrl->length =0 ; goto nomem; + }
Quoted 14 lines
mm/page_cgroup.c nomem:
Quoted 11 lines
mm/page_cgroup.c +3
-1for (idx =0 ; idx < ctrl->length; idx++) { page =alloc_page (GFP_KERNEL | __GFP_ZERO); -if (!page) +if (!page) { + ctrl->length =0 ; goto not_enough_page; + } ctrl->map[idx] = page; }return 0 ;@@ -383,6 +397,32 @@ nomem:
ctrl->length= 0 under this label would be probably nicer than keeping it at two places.
Will take care of it.
Quoted 15 lines
Quoted 15 lines
mm/page_cgroup.c +11
-0return -ENOMEM ; } +/* +* free buffer for swap_cgroup. +*/ +static void swap_cgroup_teardown (int type) +{ +struct page **map; +unsigned long length; +struct swap_cgroup_ctrl *ctrl; + + ctrl = &swap_cgroup_ctrl[type]; + map = ctrl->map;
Quoted 8 lines
mm/page_cgroup.c nomem: · line 415
Quoted 5 lines
mm/page_cgroup.c +5
-0+ length = ctrl->length; + ctrl->map =NULL ; + ctrl->length =0 ; + +if (map) {allocation path checks for
ctrl->lengthso it would be good to unify both. They are handling the same case (gone swap).
yes, will fix it accordingly.
Quoted 33 lines
Quoted 33 lines
mm/page_cgroup.c +25
-0+unsigned long i; +for (i =0 ; i < length; i++) { +struct page *page = map[i]; +if (page) +__free_page (page); + } +vfree (map); + } +} +static struct swap_cgroup *lookup_swap_cgroup (swp_entry_t ent,struct swap_cgroup_ctrl **ctrlp) {@@ -474,6 +514,56 @@ unsigned short lookup_swap_cgroup_id(swp_entry_t ent)return sc ? sc->id :0 ; } +/* +* Allocate swap cgroup accounting structures when the first non-root +* memcg is created. +*/ +int swap_cgroup_init (void ) +{ +unsigned int type; + +if (!do_swap_account) +return 0 ; + +if (atomic_add_return (1 , &memsw_accounting_users) !=1 ) +return 0 ; + +mutex_lock (&swap_cgroup_mutex);
Quoted 8 lines
mm/page_cgroup.c unsigned short lookup_swap_cgroup_id(swp_entry_t ent) · line 537
Quoted 6 lines
mm/page_cgroup.c +6
-0+for (type =0 ; type < nr_swapfiles; type++) { +if (swap_cgroup_prepare (type) <0 ) { +mutex_unlock (&swap_cgroup_mutex); + goto nomem; + } + }You should clean up those types that were successful...
Oops, those types should be deallocated...
Thanks,
-Jeff
Quoted 60 lines
Quoted 60 lines
mm/page_cgroup.c +35
-8+mutex_unlock (&swap_cgroup_mutex); +return 0 ; + +nomem: +pr_info ("couldn't allocate enough memory for swap_cgroup " +"while creating non-root memcg.\n" ); +return -ENOMEM ; +} + +/* +* Deallocate swap cgroup accounting structures on the last non-root +* memcg removal. +*/ +void swap_cgroup_free (void ) +{ +unsigned int type; + +if (!do_swap_account) +return ; + +if (atomic_sub_return (1 , &memsw_accounting_users)) +return ; + +mutex_lock (&swap_cgroup_mutex); +for (type =0 ; type < nr_swapfiles; type++) +swap_cgroup_teardown (type); +mutex_unlock (&swap_cgroup_mutex); +} +int swap_cgroup_swapon (int type,unsigned long max_pages) {unsigned long length;@@ -482,20 +572,18 @@ int swap_cgroup_swapon(int type, unsigned long max_pages)if (!do_swap_account)return 0 ; -if (!atomic_read (&memsw_accounting_users)) -return 0 ; - length =DIV_ROUND_UP (max_pages,SC_PER_PAGE ); ctrl = &swap_cgroup_ctrl[type];mutex_lock (&swap_cgroup_mutex); ctrl->length = length;spin_lock_init (&ctrl->lock); -if (swap_cgroup_prepare (type)) { -/* memory shortage */ - ctrl->length =0 ; -mutex_unlock (&swap_cgroup_mutex); - goto nomem; +if (atomic_read (&memsw_accounting_users)) { +if (swap_cgroup_prepare (type)) { +/* memory shortage */ +mutex_unlock (&swap_cgroup_mutex); + goto nomem; + } }mutex_unlock (&swap_cgroup_mutex);
Quoted 3 lines
Quoted 2 lines
Signature · 1 line
1.7.9.5
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 5/6] memcg: introduce swap_cgroup_init()/swap_cgroup_free()
Quoted 5 lines · Jeff Liu
Quoted 4 lines · Michal Hocko
Quoted 2 lines · Jeff Liu
Introduce swap_cgroup_init()/swap_cgroup_free() to allocate buffers when creating the first non-root memcg and deallocate buffers on the last non-root memcg is gone.
Quoted 7 lines
Quoted 4 lines
I think this deserves more words ;) At least it would be good to describe contexts from which init and free might be called. What are the locking rules.
Alsoswap_cgroup_destroysounds more in pair withswap_cgroup_init.Will improve the comments log as well as fix the naming. Btw, I named it as
swap_cgroup_free()because we havemem_cgroup_free()corresponding tomem_cgroup_init(). :)
I do see mem_cgroup_alloc and __mem_cgroup_free. Anyway this is not that important. Consistent naming is not any rule. It is nice to have though. So take these renaming suggestions as hints rather than you definitely _have_ to do that.
[...]
Signature · 2 lines
Michal Hocko SUSE Labs
PATCH v2 6/6 memcg: init/free swap cgroup strucutres upon create/free child memcg
Initialize swap_cgroup strucutres when creating a non-root memcg, swap_cgroup_init() will be called for multiple times but only does buffer allocation per the first non-root memcg.
Free swap_cgroup structures correspondingly on the last non-root memcg removal.
--- mm/memcontrol.c | 3 +++ 1 file changed, 3 insertions(+)
mm/memcontrol.c +3 -0
@@ -5998,6 +5998,7 @@ static void free_work(struct work_struct *work) memcg = container_of(work, struct mem_cgroup, work_freeing);__mem_cgroup_free (memcg); +swap_cgroup_free (); }static void free_rcu (struct rcu_head *rcu_head)
@@ -6116,6 +6117,8 @@ mem_cgroup_css_alloc(struct cgroup *cont)INIT_WORK (&stock->work, drain_local_stock); } }else { +if (swap_cgroup_init ()) + goto free_out; parent =mem_cgroup_from_cont (cont->parent); memcg->use_hierarchy = parent->use_hierarchy; memcg->oom_kill_disable = parent->oom_kill_disable;
Signature · 7 lines
1.7.9.5 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 6/6] memcg: init/free swap cgroup strucutres upon create/free child memcg
mm/memcontrol.c mem_cgroup_css_alloc(struct cgroup *cont) · line 6124
Quoted 10 lines · Jeff Liu
static void
free_rcu(struct rcu_head *rcu_head)mm/memcontrol.c +2
-0@@ -6116,6 +6117,8 @@ mem_cgroup_css_alloc(struct cgroup *cont)INIT_WORK (&stock->work, drain_local_stock); } }else { +if (swap_cgroup_init ()) + goto free_out; parent =mem_cgroup_from_cont (cont->parent); memcg->use_hierarchy = parent->use_hierarchy; memcg->oom_kill_disable = parent->oom_kill_disable;
Be aware that this will conflict with latest -mm where those were moved to css_online().
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 6/6] memcg: init/free swap cgroup strucutres upon create/free child memcg
Quoted 13 lines · Lord Glauber Costa of Sealand
mm/memcontrol.c mem_cgroup_css_alloc(struct cgroup *cont) · line 6124
Quoted 10 lines · Jeff Liu
static void
free_rcu(struct rcu_head *rcu_head)mm/memcontrol.c +2
-0@@ -6116,6 +6117,8 @@ mem_cgroup_css_alloc(struct cgroup *cont)INIT_WORK (&stock->work, drain_local_stock); } }else { +if (swap_cgroup_init ()) + goto free_out; parent =mem_cgroup_from_cont (cont->parent); memcg->use_hierarchy = parent->use_hierarchy; memcg->oom_kill_disable = parent->oom_kill_disable;Be aware that this will conflict with latest -mm where those were moved to
css_online().
Thanks for the kind reminder, will work out the next round posts based on latest -mm or Michal's.
-Jeff
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 6/6] memcg: init/free swap cgroup strucutres upon create/free child memcg
In reply to Jeff LiuQuoted 7 lines · Jeff Liu
Initialize
swap_cgroupstrucutres when creating a non-root memcg,swap_cgroup_init()will be called for multiple times but only does buffer allocation per the first non-root memcg.Free
swap_cgroupstructures correspondingly on the last non-root memcg removal.
Quoted 8 lines
Signed-off-by Jie Liu <[email protected]>CC Glauber Costa <[email protected]>CC Michal Hocko <[email protected]>CC Kamezawa Hiroyuki <[email protected]>CC Johannes Weiner <[email protected]>CC Mel Gorman <[email protected]>CC Andrew Morton <akpm-de/[email protected]>CC Sha Zhengju <[email protected]>
OK, looks good to me. Except for the outdated tree you are based on. You should hook into mem_cgroup_css_online for the creation path.
Please fold this into the previous patch. It won't make it harder to review and we will have all users of init/free in one patch.
Quoted 27 lines
--- mm/memcontrol.c | 3 +++ 1 file changed, 3 insertions(+)mm/memcontrol.c +3
-0@@ -5998,6 +5998,7 @@ static void free_work(struct work_struct *work) memcg = container_of(work, struct mem_cgroup, work_freeing);__mem_cgroup_free (memcg); +swap_cgroup_free (); }static void free_rcu (struct rcu_head *rcu_head)@@ -6116,6 +6117,8 @@ mem_cgroup_css_alloc(struct cgroup *cont)INIT_WORK (&stock->work, drain_local_stock); } }else { +if (swap_cgroup_init ()) + goto free_out; parent =mem_cgroup_from_cont (cont->parent); memcg->use_hierarchy = parent->use_hierarchy; memcg->oom_kill_disable = parent->oom_kill_disable;Signature · 1 line
1.7.9.5
Signature · 2 lines
Michal Hocko SUSE Labs