summaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-08-08 20:11:23 -0400
committerTejun Heo <tj@kernel.org>2013-08-08 20:11:23 -0400
commitf7d58818ba4249f04a83b73aaac135640050bb4f (patch)
tree770514a6164e8464caf0b7497bb06c68936febc6 /kernel/cgroup.c
parent2bb566cb68dfafad328af666ebadf0e49accd6ca (diff)
cgroup: pin cgroup_subsys_state when opening a cgroupfs file
Previously, each file read/write operation relied on the inode reference count pinning the cgroup and simply checked whether the cgroup was marked dead before proceeding to invoke the per-subsystem callback. This was rather silly as it didn't have any synchronization or css pinning around the check and the cgroup may be removed and all css refs drained between the DEAD check and actual method invocation. This patch pins the css between open() and release() so that it is guaranteed to be alive for all file operations and remove the silly DEAD checks from cgroup_file_read/write(). Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel/cgroup.c')
-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/*