diff options
-rw-r--r-- | kernel/cgroup.c | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index c4bc8dac3b1d..583f8f66a7e1 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -2277,6 +2277,17 @@ static int cgroup_sane_behavior_show(struct cgroup *cgrp, struct cftype *cft, | |||
2277 | return 0; | 2277 | return 0; |
2278 | } | 2278 | } |
2279 | 2279 | ||
2280 | /* return the css for the given cgroup file */ | ||
2281 | static struct cgroup_subsys_state *cgroup_file_css(struct cfent *cfe) | ||
2282 | { | ||
2283 | struct cftype *cft = cfe->type; | ||
2284 | struct cgroup *cgrp = __d_cgrp(cfe->dentry->d_parent); | ||
2285 | |||
2286 | if (cft->ss) | ||
2287 | return cgrp->subsys[cft->ss->subsys_id]; | ||
2288 | return NULL; | ||
2289 | } | ||
2290 | |||
2280 | /* A buffer size big enough for numbers or short strings */ | 2291 | /* A buffer size big enough for numbers or short strings */ |
2281 | #define CGROUP_LOCAL_BUFFER_SIZE 64 | 2292 | #define CGROUP_LOCAL_BUFFER_SIZE 64 |
2282 | 2293 | ||
@@ -2354,8 +2365,6 @@ static ssize_t cgroup_file_write(struct file *file, const char __user *buf, | |||
2354 | struct cftype *cft = __d_cft(file->f_dentry); | 2365 | struct cftype *cft = __d_cft(file->f_dentry); |
2355 | struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent); | 2366 | struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent); |
2356 | 2367 | ||
2357 | if (cgroup_is_dead(cgrp)) | ||
2358 | return -ENODEV; | ||
2359 | if (cft->write) | 2368 | if (cft->write) |
2360 | return cft->write(cgrp, cft, file, buf, nbytes, ppos); | 2369 | return cft->write(cgrp, cft, file, buf, nbytes, ppos); |
2361 | if (cft->write_u64 || cft->write_s64) | 2370 | if (cft->write_u64 || cft->write_s64) |
@@ -2399,9 +2408,6 @@ static ssize_t cgroup_file_read(struct file *file, char __user *buf, | |||
2399 | struct cftype *cft = __d_cft(file->f_dentry); | 2408 | struct cftype *cft = __d_cft(file->f_dentry); |
2400 | struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent); | 2409 | struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent); |
2401 | 2410 | ||
2402 | if (cgroup_is_dead(cgrp)) | ||
2403 | return -ENODEV; | ||
2404 | |||
2405 | if (cft->read) | 2411 | if (cft->read) |
2406 | return cft->read(cgrp, cft, file, buf, nbytes, ppos); | 2412 | return cft->read(cgrp, cft, file, buf, nbytes, ppos); |
2407 | if (cft->read_u64) | 2413 | if (cft->read_u64) |
@@ -2447,15 +2453,22 @@ static const struct file_operations cgroup_seqfile_operations = { | |||
2447 | 2453 | ||
2448 | static int cgroup_file_open(struct inode *inode, struct file *file) | 2454 | static int cgroup_file_open(struct inode *inode, struct file *file) |
2449 | { | 2455 | { |
2456 | struct cfent *cfe = __d_cfe(file->f_dentry); | ||
2457 | struct cftype *cft = __d_cft(file->f_dentry); | ||
2458 | struct cgroup_subsys_state *css = cgroup_file_css(cfe); | ||
2450 | int err; | 2459 | int err; |
2451 | struct cfent *cfe; | ||
2452 | struct cftype *cft; | ||
2453 | 2460 | ||
2454 | err = generic_file_open(inode, file); | 2461 | err = generic_file_open(inode, file); |
2455 | if (err) | 2462 | if (err) |
2456 | return err; | 2463 | return err; |
2457 | cfe = __d_cfe(file->f_dentry); | 2464 | |
2458 | cft = cfe->type; | 2465 | /* |
2466 | * If the file belongs to a subsystem, pin the css. Will be | ||
2467 | * unpinned either on open failure or release. This ensures that | ||
2468 | * @css stays alive for all file operations. | ||
2469 | */ | ||
2470 | if (css && !css_tryget(css)) | ||
2471 | return -ENODEV; | ||
2459 | 2472 | ||
2460 | if (cft->read_map || cft->read_seq_string) { | 2473 | if (cft->read_map || cft->read_seq_string) { |
2461 | file->f_op = &cgroup_seqfile_operations; | 2474 | file->f_op = &cgroup_seqfile_operations; |
@@ -2464,15 +2477,23 @@ static int cgroup_file_open(struct inode *inode, struct file *file) | |||
2464 | err = cft->open(inode, file); | 2477 | err = cft->open(inode, file); |
2465 | } | 2478 | } |
2466 | 2479 | ||
2480 | if (css && err) | ||
2481 | css_put(css); | ||
2467 | return err; | 2482 | return err; |
2468 | } | 2483 | } |
2469 | 2484 | ||
2470 | static int cgroup_file_release(struct inode *inode, struct file *file) | 2485 | static int cgroup_file_release(struct inode *inode, struct file *file) |
2471 | { | 2486 | { |
2487 | struct cfent *cfe = __d_cfe(file->f_dentry); | ||
2472 | struct cftype *cft = __d_cft(file->f_dentry); | 2488 | struct cftype *cft = __d_cft(file->f_dentry); |
2489 | struct cgroup_subsys_state *css = cgroup_file_css(cfe); | ||
2490 | int ret = 0; | ||
2491 | |||
2473 | if (cft->release) | 2492 | if (cft->release) |
2474 | return cft->release(inode, file); | 2493 | ret = cft->release(inode, file); |
2475 | return 0; | 2494 | if (css) |
2495 | css_put(css); | ||
2496 | return ret; | ||
2476 | } | 2497 | } |
2477 | 2498 | ||
2478 | /* | 2499 | /* |