diff options
-rw-r--r-- | kernel/cgroup.c | 48 |
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 */ | ||
2305 | static 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) { |