diff options
-rw-r--r-- | include/linux/cgroup.h | 33 | ||||
-rw-r--r-- | kernel/cgroup.c | 50 |
2 files changed, 53 insertions, 30 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 53e11da6e357..c3d698a72e02 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -21,6 +21,7 @@ #include <linux/xattr.h> #include <linux/fs.h> #include <linux/percpu-refcount.h> +#include <linux/seq_file.h> #ifdef CONFIG_CGROUPS @@ -490,6 +491,26 @@ struct cftype_set { }; /* + * cgroupfs file entry, pointed to from leaf dentry->d_fsdata. Don't + * access directly. + */ +struct cfent { + struct list_head node; + struct dentry *dentry; + struct cftype *type; + struct cgroup_subsys_state *css; + + /* file xattrs */ + struct simple_xattrs xattrs; +}; + +/* seq_file->private points to the following, only ->priv is public */ +struct cgroup_open_file { + struct cfent *cfe; + void *priv; +}; + +/* * See the comment above CGRP_ROOT_SANE_BEHAVIOR for details. This * function can be called as long as @cgrp is accessible. */ @@ -504,6 +525,18 @@ static inline const char *cgroup_name(const struct cgroup *cgrp) return rcu_dereference(cgrp->name)->name; } +static inline struct cgroup_subsys_state *seq_css(struct seq_file *seq) +{ + struct cgroup_open_file *of = seq->private; + return of->cfe->css; +} + +static inline struct cftype *seq_cft(struct seq_file *seq) +{ + struct cgroup_open_file *of = seq->private; + return of->cfe->type; +} + int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); int cgroup_rm_cftypes(struct cftype *cfts); diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 17272893d3b8..036c05d8e572 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -41,7 +41,6 @@ #include <linux/rcupdate.h> #include <linux/sched.h> #include <linux/backing-dev.h> -#include <linux/seq_file.h> #include <linux/slab.h> #include <linux/magic.h> #include <linux/spinlock.h> @@ -130,19 +129,6 @@ static struct cgroupfs_root cgroup_dummy_root; /* dummy_top is a shorthand for the dummy hierarchy's top cgroup */ static struct cgroup * const cgroup_dummy_top = &cgroup_dummy_root.top_cgroup; -/* - * cgroupfs file entry, pointed to from leaf dentry->d_fsdata. - */ -struct cfent { - struct list_head node; - struct dentry *dentry; - struct cftype *type; - struct cgroup_subsys_state *css; - - /* file xattrs */ - struct simple_xattrs xattrs; -}; - /* The list of hierarchy roots */ static LIST_HEAD(cgroup_roots); @@ -2302,9 +2288,8 @@ out_free: static int cgroup_seqfile_show(struct seq_file *m, void *arg) { - struct cfent *cfe = m->private; - struct cftype *cft = cfe->type; - struct cgroup_subsys_state *css = cfe->css; + struct cftype *cft = seq_cft(m); + struct cgroup_subsys_state *css = seq_css(m); if (cft->read_seq_string) return cft->read_seq_string(css, cft, m); @@ -2353,10 +2338,20 @@ static int cgroup_file_open(struct inode *inode, struct file *file) WARN_ON_ONCE(cfe->css && cfe->css != css); cfe->css = css; - if (cft->open) + if (cft->open) { err = cft->open(inode, file); - else - err = single_open(file, cgroup_seqfile_show, cfe); + } else { + struct cgroup_open_file *of; + + err = -ENOMEM; + of = kzalloc(sizeof(*of), GFP_KERNEL); + if (of) { + of->cfe = cfe; + err = single_open(file, cgroup_seqfile_show, of); + if (err) + kfree(of); + } + } if (css->ss && err) css_put(css); @@ -2370,6 +2365,7 @@ static int cgroup_file_release(struct inode *inode, struct file *file) if (css->ss) css_put(css); + kfree(((struct seq_file *)file->private_data)->private); return single_release(inode, file); } @@ -3368,12 +3364,6 @@ struct cgroup_pidlist { struct delayed_work destroy_dwork; }; -/* seq_file->private points to the following */ -struct cgroup_open_file { - struct cfent *cfe; - void *priv; -}; - /* * The following two functions "fix" the issue where there are more pids * than kmalloc will give memory for; in such cases, we use vmalloc/vfree. @@ -3689,9 +3679,9 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos) * next pid to display, if any */ struct cgroup_open_file *of = s->private; - struct cgroup *cgrp = of->cfe->css->cgroup; + struct cgroup *cgrp = seq_css(s)->cgroup; struct cgroup_pidlist *l; - enum cgroup_filetype type = of->cfe->type->private; + enum cgroup_filetype type = seq_cft(s)->private; int index = 0, pid = *pos; int *iter, ret; @@ -3749,7 +3739,7 @@ static void cgroup_pidlist_stop(struct seq_file *s, void *v) if (l) mod_delayed_work(cgroup_pidlist_destroy_wq, &l->destroy_dwork, CGROUP_PIDLIST_DESTROY_DELAY); - mutex_unlock(&of->cfe->css->cgroup->pidlist_mutex); + mutex_unlock(&seq_css(s)->cgroup->pidlist_mutex); } static void *cgroup_pidlist_next(struct seq_file *s, void *v, loff_t *pos) @@ -3766,7 +3756,7 @@ static void *cgroup_pidlist_next(struct seq_file *s, void *v, loff_t *pos) if (p >= end) { return NULL; } else { - *pos = cgroup_pid_fry(of->cfe->css->cgroup, *p); + *pos = cgroup_pid_fry(seq_css(s)->cgroup, *p); return p; } } |