aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/linux/cgroup.h6
-rw-r--r--kernel/cgroup.c112
2 files changed, 68 insertions, 50 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index b32a0f8ae9ad..8b9a594f0c92 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -434,7 +434,6 @@ struct cftype {
434 */ 434 */
435 struct cgroup_subsys *ss; 435 struct cgroup_subsys *ss;
436 436
437 int (*open)(struct inode *inode, struct file *file);
438 /* 437 /*
439 * read_u64() is a shortcut for the common case of returning a 438 * read_u64() is a shortcut for the common case of returning a
440 * single integer. Use it in place of read() 439 * single integer. Use it in place of read()
@@ -448,6 +447,11 @@ struct cftype {
448 /* generic seq_file read interface */ 447 /* generic seq_file read interface */
449 int (*seq_show)(struct seq_file *sf, void *v); 448 int (*seq_show)(struct seq_file *sf, void *v);
450 449
450 /* optional ops, implement all or none */
451 void *(*seq_start)(struct seq_file *sf, loff_t *ppos);
452 void *(*seq_next)(struct seq_file *sf, void *v, loff_t *ppos);
453 void (*seq_stop)(struct seq_file *sf, void *v);
454
451 /* 455 /*
452 * write_u64() is a shortcut for the common case of accepting 456 * write_u64() is a shortcut for the common case of accepting
453 * a single integer (as parsed by simple_strtoull) from 457 * a single integer (as parsed by simple_strtoull) from
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,