diff options
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 80 |
1 files changed, 14 insertions, 66 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index d597d3015786..86b71e714e13 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -504,10 +504,6 @@ static struct css_set *find_css_set( | |||
504 | * knows that the cgroup won't be removed, as cgroup_rmdir() | 504 | * knows that the cgroup won't be removed, as cgroup_rmdir() |
505 | * needs that mutex. | 505 | * needs that mutex. |
506 | * | 506 | * |
507 | * The cgroup_common_file_write handler for operations that modify | ||
508 | * the cgroup hierarchy holds cgroup_mutex across the entire operation, | ||
509 | * single threading all such cgroup modifications across the system. | ||
510 | * | ||
511 | * The fork and exit callbacks cgroup_fork() and cgroup_exit(), don't | 507 | * The fork and exit callbacks cgroup_fork() and cgroup_exit(), don't |
512 | * (usually) take cgroup_mutex. These are the two most performance | 508 | * (usually) take cgroup_mutex. These are the two most performance |
513 | * critical pieces of code here. The exception occurs on cgroup_exit(), | 509 | * critical pieces of code here. The exception occurs on cgroup_exit(), |
@@ -1279,18 +1275,14 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) | |||
1279 | } | 1275 | } |
1280 | 1276 | ||
1281 | /* | 1277 | /* |
1282 | * Attach task with pid 'pid' to cgroup 'cgrp'. Call with | 1278 | * Attach task with pid 'pid' to cgroup 'cgrp'. Call with cgroup_mutex |
1283 | * cgroup_mutex, may take task_lock of task | 1279 | * held. May take task_lock of task |
1284 | */ | 1280 | */ |
1285 | static int attach_task_by_pid(struct cgroup *cgrp, char *pidbuf) | 1281 | static int attach_task_by_pid(struct cgroup *cgrp, u64 pid) |
1286 | { | 1282 | { |
1287 | pid_t pid; | ||
1288 | struct task_struct *tsk; | 1283 | struct task_struct *tsk; |
1289 | int ret; | 1284 | int ret; |
1290 | 1285 | ||
1291 | if (sscanf(pidbuf, "%d", &pid) != 1) | ||
1292 | return -EIO; | ||
1293 | |||
1294 | if (pid) { | 1286 | if (pid) { |
1295 | rcu_read_lock(); | 1287 | rcu_read_lock(); |
1296 | tsk = find_task_by_vpid(pid); | 1288 | tsk = find_task_by_vpid(pid); |
@@ -1316,6 +1308,16 @@ static int attach_task_by_pid(struct cgroup *cgrp, char *pidbuf) | |||
1316 | return ret; | 1308 | return ret; |
1317 | } | 1309 | } |
1318 | 1310 | ||
1311 | static int cgroup_tasks_write(struct cgroup *cgrp, struct cftype *cft, u64 pid) | ||
1312 | { | ||
1313 | int ret; | ||
1314 | if (!cgroup_lock_live_group(cgrp)) | ||
1315 | return -ENODEV; | ||
1316 | ret = attach_task_by_pid(cgrp, pid); | ||
1317 | cgroup_unlock(); | ||
1318 | return ret; | ||
1319 | } | ||
1320 | |||
1319 | /* The various types of files and directories in a cgroup file system */ | 1321 | /* The various types of files and directories in a cgroup file system */ |
1320 | enum cgroup_filetype { | 1322 | enum cgroup_filetype { |
1321 | FILE_ROOT, | 1323 | FILE_ROOT, |
@@ -1434,60 +1436,6 @@ static ssize_t cgroup_write_string(struct cgroup *cgrp, struct cftype *cft, | |||
1434 | return retval; | 1436 | return retval; |
1435 | } | 1437 | } |
1436 | 1438 | ||
1437 | static ssize_t cgroup_common_file_write(struct cgroup *cgrp, | ||
1438 | struct cftype *cft, | ||
1439 | struct file *file, | ||
1440 | const char __user *userbuf, | ||
1441 | size_t nbytes, loff_t *unused_ppos) | ||
1442 | { | ||
1443 | enum cgroup_filetype type = cft->private; | ||
1444 | char *buffer; | ||
1445 | int retval = 0; | ||
1446 | |||
1447 | if (nbytes >= PATH_MAX) | ||
1448 | return -E2BIG; | ||
1449 | |||
1450 | /* +1 for nul-terminator */ | ||
1451 | buffer = kmalloc(nbytes + 1, GFP_KERNEL); | ||
1452 | if (buffer == NULL) | ||
1453 | return -ENOMEM; | ||
1454 | |||
1455 | if (copy_from_user(buffer, userbuf, nbytes)) { | ||
1456 | retval = -EFAULT; | ||
1457 | goto out1; | ||
1458 | } | ||
1459 | buffer[nbytes] = 0; /* nul-terminate */ | ||
1460 | strstrip(buffer); /* strip -just- trailing whitespace */ | ||
1461 | |||
1462 | mutex_lock(&cgroup_mutex); | ||
1463 | |||
1464 | /* | ||
1465 | * This was already checked for in cgroup_file_write(), but | ||
1466 | * check again now we're holding cgroup_mutex. | ||
1467 | */ | ||
1468 | if (cgroup_is_removed(cgrp)) { | ||
1469 | retval = -ENODEV; | ||
1470 | goto out2; | ||
1471 | } | ||
1472 | |||
1473 | switch (type) { | ||
1474 | case FILE_TASKLIST: | ||
1475 | retval = attach_task_by_pid(cgrp, buffer); | ||
1476 | break; | ||
1477 | default: | ||
1478 | retval = -EINVAL; | ||
1479 | goto out2; | ||
1480 | } | ||
1481 | |||
1482 | if (retval == 0) | ||
1483 | retval = nbytes; | ||
1484 | out2: | ||
1485 | mutex_unlock(&cgroup_mutex); | ||
1486 | out1: | ||
1487 | kfree(buffer); | ||
1488 | return retval; | ||
1489 | } | ||
1490 | |||
1491 | static ssize_t cgroup_file_write(struct file *file, const char __user *buf, | 1439 | static ssize_t cgroup_file_write(struct file *file, const char __user *buf, |
1492 | size_t nbytes, loff_t *ppos) | 1440 | size_t nbytes, loff_t *ppos) |
1493 | { | 1441 | { |
@@ -2265,7 +2213,7 @@ static struct cftype files[] = { | |||
2265 | .name = "tasks", | 2213 | .name = "tasks", |
2266 | .open = cgroup_tasks_open, | 2214 | .open = cgroup_tasks_open, |
2267 | .read = cgroup_tasks_read, | 2215 | .read = cgroup_tasks_read, |
2268 | .write = cgroup_common_file_write, | 2216 | .write_u64 = cgroup_tasks_write, |
2269 | .release = cgroup_tasks_release, | 2217 | .release = cgroup_tasks_release, |
2270 | .private = FILE_TASKLIST, | 2218 | .private = FILE_TASKLIST, |
2271 | }, | 2219 | }, |