Charging a peer file to a particular cgroup can result in pinning the cgroup for indefinitely long after destruction, because peer files are shared system-wide.
Signed-off-by: Vladimir Davydov <[email protected]> --- fs/ext4/pfcache.c | 13 ++++++++++++- include/linux/memcontrol.h | 11 +++++++++++ mm/memcontrol.c | 6 ++++-- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/fs/ext4/pfcache.c b/fs/ext4/pfcache.c index b9751ceac4f0..fe1296f27eb2 100644 --- a/fs/ext4/pfcache.c +++ b/fs/ext4/pfcache.c @@ -15,6 +15,7 @@ #include <linux/namei.h> #include <linux/exportfs.h> #include <linux/init_task.h> /* for init_cred */ +#include <linux/memcontrol.h> #include "ext4.h" #include "xattr.h" #include "../internal.h" @@ -59,6 +60,14 @@ int ext4_open_pfcache(struct inode *inode) pfcache_path(inode, name); + /* + * Lookups over shared area shouldn't be accounted to any particular + * memory cgroup, otherwise a cgroup can be pinned for indefinitely + * long after destruction, because a file or directory located in this + * area is likely to be in use by another containers or host. + */ + memcg_stop_kmem_account(); + cur_cred = override_creds(&init_cred); /* * Files in cache area must not have csum attributes or @@ -72,12 +81,14 @@ int ext4_open_pfcache(struct inode *inode) revert_creds(cur_cred); path_put(&root); if (ret) - return ret; + goto out; ret = open_mapping_peer(inode->i_mapping, &path, &init_cred); if (!ret) percpu_counter_inc(&EXT4_SB(inode->i_sb)->s_pfcache_peers); path_put(&path); +out: + memcg_resume_kmem_account(); return ret; } diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 743fb0b6f621..0dbb65345acc 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -511,6 +511,9 @@ extern int memcg_nr_cache_ids; extern void memcg_get_cache_ids(void); extern void memcg_put_cache_ids(void); +extern void memcg_stop_kmem_account(void); +extern void memcg_resume_kmem_account(void); + /* * Helper macro to loop through all memcg-specific caches. Callers must still * check if the cache is valid (it is either valid or NULL). @@ -702,6 +705,14 @@ static inline void memcg_put_cache_ids(void) { } +static inline void memcg_stop_kmem_account(void) +{ +} + +static inline void memcg_resume_kmem_account(void) +{ +} + static inline struct kmem_cache * memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp) { diff --git a/mm/memcontrol.c b/mm/memcontrol.c index fa66d1128cfb..19868872e393 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -3360,17 +3360,19 @@ static void memcg_free_cache_id(int id) * memcg_kmem_skip_account. So we enclose anything that might allocate memory * inside the following two functions. */ -static inline void memcg_stop_kmem_account(void) +void memcg_stop_kmem_account(void) { VM_BUG_ON(!current->mm); current->memcg_kmem_skip_account++; } +EXPORT_SYMBOL(memcg_stop_kmem_account); -static inline void memcg_resume_kmem_account(void) +void memcg_resume_kmem_account(void) { VM_BUG_ON(!current->mm); current->memcg_kmem_skip_account--; } +EXPORT_SYMBOL(memcg_resume_kmem_account); struct memcg_kmem_cache_create_work { struct mem_cgroup *memcg; -- 2.1.4 _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
