aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-12-05 12:28:04 -0500
committerTejun Heo <tj@kernel.org>2013-12-05 12:28:04 -0500
commit6612f05b88fa309c91a345690411217959bb2486 (patch)
treeb124fd822b3b2bdb169b341cff1118a586d782a7 /kernel/cgroup.c
parent2da8ca822d49c8b8781800ad155aaa00e7bb5f1a (diff)
cgroup: unify pidlist and other file handling
In preparation of conversion to kernfs, cgroup file handling is updated so that it can be easily mapped to kernfs. With the previous changes, the difference between pidlist and other files are very small. Both are served by seq_file in a pretty standard way with the only difference being !pidlist files use single_open(). This patch adds cftype->seq_start(), ->seq_next and ->seq_stop() and implements the matching cgroup_seqfile_start/next/stop() which either emulates single_open() behavior or invokes cftype->seq_*() operations if specified. This allows using single seq_operations for both pidlist and other files and makes cgroup_pidlist_operations and cgorup_pidlist_open() no longer necessary. As cgroup_pidlist_open() was the only user of cftype->open(), the method is dropped together. This brings cftype file interface very close to kernfs interface and mapping shouldn't be too difficult. Once converted to kernfs, most of the plumbing code including cgroup_seqfile_*() will be removed as kernfs provides those facilities. This patch does not introduce any behavior changes. v2: Refreshed on top of the updated "cgroup: introduce struct cgroup_pidlist_open_file". v3: Refreshed on top of the updated "cgroup: attach cgroup_open_file to all cgroup files". 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.c112
1 files changed, 63 insertions, 49 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index c45e63328a0a..f9ae38a95af2 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2286,6 +2286,45 @@ out_free:
2286 * supports string->u64 maps, but can be extended in future. 2286 * supports string->u64 maps, but can be extended in future.
2287 */ 2287 */
2288 2288
2289static void *cgroup_seqfile_start(struct seq_file *seq, loff_t *ppos)
2290{
2291 struct cftype *cft = seq_cft(seq);
2292
2293 if (cft->seq_start) {
2294 return cft->seq_start(seq, ppos);
2295 } else {
2296 /*
2297 * The same behavior and code as single_open(). Returns
2298 * !NULL if pos is at the beginning; otherwise, NULL.
2299 */
2300 return NULL + !*ppos;
2301 }
2302}
2303
2304static void *cgroup_seqfile_next(struct seq_file *seq, void *v, loff_t *ppos)
2305{
2306 struct cftype *cft = seq_cft(seq);
2307
2308 if (cft->seq_next) {
2309 return cft->seq_next(seq, v, ppos);
2310 } else {
2311 /*
2312 * The same behavior and code as single_open(), always
2313 * terminate after the initial read.
2314 */
2315 ++*ppos;
2316 return NULL;
2317 }
2318}
2319
2320static void cgroup_seqfile_stop(struct seq_file *seq, void *v)
2321{
2322 struct cftype *cft = seq_cft(seq);
2323
2324 if (cft->seq_stop)
2325 cft->seq_stop(seq, v);
2326}
2327
2289static int cgroup_seqfile_show(struct seq_file *m, void *arg) 2328static int cgroup_seqfile_show(struct seq_file *m, void *arg)
2290{ 2329{
2291 struct cftype *cft = seq_cft(m); 2330 struct cftype *cft = seq_cft(m);
@@ -2303,12 +2342,20 @@ static int cgroup_seqfile_show(struct seq_file *m, void *arg)
2303 return 0; 2342 return 0;
2304} 2343}
2305 2344
2345static struct seq_operations cgroup_seq_operations = {
2346 .start = cgroup_seqfile_start,
2347 .next = cgroup_seqfile_next,
2348 .stop = cgroup_seqfile_stop,
2349 .show = cgroup_seqfile_show,
2350};
2351
2306static int cgroup_file_open(struct inode *inode, struct file *file) 2352static int cgroup_file_open(struct inode *inode, struct file *file)
2307{ 2353{
2308 struct cfent *cfe = __d_cfe(file->f_dentry); 2354 struct cfent *cfe = __d_cfe(file->f_dentry);
2309 struct cftype *cft = __d_cft(file->f_dentry); 2355 struct cftype *cft = __d_cft(file->f_dentry);
2310 struct cgroup *cgrp = __d_cgrp(cfe->dentry->d_parent); 2356 struct cgroup *cgrp = __d_cgrp(cfe->dentry->d_parent);
2311 struct cgroup_subsys_state *css; 2357 struct cgroup_subsys_state *css;
2358 struct cgroup_open_file *of;
2312 int err; 2359 int err;
2313 2360
2314 err = generic_file_open(inode, file); 2361 err = generic_file_open(inode, file);
@@ -2338,24 +2385,16 @@ static int cgroup_file_open(struct inode *inode, struct file *file)
2338 WARN_ON_ONCE(cfe->css && cfe->css != css); 2385 WARN_ON_ONCE(cfe->css && cfe->css != css);
2339 cfe->css = css; 2386 cfe->css = css;
2340 2387
2341 if (cft->open) { 2388 of = __seq_open_private(file, &cgroup_seq_operations,
2342 err = cft->open(inode, file); 2389 sizeof(struct cgroup_open_file));
2343 } else { 2390 if (of) {
2344 struct cgroup_open_file *of; 2391 of->cfe = cfe;
2345 2392 return 0;
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 } 2393 }
2355 2394
2356 if (css->ss && err) 2395 if (css->ss)
2357 css_put(css); 2396 css_put(css);
2358 return err; 2397 return -ENOMEM;
2359} 2398}
2360 2399
2361static int cgroup_file_release(struct inode *inode, struct file *file) 2400static int cgroup_file_release(struct inode *inode, struct file *file)
@@ -2365,8 +2404,7 @@ static int cgroup_file_release(struct inode *inode, struct file *file)
2365 2404
2366 if (css->ss) 2405 if (css->ss)
2367 css_put(css); 2406 css_put(css);
2368 kfree(((struct seq_file *)file->private_data)->private); 2407 return seq_release_private(inode, file);
2369 return single_release(inode, file);
2370} 2408}
2371 2409
2372/* 2410/*
@@ -3777,36 +3815,6 @@ static const struct seq_operations cgroup_pidlist_seq_operations = {
3777 .show = cgroup_pidlist_show, 3815 .show = cgroup_pidlist_show,
3778}; 3816};
3779 3817
3780static const struct file_operations cgroup_pidlist_operations = {
3781 .read = seq_read,
3782 .llseek = seq_lseek,
3783 .write = cgroup_file_write,
3784 .release = seq_release_private,
3785};
3786
3787/*
3788 * The following functions handle opens on a file that displays a pidlist
3789 * (tasks or procs). Prepare an array of the process/thread IDs of whoever's
3790 * in the cgroup.
3791 */
3792/* helper function for the two below it */
3793static int cgroup_pidlist_open(struct inode *unused, struct file *file)
3794{
3795 struct cfent *cfe = __d_cfe(file->f_dentry);
3796 struct cgroup_open_file *of;
3797
3798 /* configure file information */
3799 file->f_op = &cgroup_pidlist_operations;
3800
3801 of = __seq_open_private(file, &cgroup_pidlist_seq_operations,
3802 sizeof(*of));
3803 if (!of)
3804 return -ENOMEM;
3805
3806 of->cfe = cfe;
3807 return 0;
3808}
3809
3810static u64 cgroup_read_notify_on_release(struct cgroup_subsys_state *css, 3818static u64 cgroup_read_notify_on_release(struct cgroup_subsys_state *css,
3811 struct cftype *cft) 3819 struct cftype *cft)
3812{ 3820{
@@ -3860,7 +3868,10 @@ static int cgroup_clone_children_write(struct cgroup_subsys_state *css,
3860static struct cftype cgroup_base_files[] = { 3868static struct cftype cgroup_base_files[] = {
3861 { 3869 {
3862 .name = "cgroup.procs", 3870 .name = "cgroup.procs",
3863 .open = cgroup_pidlist_open, 3871 .seq_start = cgroup_pidlist_start,
3872 .seq_next = cgroup_pidlist_next,
3873 .seq_stop = cgroup_pidlist_stop,
3874 .seq_show = cgroup_pidlist_show,
3864 .private = CGROUP_FILE_PROCS, 3875 .private = CGROUP_FILE_PROCS,
3865 .write_u64 = cgroup_procs_write, 3876 .write_u64 = cgroup_procs_write,
3866 .mode = S_IRUGO | S_IWUSR, 3877 .mode = S_IRUGO | S_IWUSR,
@@ -3885,7 +3896,10 @@ static struct cftype cgroup_base_files[] = {
3885 { 3896 {
3886 .name = "tasks", 3897 .name = "tasks",
3887 .flags = CFTYPE_INSANE, /* use "procs" instead */ 3898 .flags = CFTYPE_INSANE, /* use "procs" instead */
3888 .open = cgroup_pidlist_open, 3899 .seq_start = cgroup_pidlist_start,
3900 .seq_next = cgroup_pidlist_next,
3901 .seq_stop = cgroup_pidlist_stop,
3902 .seq_show = cgroup_pidlist_show,
3889 .private = CGROUP_FILE_TASKS, 3903 .private = CGROUP_FILE_TASKS,
3890 .write_u64 = cgroup_tasks_write, 3904 .write_u64 = cgroup_tasks_write,
3891 .mode = S_IRUGO | S_IWUSR, 3905 .mode = S_IRUGO | S_IWUSR,