summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/cgroup.h33
-rw-r--r--kernel/cgroup.c50
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;
}
}