[Devel] [PATCH rh7 09/11] ub: do not show dead beancounters under /proc/bc
Vladimir Davydov
vdavydov at parallels.com
Wed May 20 05:09:18 PDT 2015
A beancounter is considered "dead" if its cgroup is removed, but it is
still there. Since we are not going to use beancounters to detect memory
leaks anymore (memory accounting is up to memcg now), let's zap the code
for showing dead beancounters under /proc/bc.
Signed-off-by: Vladimir Davydov <vdavydov at parallels.com>
---
include/bc/beancounter.h | 9 +-------
include/linux/cgroup.h | 1 -
kernel/bc/beancounter.c | 33 +++++++++++++++++------------
kernel/bc/proc.c | 52 +++-------------------------------------------
kernel/cgroup.c | 18 ----------------
5 files changed, 24 insertions(+), 89 deletions(-)
diff --git a/include/bc/beancounter.h b/include/bc/beancounter.h
index a70684390171..732221b49223 100644
--- a/include/bc/beancounter.h
+++ b/include/bc/beancounter.h
@@ -115,8 +115,6 @@ struct user_beancounter {
unsigned long ub_magic;
struct list_head ub_list;
- struct rcu_head rcu;
-
spinlock_t ub_lock;
const char *ub_name;
@@ -356,12 +354,7 @@ struct user_beancounter *get_beancounter(struct user_beancounter *ub)
static inline
struct user_beancounter *get_beancounter_rcu(struct user_beancounter *ub)
{
- return css_refcnt_inc_not_zero(&ub->css) ? ub : NULL;
-}
-
-static inline bool ub_dead(struct user_beancounter *ub)
-{
- return !(ub->css.flags & CSS_ONLINE);
+ return css_tryget(&ub->css) ? ub : NULL;
}
extern uid_t ub_legacy_id(struct user_beancounter *ub);
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index a7b6941d8ad2..0108a98bb911 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -167,7 +167,6 @@ static inline void css_put(struct cgroup_subsys_state *css)
}
extern int css_refcnt(struct cgroup_subsys_state *css);
-extern bool css_refcnt_inc_not_zero(struct cgroup_subsys_state *css);
/* bits in struct cgroup flags field */
enum {
diff --git a/kernel/bc/beancounter.c b/kernel/bc/beancounter.c
index 4421e9fc379c..a1ca6f86198b 100644
--- a/kernel/bc/beancounter.c
+++ b/kernel/bc/beancounter.c
@@ -414,14 +414,6 @@ static inline int bc_verify_held(struct user_beancounter *ub)
return clean;
}
-static void bc_free_rcu(struct rcu_head *rcu)
-{
- struct user_beancounter *ub;
-
- ub = container_of(rcu, struct user_beancounter, rcu);
- free_ub(ub);
-}
-
static struct cgroup_subsys_state *ub_cgroup_css_alloc(struct cgroup *cg)
{
struct user_beancounter *ub;
@@ -437,16 +429,25 @@ static struct cgroup_subsys_state *ub_cgroup_css_alloc(struct cgroup *cg)
if (!ub)
return ERR_PTR(-ENOMEM);
+ return &ub->css;
+}
+
+static int ub_cgroup_css_online(struct cgroup *cg)
+{
+ struct user_beancounter *ub = cgroup_ub(cg);
+
+ if (!cg->parent)
+ return 0;
+
init_beancounter_nolimits(ub);
spin_lock(&ub_list_lock);
list_add_rcu(&ub->ub_list, &ub_list_head);
ub_count++;
spin_unlock(&ub_list_lock);
-
- return &ub->css;
+ return 0;
}
-static void ub_cgroup_css_free(struct cgroup *cg)
+static void ub_cgroup_css_offline(struct cgroup *cg)
{
struct user_beancounter *ub = cgroup_ub(cg);
@@ -454,6 +455,11 @@ static void ub_cgroup_css_free(struct cgroup *cg)
ub_count--;
list_del_rcu(&ub->ub_list);
spin_unlock(&ub_list_lock);
+}
+
+static void ub_cgroup_css_free(struct cgroup *cg)
+{
+ struct user_beancounter *ub = cgroup_ub(cg);
if (!bc_verify_held(ub)) {
printk(KERN_ERR "UB: leaked beancounter %s (%p)\n",
@@ -461,8 +467,7 @@ static void ub_cgroup_css_free(struct cgroup *cg)
add_taint(TAINT_CRAP, LOCKDEP_STILL_OK);
return;
}
-
- call_rcu(&ub->rcu, bc_free_rcu);
+ free_ub(ub);
}
static void ub_cgroup_attach_work_fn(struct callback_head *ch)
@@ -645,6 +650,8 @@ struct cgroup_subsys ub_subsys = {
.name = "beancounter",
.subsys_id = ub_subsys_id,
.css_alloc = ub_cgroup_css_alloc,
+ .css_online = ub_cgroup_css_online,
+ .css_offline = ub_cgroup_css_offline,
.css_free = ub_cgroup_css_free,
.attach = ub_cgroup_attach,
.use_id = true,
diff --git a/kernel/bc/proc.c b/kernel/bc/proc.c
index 02b5cfb0c306..a35d3f92e7bf 100644
--- a/kernel/bc/proc.c
+++ b/kernel/bc/proc.c
@@ -301,8 +301,6 @@ static int res_show(struct seq_file *f, void *v)
static int ub_accessible(struct user_beancounter *exec,
struct user_beancounter *target)
{
- if (ub_dead(target))
- return 0;
return (exec == get_ub0() || exec == target);
}
@@ -496,7 +494,6 @@ static int bc_readdir(struct file *file, filldir_t filler, void *data,
loff_t pos, filled;
struct user_beancounter *ub, *prev;
struct bc_proc_entry *pde;
- char *buf = NULL;
if (!(capable(CAP_DAC_OVERRIDE) && capable(CAP_DAC_READ_SEARCH)))
return -EPERM;
@@ -540,19 +537,10 @@ static int bc_readdir(struct file *file, filldir_t filler, void *data,
if (parent)
goto out;
- buf = kmalloc(NAME_MAX + 1, GFP_KERNEL);
- if (!buf) {
- err = -ENOMEM;
- goto out;
- }
-
rcu_read_lock();
prev = NULL;
ub = list_entry(&ub_list_head, struct user_beancounter, ub_list);
while (1) {
- unsigned long ino;
- const char *name;
-
ub = list_entry(rcu_dereference(ub->ub_list.next),
struct user_beancounter, ub_list);
if (&ub->ub_list == &ub_list_head)
@@ -569,15 +557,8 @@ static int bc_readdir(struct file *file, filldir_t filler, void *data,
rcu_read_unlock();
put_beancounter(prev);
- ino = bc_make_ino(ub);
- name = ub->ub_name;
- if (ub_dead(ub)) {
- snprintf(buf, NAME_MAX + 1, "%s-%p", name, ub);
- name = buf;
- }
-
- err = (*filler)(data, name, strlen(name),
- pos, ino, DT_DIR);
+ err = (*filler)(data, ub->ub_name, strlen(ub->ub_name),
+ pos, bc_make_ino(ub), DT_DIR);
if (err < 0) {
err = 0;
put_beancounter(ub);
@@ -592,7 +573,6 @@ static int bc_readdir(struct file *file, filldir_t filler, void *data,
put_beancounter(prev);
out:
file->f_pos = pos;
- kfree(buf);
return err;
}
@@ -803,32 +783,6 @@ static int bc_root_readdir(struct file *file, void *data, filldir_t filler)
return bc_readdir(file, filler, data, NULL);
}
-static struct user_beancounter *lookup_beancounter(const char *name)
-{
- char *p;
- unsigned long ptr;
- struct user_beancounter *ub, *ret = NULL;
-
- p = strrchr(name, '-');
- if (p && p != name && kstrtoul(p + 1, 16, &ptr) == 0) {
- rcu_read_lock();
- for_each_beancounter(ub) {
- if ((unsigned long)ub != ptr || !ub_dead(ub) ||
- strncmp(name, ub->ub_name, max_t(size_t,
- strlen(ub->ub_name), p - name)))
- continue;
- if (get_beancounter_rcu(ub)) {
- ret = ub;
- break;
- }
- }
- rcu_read_unlock();
- }
- if (!ret)
- ret = get_beancounter_by_name(name, 0);
- return ret;
-}
-
static struct dentry *bc_root_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags)
{
@@ -842,7 +796,7 @@ static struct dentry *bc_root_lookup(struct inode *dir, struct dentry *dentry,
if (de != ERR_PTR(-ESRCH))
return de;
- ub = lookup_beancounter(dentry->d_name.name);
+ ub = get_beancounter_by_name(dentry->d_name.name, 0);
if (IS_ERR_OR_NULL(ub))
return ub ? ERR_CAST(ub) : ERR_PTR(-ENOENT);
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index f881f6934e8c..9b3d0e2ebbae 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -5036,24 +5036,6 @@ static void check_for_release(struct cgroup *cgrp)
}
}
-bool css_refcnt_inc_not_zero(struct cgroup_subsys_state *css)
-{
- if (css->flags & CSS_ROOT)
- return true;
-
- while (true) {
- int t, v;
-
- v = atomic_read(&css->refcnt);
- if (!css_unbias_refcnt(v))
- return false;
- t = atomic_cmpxchg(&css->refcnt, v, v + 1);
- if (likely(t == v))
- return true;
- cpu_relax();
- }
-}
-
/* Caller must verify that the css is not for root cgroup */
bool __css_tryget(struct cgroup_subsys_state *css)
{
--
1.7.10.4
More information about the Devel
mailing list