提交 a85373fe 编写于 作者: L Linus Torvalds

Merge branch 'for-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup

Pull cgroup updates from Tejun Heo:

 - The misc controller now reports allocation rejections through
   misc.events instead of printking

 - cgroup_mutex usage is reduced to improve scalability of some
   operations

 - vhost helper threads are now assigned to the right cgroup on cgroup2

 - Bug fixes

* 'for-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup:
  cgroup: bpf: Move wrapper for __cgroup_bpf_*() to kernel/bpf/cgroup.c
  cgroup: Fix rootcg cpu.stat guest double counting
  cgroup: no need for cgroup_mutex for /proc/cgroups
  cgroup: remove cgroup_mutex from cgroupstats_build
  cgroup: reduce dependency on cgroup_mutex
  cgroup: cgroup-v1: do not exclude cgrp_dfl_root
  cgroup: Make rebind_subsystems() disable v2 controllers all at once
  docs/cgroup: add entry for misc.events
  misc_cgroup: remove error log to avoid log flood
  misc_cgroup: introduce misc.events to count failures
...@@ -2318,6 +2318,16 @@ Miscellaneous controller provides 3 interface files. If two misc resources (res_ ...@@ -2318,6 +2318,16 @@ Miscellaneous controller provides 3 interface files. If two misc resources (res_
Limits can be set higher than the capacity value in the misc.capacity Limits can be set higher than the capacity value in the misc.capacity
file. file.
misc.events
A read-only flat-keyed file which exists on non-root cgroups. The
following entries are defined. Unless specified otherwise, a value
change in this file generates a file modified event. All fields in
this file are hierarchical.
max
The number of times the cgroup's resource usage was
about to go over the max boundary.
Migration and Ownership Migration and Ownership
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
......
...@@ -157,26 +157,6 @@ struct cgroup_bpf { ...@@ -157,26 +157,6 @@ struct cgroup_bpf {
int cgroup_bpf_inherit(struct cgroup *cgrp); int cgroup_bpf_inherit(struct cgroup *cgrp);
void cgroup_bpf_offline(struct cgroup *cgrp); void cgroup_bpf_offline(struct cgroup *cgrp);
int __cgroup_bpf_attach(struct cgroup *cgrp,
struct bpf_prog *prog, struct bpf_prog *replace_prog,
struct bpf_cgroup_link *link,
enum bpf_attach_type type, u32 flags);
int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
struct bpf_cgroup_link *link,
enum bpf_attach_type type);
int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
union bpf_attr __user *uattr);
/* Wrapper for __cgroup_bpf_*() protected by cgroup_mutex */
int cgroup_bpf_attach(struct cgroup *cgrp,
struct bpf_prog *prog, struct bpf_prog *replace_prog,
struct bpf_cgroup_link *link, enum bpf_attach_type type,
u32 flags);
int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
enum bpf_attach_type type);
int cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
union bpf_attr __user *uattr);
int __cgroup_bpf_run_filter_skb(struct sock *sk, int __cgroup_bpf_run_filter_skb(struct sock *sk,
struct sk_buff *skb, struct sk_buff *skb,
enum cgroup_bpf_attach_type atype); enum cgroup_bpf_attach_type atype);
......
...@@ -36,7 +36,7 @@ struct misc_cg; ...@@ -36,7 +36,7 @@ struct misc_cg;
struct misc_res { struct misc_res {
unsigned long max; unsigned long max;
atomic_long_t usage; atomic_long_t usage;
bool failed; atomic_long_t events;
}; };
/** /**
...@@ -46,6 +46,10 @@ struct misc_res { ...@@ -46,6 +46,10 @@ struct misc_res {
*/ */
struct misc_cg { struct misc_cg {
struct cgroup_subsys_state css; struct cgroup_subsys_state css;
/* misc.events */
struct cgroup_file events_file;
struct misc_res res[MISC_CG_RES_TYPES]; struct misc_res res[MISC_CG_RES_TYPES];
}; };
......
...@@ -430,10 +430,10 @@ static struct bpf_prog_list *find_attach_entry(struct list_head *progs, ...@@ -430,10 +430,10 @@ static struct bpf_prog_list *find_attach_entry(struct list_head *progs,
* Exactly one of @prog or @link can be non-null. * Exactly one of @prog or @link can be non-null.
* Must be called with cgroup_mutex held. * Must be called with cgroup_mutex held.
*/ */
int __cgroup_bpf_attach(struct cgroup *cgrp, static int __cgroup_bpf_attach(struct cgroup *cgrp,
struct bpf_prog *prog, struct bpf_prog *replace_prog, struct bpf_prog *prog, struct bpf_prog *replace_prog,
struct bpf_cgroup_link *link, struct bpf_cgroup_link *link,
enum bpf_attach_type type, u32 flags) enum bpf_attach_type type, u32 flags)
{ {
u32 saved_flags = (flags & (BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI)); u32 saved_flags = (flags & (BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI));
struct bpf_prog *old_prog = NULL; struct bpf_prog *old_prog = NULL;
...@@ -523,6 +523,20 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, ...@@ -523,6 +523,20 @@ int __cgroup_bpf_attach(struct cgroup *cgrp,
return err; return err;
} }
static int cgroup_bpf_attach(struct cgroup *cgrp,
struct bpf_prog *prog, struct bpf_prog *replace_prog,
struct bpf_cgroup_link *link,
enum bpf_attach_type type,
u32 flags)
{
int ret;
mutex_lock(&cgroup_mutex);
ret = __cgroup_bpf_attach(cgrp, prog, replace_prog, link, type, flags);
mutex_unlock(&cgroup_mutex);
return ret;
}
/* Swap updated BPF program for given link in effective program arrays across /* Swap updated BPF program for given link in effective program arrays across
* all descendant cgroups. This function is guaranteed to succeed. * all descendant cgroups. This function is guaranteed to succeed.
*/ */
...@@ -672,14 +686,14 @@ static struct bpf_prog_list *find_detach_entry(struct list_head *progs, ...@@ -672,14 +686,14 @@ static struct bpf_prog_list *find_detach_entry(struct list_head *progs,
* propagate the change to descendants * propagate the change to descendants
* @cgrp: The cgroup which descendants to traverse * @cgrp: The cgroup which descendants to traverse
* @prog: A program to detach or NULL * @prog: A program to detach or NULL
* @prog: A link to detach or NULL * @link: A link to detach or NULL
* @type: Type of detach operation * @type: Type of detach operation
* *
* At most one of @prog or @link can be non-NULL. * At most one of @prog or @link can be non-NULL.
* Must be called with cgroup_mutex held. * Must be called with cgroup_mutex held.
*/ */
int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, static int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
struct bpf_cgroup_link *link, enum bpf_attach_type type) struct bpf_cgroup_link *link, enum bpf_attach_type type)
{ {
enum cgroup_bpf_attach_type atype; enum cgroup_bpf_attach_type atype;
struct bpf_prog *old_prog; struct bpf_prog *old_prog;
...@@ -730,9 +744,20 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, ...@@ -730,9 +744,20 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
return err; return err;
} }
static int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
enum bpf_attach_type type)
{
int ret;
mutex_lock(&cgroup_mutex);
ret = __cgroup_bpf_detach(cgrp, prog, NULL, type);
mutex_unlock(&cgroup_mutex);
return ret;
}
/* Must be called with cgroup_mutex held to avoid races. */ /* Must be called with cgroup_mutex held to avoid races. */
int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
union bpf_attr __user *uattr) union bpf_attr __user *uattr)
{ {
__u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids); __u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids);
enum bpf_attach_type type = attr->query.attach_type; enum bpf_attach_type type = attr->query.attach_type;
...@@ -789,6 +814,17 @@ int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, ...@@ -789,6 +814,17 @@ int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
return ret; return ret;
} }
static int cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
union bpf_attr __user *uattr)
{
int ret;
mutex_lock(&cgroup_mutex);
ret = __cgroup_bpf_query(cgrp, attr, uattr);
mutex_unlock(&cgroup_mutex);
return ret;
}
int cgroup_bpf_prog_attach(const union bpf_attr *attr, int cgroup_bpf_prog_attach(const union bpf_attr *attr,
enum bpf_prog_type ptype, struct bpf_prog *prog) enum bpf_prog_type ptype, struct bpf_prog *prog)
{ {
......
...@@ -63,9 +63,6 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk) ...@@ -63,9 +63,6 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
for_each_root(root) { for_each_root(root) {
struct cgroup *from_cgrp; struct cgroup *from_cgrp;
if (root == &cgrp_dfl_root)
continue;
spin_lock_irq(&css_set_lock); spin_lock_irq(&css_set_lock);
from_cgrp = task_cgroup_from_root(from, root); from_cgrp = task_cgroup_from_root(from, root);
spin_unlock_irq(&css_set_lock); spin_unlock_irq(&css_set_lock);
...@@ -662,11 +659,9 @@ int proc_cgroupstats_show(struct seq_file *m, void *v) ...@@ -662,11 +659,9 @@ int proc_cgroupstats_show(struct seq_file *m, void *v)
seq_puts(m, "#subsys_name\thierarchy\tnum_cgroups\tenabled\n"); seq_puts(m, "#subsys_name\thierarchy\tnum_cgroups\tenabled\n");
/* /*
* ideally we don't want subsystems moving around while we do this. * Grab the subsystems state racily. No need to add avenue to
* cgroup_mutex is also necessary to guarantee an atomic snapshot of * cgroup_mutex contention.
* subsys/hierarchy state.
*/ */
mutex_lock(&cgroup_mutex);
for_each_subsys(ss, i) for_each_subsys(ss, i)
seq_printf(m, "%s\t%d\t%d\t%d\n", seq_printf(m, "%s\t%d\t%d\t%d\n",
...@@ -674,7 +669,6 @@ int proc_cgroupstats_show(struct seq_file *m, void *v) ...@@ -674,7 +669,6 @@ int proc_cgroupstats_show(struct seq_file *m, void *v)
atomic_read(&ss->root->nr_cgrps), atomic_read(&ss->root->nr_cgrps),
cgroup_ssid_enabled(i)); cgroup_ssid_enabled(i));
mutex_unlock(&cgroup_mutex);
return 0; return 0;
} }
...@@ -701,8 +695,6 @@ int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry) ...@@ -701,8 +695,6 @@ int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry)
kernfs_type(kn) != KERNFS_DIR) kernfs_type(kn) != KERNFS_DIR)
return -EINVAL; return -EINVAL;
mutex_lock(&cgroup_mutex);
/* /*
* We aren't being called from kernfs and there's no guarantee on * We aren't being called from kernfs and there's no guarantee on
* @kn->priv's validity. For this and css_tryget_online_from_dir(), * @kn->priv's validity. For this and css_tryget_online_from_dir(),
...@@ -710,9 +702,8 @@ int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry) ...@@ -710,9 +702,8 @@ int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry)
*/ */
rcu_read_lock(); rcu_read_lock();
cgrp = rcu_dereference(*(void __rcu __force **)&kn->priv); cgrp = rcu_dereference(*(void __rcu __force **)&kn->priv);
if (!cgrp || cgroup_is_dead(cgrp)) { if (!cgrp || !cgroup_tryget(cgrp)) {
rcu_read_unlock(); rcu_read_unlock();
mutex_unlock(&cgroup_mutex);
return -ENOENT; return -ENOENT;
} }
rcu_read_unlock(); rcu_read_unlock();
...@@ -740,7 +731,7 @@ int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry) ...@@ -740,7 +731,7 @@ int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry)
} }
css_task_iter_end(&it); css_task_iter_end(&it);
mutex_unlock(&cgroup_mutex); cgroup_put(cgrp);
return 0; return 0;
} }
......
...@@ -1740,6 +1740,7 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask) ...@@ -1740,6 +1740,7 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
struct cgroup *dcgrp = &dst_root->cgrp; struct cgroup *dcgrp = &dst_root->cgrp;
struct cgroup_subsys *ss; struct cgroup_subsys *ss;
int ssid, i, ret; int ssid, i, ret;
u16 dfl_disable_ss_mask = 0;
lockdep_assert_held(&cgroup_mutex); lockdep_assert_held(&cgroup_mutex);
...@@ -1756,8 +1757,28 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask) ...@@ -1756,8 +1757,28 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
/* can't move between two non-dummy roots either */ /* can't move between two non-dummy roots either */
if (ss->root != &cgrp_dfl_root && dst_root != &cgrp_dfl_root) if (ss->root != &cgrp_dfl_root && dst_root != &cgrp_dfl_root)
return -EBUSY; return -EBUSY;
/*
* Collect ssid's that need to be disabled from default
* hierarchy.
*/
if (ss->root == &cgrp_dfl_root)
dfl_disable_ss_mask |= 1 << ssid;
} while_each_subsys_mask(); } while_each_subsys_mask();
if (dfl_disable_ss_mask) {
struct cgroup *scgrp = &cgrp_dfl_root.cgrp;
/*
* Controllers from default hierarchy that need to be rebound
* are all disabled together in one go.
*/
cgrp_dfl_root.subsys_mask &= ~dfl_disable_ss_mask;
WARN_ON(cgroup_apply_control(scgrp));
cgroup_finalize_control(scgrp, 0);
}
do_each_subsys_mask(ss, ssid, ss_mask) { do_each_subsys_mask(ss, ssid, ss_mask) {
struct cgroup_root *src_root = ss->root; struct cgroup_root *src_root = ss->root;
struct cgroup *scgrp = &src_root->cgrp; struct cgroup *scgrp = &src_root->cgrp;
...@@ -1766,10 +1787,12 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask) ...@@ -1766,10 +1787,12 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
WARN_ON(!css || cgroup_css(dcgrp, ss)); WARN_ON(!css || cgroup_css(dcgrp, ss));
/* disable from the source */ if (src_root != &cgrp_dfl_root) {
src_root->subsys_mask &= ~(1 << ssid); /* disable from the source */
WARN_ON(cgroup_apply_control(scgrp)); src_root->subsys_mask &= ~(1 << ssid);
cgroup_finalize_control(scgrp, 0); WARN_ON(cgroup_apply_control(scgrp));
cgroup_finalize_control(scgrp, 0);
}
/* rebind */ /* rebind */
RCU_INIT_POINTER(scgrp->subsys[ssid], NULL); RCU_INIT_POINTER(scgrp->subsys[ssid], NULL);
...@@ -5911,17 +5934,20 @@ struct cgroup *cgroup_get_from_id(u64 id) ...@@ -5911,17 +5934,20 @@ struct cgroup *cgroup_get_from_id(u64 id)
struct kernfs_node *kn; struct kernfs_node *kn;
struct cgroup *cgrp = NULL; struct cgroup *cgrp = NULL;
mutex_lock(&cgroup_mutex);
kn = kernfs_find_and_get_node_by_id(cgrp_dfl_root.kf_root, id); kn = kernfs_find_and_get_node_by_id(cgrp_dfl_root.kf_root, id);
if (!kn) if (!kn)
goto out_unlock; goto out;
cgrp = kn->priv; rcu_read_lock();
if (cgroup_is_dead(cgrp) || !cgroup_tryget(cgrp))
cgrp = rcu_dereference(*(void __rcu __force **)&kn->priv);
if (cgrp && !cgroup_tryget(cgrp))
cgrp = NULL; cgrp = NULL;
rcu_read_unlock();
kernfs_put(kn); kernfs_put(kn);
out_unlock: out:
mutex_unlock(&cgroup_mutex);
return cgrp; return cgrp;
} }
EXPORT_SYMBOL_GPL(cgroup_get_from_id); EXPORT_SYMBOL_GPL(cgroup_get_from_id);
...@@ -6474,30 +6500,34 @@ struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss) ...@@ -6474,30 +6500,34 @@ struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss)
* *
* Find the cgroup at @path on the default hierarchy, increment its * Find the cgroup at @path on the default hierarchy, increment its
* reference count and return it. Returns pointer to the found cgroup on * reference count and return it. Returns pointer to the found cgroup on
* success, ERR_PTR(-ENOENT) if @path doesn't exist and ERR_PTR(-ENOTDIR) * success, ERR_PTR(-ENOENT) if @path doesn't exist or if the cgroup has already
* if @path points to a non-directory. * been released and ERR_PTR(-ENOTDIR) if @path points to a non-directory.
*/ */
struct cgroup *cgroup_get_from_path(const char *path) struct cgroup *cgroup_get_from_path(const char *path)
{ {
struct kernfs_node *kn; struct kernfs_node *kn;
struct cgroup *cgrp; struct cgroup *cgrp = ERR_PTR(-ENOENT);
mutex_lock(&cgroup_mutex);
kn = kernfs_walk_and_get(cgrp_dfl_root.cgrp.kn, path); kn = kernfs_walk_and_get(cgrp_dfl_root.cgrp.kn, path);
if (kn) { if (!kn)
if (kernfs_type(kn) == KERNFS_DIR) { goto out;
cgrp = kn->priv;
cgroup_get_live(cgrp); if (kernfs_type(kn) != KERNFS_DIR) {
} else { cgrp = ERR_PTR(-ENOTDIR);
cgrp = ERR_PTR(-ENOTDIR); goto out_kernfs;
}
kernfs_put(kn);
} else {
cgrp = ERR_PTR(-ENOENT);
} }
mutex_unlock(&cgroup_mutex); rcu_read_lock();
cgrp = rcu_dereference(*(void __rcu __force **)&kn->priv);
if (!cgrp || !cgroup_tryget(cgrp))
cgrp = ERR_PTR(-ENOENT);
rcu_read_unlock();
out_kernfs:
kernfs_put(kn);
out:
return cgrp; return cgrp;
} }
EXPORT_SYMBOL_GPL(cgroup_get_from_path); EXPORT_SYMBOL_GPL(cgroup_get_from_path);
...@@ -6625,44 +6655,6 @@ void cgroup_sk_free(struct sock_cgroup_data *skcd) ...@@ -6625,44 +6655,6 @@ void cgroup_sk_free(struct sock_cgroup_data *skcd)
#endif /* CONFIG_SOCK_CGROUP_DATA */ #endif /* CONFIG_SOCK_CGROUP_DATA */
#ifdef CONFIG_CGROUP_BPF
int cgroup_bpf_attach(struct cgroup *cgrp,
struct bpf_prog *prog, struct bpf_prog *replace_prog,
struct bpf_cgroup_link *link,
enum bpf_attach_type type,
u32 flags)
{
int ret;
mutex_lock(&cgroup_mutex);
ret = __cgroup_bpf_attach(cgrp, prog, replace_prog, link, type, flags);
mutex_unlock(&cgroup_mutex);
return ret;
}
int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
enum bpf_attach_type type)
{
int ret;
mutex_lock(&cgroup_mutex);
ret = __cgroup_bpf_detach(cgrp, prog, NULL, type);
mutex_unlock(&cgroup_mutex);
return ret;
}
int cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
union bpf_attr __user *uattr)
{
int ret;
mutex_lock(&cgroup_mutex);
ret = __cgroup_bpf_query(cgrp, attr, uattr);
mutex_unlock(&cgroup_mutex);
return ret;
}
#endif /* CONFIG_CGROUP_BPF */
#ifdef CONFIG_SYSFS #ifdef CONFIG_SYSFS
static ssize_t show_delegatable_files(struct cftype *files, char *buf, static ssize_t show_delegatable_files(struct cftype *files, char *buf,
ssize_t size, const char *prefix) ssize_t size, const char *prefix)
......
...@@ -157,13 +157,6 @@ int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg, ...@@ -157,13 +157,6 @@ int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg,
new_usage = atomic_long_add_return(amount, &res->usage); new_usage = atomic_long_add_return(amount, &res->usage);
if (new_usage > READ_ONCE(res->max) || if (new_usage > READ_ONCE(res->max) ||
new_usage > READ_ONCE(misc_res_capacity[type])) { new_usage > READ_ONCE(misc_res_capacity[type])) {
if (!res->failed) {
pr_info("cgroup: charge rejected by the misc controller for %s resource in ",
misc_res_name[type]);
pr_cont_cgroup_path(i->css.cgroup);
pr_cont("\n");
res->failed = true;
}
ret = -EBUSY; ret = -EBUSY;
goto err_charge; goto err_charge;
} }
...@@ -171,6 +164,11 @@ int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg, ...@@ -171,6 +164,11 @@ int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg,
return 0; return 0;
err_charge: err_charge:
for (j = i; j; j = parent_misc(j)) {
atomic_long_inc(&j->res[type].events);
cgroup_file_notify(&j->events_file);
}
for (j = cg; j != i; j = parent_misc(j)) for (j = cg; j != i; j = parent_misc(j))
misc_cg_cancel_charge(type, j, amount); misc_cg_cancel_charge(type, j, amount);
misc_cg_cancel_charge(type, i, amount); misc_cg_cancel_charge(type, i, amount);
...@@ -335,6 +333,19 @@ static int misc_cg_capacity_show(struct seq_file *sf, void *v) ...@@ -335,6 +333,19 @@ static int misc_cg_capacity_show(struct seq_file *sf, void *v)
return 0; return 0;
} }
static int misc_events_show(struct seq_file *sf, void *v)
{
struct misc_cg *cg = css_misc(seq_css(sf));
unsigned long events, i;
for (i = 0; i < MISC_CG_RES_TYPES; i++) {
events = atomic_long_read(&cg->res[i].events);
if (READ_ONCE(misc_res_capacity[i]) || events)
seq_printf(sf, "%s.max %lu\n", misc_res_name[i], events);
}
return 0;
}
/* Misc cgroup interface files */ /* Misc cgroup interface files */
static struct cftype misc_cg_files[] = { static struct cftype misc_cg_files[] = {
{ {
...@@ -353,6 +364,12 @@ static struct cftype misc_cg_files[] = { ...@@ -353,6 +364,12 @@ static struct cftype misc_cg_files[] = {
.seq_show = misc_cg_capacity_show, .seq_show = misc_cg_capacity_show,
.flags = CFTYPE_ONLY_ON_ROOT, .flags = CFTYPE_ONLY_ON_ROOT,
}, },
{
.name = "events",
.flags = CFTYPE_NOT_ON_ROOT,
.file_offset = offsetof(struct misc_cg, events_file),
.seq_show = misc_events_show,
},
{} {}
}; };
......
...@@ -433,8 +433,6 @@ static void root_cgroup_cputime(struct task_cputime *cputime) ...@@ -433,8 +433,6 @@ static void root_cgroup_cputime(struct task_cputime *cputime)
cputime->sum_exec_runtime += user; cputime->sum_exec_runtime += user;
cputime->sum_exec_runtime += sys; cputime->sum_exec_runtime += sys;
cputime->sum_exec_runtime += cpustat[CPUTIME_STEAL]; cputime->sum_exec_runtime += cpustat[CPUTIME_STEAL];
cputime->sum_exec_runtime += cpustat[CPUTIME_GUEST];
cputime->sum_exec_runtime += cpustat[CPUTIME_GUEST_NICE];
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册