mm: memcontrol: account "kmem" in cgroup2
Subsystems (11)
Johannes Weiner
maintainercover mm: memcontrol: account "kmem" in cgroup2
Hi,
this series adds accounting of the historical "kmem" memory consumers to the cgroup2 memory controller.
These consumers include the dentry cache, the inode cache, kernel stack pages, and a few others that are pointed out in patch 7/8. The footprint of these consumers is directly tied to userspace activity in common workloads, and so they have to be part of the minimally viable configuration in order to present a complete feature to our users.
The cgroup2 interface of the memory controller is far from complete, but this series, along with the socket memory accounting series, provides the final semantic changes for the existing memory knobs in the cgroup2 interface, which is scheduled for initial release in the next merge window.
Thanks!
include/linux/list_lru.h | 4 +- include/linux/memcontrol.h | 330 +++++++++++++++++++++-------------------- include/linux/sched.h | 2 - include/linux/slab.h | 2 +- include/linux/slab_def.h | 3 +- include/linux/slub_def.h | 2 +- include/net/tcp_memcontrol.h | 3 +- init/Kconfig | 10 +- mm/list_lru.c | 12 +- mm/memcontrol.c | 246 ++++++++++++++---------------- mm/slab.h | 6 +- mm/slab_common.c | 14 +- mm/slub.c | 10 +- mm/vmscan.c | 2 +- net/ipv4/Makefile | 2 +- net/ipv4/tcp_memcontrol.c | 2 +- 16 files changed, 319 insertions(+), 331 deletions(-)
Johannes Weiner
maintainerPATCH 1/8 mm: memcontrol: drop unused @css argument in memcg_init_kmem
--- include/net/tcp_memcontrol.h | 3 ++- mm/memcontrol.c | 6 +++--- net/ipv4/tcp_memcontrol.c | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-)
include/net/tcp_memcontrol.h +2 -1
@@ -1,6 +1,7 @@#ifndef _TCP_MEMCG_H#define _TCP_MEMCG_H -int tcp_init_cgroup (struct mem_cgroup *memcg,struct cgroup_subsys *ss); +int tcp_init_cgroup (struct mem_cgroup *memcg);void tcp_destroy_cgroup (struct mem_cgroup *memcg); +#endif /* _TCP_MEMCG_H */
mm/memcontrol.c +3 -3
@@ -3561,7 +3561,7 @@ static int mem_cgroup_oom_control_write(struct cgroup_subsys_state *css, }#ifdef CONFIG_MEMCG_KMEM -static int memcg_init_kmem (struct mem_cgroup *memcg,struct cgroup_subsys *ss) +static int memcg_init_kmem (struct mem_cgroup *memcg) {int ret;
@@ -3569,7 +3569,7 @@ static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss)if (ret)return ret; -return tcp_init_cgroup (memcg, ss); +return tcp_init_cgroup (memcg); }static void memcg_deactivate_kmem (struct mem_cgroup *memcg)
@@ -4252,7 +4252,7 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css) }mutex_unlock (&memcg_create_mutex); - ret =memcg_init_kmem (memcg, &memory_cgrp_subsys); + ret =memcg_init_kmem (memcg);if (ret)return ret;
net/ipv4/tcp_memcontrol.c +1 -1
@@ -6,7 +6,7 @@#include <linux/memcontrol.h> #include <linux/module.h> -int tcp_init_cgroup (struct mem_cgroup *memcg,struct cgroup_subsys *ss) +int tcp_init_cgroup (struct mem_cgroup *memcg) {struct mem_cgroup *parent =parent_mem_cgroup (memcg);struct page_counter *counter_parent =NULL ;
Signature · 7 lines
2.6.3 -- 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 1/8] mm: memcontrol: drop unused @css argument in memcg_init_kmem
Quoted 1 line · Johannes Weiner
Signed-off-by Johannes Weiner <[email protected]>
Re: [PATCH 1/8] mm: memcontrol: drop unused @css argument in memcg_init_kmem
In reply to Johannes WeinerQuoted 1 line · Johannes Weiner
Signed-off-by Johannes Weiner <[email protected]>
Quoted 65 lines
--- include/net/tcp_memcontrol.h | 3 ++- mm/memcontrol.c | 6 +++--- net/ipv4/tcp_memcontrol.c | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-)include/net/tcp_memcontrol.h +2
-1@@ -1,6 +1,7 @@#ifndef _TCP_MEMCG_H#define _TCP_MEMCG_H -int tcp_init_cgroup (struct mem_cgroup *memcg,struct cgroup_subsys *ss); +int tcp_init_cgroup (struct mem_cgroup *memcg);void tcp_destroy_cgroup (struct mem_cgroup *memcg); +#endif /* _TCP_MEMCG_H */ mm/memcontrol.c +3
-3@@ -3561,7 +3561,7 @@ static int mem_cgroup_oom_control_write(struct cgroup_subsys_state *css, }#ifdef CONFIG_MEMCG_KMEM -static int memcg_init_kmem (struct mem_cgroup *memcg,struct cgroup_subsys *ss) +static int memcg_init_kmem (struct mem_cgroup *memcg) {int ret;@@ -3569,7 +3569,7 @@ static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss)if (ret)return ret; -return tcp_init_cgroup (memcg, ss); +return tcp_init_cgroup (memcg); }static void memcg_deactivate_kmem (struct mem_cgroup *memcg)@@ -4252,7 +4252,7 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css) }mutex_unlock (&memcg_create_mutex); - ret =memcg_init_kmem (memcg, &memory_cgrp_subsys); + ret =memcg_init_kmem (memcg);if (ret)return ret;net/ipv4/tcp_memcontrol.c +1
-1@@ -6,7 +6,7 @@#include <linux/memcontrol.h> #include <linux/module.h> -int tcp_init_cgroup (struct mem_cgroup *memcg,struct cgroup_subsys *ss) +int tcp_init_cgroup (struct mem_cgroup *memcg) {struct mem_cgroup *parent =parent_mem_cgroup (memcg);struct page_counter *counter_parent =NULL ;Signature · 1 line
2.6.3
Signature · 2 lines
Michal Hocko SUSE Labs
Johannes Weiner
maintainerPATCH 2/8 mm: memcontrol: remove double kmem page_counter init
In reply to Johannes WeinerThe kmem page_counter's limit is initialized to PAGE_COUNTER_MAX inside mem_cgroup_css_online(). There is no need to repeat this from memcg_propagate_kmem().
--- mm/memcontrol.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-)
mm/memcontrol.c +10 -14
@@ -2840,8 +2840,7 @@ static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css, }#ifdef CONFIG_MEMCG_KMEM -static int memcg_activate_kmem (struct mem_cgroup *memcg, -unsigned long nr_pages) +static int memcg_activate_kmem (struct mem_cgroup *memcg) {int err =0 ;int memcg_id;
@@ -2876,13 +2875,6 @@ static int memcg_activate_kmem(struct mem_cgroup *memcg, goto out; } -/* -* We couldn't have accounted to this cgroup, because it hasn't got -* activated yet, so this should succeed. -*/ - err =page_counter_limit (&memcg->kmem, nr_pages); -VM_BUG_ON (err); -static_branch_inc (&memcg_kmem_enabled_key);/* * A memory cgroup is considered kmem-active as soon as it gets
@@ -2903,10 +2895,14 @@ static int memcg_update_kmem_limit(struct mem_cgroup *memcg,int ret;mutex_lock (&memcg_limit_mutex); -if (!memcg_kmem_is_active (memcg)) - ret =memcg_activate_kmem (memcg, limit); -else - ret =page_counter_limit (&memcg->kmem, limit); +/* Top-level cgroup doesn't propagate from root */ +if (!memcg_kmem_is_active (memcg)) { + ret =memcg_activate_kmem (memcg); +if (ret) + goto out; + } + ret =page_counter_limit (&memcg->kmem, limit); +out:mutex_unlock (&memcg_limit_mutex);return ret; }
@@ -2925,7 +2921,7 @@ static int memcg_propagate_kmem(struct mem_cgroup *memcg)* after this point, because it has at least one child already. */ if (memcg_kmem_is_active (parent)) - ret =memcg_activate_kmem (memcg,PAGE_COUNTER_MAX ); + ret =memcg_activate_kmem (memcg);mutex_unlock (&memcg_limit_mutex);return ret; }
Signature · 7 lines
2.6.3 -- 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 2/8] mm: memcontrol: remove double kmem page_counter init
Quoted 5 lines · Johannes Weiner
The kmem page_counter's limit is initialized to
PAGE_COUNTER_MAXinsidemem_cgroup_css_online(). There is no need to repeat this frommemcg_propagate_kmem().Signed-off-by Johannes Weiner <[email protected]>
--
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 2/8] mm: memcontrol: remove double kmem page_counter init
In reply to Johannes WeinerQuoted 5 lines · Johannes Weiner
The kmem page_counter's limit is initialized to
PAGE_COUNTER_MAXinsidemem_cgroup_css_online(). There is no need to repeat this frommemcg_propagate_kmem().Signed-off-by Johannes Weiner <[email protected]>
Quoted 62 lines
--- mm/memcontrol.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-)mm/memcontrol.c +10
-14@@ -2840,8 +2840,7 @@ static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css, }#ifdef CONFIG_MEMCG_KMEM -static int memcg_activate_kmem (struct mem_cgroup *memcg, -unsigned long nr_pages) +static int memcg_activate_kmem (struct mem_cgroup *memcg) {int err =0 ;int memcg_id;@@ -2876,13 +2875,6 @@ static int memcg_activate_kmem(struct mem_cgroup *memcg, goto out; } -/* -* We couldn't have accounted to this cgroup, because it hasn't got -* activated yet, so this should succeed. -*/ - err =page_counter_limit (&memcg->kmem, nr_pages); -VM_BUG_ON (err); -static_branch_inc (&memcg_kmem_enabled_key);/* * A memory cgroup is considered kmem-active as soon as it gets @@ -2903,10 +2895,14 @@ static int memcg_update_kmem_limit(struct mem_cgroup *memcg,int ret;mutex_lock (&memcg_limit_mutex); -if (!memcg_kmem_is_active (memcg)) - ret =memcg_activate_kmem (memcg, limit); -else - ret =page_counter_limit (&memcg->kmem, limit); +/* Top-level cgroup doesn't propagate from root */ +if (!memcg_kmem_is_active (memcg)) { + ret =memcg_activate_kmem (memcg); +if (ret) + goto out; + } + ret =page_counter_limit (&memcg->kmem, limit); +out:mutex_unlock (&memcg_limit_mutex);return ret; }@@ -2925,7 +2921,7 @@ static int memcg_propagate_kmem(struct mem_cgroup *memcg)* after this point, because it has at least one child already. */ if (memcg_kmem_is_active (parent)) - ret =memcg_activate_kmem (memcg,PAGE_COUNTER_MAX ); + ret =memcg_activate_kmem (memcg);mutex_unlock (&memcg_limit_mutex);return ret; }Signature · 1 line
2.6.3
Signature · 2 lines
Michal Hocko SUSE Labs
Johannes Weiner
maintainerPATCH 3/8 mm: memcontrol: give the kmem states more descriptive names
In reply to Johannes WeinerOn any given memcg, the kmem accounting feature has three separate
states: not initialized, structures allocated, and actively accounting slab memory. These are represented through a combination of the kmem_acct_activated and kmem_acct_active flags, which is confusing.
Convert to a kmem_state enum with the states NONE, ALLOCATED, and ONLINE. Then rename the functions to modify the state accordingly. This follows the nomenclature of css object states more closely.
--- include/linux/memcontrol.h | 15 ++++++++----- mm/memcontrol.c | 52 ++++++++++++++++++++++------------------------ mm/slab_common.c | 4 ++-- mm/vmscan.c | 2 +- 4 files changed, 38 insertions(+), 35 deletions(-)
include/linux/memcontrol.h +10 -5
@@ -152,6 +152,12 @@ struct mem_cgroup_thresholds {struct mem_cgroup_threshold_ary *spare; }; +enum memcg_kmem_state { +KMEM_NONE , +KMEM_ALLOCATED , +KMEM_ONLINE , +}; +/* * The memory controller data structure. The memory controller controls both * page cache and RSS per cgroup. We would eventually like to provide
@@ -233,8 +239,7 @@ struct mem_cgroup {#if defined(CONFIG_MEMCG_KMEM )/* Index in the kmem_cache->memcg_params.memcg_caches array */ int kmemcg_id; -bool kmem_acct_activated; -bool kmem_acct_active; +enum memcg_kmem_state kmem_state;#endif int last_scanned_node;
@@ -750,9 +755,9 @@ static inline bool memcg_kmem_enabled(void)return static_branch_unlikely (&memcg_kmem_enabled_key); } -static inline bool memcg_kmem_is_active (struct mem_cgroup *memcg) +static inline bool memcg_kmem_online (struct mem_cgroup *memcg) { -return memcg->kmem_acct_active; +return memcg->kmem_state ==KMEM_ONLINE ; }/*
@@ -850,7 +855,7 @@ static inline bool memcg_kmem_enabled(void)return false; } -static inline bool memcg_kmem_is_active (struct mem_cgroup *memcg) +static inline bool memcg_kmem_online (struct mem_cgroup *memcg) {return false; }
mm/memcontrol.c +25 -27
135 lines not on this page · raw message
mm/slab_common.c +2 -2
@@ -503,10 +503,10 @@ void memcg_create_kmem_cache(struct mem_cgroup *memcg,mutex_lock (&slab_mutex);/* -* The memory cgroup could have been deactivated while the cache +* The memory cgroup could have been offlined while the cache * creation work was pending. */ -if (!memcg_kmem_is_active (memcg)) +if (!memcg_kmem_online (memcg)) goto out_unlock; idx =memcg_cache_id (memcg);
mm/vmscan.c +1 -1
@@ -411,7 +411,7 @@ static unsigned long shrink_slab(gfp_t gfp_mask, int nid,struct shrinker *shrinker;unsigned long freed =0 ; -if (memcg && !memcg_kmem_is_active (memcg)) +if (memcg && !memcg_kmem_online (memcg))return 0 ;if (nr_scanned ==0 )
Signature · 7 lines
2.6.3 -- 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 3/8] mm: memcontrol: give the kmem states more descriptive names
Quoted 10 lines · Johannes Weiner
On any given memcg, the kmem accounting feature has three separate
states: not initialized, structures allocated, and actively accounting slab memory. These are represented through a combination of thekmem_acct_activatedandkmem_acct_activeflags, which is confusing.Convert to a
kmem_stateenum with the states NONE, ALLOCATED, and ONLINE. Then rename the functions to modify the state accordingly. This follows the nomenclature of css object states more closely.Signed-off-by Johannes Weiner <[email protected]>
Re: [PATCH 3/8] mm: memcontrol: give the kmem states more descriptive names
In reply to Johannes WeinerQuoted 8 lines · Johannes Weiner
On any given memcg, the kmem accounting feature has three separate
states: not initialized, structures allocated, and actively accounting slab memory. These are represented through a combination of thekmem_acct_activatedandkmem_acct_activeflags, which is confusing.Convert to a
kmem_stateenum with the states NONE, ALLOCATED, and ONLINE. Then rename the functions to modify the state accordingly. This follows the nomenclature of css object states more closely.
I like this! It is much easier to follow than two separate flags.
Quoted 1 line
Signed-off-by Johannes Weiner <[email protected]>
Quoted 236 lines
--- include/linux/memcontrol.h | 15 ++++++++----- mm/memcontrol.c | 52 ++++++++++++++++++++++------------------------ mm/slab_common.c | 4 ++-- mm/vmscan.c | 2 +- 4 files changed, 38 insertions(+), 35 deletions(-)include/linux/memcontrol.h +10
-5@@ -152,6 +152,12 @@ struct mem_cgroup_thresholds {struct mem_cgroup_threshold_ary *spare; }; +enum memcg_kmem_state { +KMEM_NONE , +KMEM_ALLOCATED , +KMEM_ONLINE , +}; +/* * The memory controller data structure. The memory controller controls both * page cache and RSS per cgroup. We would eventually like to provide @@ -233,8 +239,7 @@ struct mem_cgroup {#if defined(CONFIG_MEMCG_KMEM )/* Index in the kmem_cache->memcg_params.memcg_caches array */ int kmemcg_id; -bool kmem_acct_activated; -bool kmem_acct_active; +enum memcg_kmem_state kmem_state;#endif int last_scanned_node;@@ -750,9 +755,9 @@ static inline bool memcg_kmem_enabled(void)return static_branch_unlikely (&memcg_kmem_enabled_key); } -static inline bool memcg_kmem_is_active (struct mem_cgroup *memcg) +static inline bool memcg_kmem_online (struct mem_cgroup *memcg) { -return memcg->kmem_acct_active; +return memcg->kmem_state ==KMEM_ONLINE ; }/* @@ -850,7 +855,7 @@ static inline bool memcg_kmem_enabled(void)return false; } -static inline bool memcg_kmem_is_active (struct mem_cgroup *memcg) +static inline bool memcg_kmem_online (struct mem_cgroup *memcg) {return false; }mm/memcontrol.c +25
-27@@ -2357,7 +2357,7 @@ int __memcg_kmem_charge_memcg(struct page *page, gfp_t gfp, int order,struct page_counter *counter;int ret; -if (!memcg_kmem_is_active (memcg)) +if (!memcg_kmem_online (memcg))return 0 ;if (!page_counter_try_charge (&memcg->kmem, nr_pages, &counter))@@ -2840,14 +2840,13 @@ static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css, }#ifdef CONFIG_MEMCG_KMEM -static int memcg_activate_kmem (struct mem_cgroup *memcg) +static int memcg_online_kmem (struct mem_cgroup *memcg) {int err =0 ;int memcg_id;BUG_ON (memcg->kmemcg_id >=0 ); -BUG_ON (memcg->kmem_acct_activated); -BUG_ON (memcg->kmem_acct_active); +BUG_ON (memcg->kmem_state);/* * For simplicity, we won't allow this to be disabled. It also can't @@ -2877,14 +2876,13 @@ static int memcg_activate_kmem(struct mem_cgroup *memcg)static_branch_inc (&memcg_kmem_enabled_key);/* -* A memory cgroup is considered kmem-active as soon as it gets +* A memory cgroup is considered kmem-online as soon as it gets * kmemcg_id. Setting the id after enabling static branching will * guarantee no one starts accounting before all call sites are * patched. */ memcg->kmemcg_id = memcg_id; - memcg->kmem_acct_activated = true; - memcg->kmem_acct_active = true; + memcg->kmem_state =KMEM_ONLINE ; out:return err; }@@ -2896,8 +2894,8 @@ static int memcg_update_kmem_limit(struct mem_cgroup *memcg,mutex_lock (&memcg_limit_mutex);/* Top-level cgroup doesn't propagate from root */ -if (!memcg_kmem_is_active (memcg)) { - ret =memcg_activate_kmem (memcg); +if (!memcg_kmem_online (memcg)) { + ret =memcg_online_kmem (memcg);if (ret) goto out; }@@ -2917,11 +2915,12 @@ static int memcg_propagate_kmem(struct mem_cgroup *memcg)mutex_lock (&memcg_limit_mutex);/* -* If the parent cgroup is not kmem-active now, it cannot be activated -* after this point, because it has at least one child already. +* If the parent cgroup is not kmem-online now, it cannot be +* onlined after this point, because it has at least one child +* already. */ -if (memcg_kmem_is_active (parent)) - ret =memcg_activate_kmem (memcg); +if (memcg_kmem_online (parent)) + ret =memcg_online_kmem (memcg);mutex_unlock (&memcg_limit_mutex);return ret; }@@ -3568,22 +3567,21 @@ static int memcg_init_kmem(struct mem_cgroup *memcg)return tcp_init_cgroup (memcg); } -static void memcg_deactivate_kmem (struct mem_cgroup *memcg) +static void memcg_offline_kmem (struct mem_cgroup *memcg) {struct cgroup_subsys_state *css;struct mem_cgroup *parent, *child;int kmemcg_id; -if (!memcg->kmem_acct_active) +if (memcg->kmem_state !=KMEM_ONLINE )return ; -/* -* Clear the 'active' flag before clearing memcg_caches arrays entries. -* Since we take the slab_mutex in memcg_deactivate_kmem_caches(), it -* guarantees no cache will be created for this cgroup after we are -* done (see memcg_create_kmem_cache()). +* Clear the online state before clearing memcg_caches array +* entries. The slab_mutex in memcg_deactivate_kmem_caches() +* guarantees that no cache will be created for this cgroup +* after we are done (see memcg_create_kmem_cache()). */ - memcg->kmem_acct_active = false; + memcg->kmem_state =KMEM_ALLOCATED ;memcg_deactivate_kmem_caches (memcg);@@ -3614,9 +3612,9 @@ static void memcg_deactivate_kmem(struct mem_cgroup *memcg)memcg_free_cache_id (kmemcg_id); } -static void memcg_destroy_kmem (struct mem_cgroup *memcg) +static void memcg_free_kmem (struct mem_cgroup *memcg) { -if (memcg->kmem_acct_activated) { +if (memcg->kmem_state ==KMEM_ALLOCATED ) {memcg_destroy_kmem_caches (memcg);static_branch_dec (&memcg_kmem_enabled_key);WARN_ON (page_counter_read (&memcg->kmem));@@ -3629,11 +3627,11 @@ static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss) return 0; } -static void memcg_deactivate_kmem (struct mem_cgroup *memcg) +static void memcg_offline_kmem (struct mem_cgroup *memcg) { } -static void memcg_destroy_kmem (struct mem_cgroup *memcg) +static void memcg_free_kmem (struct mem_cgroup *memcg) { }#endif @@ -4286,7 +4284,7 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)vmpressure_cleanup (&memcg->vmpressure); -memcg_deactivate_kmem (memcg); +memcg_offline_kmem (memcg);wb_memcg_offline (memcg); }@@ -4295,7 +4293,7 @@ static void mem_cgroup_css_free(struct cgroup_subsys_state *css) {struct mem_cgroup *memcg =mem_cgroup_from_css (css); -memcg_destroy_kmem (memcg); +memcg_free_kmem (memcg);#ifdef CONFIG_INET if (cgroup_subsys_on_dfl (memory_cgrp_subsys) && !cgroup_memory_nosocket)static_branch_dec (&memcg_sockets_enabled_key);mm/slab_common.c +2
-2@@ -503,10 +503,10 @@ void memcg_create_kmem_cache(struct mem_cgroup *memcg,mutex_lock (&slab_mutex);/* -* The memory cgroup could have been deactivated while the cache +* The memory cgroup could have been offlined while the cache * creation work was pending. */ -if (!memcg_kmem_is_active (memcg)) +if (!memcg_kmem_online (memcg)) goto out_unlock; idx =memcg_cache_id (memcg);mm/vmscan.c +1
-1@@ -411,7 +411,7 @@ static unsigned long shrink_slab(gfp_t gfp_mask, int nid,struct shrinker *shrinker;unsigned long freed =0 ; -if (memcg && !memcg_kmem_is_active (memcg)) +if (memcg && !memcg_kmem_online (memcg))return 0 ;if (nr_scanned ==0 )Signature · 1 line
2.6.3
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>
Johannes Weiner
maintainerPATCH 4/8 mm: memcontrol: group kmem init and exit functions together
In reply to Johannes WeinerPut all the related code to setup and teardown the kmem accounting state into the same location. No functional change intended.
--- mm/memcontrol.c | 157 +++++++++++++++++++++++++++----------------------------- 1 file changed, 76 insertions(+), 81 deletions(-)
mm/memcontrol.c +76 -81
@@ -2924,12 +2924,88 @@ static int memcg_propagate_kmem(struct mem_cgroup *memcg)mutex_unlock (&memcg_limit_mutex);return ret; } + +static int memcg_init_kmem (struct mem_cgroup *memcg) +{ +int ret; + + ret =memcg_propagate_kmem (memcg); +if (ret) +return ret; + +return tcp_init_cgroup (memcg); +} + +static void memcg_offline_kmem (struct mem_cgroup *memcg) +{ +struct cgroup_subsys_state *css; +struct mem_cgroup *parent, *child; +int kmemcg_id; + +if (memcg->kmem_state !=KMEM_ONLINE ) +return ; +/* +* Clear the online state before clearing memcg_caches array +* entries. The slab_mutex in memcg_deactivate_kmem_caches() +* guarantees that no cache will be created for this cgroup +* after we are done (see memcg_create_kmem_cache()). +*/ + memcg->kmem_state =KMEM_ALLOCATED ; + +memcg_deactivate_kmem_caches (memcg); + + kmemcg_id = memcg->kmemcg_id; +BUG_ON (kmemcg_id <0 ); + + parent =parent_mem_cgroup (memcg); +if (!parent) + parent = root_mem_cgroup; + +/* +* Change kmemcg_id of this cgroup and all its descendants to the +* parent's id, and then move all entries from this cgroup's list_lrus +* to ones of the parent. After we have finished, all list_lrus +* corresponding to this cgroup are guaranteed to remain empty. The +* ordering is imposed by list_lru_node->lock taken by +* memcg_drain_all_list_lrus(). +*/ +css_for_each_descendant_pre (css, &memcg->css) { + child =mem_cgroup_from_css (css); +BUG_ON (child->kmemcg_id != kmemcg_id); + child->kmemcg_id = parent->kmemcg_id; +if (!memcg->use_hierarchy) +break ; + } +memcg_drain_all_list_lrus (kmemcg_id, parent->kmemcg_id); + +memcg_free_cache_id (kmemcg_id); +} + +static void memcg_free_kmem (struct mem_cgroup *memcg) +{ +if (memcg->kmem_state ==KMEM_ALLOCATED ) { +memcg_destroy_kmem_caches (memcg); +static_branch_dec (&memcg_kmem_enabled_key); +WARN_ON (page_counter_read (&memcg->kmem)); + } +tcp_destroy_cgroup (memcg); +}#else static int memcg_update_kmem_limit (struct mem_cgroup *memcg,unsigned long limit) {return -EINVAL ; } +static int memcg_init_kmem (struct mem_cgroup *memcg) +{ +return 0 ; +} +static void memcg_offline_kmem (struct mem_cgroup *memcg) +{ +} +static void memcg_free_kmem (struct mem_cgroup *memcg) +{ +}#endif /* CONFIG_MEMCG_KMEM */ /*
@@ -3555,87 +3631,6 @@ static int mem_cgroup_oom_control_write(struct cgroup_subsys_state *css,return 0 ; } -#ifdef CONFIG_MEMCG_KMEM -static int memcg_init_kmem (struct mem_cgroup *memcg) -{ -int ret; - - ret =memcg_propagate_kmem (memcg); -if (ret) -return ret; - -return tcp_init_cgroup (memcg); -} - -static void memcg_offline_kmem (struct mem_cgroup *memcg) -{ -struct cgroup_subsys_state *css; -struct mem_cgroup *parent, *child; -int kmemcg_id; - -if (memcg->kmem_state !=KMEM_ONLINE ) -return ; -/* -* Clear the online state before clearing memcg_caches array -* entries. The slab_mutex in memcg_deactivate_kmem_caches() -* guarantees that no cache will be created for this cgroup -* after we are done (see memcg_create_kmem_cache()). -*/ - memcg->kmem_state =KMEM_ALLOCATED ; - -memcg_deactivate_kmem_caches (memcg); - - kmemcg_id = memcg->kmemcg_id; -BUG_ON (kmemcg_id <0 ); - - parent =parent_mem_cgroup (memcg); -if (!parent) - parent = root_mem_cgroup; - -/* -* Change kmemcg_id of this cgroup and all its descendants to the -* parent's id, and then move all entries from this cgroup's list_lrus -* to ones of the parent. After we have finished, all list_lrus -* corresponding to this cgroup are guaranteed to remain empty. The -* ordering is imposed by list_lru_node->lock taken by -* memcg_drain_all_list_lrus(). -*/ -css_for_each_descendant_pre (css, &memcg->css) { - child =mem_cgroup_from_css (css); -BUG_ON (child->kmemcg_id != kmemcg_id); - child->kmemcg_id = parent->kmemcg_id; -if (!memcg->use_hierarchy) -break ; - } -memcg_drain_all_list_lrus (kmemcg_id, parent->kmemcg_id); - -memcg_free_cache_id (kmemcg_id); -} - -static void memcg_free_kmem (struct mem_cgroup *memcg) -{ -if (memcg->kmem_state ==KMEM_ALLOCATED ) { -memcg_destroy_kmem_caches (memcg); -static_branch_dec (&memcg_kmem_enabled_key); -WARN_ON (page_counter_read (&memcg->kmem)); - } -tcp_destroy_cgroup (memcg); -} -#else -static int memcg_init_kmem (struct mem_cgroup *memcg,struct cgroup_subsys *ss) -{ -return 0 ; -} - -static void memcg_offline_kmem (struct mem_cgroup *memcg) -{ -} - -static void memcg_free_kmem (struct mem_cgroup *memcg) -{ -} -#endif -#ifdef CONFIG_CGROUP_WRITEBACK struct list_head *mem_cgroup_cgwb_list (struct mem_cgroup *memcg)
Signature · 7 lines
2.6.3 -- 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 4/8] mm: memcontrol: group kmem init and exit functions together
Quoted 4 lines · Johannes Weiner
Put all the related code to setup and teardown the kmem accounting state into the same location. No functional change intended.
Signed-off-by Johannes Weiner <[email protected]>
Re: [PATCH 4/8] mm: memcontrol: group kmem init and exit functions together
In reply to Johannes WeinerQuoted 4 lines · Johannes Weiner
Put all the related code to setup and teardown the kmem accounting state into the same location. No functional change intended.
Signed-off-by Johannes Weiner <[email protected]>
Quoted 187 lines
--- mm/memcontrol.c | 157 +++++++++++++++++++++++++++----------------------------- 1 file changed, 76 insertions(+), 81 deletions(-)mm/memcontrol.c +76
-81@@ -2924,12 +2924,88 @@ static int memcg_propagate_kmem(struct mem_cgroup *memcg)mutex_unlock (&memcg_limit_mutex);return ret; } + +static int memcg_init_kmem (struct mem_cgroup *memcg) +{ +int ret; + + ret =memcg_propagate_kmem (memcg); +if (ret) +return ret; + +return tcp_init_cgroup (memcg); +} + +static void memcg_offline_kmem (struct mem_cgroup *memcg) +{ +struct cgroup_subsys_state *css; +struct mem_cgroup *parent, *child; +int kmemcg_id; + +if (memcg->kmem_state !=KMEM_ONLINE ) +return ; +/* +* Clear the online state before clearing memcg_caches array +* entries. The slab_mutex in memcg_deactivate_kmem_caches() +* guarantees that no cache will be created for this cgroup +* after we are done (see memcg_create_kmem_cache()). +*/ + memcg->kmem_state =KMEM_ALLOCATED ; + +memcg_deactivate_kmem_caches (memcg); + + kmemcg_id = memcg->kmemcg_id; +BUG_ON (kmemcg_id <0 ); + + parent =parent_mem_cgroup (memcg); +if (!parent) + parent = root_mem_cgroup; + +/* +* Change kmemcg_id of this cgroup and all its descendants to the +* parent's id, and then move all entries from this cgroup's list_lrus +* to ones of the parent. After we have finished, all list_lrus +* corresponding to this cgroup are guaranteed to remain empty. The +* ordering is imposed by list_lru_node->lock taken by +* memcg_drain_all_list_lrus(). +*/ +css_for_each_descendant_pre (css, &memcg->css) { + child =mem_cgroup_from_css (css); +BUG_ON (child->kmemcg_id != kmemcg_id); + child->kmemcg_id = parent->kmemcg_id; +if (!memcg->use_hierarchy) +break ; + } +memcg_drain_all_list_lrus (kmemcg_id, parent->kmemcg_id); + +memcg_free_cache_id (kmemcg_id); +} + +static void memcg_free_kmem (struct mem_cgroup *memcg) +{ +if (memcg->kmem_state ==KMEM_ALLOCATED ) { +memcg_destroy_kmem_caches (memcg); +static_branch_dec (&memcg_kmem_enabled_key); +WARN_ON (page_counter_read (&memcg->kmem)); + } +tcp_destroy_cgroup (memcg); +}#else static int memcg_update_kmem_limit (struct mem_cgroup *memcg,unsigned long limit) {return -EINVAL ; } +static int memcg_init_kmem (struct mem_cgroup *memcg) +{ +return 0 ; +} +static void memcg_offline_kmem (struct mem_cgroup *memcg) +{ +} +static void memcg_free_kmem (struct mem_cgroup *memcg) +{ +}#endif /* CONFIG_MEMCG_KMEM */ /* @@ -3555,87 +3631,6 @@ static int mem_cgroup_oom_control_write(struct cgroup_subsys_state *css,return 0 ; } -#ifdef CONFIG_MEMCG_KMEM -static int memcg_init_kmem (struct mem_cgroup *memcg) -{ -int ret; - - ret =memcg_propagate_kmem (memcg); -if (ret) -return ret; - -return tcp_init_cgroup (memcg); -} - -static void memcg_offline_kmem (struct mem_cgroup *memcg) -{ -struct cgroup_subsys_state *css; -struct mem_cgroup *parent, *child; -int kmemcg_id; - -if (memcg->kmem_state !=KMEM_ONLINE ) -return ; -/* -* Clear the online state before clearing memcg_caches array -* entries. The slab_mutex in memcg_deactivate_kmem_caches() -* guarantees that no cache will be created for this cgroup -* after we are done (see memcg_create_kmem_cache()). -*/ - memcg->kmem_state =KMEM_ALLOCATED ; - -memcg_deactivate_kmem_caches (memcg); - - kmemcg_id = memcg->kmemcg_id; -BUG_ON (kmemcg_id <0 ); - - parent =parent_mem_cgroup (memcg); -if (!parent) - parent = root_mem_cgroup; - -/* -* Change kmemcg_id of this cgroup and all its descendants to the -* parent's id, and then move all entries from this cgroup's list_lrus -* to ones of the parent. After we have finished, all list_lrus -* corresponding to this cgroup are guaranteed to remain empty. The -* ordering is imposed by list_lru_node->lock taken by -* memcg_drain_all_list_lrus(). -*/ -css_for_each_descendant_pre (css, &memcg->css) { - child =mem_cgroup_from_css (css); -BUG_ON (child->kmemcg_id != kmemcg_id); - child->kmemcg_id = parent->kmemcg_id; -if (!memcg->use_hierarchy) -break ; - } -memcg_drain_all_list_lrus (kmemcg_id, parent->kmemcg_id); - -memcg_free_cache_id (kmemcg_id); -} - -static void memcg_free_kmem (struct mem_cgroup *memcg) -{ -if (memcg->kmem_state ==KMEM_ALLOCATED ) { -memcg_destroy_kmem_caches (memcg); -static_branch_dec (&memcg_kmem_enabled_key); -WARN_ON (page_counter_read (&memcg->kmem)); - } -tcp_destroy_cgroup (memcg); -} -#else -static int memcg_init_kmem (struct mem_cgroup *memcg,struct cgroup_subsys *ss) -{ -return 0 ; -} - -static void memcg_offline_kmem (struct mem_cgroup *memcg) -{ -} - -static void memcg_free_kmem (struct mem_cgroup *memcg) -{ -} -#endif -#ifdef CONFIG_CGROUP_WRITEBACK struct list_head *mem_cgroup_cgwb_list (struct mem_cgroup *memcg)Signature · 1 line
2.6.3
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>
Johannes Weiner
maintainerPATCH 5/8 mm: memcontrol: separate kmem code from legacy tcp accounting code
In reply to Johannes WeinerThe cgroup2 memory controller will include important in-kernel memory consumers per default, including socket memory, but it will no longer carry the historic tcp control interface.
Separate the kmem state init from the tcp control interface init in preparation for that.
--- mm/memcontrol.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-)
mm/memcontrol.c +12 -21
@@ -2925,17 +2925,6 @@ static int memcg_propagate_kmem(struct mem_cgroup *memcg)return ret; } -static int memcg_init_kmem (struct mem_cgroup *memcg) -{ -int ret; - - ret =memcg_propagate_kmem (memcg); -if (ret) -return ret; - -return tcp_init_cgroup (memcg); -} -static void memcg_offline_kmem (struct mem_cgroup *memcg) {struct cgroup_subsys_state *css;
@@ -2988,7 +2977,6 @@ static void memcg_free_kmem(struct mem_cgroup *memcg)static_branch_dec (&memcg_kmem_enabled_key); WARN_ON(page_counter_read(&memcg->kmem)); } -tcp_destroy_cgroup (memcg); }#else static int memcg_update_kmem_limit(struct mem_cgroup *memcg,
@@ -2996,16 +2984,9 @@ static int memcg_update_kmem_limit(struct mem_cgroup *memcg, {return -EINVAL ; } -static int memcg_init_kmem (struct mem_cgroup *memcg) -{ -return 0 ; -}static void memcg_offline_kmem (struct mem_cgroup *memcg) { } -static void memcg_free_kmem (struct mem_cgroup *memcg) -{ -}#endif /* CONFIG_MEMCG_KMEM */ /*
@@ -4241,9 +4222,14 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css) }mutex_unlock (&memcg_create_mutex); - ret =memcg_init_kmem (memcg); +#ifdef CONFIG_MEMCG_KMEM + ret =memcg_propagate_kmem (memcg);if (ret)return ret; + ret =tcp_init_cgroup (memcg); +if (ret) +return ret; +#endif #ifdef CONFIG_INET if (cgroup_subsys_on_dfl (memory_cgrp_subsys) && !cgroup_memory_nosocket)
@@ -4288,11 +4274,16 @@ static void mem_cgroup_css_free(struct cgroup_subsys_state *css) {struct mem_cgroup *memcg =mem_cgroup_from_css (css); -memcg_free_kmem (memcg);#ifdef CONFIG_INET if (cgroup_subsys_on_dfl (memory_cgrp_subsys) && !cgroup_memory_nosocket)static_branch_dec (&memcg_sockets_enabled_key);#endif + +#ifdef CONFIG_MEMCG_KMEM +memcg_free_kmem (memcg); +tcp_destroy_cgroup (memcg); +#endif +__mem_cgroup_free (memcg); }
Signature · 7 lines
2.6.3 -- 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 5/8] mm: memcontrol: separate kmem code from legacy tcp accounting code
Quoted 8 lines · Johannes Weiner
The cgroup2 memory controller will include important in-kernel memory consumers per default, including socket memory, but it will no longer carry the historic tcp control interface.
Separate the kmem state init from the tcp control interface init in preparation for that.
Signed-off-by Johannes Weiner <[email protected]>
Re: [PATCH 5/8] mm: memcontrol: separate kmem code from legacy tcp accounting code
In reply to Johannes WeinerQuoted 8 lines · Johannes Weiner
The cgroup2 memory controller will include important in-kernel memory consumers per default, including socket memory, but it will no longer carry the historic tcp control interface.
Separate the kmem state init from the tcp control interface init in preparation for that.
Signed-off-by Johannes Weiner <[email protected]>
Quoted 87 lines
--- mm/memcontrol.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-)mm/memcontrol.c +12
-21@@ -2925,17 +2925,6 @@ static int memcg_propagate_kmem(struct mem_cgroup *memcg)return ret; } -static int memcg_init_kmem (struct mem_cgroup *memcg) -{ -int ret; - - ret =memcg_propagate_kmem (memcg); -if (ret) -return ret; - -return tcp_init_cgroup (memcg); -} -static void memcg_offline_kmem (struct mem_cgroup *memcg) {struct cgroup_subsys_state *css;@@ -2988,7 +2977,6 @@ static void memcg_free_kmem(struct mem_cgroup *memcg)static_branch_dec (&memcg_kmem_enabled_key); WARN_ON(page_counter_read(&memcg->kmem)); } -tcp_destroy_cgroup (memcg); }#else static int memcg_update_kmem_limit(struct mem_cgroup *memcg,@@ -2996,16 +2984,9 @@ static int memcg_update_kmem_limit(struct mem_cgroup *memcg, {return -EINVAL ; } -static int memcg_init_kmem (struct mem_cgroup *memcg) -{ -return 0 ; -}static void memcg_offline_kmem (struct mem_cgroup *memcg) { } -static void memcg_free_kmem (struct mem_cgroup *memcg) -{ -}#endif /* CONFIG_MEMCG_KMEM */ /* @@ -4241,9 +4222,14 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css) }mutex_unlock (&memcg_create_mutex); - ret =memcg_init_kmem (memcg); +#ifdef CONFIG_MEMCG_KMEM + ret =memcg_propagate_kmem (memcg);if (ret)return ret; + ret =tcp_init_cgroup (memcg); +if (ret) +return ret; +#endif #ifdef CONFIG_INET if (cgroup_subsys_on_dfl (memory_cgrp_subsys) && !cgroup_memory_nosocket)@@ -4288,11 +4274,16 @@ static void mem_cgroup_css_free(struct cgroup_subsys_state *css) {struct mem_cgroup *memcg =mem_cgroup_from_css (css); -memcg_free_kmem (memcg);#ifdef CONFIG_INET if (cgroup_subsys_on_dfl (memory_cgrp_subsys) && !cgroup_memory_nosocket)static_branch_dec (&memcg_sockets_enabled_key);#endif + +#ifdef CONFIG_MEMCG_KMEM +memcg_free_kmem (memcg); +tcp_destroy_cgroup (memcg); +#endif +__mem_cgroup_free (memcg); }Signature · 1 line
2.6.3
Signature · 2 lines
Michal Hocko SUSE Labs
Johannes Weiner
maintainerPATCH 6/8 mm: memcontrol: move kmem accounting code to CONFIG_MEMCG
In reply to Johannes WeinerThe cgroup2 memory controller will account important in-kernel memory consumers per default. Move all necessary components to CONFIG_MEMCG.
--- include/linux/list_lru.h | 4 +- include/linux/memcontrol.h | 317 ++++++++++++++++++++++----------------------- include/linux/sched.h | 2 - include/linux/slab.h | 2 +- include/linux/slab_def.h | 3 +- include/linux/slub_def.h | 2 +- mm/list_lru.c | 12 +- mm/memcontrol.c | 54 ++++---- mm/slab.h | 6 +- mm/slab_common.c | 10 +- mm/slub.c | 10 +- 11 files changed, 206 insertions(+), 216 deletions(-)
include/linux/list_lru.h +2 -2
@@ -40,7 +40,7 @@ struct list_lru_node {spinlock_t lock;/* global list, used for the root cgroup in cgroup aware lrus */ struct list_lru_one lru; -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG /* for cgroup aware lrus points to per cgroup lists, otherwise NULL */ struct list_lru_memcg *memcg_lrus;#endif
@@ -48,7 +48,7 @@ struct list_lru_node {struct list_lru {struct list_lru_node *node; -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG struct list_head list;#endif };
include/linux/memcontrol.h +158 -159
342 lines not on this page · raw message
include/linux/sched.h +0 -2
@@ -1465,8 +1465,6 @@ struct task_struct { unsigned sched_migrated:1;#ifdef CONFIG_MEMCG unsigned memcg_may_oom:1; -#endif -#ifdef CONFIG_MEMCG_KMEM unsigned memcg_kmem_skip_account:1;#endif #ifdef CONFIG_COMPAT_BRK
include/linux/slab.h +1 -1
@@ -86,7 +86,7 @@#else # define SLAB_FAILSLAB 0x00000000UL#endif -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG # define SLAB_ACCOUNT 0x04000000UL/* Account to memcg */ #else # define SLAB_ACCOUNT 0x00000000UL
include/linux/slab_def.h +2 -1
@@ -69,7 +69,8 @@ struct kmem_cache {*/ int obj_offset;#endif /* CONFIG_DEBUG_SLAB */ -#ifdef CONFIG_MEMCG_KMEM + +#ifdef CONFIG_MEMCG struct memcg_cache_params memcg_params;#endif
include/linux/slub_def.h +1 -1
@@ -84,7 +84,7 @@ struct kmem_cache {#ifdef CONFIG_SYSFS struct kobject kobj;/* For sysfs */ #endif -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG struct memcg_cache_params memcg_params;int max_attr_size;/* for propagation, maximum size of a stored attr */ #ifdef CONFIG_SYSFS
mm/list_lru.c +6 -6
@@ -12,7 +12,7 @@#include <linux/mutex.h> #include <linux/memcontrol.h> -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG static LIST_HEAD (list_lrus);static DEFINE_MUTEX (list_lrus_mutex);
@@ -37,9 +37,9 @@ static void list_lru_register(struct list_lru *lru)static void list_lru_unregister (struct list_lru *lru) { } -#endif /* CONFIG_MEMCG_KMEM */ +#endif /* CONFIG_MEMCG */ -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG static inline bool list_lru_memcg_aware (struct list_lru *lru) {/*
@@ -104,7 +104,7 @@ list_lru_from_kmem(struct list_lru_node *nlru, void *ptr) {return &nlru->lru; } -#endif /* CONFIG_MEMCG_KMEM */ +#endif /* CONFIG_MEMCG */ bool list_lru_add (struct list_lru *lru,struct list_head *item) {
@@ -292,7 +292,7 @@ static void init_one_lru(struct list_lru_one *l) l->nr_items =0 ; } -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG static void __memcg_destroy_list_lru_node (struct list_lru_memcg *memcg_lrus,int begin,int end) {
@@ -529,7 +529,7 @@ static int memcg_init_list_lru(struct list_lru *lru, bool memcg_aware)static void memcg_destroy_list_lru (struct list_lru *lru) { } -#endif /* CONFIG_MEMCG_KMEM */ +#endif /* CONFIG_MEMCG */ int __list_lru_init (struct list_lru *lru,bool memcg_aware,struct lock_class_key *key)
mm/memcontrol.c +23 -31
124 lines not on this page · raw message
mm/slab.h +3 -3
@@ -173,7 +173,7 @@ ssize_t slabinfo_write(struct file *file, const char __user *buffer,void __kmem_cache_free_bulk (struct kmem_cache *,size_t ,void **);int __kmem_cache_alloc_bulk (struct kmem_cache *,gfp_t ,size_t ,void **); -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG /* * Iterate over all memcg caches of the given root cache. The caller must hold * slab_mutex.
@@ -251,7 +251,7 @@ static __always_inline int memcg_charge_slab(struct page *page,extern void slab_init_memcg_params (struct kmem_cache *); -#else /* !CONFIG_MEMCG_KMEM */ +#else /* !CONFIG_MEMCG */ #define for_each_memcg_cache (iter, root) \ for ((void)(iter), (void)(root); 0; )
@@ -292,7 +292,7 @@ static inline int memcg_charge_slab(struct page *page, gfp_t gfp, int order,static inline void slab_init_memcg_params (struct kmem_cache *s) { } -#endif /* CONFIG_MEMCG_KMEM */ +#endif /* CONFIG_MEMCG */ static inline struct kmem_cache *cache_from_obj (struct kmem_cache *s,void *x) {
mm/slab_common.c +5 -5
@@ -128,7 +128,7 @@ int __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t nr,return i; } -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG void slab_init_memcg_params (struct kmem_cache *s) { s->memcg_params.is_root_cache = true;
@@ -221,7 +221,7 @@ static inline int init_memcg_params(struct kmem_cache *s,static inline void destroy_memcg_params (struct kmem_cache *s) { } -#endif /* CONFIG_MEMCG_KMEM */ +#endif /* CONFIG_MEMCG */ /* * Find a mergeable slab cache
@@ -477,7 +477,7 @@ static void release_caches(struct list_head *release, bool need_rcu_barrier) } } -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG /* * memcg_create_kmem_cache - Create a cache for a memory cgroup. * @memcg: The memory cgroup the new cache is for.
@@ -689,7 +689,7 @@ static inline int shutdown_memcg_caches(struct kmem_cache *s, {return 0 ; } -#endif /* CONFIG_MEMCG_KMEM */ +#endif /* CONFIG_MEMCG */ void slab_kmem_cache_release (struct kmem_cache *s) {
@@ -1123,7 +1123,7 @@ static int slab_show(struct seq_file *m, void *p)return 0 ; } -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG int memcg_slab_show (struct seq_file *m,void *p) { struct kmem_cache *s = list_entry(p, struct kmem_cache, list);
mm/slub.c +5 -5
@@ -5207,7 +5207,7 @@ static ssize_t slab_attr_store(struct kobject *kobj,return -EIO ; err = attribute->store (s, buf, len); -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG if (slab_state >=FULL && err >=0 &&is_root_cache (s)) {struct kmem_cache *c;
@@ -5242,7 +5242,7 @@ static ssize_t slab_attr_store(struct kobject *kobj,static void memcg_propagate_slab_attrs (struct kmem_cache *s) { -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG int i;char *buffer =NULL ;struct kmem_cache *root_cache;
@@ -5328,7 +5328,7 @@ static struct kset *slab_kset;static inline struct kset *cache_kset (struct kmem_cache *s) { -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG if (!is_root_cache (s))return s->memcg_params.root_cache->memcg_kset;#endif
@@ -5405,7 +5405,7 @@ static int sysfs_slab_add(struct kmem_cache *s)if (err) goto out_del_kobj; -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG if (is_root_cache (s)) { s->memcg_kset =kset_create_and_add ("cgroup" ,NULL , &s->kobj);if (!s->memcg_kset) {
@@ -5438,7 +5438,7 @@ void sysfs_slab_remove(struct kmem_cache *s)*/ return ; -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG kset_unregister (s->memcg_kset);#endif kobject_uevent (&s->kobj,KOBJ_REMOVE );
Signature · 7 lines
2.6.3 -- 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 6/8] mm: memcontrol: move kmem accounting code to CONFIG_MEMCG
Quoted 4 lines · Johannes Weiner
The cgroup2 memory controller will account important in-kernel memory consumers per default. Move all necessary components to
CONFIG_MEMCG.Signed-off-by Johannes Weiner <[email protected]>
Michal Hocko
maintainerRe: [PATCH 6/8] mm: memcontrol: move kmem accounting code to CONFIG_MEMCG
In reply to Johannes WeinerQuoted 2 lines · Johannes Weiner
The cgroup2 memory controller will account important in-kernel memory consumers per default. Move all necessary components to
CONFIG_MEMCG.
Hmm, that bloats the kernel also for users who are not using cgroup2 and have CONFIG_MEMCG_KMEM disabled.
This is the situation before this patch
text data bss dec hex filename
521342 97516 44312 663170 a1e82 mm/built-in.o.kmem 513349 96299 43960 653608 9f928 mm/built-in.o.nokmem
and after with CONFIG_MEMCG_KMEM=n
521028 96556 44312 661896 a1988 mm/built-in.o
we are basically back to CONFIG_MEMCG_KMEM=y. This sounds like a wastage to me. Do we really need this?
Quoted 2 lines
Signed-off-by Johannes Weiner <[email protected]>
[...]
Signature · 2 lines
Michal Hocko SUSE Labs
Johannes Weiner
maintainerRe: [PATCH 6/8] mm: memcontrol: move kmem accounting code to CONFIG_MEMCG
Quoted 6 lines · Michal Hocko
Quoted 2 lines · Johannes Weiner
The cgroup2 memory controller will account important in-kernel memory consumers per default. Move all necessary components to
CONFIG_MEMCG.Hmm, that bloats the kernel also for users who are not using cgroup2 and have
CONFIG_MEMCG_KMEMdisabled.
Huh? The clock is ticking for them. We'll keep the original cgroup interface around for backwards compatibility as long as we think there are activer users, but this is not the time to microoptimize v1. A slight increase to kernel size is unfortunate, but I don't think this could be considered a regression in the sense that it breaks anything.
I'm more concerned with cgroup2 users having to pay the excessive cost of v1-only features, like the entire soft limit implementation, charge migration, which also has its fangs in VM hotpaths, the eventfd stuff, arbitrarily-configurable usage thresholds. That's a *ton* of code. If you want to tackle kernel bloat, grouping this stuff all together and slapping a CONFIG_MEMCG_LEGACY around it would be a real step forward.
Johannes Weiner
maintainerPATCH v2 6/8 mm: memcontrol: move kmem accounting code to CONFIG_MEMCG
In reply to Johannes WeinerThe cgroup2 memory controller will account important in-kernel memory consumers per default. Move all necessary components to CONFIG_MEMCG.
---
Hi Andrew,
here is a drop-in replacement for what's in your tree to make slob work with memcg again. It guards all the kmem-specific stuff with CONFIG_MEMCG && !CONFIG_SLOB. A little lame but I figure it's not worth introducing another level of indirection and go through the trouble of finding a more meaningful symbol (CONFIG_MEMCG_KMEM is taken, CONFIG_MEMCG_SLAB is ambiguous with SLAB vs. SLUB etc.).
So there.
The rest of my series applies fine on top, but if this creates fallout in subsequent patches you have in your tree I'm happy to send refreshs.
Thanks again for your report, Arnd!
include/linux/list_lru.h | 4 +-- include/linux/memcontrol.h | 7 +++-- include/linux/sched.h | 4 +-- include/linux/slab_def.h | 3 +- include/linux/slub_def.h | 2 +- mm/list_lru.c | 12 ++++---- mm/memcontrol.c | 69 +++++++++++++++++++++++++++------------------- mm/slab.h | 6 ++-- mm/slab_common.c | 10 +++---- mm/slub.c | 10 +++---- 10 files changed, 71 insertions(+), 56 deletions(-)
include/linux/list_lru.h +2 -2
@@ -40,7 +40,7 @@ struct list_lru_node {spinlock_t lock;/* global list, used for the root cgroup in cgroup aware lrus */ struct list_lru_one lru; -#ifdef CONFIG_MEMCG_KMEM +#if defined(CONFIG_MEMCG ) && !defined(CONFIG_SLOB )/* for cgroup aware lrus points to per cgroup lists, otherwise NULL */ struct list_lru_memcg *memcg_lrus;#endif
@@ -48,7 +48,7 @@ struct list_lru_node {struct list_lru {struct list_lru_node *node; -#ifdef CONFIG_MEMCG_KMEM +#if defined(CONFIG_MEMCG ) && !defined(CONFIG_SLOB )struct list_head list;#endif };
include/linux/memcontrol.h +4 -3
@@ -236,7 +236,7 @@ struct mem_cgroup {#if defined(CONFIG_MEMCG_KMEM ) && defined(CONFIG_INET )struct cg_proto tcp_mem;#endif -#if defined(CONFIG_MEMCG_KMEM ) +#ifndef CONFIG_SLOB /* Index in the kmem_cache->memcg_params.memcg_caches array */ int kmemcg_id;enum memcg_kmem_state kmem_state;
@@ -735,7 +735,7 @@ static inline bool mem_cgroup_under_socket_pressure(struct mem_cgroup *memcg) }#endif -#ifdef CONFIG_MEMCG_KMEM +#if defined(CONFIG_MEMCG ) && !defined(CONFIG_SLOB )extern struct static_key_false memcg_kmem_enabled_key;extern int memcg_nr_cache_ids;
@@ -891,5 +891,6 @@ memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp)static inline void memcg_kmem_put_cache (struct kmem_cache *cachep) { } -#endif /* CONFIG_MEMCG_KMEM */ +#endif /* CONFIG_MEMCG && !CONFIG_SLOB */ +#endif /* _LINUX_MEMCONTROL_H */
include/linux/sched.h +2 -2
@@ -1465,10 +1465,10 @@ struct task_struct { unsigned sched_migrated:1;#ifdef CONFIG_MEMCG unsigned memcg_may_oom:1; -#endif -#ifdef CONFIG_MEMCG_KMEM +#ifndef CONFIG_SLOB unsigned memcg_kmem_skip_account:1;#endif +#endif #ifdef CONFIG_COMPAT_BRK unsigned brk_randomized:1;#endif
include/linux/slab_def.h +2 -1
@@ -69,7 +69,8 @@ struct kmem_cache {*/ int obj_offset;#endif /* CONFIG_DEBUG_SLAB */ -#ifdef CONFIG_MEMCG_KMEM + +#ifdef CONFIG_MEMCG struct memcg_cache_params memcg_params;#endif
include/linux/slub_def.h +1 -1
@@ -84,7 +84,7 @@ struct kmem_cache {#ifdef CONFIG_SYSFS struct kobject kobj;/* For sysfs */ #endif -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG struct memcg_cache_params memcg_params;int max_attr_size;/* for propagation, maximum size of a stored attr */ #ifdef CONFIG_SYSFS
mm/list_lru.c +6 -6
@@ -12,7 +12,7 @@#include <linux/mutex.h> #include <linux/memcontrol.h> -#ifdef CONFIG_MEMCG_KMEM +#if defined(CONFIG_MEMCG ) && !defined(CONFIG_SLOB )static LIST_HEAD (list_lrus);static DEFINE_MUTEX (list_lrus_mutex);
@@ -37,9 +37,9 @@ static void list_lru_register(struct list_lru *lru)static void list_lru_unregister (struct list_lru *lru) { } -#endif /* CONFIG_MEMCG_KMEM */ +#endif /* CONFIG_MEMCG && !CONFIG_SLOB */ -#ifdef CONFIG_MEMCG_KMEM +#if defined(CONFIG_MEMCG ) && !defined(CONFIG_SLOB )static inline bool list_lru_memcg_aware (struct list_lru *lru) {/*
@@ -104,7 +104,7 @@ list_lru_from_kmem(struct list_lru_node *nlru, void *ptr) {return &nlru->lru; } -#endif /* CONFIG_MEMCG_KMEM */ +#endif /* CONFIG_MEMCG && !CONFIG_SLOB */ bool list_lru_add (struct list_lru *lru,struct list_head *item) {
@@ -292,7 +292,7 @@ static void init_one_lru(struct list_lru_one *l) l->nr_items =0 ; } -#ifdef CONFIG_MEMCG_KMEM +#if defined(CONFIG_MEMCG ) && !defined(CONFIG_SLOB )static void __memcg_destroy_list_lru_node (struct list_lru_memcg *memcg_lrus,int begin,int end) {
@@ -529,7 +529,7 @@ static int memcg_init_list_lru(struct list_lru *lru, bool memcg_aware)static void memcg_destroy_list_lru (struct list_lru *lru) { } -#endif /* CONFIG_MEMCG_KMEM */ +#endif /* CONFIG_MEMCG && !CONFIG_SLOB */ int __list_lru_init (struct list_lru *lru,bool memcg_aware,struct lock_class_key *key)
mm/memcontrol.c +41 -28
141 lines not on this page · raw message
mm/slab.h +3 -3
@@ -173,7 +173,7 @@ ssize_t slabinfo_write(struct file *file, const char __user *buffer,void __kmem_cache_free_bulk (struct kmem_cache *,size_t ,void **);int __kmem_cache_alloc_bulk (struct kmem_cache *,gfp_t ,size_t ,void **); -#ifdef CONFIG_MEMCG_KMEM +#if defined(CONFIG_MEMCG ) && !defined(CONFIG_SLOB )/* * Iterate over all memcg caches of the given root cache. The caller must hold * slab_mutex.
@@ -251,7 +251,7 @@ static __always_inline int memcg_charge_slab(struct page *page,extern void slab_init_memcg_params (struct kmem_cache *); -#else /* !CONFIG_MEMCG_KMEM */ +#else /* CONFIG_MEMCG && !CONFIG_SLOB */ #define for_each_memcg_cache (iter, root) \ for ((void)(iter), (void)(root); 0; )
@@ -292,7 +292,7 @@ static inline int memcg_charge_slab(struct page *page, gfp_t gfp, int order,static inline void slab_init_memcg_params (struct kmem_cache *s) { } -#endif /* CONFIG_MEMCG_KMEM */ +#endif /* CONFIG_MEMCG && !CONFIG_SLOB */ static inline struct kmem_cache *cache_from_obj (struct kmem_cache *s,void *x) {
mm/slab_common.c +5 -5
@@ -128,7 +128,7 @@ int __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t nr,return i; } -#ifdef CONFIG_MEMCG_KMEM +#if defined(CONFIG_MEMCG ) && !defined(CONFIG_SLOB )void slab_init_memcg_params (struct kmem_cache *s) { s->memcg_params.is_root_cache = true;
@@ -221,7 +221,7 @@ static inline int init_memcg_params(struct kmem_cache *s,static inline void destroy_memcg_params (struct kmem_cache *s) { } -#endif /* CONFIG_MEMCG_KMEM */ +#endif /* CONFIG_MEMCG && !CONFIG_SLOB */ /* * Find a mergeable slab cache
@@ -477,7 +477,7 @@ static void release_caches(struct list_head *release, bool need_rcu_barrier) } } -#ifdef CONFIG_MEMCG_KMEM +#if defined(CONFIG_MEMCG ) && !defined(CONFIG_SLOB )/* * memcg_create_kmem_cache - Create a cache for a memory cgroup. * @memcg: The memory cgroup the new cache is for.
@@ -689,7 +689,7 @@ static inline int shutdown_memcg_caches(struct kmem_cache *s, {return 0 ; } -#endif /* CONFIG_MEMCG_KMEM */ +#endif /* CONFIG_MEMCG && !CONFIG_SLOB */ void slab_kmem_cache_release (struct kmem_cache *s) {
@@ -1123,7 +1123,7 @@ static int slab_show(struct seq_file *m, void *p)return 0 ; } -#ifdef CONFIG_MEMCG_KMEM +#if defined(CONFIG_MEMCG ) && !defined(CONFIG_SLOB )int memcg_slab_show (struct seq_file *m,void *p) { struct kmem_cache *s = list_entry(p, struct kmem_cache, list);
mm/slub.c +5 -5
@@ -5207,7 +5207,7 @@ static ssize_t slab_attr_store(struct kobject *kobj,return -EIO ; err = attribute->store (s, buf, len); -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG if (slab_state >=FULL && err >=0 &&is_root_cache (s)) {struct kmem_cache *c;
@@ -5242,7 +5242,7 @@ static ssize_t slab_attr_store(struct kobject *kobj,static void memcg_propagate_slab_attrs (struct kmem_cache *s) { -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG int i;char *buffer =NULL ;struct kmem_cache *root_cache;
@@ -5328,7 +5328,7 @@ static struct kset *slab_kset;static inline struct kset *cache_kset (struct kmem_cache *s) { -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG if (!is_root_cache (s))return s->memcg_params.root_cache->memcg_kset;#endif
@@ -5405,7 +5405,7 @@ static int sysfs_slab_add(struct kmem_cache *s)if (err) goto out_del_kobj; -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG if (is_root_cache (s)) { s->memcg_kset =kset_create_and_add ("cgroup" ,NULL , &s->kobj);if (!s->memcg_kset) {
@@ -5438,7 +5438,7 @@ void sysfs_slab_remove(struct kmem_cache *s)*/ return ; -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG kset_unregister (s->memcg_kset);#endif kobject_uevent (&s->kobj,KOBJ_REMOVE );
Signature · 1 line
2.6.3
Johannes Weiner
maintainerRe: [PATCH 6/8 v2] mm: memcontrol: move kmem accounting code to CONFIG_MEMCG
Narf. Almost there...
From db4522b2b3e6ca8ce5f6e673948772bcd8fdd298 Mon Sep 17 00:00:00 2001
From: Johannes Weiner <[email protected]>
Date: Thu, 10 Dec 2015 15:42:54 -0500
Subject: [PATCH] mm: memcontrol: move kmem accounting code to CONFIG_MEMCG fix
--- include/linux/slab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/slab.h +1 -1
@@ -86,7 +86,7 @@#else # define SLAB_FAILSLAB 0x00000000UL#endif -#ifdef CONFIG_MEMCG_KMEM +#if defined(CONFIG_MEMCG ) && !defined(CONFIG_SLOB )# define SLAB_ACCOUNT 0x04000000UL/* Account to memcg */ #else # define SLAB_ACCOUNT 0x00000000UL
Signature · 1 line
2.6.3
Johannes Weiner
maintainerPATCH 7/8 mm: memcontrol: account "kmem" consumers in cgroup2 memory controller
In reply to Johannes WeinerThe original cgroup memory controller has an extension to account slab memory (and other "kernel memory" consumers) in a separate "kmem" counter, once the user set an explicit limit on that "kmem" pool.
However, this includes various consumers whose sizes are directly linked to userspace activity. Accounting them as an optional "kmem" extension is problematic for several reasons:
1. It leaves the main memory interface with incomplete semantics. A user who puts their workload into a cgroup and configures a memory limit does not expect us to leave holes in the containment as big as the dentry and inode cache, or the kernel stack pages.
2. If the limit set on this random historical subgroup of consumers is reached, subsequent allocations will fail even when the main memory pool available to the cgroup is not yet exhausted and/or has reclaimable memory in it.
3. Calling it 'kernel memory' is misleading. The dentry and inode caches are no more 'kernel' (or no less 'user') memory than the page cache itself. Treating these consumers as different classes is a historical implementation detail that should not leak to users.
So, in addition to page cache, anonymous memory, and network socket memory, account the following memory consumers per default in the cgroup2 memory controller:
- threadinfo
- task_struct
- task_delay_info
- pid
- cred
- mm_struct
- vm_area_struct and vm_region (nommu)
- anon_vma and anon_vma_chain
- signal_struct
- sighand_struct
- fs_struct
- files_struct
- fdtable and fdtable->full_fds_bits
- dentry and external_name
- inode for all filesystems.
This should give us reasonable memory isolation for most common workloads out of the box.
--- mm/memcontrol.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
mm/memcontrol.c +11 -7
@@ -2356,13 +2356,14 @@ int __memcg_kmem_charge_memcg(struct page *page, gfp_t gfp, int order,if (!memcg_kmem_online (memcg))return 0 ; -if (!page_counter_try_charge (&memcg->kmem, nr_pages, &counter)) -return -ENOMEM ; - ret =try_charge (memcg, gfp, nr_pages); -if (ret) { -page_counter_uncharge (&memcg->kmem, nr_pages); +if (ret)return ret; + +if (!cgroup_subsys_on_dfl (memory_cgrp_subsys) && + !page_counter_try_charge (&memcg->kmem, nr_pages, &counter)) { +cancel_charge (memcg, nr_pages); +return -ENOMEM ; } page->mem_cgroup = memcg;
@@ -2391,7 +2392,9 @@ void __memcg_kmem_uncharge(struct page *page, int order)VM_BUG_ON_PAGE (mem_cgroup_is_root (memcg), page); -page_counter_uncharge (&memcg->kmem, nr_pages); +if (!cgroup_subsys_on_dfl (memory_cgrp_subsys)) +page_counter_uncharge (&memcg->kmem, nr_pages); +page_counter_uncharge (&memcg->memory, nr_pages);if (do_memsw_account ())page_counter_uncharge (&memcg->memsw, nr_pages);
@@ -2895,7 +2898,8 @@ static int memcg_propagate_kmem(struct mem_cgroup *memcg)* onlined after this point, because it has at least one child * already. */ -if (memcg_kmem_online (parent)) +if (cgroup_subsys_on_dfl (memory_cgrp_subsys) || +memcg_kmem_online (parent)) ret =memcg_online_kmem (memcg);mutex_unlock (&memcg_limit_mutex);return ret;
Signature · 7 lines
2.6.3 -- 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 7/8] mm: memcontrol: account "kmem" consumers in cgroup2 memory controller
Quoted 43 lines · Johannes Weiner
The original cgroup memory controller has an extension to account slab memory (and other "kernel memory" consumers) in a separate "kmem" counter, once the user set an explicit limit on that "kmem" pool.
However, this includes various consumers whose sizes are directly linked to userspace activity. Accounting them as an optional "kmem" extension is problematic for several reasons:
1. It leaves the main memory interface with incomplete semantics. A user who puts their workload into a cgroup and configures a memory limit does not expect us to leave holes in the containment as big as the dentry and inode cache, or the kernel stack pages.
2. If the limit set on this random historical subgroup of consumers is reached, subsequent allocations will fail even when the main memory pool available to the cgroup is not yet exhausted and/or has reclaimable memory in it.
3. Calling it 'kernel memory' is misleading. The dentry and inode caches are no more 'kernel' (or no less 'user') memory than the page cache itself. Treating these consumers as different classes is a historical implementation detail that should not leak to users.
So, in addition to page cache, anonymous memory, and network socket memory, account the following memory consumers per default in the cgroup2 memory controller:
- threadinfo
-task_struct
-task_delay_info
- pid
- cred
-mm_struct
-vm_area_structandvm_region(nommu)
-anon_vmaandanon_vma_chain
-signal_struct
-sighand_struct
-fs_struct
-files_struct
- fdtable andfdtable->full_fds_bits
- dentry andexternal_name
- inode for all filesystems.
Quoted 4 lines
This should give us reasonable memory isolation for most common workloads out of the box.
Signed-off-by Johannes Weiner <[email protected]>
The patch looks good to me, but I think we still need to add a boot-time knob to disable kmem accounting, as we do for sockets:
From: Vladimir Davydov <[email protected]>
Subject: [PATCH] mm: memcontrol: allow to disable kmem accounting for cgroup2
Kmem accounting might incur overhead that some users can't put up with. Besides, the implementation is still considered unstable. So let's provide a way to disable it for those users who aren't happy with it.
To disable kmem accounting for cgroup2, pass cgroup.memory=nokmem at boot time.
Documentation/kernel-parameters.txt +1 -0
@@ -602,6 +602,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. cgroup.memory= [KNL] Pass options to the cgroup memory controller. Format: <string> nosocket -- Disable socket memory accounting. + nokmem -- Disable kernel memory accounting. checkreqprot [SELINUX] Set initial checkreqprot flag value. Format: { "0" | "1" }
mm/memcontrol.c +7 -2
@@ -83,6 +83,9 @@ struct mem_cgroup *root_mem_cgroup __read_mostly;/* Socket memory accounting disabled? */ static bool cgroup_memory_nosocket; +/* Kernel memory accounting disabled? */ +static bool cgroup_memory_nokmem; +/* Whether the swap controller is active */ #ifdef CONFIG_MEMCG_SWAP int do_swap_account__read_mostly ;
@@ -2898,8 +2901,8 @@ static int memcg_propagate_kmem(struct mem_cgroup *memcg)* onlined after this point, because it has at least one child * already. */ -if (cgroup_subsys_on_dfl (memory_cgrp_subsys) || -memcg_kmem_online (parent)) +if (memcg_kmem_online (parent) || + (cgroup_subsys_on_dfl (memory_cgrp_subsys) && !cgroup_memory_nokmem)) ret =memcg_online_kmem (memcg);mutex_unlock (&memcg_limit_mutex);return ret;
@@ -5587,6 +5590,8 @@ static int __init cgroup_memory(char *s)continue ;if (!strcmp (token,"nosocket" )) cgroup_memory_nosocket = true; +if (!strcmp (token,"nokmem" )) + cgroup_memory_nokmem = true; }return 0 ; }
Re: [PATCH 7/8] mm: memcontrol: account "kmem" consumers in cgroup2 memory controller
Quoted 44 lines · Vladimir Davydov
Quoted 43 lines · Johannes Weiner
The original cgroup memory controller has an extension to account slab memory (and other "kernel memory" consumers) in a separate "kmem" counter, once the user set an explicit limit on that "kmem" pool.
However, this includes various consumers whose sizes are directly linked to userspace activity. Accounting them as an optional "kmem" extension is problematic for several reasons:
1. It leaves the main memory interface with incomplete semantics. A user who puts their workload into a cgroup and configures a memory limit does not expect us to leave holes in the containment as big as the dentry and inode cache, or the kernel stack pages.
2. If the limit set on this random historical subgroup of consumers is reached, subsequent allocations will fail even when the main memory pool available to the cgroup is not yet exhausted and/or has reclaimable memory in it.
3. Calling it 'kernel memory' is misleading. The dentry and inode caches are no more 'kernel' (or no less 'user') memory than the page cache itself. Treating these consumers as different classes is a historical implementation detail that should not leak to users.
So, in addition to page cache, anonymous memory, and network socket memory, account the following memory consumers per default in the cgroup2 memory controller:
- threadinfo
-task_struct
-task_delay_info
- pid
- cred
-mm_struct
-vm_area_structandvm_region(nommu)
-anon_vmaandanon_vma_chain
-signal_struct
-sighand_struct
-fs_struct
-files_struct
- fdtable andfdtable->full_fds_bits
- dentry andexternal_name
- inode for all filesystems.
Quoted 6 lines
Quoted 4 lines
This should give us reasonable memory isolation for most common workloads out of the box.
Signed-off-by Johannes Weiner <[email protected]>Acked-by Vladimir Davydov <[email protected]>
Thank you!
Quoted 6 lines
The patch looks good to me, but I think we still need to add a boot-time knob to disable kmem accounting, as we do for sockets:
From: Vladimir Davydov <[email protected]>
Subject: [PATCH] mm: memcontrol: allow to disable kmem accounting for cgroup2
Quoted 8 lines
Kmem accounting might incur overhead that some users can't put up with. Besides, the implementation is still considered unstable. So let's provide a way to disable it for those users who aren't happy with it.
To disable kmem accounting for cgroup2, pass cgroup.memory=nokmem at boot time.
Signed-off-by Vladimir Davydov <[email protected]>
Especially in the early release phases, there might be birthing pain that users in the field would want to work around. And I'd rather they can selectively disable problematic parts during the transition than switching back wholesale to the old cgroup interface.
For me that would be the prime reason: a temporary workaround for legacy users until we get our stuff sorted out. Unacceptable overhead or instability would be something we would have to address anyway. And then it's fine too that the flag continues to use the historic misnomer "kmem".
Re: [PATCH 7/8] mm: memcontrol: account "kmem" consumers in cgroup2 memory controller
In reply to Vladimir DavydovQuoted 6 lines · Vladimir Davydov
From: Vladimir Davydov <[email protected]>
Subject: [PATCH] mm: memcontrol: allow to disable kmem accounting for cgroup2Kmem accounting might incur overhead that some users can't put up with. Besides, the implementation is still considered unstable. So let's provide a way to disable it for those users who aren't happy with it.
Yes there will be users who do not want to pay an additional overhead and still accoplish what they need.
I haven't measured the overhead lately - especially after the opt-out -> opt-in change so it might be much lower than my previous ~5% for kbuild load.
Quoted 4 lines
To disable kmem accounting for cgroup2, pass cgroup.memory=nokmem at boot time.
Signed-off-by Vladimir Davydov <[email protected]>
Thanks!
Quoted 51 lines
Documentation/kernel-parameters.txt +1
-0@@ -602,6 +602,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. cgroup.memory= [KNL] Pass options to the cgroup memory controller. Format: <string> nosocket -- Disable socket memory accounting. + nokmem -- Disable kernel memory accounting. checkreqprot [SELINUX] Set initial checkreqprot flag value. Format: { "0" | "1" }mm/memcontrol.c +7
-3@@ -83,6 +83,9 @@ struct mem_cgroup *root_mem_cgroup __read_mostly;/* Socket memory accounting disabled? */ static bool cgroup_memory_nosocket; +/* Kernel memory accounting disabled? */ +static bool cgroup_memory_nokmem; +/* Whether the swap controller is active */ #ifdef CONFIG_MEMCG_SWAP int do_swap_account__read_mostly ;@@ -2898,8 +2901,8 @@ static int memcg_propagate_kmem(struct mem_cgroup *memcg)* onlined after this point, because it has at least one child * already. */ -if (cgroup_subsys_on_dfl (memory_cgrp_subsys) || -memcg_kmem_online (parent)) +if (memcg_kmem_online (parent) || + (cgroup_subsys_on_dfl (memory_cgrp_subsys) && !cgroup_memory_nokmem)) ret =memcg_online_kmem (memcg);mutex_unlock (&memcg_limit_mutex);return ret;@@ -5587,6 +5590,8 @@ static int __init cgroup_memory(char *s)continue ;if (!strcmp (token,"nosocket" )) cgroup_memory_nosocket = true; +if (!strcmp (token,"nokmem" )) + cgroup_memory_nokmem = true; }return 0 ; } --To unsubscribe from this list: send the line "unsubscribe cgroups" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 2 lines
Michal Hocko SUSE Labs
Johannes Weiner
maintainerRe: [PATCH 7/8] mm: memcontrol: account "kmem" consumers in cgroup2 memory controller
Quoted 8 lines · Michal Hocko
Quoted 6 lines · Vladimir Davydov
From: Vladimir Davydov <[email protected]>
Subject: [PATCH] mm: memcontrol: allow to disable kmem accounting for cgroup2Kmem accounting might incur overhead that some users can't put up with. Besides, the implementation is still considered unstable. So let's provide a way to disable it for those users who aren't happy with it.
Quoted 5 lines
Yes there will be users who do not want to pay an additional overhead and still accoplish what they need.
I haven't measured the overhead lately - especially after the opt-out -> opt-in change so it might be much lower than my previous ~5% for kbuild load.
I think switching from accounting *all* slab allocations to accounting a list of, what, less than 20 select slabs, counts as a change significant enough to entirely invalidate those measurements and never bring up that number again in the context of kmem cost, don't you think?
There isn't that much that the kmem is doing, but for posterity I ran kbuild test inside a cgroup2, with and without cgroup.memory=nokmem, and these are the results:
default:
Performance counter stats for 'make -j16 -s clean bzImage' (3 runs):
715823.047005 task-clock (msec) # 3.794 CPUs utilized
252,538 context-switches # 0.353 K/sec
32,018 cpu-migrations # 0.045 K/sec
16,678,202 page-faults # 0.023 M/sec
1,783,804,914,980 cycles # 2.492 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,346,424,021,728 instructions # 0.75 insns per cycle
298,744,956,474 branches # 417.363 M/sec
10,207,872,737 branch-misses # 3.42% of all branches 188.667608149 seconds time elapsed ( +- 0.66% )
cgroup.memory=nokmem
Performance counter stats for 'make -j16 -s clean bzImage' (3 runs):
729028.322760 task-clock (msec) # 3.805 CPUs utilized
258,775 context-switches # 0.356 K/sec
32,241 cpu-migrations # 0.044 K/sec
16,647,817 page-faults # 0.023 M/sec
1,816,827,061,194 cycles # 2.497 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,345,446,962,095 instructions # 0.74 insns per cycle
298,461,034,326 branches # 410.277 M/sec
10,215,145,963 branch-misses # 3.42% of all branches 191.583957742 seconds time elapsed ( +- 0.57% )
I would say the difference is solidly in the noise.
I also profiled a silly find | xargs stat pipe to excercise the dentry and inode accounting, and this was the highest kmem-specific entry:
0.27% 0.27% find [kernel.kallsyms] [k] __memcg_kmem_get_cache
|
---__memcg_kmem_get_cache
__kmalloc
ext4_htree_store_dirent
htree_dirblock_to_tree
ext4_htree_fill_tree
ext4_readdir
iterate_dir
sys_getdents
entry_SYSCALL_64_fastpath
__getdents64So can we *please* lay this whole "unreasonable burden to legacy and power users" line of argument to rest and get on with our work? And then tackle scalability problems as they show up in real workloads?
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>
Michal Hocko
maintainerRe: [PATCH 7/8] mm: memcontrol: account "kmem" consumers in cgroup2 memory controller
Quoted 15 lines · Johannes Weiner
Quoted 8 lines · Michal Hocko
Quoted 6 lines · Vladimir Davydov
From: Vladimir Davydov <[email protected]>
Subject: [PATCH] mm: memcontrol: allow to disable kmem accounting for cgroup2Kmem accounting might incur overhead that some users can't put up with. Besides, the implementation is still considered unstable. So let's provide a way to disable it for those users who aren't happy with it.
Quoted 5 lines
Yes there will be users who do not want to pay an additional overhead and still accoplish what they need.
I haven't measured the overhead lately - especially after the opt-out -> opt-in change so it might be much lower than my previous ~5% for kbuild load.
Quoted 4 lines
I think switching from accounting *all* slab allocations to accounting a list of, what, less than 20 select slabs, counts as a change significant enough to entirely invalidate those measurements and never bring up that number again in the context of kmem cost, don't you think?
Yes, as I've said the numbers are expected to be much lower. That is one of the reasons I have acknowledged kmem enabled as a reasonable default. There will always be _special_ loads where numbers might look differently, though, and having a disabling knob is a reasonable thing to offer with a minimum maintenance overhead. And this is the argument for the inclusion of the patch from Vladimir.
Signature · 2 lines
Michal Hocko SUSE Labs
Re: [PATCH 7/8] mm: memcontrol: account "kmem" consumers in cgroup2 memory controller
In reply to Johannes WeinerQuoted 43 lines · Johannes Weiner
The original cgroup memory controller has an extension to account slab memory (and other "kernel memory" consumers) in a separate "kmem" counter, once the user set an explicit limit on that "kmem" pool.
However, this includes various consumers whose sizes are directly linked to userspace activity. Accounting them as an optional "kmem" extension is problematic for several reasons:
1. It leaves the main memory interface with incomplete semantics. A user who puts their workload into a cgroup and configures a memory limit does not expect us to leave holes in the containment as big as the dentry and inode cache, or the kernel stack pages.
2. If the limit set on this random historical subgroup of consumers is reached, subsequent allocations will fail even when the main memory pool available to the cgroup is not yet exhausted and/or has reclaimable memory in it.
3. Calling it 'kernel memory' is misleading. The dentry and inode caches are no more 'kernel' (or no less 'user') memory than the page cache itself. Treating these consumers as different classes is a historical implementation detail that should not leak to users.
So, in addition to page cache, anonymous memory, and network socket memory, account the following memory consumers per default in the cgroup2 memory controller:
- threadinfo
-task_struct
-task_delay_info
- pid
- cred
-mm_struct
-vm_area_structandvm_region(nommu)
-anon_vmaandanon_vma_chain
-signal_struct
-sighand_struct
-fs_struct
-files_struct
- fdtable andfdtable->full_fds_bits
- dentry andexternal_name
- inode for all filesystems.
Quoted 4 lines
This should give us reasonable memory isolation for most common workloads out of the box.
Signed-off-by Johannes Weiner <[email protected]>
Quoted 51 lines
--- mm/memcontrol.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)mm/memcontrol.c +11
-7@@ -2356,13 +2356,14 @@ int __memcg_kmem_charge_memcg(struct page *page, gfp_t gfp, int order,if (!memcg_kmem_online (memcg))return 0 ; -if (!page_counter_try_charge (&memcg->kmem, nr_pages, &counter)) -return -ENOMEM ; - ret =try_charge (memcg, gfp, nr_pages); -if (ret) { -page_counter_uncharge (&memcg->kmem, nr_pages); +if (ret)return ret; + +if (!cgroup_subsys_on_dfl (memory_cgrp_subsys) && + !page_counter_try_charge (&memcg->kmem, nr_pages, &counter)) { +cancel_charge (memcg, nr_pages); +return -ENOMEM ; } page->mem_cgroup = memcg;@@ -2391,7 +2392,9 @@ void __memcg_kmem_uncharge(struct page *page, int order)VM_BUG_ON_PAGE (mem_cgroup_is_root (memcg), page); -page_counter_uncharge (&memcg->kmem, nr_pages); +if (!cgroup_subsys_on_dfl (memory_cgrp_subsys)) +page_counter_uncharge (&memcg->kmem, nr_pages); +page_counter_uncharge (&memcg->memory, nr_pages);if (do_memsw_account ())page_counter_uncharge (&memcg->memsw, nr_pages);@@ -2895,7 +2898,8 @@ static int memcg_propagate_kmem(struct mem_cgroup *memcg)* onlined after this point, because it has at least one child * already. */ -if (memcg_kmem_online (parent)) +if (cgroup_subsys_on_dfl (memory_cgrp_subsys) || +memcg_kmem_online (parent)) ret =memcg_online_kmem (memcg);mutex_unlock (&memcg_limit_mutex);return ret;Signature · 1 line
2.6.3
Signature · 2 lines
Michal Hocko SUSE Labs
Johannes Weiner
maintainerPATCH 8/8 mm: memcontrol: introduce CONFIG_MEMCG_LEGACY_KMEM
In reply to Johannes WeinerLet the user know that CONFIG_MEMCG_KMEM does not apply to the cgroup2 interface. This also makes legacy-only code sections stand out better.
--- include/linux/memcontrol.h | 4 ++-- init/Kconfig | 10 +++++++++- mm/memcontrol.c | 16 ++++++++-------- net/ipv4/Makefile | 2 +- 4 files changed, 20 insertions(+), 12 deletions(-)
include/linux/memcontrol.h +2 -2
@@ -233,7 +233,7 @@ struct mem_cgroup {*/ struct mem_cgroup_stat_cpu __percpu *stat; -#if defined(CONFIG_MEMCG_KMEM ) && defined(CONFIG_INET ) +#if defined(CONFIG_MEMCG_LEGACY_KMEM ) && defined(CONFIG_INET )struct cg_proto tcp_mem;#endif
@@ -873,7 +873,7 @@ extern struct static_key_false memcg_sockets_enabled_key;#define mem_cgroup_sockets_enabled static_branch_unlikely(&memcg_sockets_enabled_key)static inline bool mem_cgroup_under_socket_pressure (struct mem_cgroup *memcg) { -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG_LEGACY_KMEM if (memcg->tcp_mem.memory_pressure)return true;#endif
init/Kconfig +9 -1
@@ -1040,10 +1040,13 @@ config MEMCG_SWAP_ENABLED For those who want to have the feature enabled by default should select this option (if, for some reason, they need to disable it then swapaccount=0 does the trick). +config MEMCG_LEGACY_KMEM + bool config MEMCG_KMEM - bool "Memory Resource Controller Kernel Memory accounting" + bool "Legacy Memory Resource Controller Kernel Memory accounting" depends on MEMCG depends on SLUB || SLAB + select MEMCG_LEGACY_KMEM help The Kernel Memory extension for Memory Resource Controller can limit the amount of memory used by kernel objects in the system. Those are
@@ -1052,6 +1055,11 @@ config MEMCG_KMEM the kmem extension can use it to guarantee that no group of processes will ever exhaust kernel resources alone. + This option affects the ORIGINAL cgroup interface. The cgroup2 memory + controller includes important in-kernel memory consumers per default. + + If you're using cgroup2, say N. + config CGROUP_HUGETLB bool "HugeTLB Resource Controller for Control Groups" depends on HUGETLB_PAGE
mm/memcontrol.c +8 -8
@@ -2959,7 +2959,7 @@ static void memcg_free_kmem(struct mem_cgroup *memcg) } } -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG_LEGACY_KMEM static int memcg_update_kmem_limit (struct mem_cgroup *memcg,unsigned long limit) {
@@ -2983,7 +2983,7 @@ static int memcg_update_kmem_limit(struct mem_cgroup *memcg, {return -EINVAL ; } -#endif /* CONFIG_MEMCG_KMEM */ +#endif /* CONFIG_MEMCG_LEGACY_KMEM */ /* * The user of this function is...
@@ -3995,7 +3995,7 @@ static struct cftype mem_cgroup_legacy_files[] = { .seq_show = memcg_numa_stat_show, },#endif -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG_LEGACY_KMEM { .name = "kmem.limit_in_bytes", .private = MEMFILE_PRIVATE(_KMEM, RES_LIMIT),
@@ -4220,7 +4220,7 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css)if (ret)return ret; -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG_LEGACY_KMEM ret =tcp_init_cgroup (memcg);if (ret)return ret;
@@ -4276,7 +4276,7 @@ static void mem_cgroup_css_free(struct cgroup_subsys_state *css)memcg_free_kmem (memcg); -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG_LEGACY_KMEM tcp_destroy_cgroup (memcg);#endif
@@ -5495,7 +5495,7 @@ void sock_update_memcg(struct sock *sk) memcg =mem_cgroup_from_task (current);if (memcg == root_mem_cgroup) goto out; -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG_LEGACY_KMEM if (!cgroup_subsys_on_dfl (memory_cgrp_subsys) && !memcg->tcp_mem.active) goto out;#endif
@@ -5524,7 +5524,7 @@ bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages) {gfp_t gfp_mask =GFP_KERNEL ; -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG_LEGACY_KMEM if (!cgroup_subsys_on_dfl (memory_cgrp_subsys)) {struct page_counter *counter;
@@ -5556,7 +5556,7 @@ bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)*/ void mem_cgroup_uncharge_skmem (struct mem_cgroup *memcg,unsigned int nr_pages) { -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG_LEGACY_KMEM if (!cgroup_subsys_on_dfl (memory_cgrp_subsys)) {page_counter_uncharge (&memcg->tcp_mem.memory_allocated, nr_pages);
net/ipv4/Makefile +1 -1
@@ -56,7 +56,7 @@ obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o -obj-$(CONFIG_MEMCG_KMEM) += tcp_memcontrol.o +obj-$(CONFIG_MEMCG_LEGACY_KMEM) += tcp_memcontrol.o obj-$(CONFIG_NETLABEL) += cipso_ipv4.o obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
Signature · 7 lines
2.6.3 -- 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 8/8] mm: memcontrol: introduce CONFIG_MEMCG_LEGACY_KMEM
Quoted 4 lines · Johannes Weiner
Let the user know that
CONFIG_MEMCG_KMEMdoes not apply to the cgroup2 interface. This also makes legacy-only code sections stand out better.Signed-off-by Johannes Weiner <[email protected]>