aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-08-13 11:01:55 -0400
committerTejun Heo <tj@kernel.org>2013-08-13 11:01:55 -0400
commit105347ba5da3e87facce2337c50cd5df93cc6bec (patch)
treec2f65ed8387a08004ac6dafb38bbaa294dd3900d
parentb77d7b6088377998ebf65eaea5e51008c2d75e94 (diff)
cgroup: make cgroup_file_open() rcu_read_lock() around cgroup_css() and add cfent->css
For the planned unified hierarchy, each css (cgroup_subsys_state) will be RCU protected so that it can be created and destroyed individually while allowing RCU accesses, and cgroup_css() will soon require either holding cgroup_mutex or RCU read lock. This patch updates cgroup_file_open() such that it acquires the associated css under rcu_read_lock(). While cgroup_file_css() usages in other file operations are safe due to the reference from open, cgroup_css() wouldn't know that and will still trigger warnings. It'd be cleanest to store the acquired css in file->prvidate_data for further file operations but that's already used by seqfile. This patch instead adds cfent->css to cache the associated css. Note that while this field is initialized during cfe init, it should only be considered valid while the file is open. This patch doesn't change visible behavior. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com>
-rw-r--r--kernel/cgroup.c48
1 files changed, 31 insertions, 17 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index cbb6314f1836..d63beffd41e1 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -117,6 +117,7 @@ struct cfent {
117 struct list_head node; 117 struct list_head node;
118 struct dentry *dentry; 118 struct dentry *dentry;
119 struct cftype *type; 119 struct cftype *type;
120 struct cgroup_subsys_state *css;
120 121
121 /* file xattrs */ 122 /* file xattrs */
122 struct simple_xattrs xattrs; 123 struct simple_xattrs xattrs;
@@ -2301,17 +2302,6 @@ static int cgroup_sane_behavior_show(struct cgroup_subsys_state *css,
2301 return 0; 2302 return 0;
2302} 2303}
2303 2304
2304/* return the css for the given cgroup file */
2305static struct cgroup_subsys_state *cgroup_file_css(struct cfent *cfe)
2306{
2307 struct cftype *cft = cfe->type;
2308 struct cgroup *cgrp = __d_cgrp(cfe->dentry->d_parent);
2309
2310 if (cft->ss)
2311 return cgroup_css(cgrp, cft->ss->subsys_id);
2312 return &cgrp->dummy_css;
2313}
2314
2315/* A buffer size big enough for numbers or short strings */ 2305/* A buffer size big enough for numbers or short strings */
2316#define CGROUP_LOCAL_BUFFER_SIZE 64 2306#define CGROUP_LOCAL_BUFFER_SIZE 64
2317 2307
@@ -2388,7 +2378,7 @@ static ssize_t cgroup_file_write(struct file *file, const char __user *buf,
2388{ 2378{
2389 struct cfent *cfe = __d_cfe(file->f_dentry); 2379 struct cfent *cfe = __d_cfe(file->f_dentry);
2390 struct cftype *cft = __d_cft(file->f_dentry); 2380 struct cftype *cft = __d_cft(file->f_dentry);
2391 struct cgroup_subsys_state *css = cgroup_file_css(cfe); 2381 struct cgroup_subsys_state *css = cfe->css;
2392 2382
2393 if (cft->write) 2383 if (cft->write)
2394 return cft->write(css, cft, file, buf, nbytes, ppos); 2384 return cft->write(css, cft, file, buf, nbytes, ppos);
@@ -2430,7 +2420,7 @@ static ssize_t cgroup_file_read(struct file *file, char __user *buf,
2430{ 2420{
2431 struct cfent *cfe = __d_cfe(file->f_dentry); 2421 struct cfent *cfe = __d_cfe(file->f_dentry);
2432 struct cftype *cft = __d_cft(file->f_dentry); 2422 struct cftype *cft = __d_cft(file->f_dentry);
2433 struct cgroup_subsys_state *css = cgroup_file_css(cfe); 2423 struct cgroup_subsys_state *css = cfe->css;
2434 2424
2435 if (cft->read) 2425 if (cft->read)
2436 return cft->read(css, cft, file, buf, nbytes, ppos); 2426 return cft->read(css, cft, file, buf, nbytes, ppos);
@@ -2456,7 +2446,7 @@ static int cgroup_seqfile_show(struct seq_file *m, void *arg)
2456{ 2446{
2457 struct cfent *cfe = m->private; 2447 struct cfent *cfe = m->private;
2458 struct cftype *cft = cfe->type; 2448 struct cftype *cft = cfe->type;
2459 struct cgroup_subsys_state *css = cgroup_file_css(cfe); 2449 struct cgroup_subsys_state *css = cfe->css;
2460 2450
2461 if (cft->read_map) { 2451 if (cft->read_map) {
2462 struct cgroup_map_cb cb = { 2452 struct cgroup_map_cb cb = {
@@ -2479,7 +2469,8 @@ static int cgroup_file_open(struct inode *inode, struct file *file)
2479{ 2469{
2480 struct cfent *cfe = __d_cfe(file->f_dentry); 2470 struct cfent *cfe = __d_cfe(file->f_dentry);
2481 struct cftype *cft = __d_cft(file->f_dentry); 2471 struct cftype *cft = __d_cft(file->f_dentry);
2482 struct cgroup_subsys_state *css = cgroup_file_css(cfe); 2472 struct cgroup *cgrp = __d_cgrp(cfe->dentry->d_parent);
2473 struct cgroup_subsys_state *css;
2483 int err; 2474 int err;
2484 2475
2485 err = generic_file_open(inode, file); 2476 err = generic_file_open(inode, file);
@@ -2491,7 +2482,18 @@ static int cgroup_file_open(struct inode *inode, struct file *file)
2491 * unpinned either on open failure or release. This ensures that 2482 * unpinned either on open failure or release. This ensures that
2492 * @css stays alive for all file operations. 2483 * @css stays alive for all file operations.
2493 */ 2484 */
2494 if (css->ss && !css_tryget(css)) 2485 rcu_read_lock();
2486 if (cft->ss) {
2487 css = cgroup_css(cgrp, cft->ss->subsys_id);
2488 if (!css_tryget(css))
2489 css = NULL;
2490 } else {
2491 css = &cgrp->dummy_css;
2492 }
2493 rcu_read_unlock();
2494
2495 /* css should match @cfe->css, see cgroup_add_file() for details */
2496 if (!css || WARN_ON_ONCE(css != cfe->css))
2495 return -ENODEV; 2497 return -ENODEV;
2496 2498
2497 if (cft->read_map || cft->read_seq_string) { 2499 if (cft->read_map || cft->read_seq_string) {
@@ -2510,7 +2512,7 @@ static int cgroup_file_release(struct inode *inode, struct file *file)
2510{ 2512{
2511 struct cfent *cfe = __d_cfe(file->f_dentry); 2513 struct cfent *cfe = __d_cfe(file->f_dentry);
2512 struct cftype *cft = __d_cft(file->f_dentry); 2514 struct cftype *cft = __d_cft(file->f_dentry);
2513 struct cgroup_subsys_state *css = cgroup_file_css(cfe); 2515 struct cgroup_subsys_state *css = cfe->css;
2514 int ret = 0; 2516 int ret = 0;
2515 2517
2516 if (cft->release) 2518 if (cft->release)
@@ -2772,6 +2774,18 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cftype *cft)
2772 dentry->d_fsdata = cfe; 2774 dentry->d_fsdata = cfe;
2773 simple_xattrs_init(&cfe->xattrs); 2775 simple_xattrs_init(&cfe->xattrs);
2774 2776
2777 /*
2778 * cfe->css is used by read/write/close to determine the associated
2779 * css. file->private_data would be a better place but that's
2780 * already used by seqfile. Note that open will use the usual
2781 * cgroup_css() and css_tryget() to acquire the css and this
2782 * caching doesn't affect css lifetime management.
2783 */
2784 if (cft->ss)
2785 cfe->css = cgroup_css(cgrp, cft->ss->subsys_id);
2786 else
2787 cfe->css = &cgrp->dummy_css;
2788
2775 mode = cgroup_file_mode(cft); 2789 mode = cgroup_file_mode(cft);
2776 error = cgroup_create_file(dentry, mode | S_IFREG, cgrp->root->sb); 2790 error = cgroup_create_file(dentry, mode | S_IFREG, cgrp->root->sb);
2777 if (!error) { 2791 if (!error) {