Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

Tejun Heo 7da11279 5d22444f

+53 -30
+33
include/linux/cgroup.h
··· 21 21 #include <linux/xattr.h> 22 22 #include <linux/fs.h> 23 23 #include <linux/percpu-refcount.h> 24 + #include <linux/seq_file.h> 24 25 25 26 #ifdef CONFIG_CGROUPS 26 27 ··· 491 490 }; 492 491 493 492 /* 493 + * cgroupfs file entry, pointed to from leaf dentry->d_fsdata. Don't 494 + * access directly. 495 + */ 496 + struct cfent { 497 + struct list_head node; 498 + struct dentry *dentry; 499 + struct cftype *type; 500 + struct cgroup_subsys_state *css; 501 + 502 + /* file xattrs */ 503 + struct simple_xattrs xattrs; 504 + }; 505 + 506 + /* seq_file->private points to the following, only ->priv is public */ 507 + struct cgroup_open_file { 508 + struct cfent *cfe; 509 + void *priv; 510 + }; 511 + 512 + /* 494 513 * See the comment above CGRP_ROOT_SANE_BEHAVIOR for details. This 495 514 * function can be called as long as @cgrp is accessible. 496 515 */ ··· 523 502 static inline const char *cgroup_name(const struct cgroup *cgrp) 524 503 { 525 504 return rcu_dereference(cgrp->name)->name; 505 + } 506 + 507 + static inline struct cgroup_subsys_state *seq_css(struct seq_file *seq) 508 + { 509 + struct cgroup_open_file *of = seq->private; 510 + return of->cfe->css; 511 + } 512 + 513 + static inline struct cftype *seq_cft(struct seq_file *seq) 514 + { 515 + struct cgroup_open_file *of = seq->private; 516 + return of->cfe->type; 526 517 } 527 518 528 519 int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
+20 -30
kernel/cgroup.c
··· 41 41 #include <linux/rcupdate.h> 42 42 #include <linux/sched.h> 43 43 #include <linux/backing-dev.h> 44 - #include <linux/seq_file.h> 45 44 #include <linux/slab.h> 46 45 #include <linux/magic.h> 47 46 #include <linux/spinlock.h> ··· 128 129 129 130 /* dummy_top is a shorthand for the dummy hierarchy's top cgroup */ 130 131 static struct cgroup * const cgroup_dummy_top = &cgroup_dummy_root.top_cgroup; 131 - 132 - /* 133 - * cgroupfs file entry, pointed to from leaf dentry->d_fsdata. 134 - */ 135 - struct cfent { 136 - struct list_head node; 137 - struct dentry *dentry; 138 - struct cftype *type; 139 - struct cgroup_subsys_state *css; 140 - 141 - /* file xattrs */ 142 - struct simple_xattrs xattrs; 143 - }; 144 132 145 133 /* The list of hierarchy roots */ 146 134 ··· 2288 2302 2289 2303 static int cgroup_seqfile_show(struct seq_file *m, void *arg) 2290 2304 { 2291 - struct cfent *cfe = m->private; 2292 - struct cftype *cft = cfe->type; 2293 - struct cgroup_subsys_state *css = cfe->css; 2305 + struct cftype *cft = seq_cft(m); 2306 + struct cgroup_subsys_state *css = seq_css(m); 2294 2307 2295 2308 if (cft->read_seq_string) 2296 2309 return cft->read_seq_string(css, cft, m); ··· 2338 2353 WARN_ON_ONCE(cfe->css && cfe->css != css); 2339 2354 cfe->css = css; 2340 2355 2341 - if (cft->open) 2356 + if (cft->open) { 2342 2357 err = cft->open(inode, file); 2343 - else 2344 - err = single_open(file, cgroup_seqfile_show, cfe); 2358 + } else { 2359 + struct cgroup_open_file *of; 2360 + 2361 + err = -ENOMEM; 2362 + of = kzalloc(sizeof(*of), GFP_KERNEL); 2363 + if (of) { 2364 + of->cfe = cfe; 2365 + err = single_open(file, cgroup_seqfile_show, of); 2366 + if (err) 2367 + kfree(of); 2368 + } 2369 + } 2345 2370 2346 2371 if (css->ss && err) 2347 2372 css_put(css); ··· 2365 2370 2366 2371 if (css->ss) 2367 2372 css_put(css); 2373 + kfree(((struct seq_file *)file->private_data)->private); 2368 2374 return single_release(inode, file); 2369 2375 } 2370 2376 ··· 3364 3368 struct delayed_work destroy_dwork; 3365 3369 }; 3366 3370 3367 - /* seq_file->private points to the following */ 3368 - struct cgroup_open_file { 3369 - struct cfent *cfe; 3370 - void *priv; 3371 - }; 3372 - 3373 3371 /* 3374 3372 * The following two functions "fix" the issue where there are more pids 3375 3373 * than kmalloc will give memory for; in such cases, we use vmalloc/vfree. ··· 3679 3689 * next pid to display, if any 3680 3690 */ 3681 3691 struct cgroup_open_file *of = s->private; 3682 - struct cgroup *cgrp = of->cfe->css->cgroup; 3692 + struct cgroup *cgrp = seq_css(s)->cgroup; 3683 3693 struct cgroup_pidlist *l; 3684 - enum cgroup_filetype type = of->cfe->type->private; 3694 + enum cgroup_filetype type = seq_cft(s)->private; 3685 3695 int index = 0, pid = *pos; 3686 3696 int *iter, ret; 3687 3697 ··· 3739 3749 if (l) 3740 3750 mod_delayed_work(cgroup_pidlist_destroy_wq, &l->destroy_dwork, 3741 3751 CGROUP_PIDLIST_DESTROY_DELAY); 3742 - mutex_unlock(&of->cfe->css->cgroup->pidlist_mutex); 3752 + mutex_unlock(&seq_css(s)->cgroup->pidlist_mutex); 3743 3753 } 3744 3754 3745 3755 static void *cgroup_pidlist_next(struct seq_file *s, void *v, loff_t *pos) ··· 3756 3766 if (p >= end) { 3757 3767 return NULL; 3758 3768 } else { 3759 - *pos = cgroup_pid_fry(of->cfe->css->cgroup, *p); 3769 + *pos = cgroup_pid_fry(seq_css(s)->cgroup, *p); 3760 3770 return p; 3761 3771 } 3762 3772 }