aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/cgroup.c43
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 */
2281static 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
2448static int cgroup_file_open(struct inode *inode, struct file *file) 2454static 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
2470static int cgroup_file_release(struct inode *inode, struct file *file) 2485static 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/*