diff options
author | Tejun Heo <tj@kernel.org> | 2013-12-05 12:28:04 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-12-05 12:28:04 -0500 |
commit | 7da112792753d71aed44b918395892a1fc53048a (patch) | |
tree | 7b370245a961024428a9247f8999f0f4b51c2c4f /kernel/cgroup.c | |
parent | 5d22444f427511fe7c4733b233680309af5b071c (diff) |
cgroup: attach cgroup_open_file to all cgroup files
In preparation of conversion to kernfs, cgroup file handling is
updated so that it can be easily mapped to kernfs. This patch
attaches cgroup_open_file, which used to be attached to pidlist files,
to all cgroup files, introduces seq_css/cft() accessors to determine
the cgroup_subsys_state and cftype associated with a given cgroup
seq_file, exports them as public interface.
This doesn't cause any behavior changes but unifies cgroup file
handling across different file types and will help converting them to
kernfs seq_show() interface.
v2: Li pointed out that the original patch was using
single_open_size() incorrectly assuming that the size param is
private data size. Fix it by allocating @of separately and
passing it to single_open() and explicitly freeing it in the
release path. This isn't the prettiest but this path is gonna be
restructured by the following patches pretty soon.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 50 |
1 files changed, 20 insertions, 30 deletions
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 @@ | |||
41 | #include <linux/rcupdate.h> | 41 | #include <linux/rcupdate.h> |
42 | #include <linux/sched.h> | 42 | #include <linux/sched.h> |
43 | #include <linux/backing-dev.h> | 43 | #include <linux/backing-dev.h> |
44 | #include <linux/seq_file.h> | ||
45 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
46 | #include <linux/magic.h> | 45 | #include <linux/magic.h> |
47 | #include <linux/spinlock.h> | 46 | #include <linux/spinlock.h> |
@@ -130,19 +129,6 @@ static struct cgroupfs_root cgroup_dummy_root; | |||
130 | /* dummy_top is a shorthand for the dummy hierarchy's top cgroup */ | 129 | /* dummy_top is a shorthand for the dummy hierarchy's top cgroup */ |
131 | static struct cgroup * const cgroup_dummy_top = &cgroup_dummy_root.top_cgroup; | 130 | static struct cgroup * const cgroup_dummy_top = &cgroup_dummy_root.top_cgroup; |
132 | 131 | ||
133 | /* | ||
134 | * cgroupfs file entry, pointed to from leaf dentry->d_fsdata. | ||
135 | */ | ||
136 | struct cfent { | ||
137 | struct list_head node; | ||
138 | struct dentry *dentry; | ||
139 | struct cftype *type; | ||
140 | struct cgroup_subsys_state *css; | ||
141 | |||
142 | /* file xattrs */ | ||
143 | struct simple_xattrs xattrs; | ||
144 | }; | ||
145 | |||
146 | /* The list of hierarchy roots */ | 132 | /* The list of hierarchy roots */ |
147 | 133 | ||
148 | static LIST_HEAD(cgroup_roots); | 134 | static LIST_HEAD(cgroup_roots); |
@@ -2302,9 +2288,8 @@ out_free: | |||
2302 | 2288 | ||
2303 | static int cgroup_seqfile_show(struct seq_file *m, void *arg) | 2289 | static int cgroup_seqfile_show(struct seq_file *m, void *arg) |
2304 | { | 2290 | { |
2305 | struct cfent *cfe = m->private; | 2291 | struct cftype *cft = seq_cft(m); |
2306 | struct cftype *cft = cfe->type; | 2292 | struct cgroup_subsys_state *css = seq_css(m); |
2307 | struct cgroup_subsys_state *css = cfe->css; | ||
2308 | 2293 | ||
2309 | if (cft->read_seq_string) | 2294 | if (cft->read_seq_string) |
2310 | return cft->read_seq_string(css, cft, m); | 2295 | return cft->read_seq_string(css, cft, m); |
@@ -2353,10 +2338,20 @@ static int cgroup_file_open(struct inode *inode, struct file *file) | |||
2353 | WARN_ON_ONCE(cfe->css && cfe->css != css); | 2338 | WARN_ON_ONCE(cfe->css && cfe->css != css); |
2354 | cfe->css = css; | 2339 | cfe->css = css; |
2355 | 2340 | ||
2356 | if (cft->open) | 2341 | if (cft->open) { |
2357 | err = cft->open(inode, file); | 2342 | err = cft->open(inode, file); |
2358 | else | 2343 | } else { |
2359 | err = single_open(file, cgroup_seqfile_show, cfe); | 2344 | struct cgroup_open_file *of; |
2345 | |||
2346 | err = -ENOMEM; | ||
2347 | of = kzalloc(sizeof(*of), GFP_KERNEL); | ||
2348 | if (of) { | ||
2349 | of->cfe = cfe; | ||
2350 | err = single_open(file, cgroup_seqfile_show, of); | ||
2351 | if (err) | ||
2352 | kfree(of); | ||
2353 | } | ||
2354 | } | ||
2360 | 2355 | ||
2361 | if (css->ss && err) | 2356 | if (css->ss && err) |
2362 | css_put(css); | 2357 | css_put(css); |
@@ -2370,6 +2365,7 @@ static int cgroup_file_release(struct inode *inode, struct file *file) | |||
2370 | 2365 | ||
2371 | if (css->ss) | 2366 | if (css->ss) |
2372 | css_put(css); | 2367 | css_put(css); |
2368 | kfree(((struct seq_file *)file->private_data)->private); | ||
2373 | return single_release(inode, file); | 2369 | return single_release(inode, file); |
2374 | } | 2370 | } |
2375 | 2371 | ||
@@ -3368,12 +3364,6 @@ struct cgroup_pidlist { | |||
3368 | struct delayed_work destroy_dwork; | 3364 | struct delayed_work destroy_dwork; |
3369 | }; | 3365 | }; |
3370 | 3366 | ||
3371 | /* seq_file->private points to the following */ | ||
3372 | struct cgroup_open_file { | ||
3373 | struct cfent *cfe; | ||
3374 | void *priv; | ||
3375 | }; | ||
3376 | |||
3377 | /* | 3367 | /* |
3378 | * The following two functions "fix" the issue where there are more pids | 3368 | * The following two functions "fix" the issue where there are more pids |
3379 | * than kmalloc will give memory for; in such cases, we use vmalloc/vfree. | 3369 | * 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) | |||
3689 | * next pid to display, if any | 3679 | * next pid to display, if any |
3690 | */ | 3680 | */ |
3691 | struct cgroup_open_file *of = s->private; | 3681 | struct cgroup_open_file *of = s->private; |
3692 | struct cgroup *cgrp = of->cfe->css->cgroup; | 3682 | struct cgroup *cgrp = seq_css(s)->cgroup; |
3693 | struct cgroup_pidlist *l; | 3683 | struct cgroup_pidlist *l; |
3694 | enum cgroup_filetype type = of->cfe->type->private; | 3684 | enum cgroup_filetype type = seq_cft(s)->private; |
3695 | int index = 0, pid = *pos; | 3685 | int index = 0, pid = *pos; |
3696 | int *iter, ret; | 3686 | int *iter, ret; |
3697 | 3687 | ||
@@ -3749,7 +3739,7 @@ static void cgroup_pidlist_stop(struct seq_file *s, void *v) | |||
3749 | if (l) | 3739 | if (l) |
3750 | mod_delayed_work(cgroup_pidlist_destroy_wq, &l->destroy_dwork, | 3740 | mod_delayed_work(cgroup_pidlist_destroy_wq, &l->destroy_dwork, |
3751 | CGROUP_PIDLIST_DESTROY_DELAY); | 3741 | CGROUP_PIDLIST_DESTROY_DELAY); |
3752 | mutex_unlock(&of->cfe->css->cgroup->pidlist_mutex); | 3742 | mutex_unlock(&seq_css(s)->cgroup->pidlist_mutex); |
3753 | } | 3743 | } |
3754 | 3744 | ||
3755 | static void *cgroup_pidlist_next(struct seq_file *s, void *v, loff_t *pos) | 3745 | 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) | |||
3766 | if (p >= end) { | 3756 | if (p >= end) { |
3767 | return NULL; | 3757 | return NULL; |
3768 | } else { | 3758 | } else { |
3769 | *pos = cgroup_pid_fry(of->cfe->css->cgroup, *p); | 3759 | *pos = cgroup_pid_fry(seq_css(s)->cgroup, *p); |
3770 | return p; | 3760 | return p; |
3771 | } | 3761 | } |
3772 | } | 3762 | } |