[Devel] [PATCH rh7] pfcache: do not account peer files to memcg
Vladimir Davydov
vdavydov at virtuozzo.com
Thu Apr 28 09:23:48 PDT 2016
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 <vdavydov at virtuozzo.com>
---
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
More information about the Devel
mailing list