diff options
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 331 |
1 files changed, 153 insertions, 178 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 15ac0e1e4f4d..13932abde159 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/delayacct.h> | 45 | #include <linux/delayacct.h> |
46 | #include <linux/cgroupstats.h> | 46 | #include <linux/cgroupstats.h> |
47 | #include <linux/hash.h> | 47 | #include <linux/hash.h> |
48 | #include <linux/namei.h> | ||
48 | 49 | ||
49 | #include <asm/atomic.h> | 50 | #include <asm/atomic.h> |
50 | 51 | ||
@@ -89,11 +90,7 @@ struct cgroupfs_root { | |||
89 | /* Hierarchy-specific flags */ | 90 | /* Hierarchy-specific flags */ |
90 | unsigned long flags; | 91 | unsigned long flags; |
91 | 92 | ||
92 | /* The path to use for release notifications. No locking | 93 | /* The path to use for release notifications. */ |
93 | * between setting and use - so if userspace updates this | ||
94 | * while child cgroups exist, you could miss a | ||
95 | * notification. We ensure that it's always a valid | ||
96 | * NUL-terminated string */ | ||
97 | char release_agent_path[PATH_MAX]; | 94 | char release_agent_path[PATH_MAX]; |
98 | }; | 95 | }; |
99 | 96 | ||
@@ -118,7 +115,7 @@ static int root_count; | |||
118 | * extra work in the fork/exit path if none of the subsystems need to | 115 | * extra work in the fork/exit path if none of the subsystems need to |
119 | * be called. | 116 | * be called. |
120 | */ | 117 | */ |
121 | static int need_forkexit_callback; | 118 | static int need_forkexit_callback __read_mostly; |
122 | static int need_mm_owner_callback __read_mostly; | 119 | static int need_mm_owner_callback __read_mostly; |
123 | 120 | ||
124 | /* convenient tests for these bits */ | 121 | /* convenient tests for these bits */ |
@@ -220,7 +217,7 @@ static struct hlist_head *css_set_hash(struct cgroup_subsys_state *css[]) | |||
220 | * task until after the first call to cgroup_iter_start(). This | 217 | * task until after the first call to cgroup_iter_start(). This |
221 | * reduces the fork()/exit() overhead for people who have cgroups | 218 | * reduces the fork()/exit() overhead for people who have cgroups |
222 | * compiled into their kernel but not actually in use */ | 219 | * compiled into their kernel but not actually in use */ |
223 | static int use_task_css_set_links; | 220 | static int use_task_css_set_links __read_mostly; |
224 | 221 | ||
225 | /* When we create or destroy a css_set, the operation simply | 222 | /* When we create or destroy a css_set, the operation simply |
226 | * takes/releases a reference count on all the cgroups referenced | 223 | * takes/releases a reference count on all the cgroups referenced |
@@ -241,17 +238,20 @@ static int use_task_css_set_links; | |||
241 | */ | 238 | */ |
242 | static void unlink_css_set(struct css_set *cg) | 239 | static void unlink_css_set(struct css_set *cg) |
243 | { | 240 | { |
241 | struct cg_cgroup_link *link; | ||
242 | struct cg_cgroup_link *saved_link; | ||
243 | |||
244 | write_lock(&css_set_lock); | 244 | write_lock(&css_set_lock); |
245 | hlist_del(&cg->hlist); | 245 | hlist_del(&cg->hlist); |
246 | css_set_count--; | 246 | css_set_count--; |
247 | while (!list_empty(&cg->cg_links)) { | 247 | |
248 | struct cg_cgroup_link *link; | 248 | list_for_each_entry_safe(link, saved_link, &cg->cg_links, |
249 | link = list_entry(cg->cg_links.next, | 249 | cg_link_list) { |
250 | struct cg_cgroup_link, cg_link_list); | ||
251 | list_del(&link->cg_link_list); | 250 | list_del(&link->cg_link_list); |
252 | list_del(&link->cgrp_link_list); | 251 | list_del(&link->cgrp_link_list); |
253 | kfree(link); | 252 | kfree(link); |
254 | } | 253 | } |
254 | |||
255 | write_unlock(&css_set_lock); | 255 | write_unlock(&css_set_lock); |
256 | } | 256 | } |
257 | 257 | ||
@@ -355,6 +355,17 @@ static struct css_set *find_existing_css_set( | |||
355 | return NULL; | 355 | return NULL; |
356 | } | 356 | } |
357 | 357 | ||
358 | static void free_cg_links(struct list_head *tmp) | ||
359 | { | ||
360 | struct cg_cgroup_link *link; | ||
361 | struct cg_cgroup_link *saved_link; | ||
362 | |||
363 | list_for_each_entry_safe(link, saved_link, tmp, cgrp_link_list) { | ||
364 | list_del(&link->cgrp_link_list); | ||
365 | kfree(link); | ||
366 | } | ||
367 | } | ||
368 | |||
358 | /* | 369 | /* |
359 | * allocate_cg_links() allocates "count" cg_cgroup_link structures | 370 | * allocate_cg_links() allocates "count" cg_cgroup_link structures |
360 | * and chains them on tmp through their cgrp_link_list fields. Returns 0 on | 371 | * and chains them on tmp through their cgrp_link_list fields. Returns 0 on |
@@ -368,13 +379,7 @@ static int allocate_cg_links(int count, struct list_head *tmp) | |||
368 | for (i = 0; i < count; i++) { | 379 | for (i = 0; i < count; i++) { |
369 | link = kmalloc(sizeof(*link), GFP_KERNEL); | 380 | link = kmalloc(sizeof(*link), GFP_KERNEL); |
370 | if (!link) { | 381 | if (!link) { |
371 | while (!list_empty(tmp)) { | 382 | free_cg_links(tmp); |
372 | link = list_entry(tmp->next, | ||
373 | struct cg_cgroup_link, | ||
374 | cgrp_link_list); | ||
375 | list_del(&link->cgrp_link_list); | ||
376 | kfree(link); | ||
377 | } | ||
378 | return -ENOMEM; | 383 | return -ENOMEM; |
379 | } | 384 | } |
380 | list_add(&link->cgrp_link_list, tmp); | 385 | list_add(&link->cgrp_link_list, tmp); |
@@ -382,18 +387,6 @@ static int allocate_cg_links(int count, struct list_head *tmp) | |||
382 | return 0; | 387 | return 0; |
383 | } | 388 | } |
384 | 389 | ||
385 | static void free_cg_links(struct list_head *tmp) | ||
386 | { | ||
387 | while (!list_empty(tmp)) { | ||
388 | struct cg_cgroup_link *link; | ||
389 | link = list_entry(tmp->next, | ||
390 | struct cg_cgroup_link, | ||
391 | cgrp_link_list); | ||
392 | list_del(&link->cgrp_link_list); | ||
393 | kfree(link); | ||
394 | } | ||
395 | } | ||
396 | |||
397 | /* | 390 | /* |
398 | * find_css_set() takes an existing cgroup group and a | 391 | * find_css_set() takes an existing cgroup group and a |
399 | * cgroup object, and returns a css_set object that's | 392 | * cgroup object, and returns a css_set object that's |
@@ -415,11 +408,11 @@ static struct css_set *find_css_set( | |||
415 | 408 | ||
416 | /* First see if we already have a cgroup group that matches | 409 | /* First see if we already have a cgroup group that matches |
417 | * the desired set */ | 410 | * the desired set */ |
418 | write_lock(&css_set_lock); | 411 | read_lock(&css_set_lock); |
419 | res = find_existing_css_set(oldcg, cgrp, template); | 412 | res = find_existing_css_set(oldcg, cgrp, template); |
420 | if (res) | 413 | if (res) |
421 | get_css_set(res); | 414 | get_css_set(res); |
422 | write_unlock(&css_set_lock); | 415 | read_unlock(&css_set_lock); |
423 | 416 | ||
424 | if (res) | 417 | if (res) |
425 | return res; | 418 | return res; |
@@ -507,10 +500,6 @@ static struct css_set *find_css_set( | |||
507 | * knows that the cgroup won't be removed, as cgroup_rmdir() | 500 | * knows that the cgroup won't be removed, as cgroup_rmdir() |
508 | * needs that mutex. | 501 | * needs that mutex. |
509 | * | 502 | * |
510 | * The cgroup_common_file_write handler for operations that modify | ||
511 | * the cgroup hierarchy holds cgroup_mutex across the entire operation, | ||
512 | * single threading all such cgroup modifications across the system. | ||
513 | * | ||
514 | * The fork and exit callbacks cgroup_fork() and cgroup_exit(), don't | 503 | * The fork and exit callbacks cgroup_fork() and cgroup_exit(), don't |
515 | * (usually) take cgroup_mutex. These are the two most performance | 504 | * (usually) take cgroup_mutex. These are the two most performance |
516 | * critical pieces of code here. The exception occurs on cgroup_exit(), | 505 | * critical pieces of code here. The exception occurs on cgroup_exit(), |
@@ -962,7 +951,6 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
962 | struct super_block *sb; | 951 | struct super_block *sb; |
963 | struct cgroupfs_root *root; | 952 | struct cgroupfs_root *root; |
964 | struct list_head tmp_cg_links; | 953 | struct list_head tmp_cg_links; |
965 | INIT_LIST_HEAD(&tmp_cg_links); | ||
966 | 954 | ||
967 | /* First find the desired set of subsystems */ | 955 | /* First find the desired set of subsystems */ |
968 | ret = parse_cgroupfs_options(data, &opts); | 956 | ret = parse_cgroupfs_options(data, &opts); |
@@ -1093,6 +1081,8 @@ static void cgroup_kill_sb(struct super_block *sb) { | |||
1093 | struct cgroupfs_root *root = sb->s_fs_info; | 1081 | struct cgroupfs_root *root = sb->s_fs_info; |
1094 | struct cgroup *cgrp = &root->top_cgroup; | 1082 | struct cgroup *cgrp = &root->top_cgroup; |
1095 | int ret; | 1083 | int ret; |
1084 | struct cg_cgroup_link *link; | ||
1085 | struct cg_cgroup_link *saved_link; | ||
1096 | 1086 | ||
1097 | BUG_ON(!root); | 1087 | BUG_ON(!root); |
1098 | 1088 | ||
@@ -1112,10 +1102,9 @@ static void cgroup_kill_sb(struct super_block *sb) { | |||
1112 | * root cgroup | 1102 | * root cgroup |
1113 | */ | 1103 | */ |
1114 | write_lock(&css_set_lock); | 1104 | write_lock(&css_set_lock); |
1115 | while (!list_empty(&cgrp->css_sets)) { | 1105 | |
1116 | struct cg_cgroup_link *link; | 1106 | list_for_each_entry_safe(link, saved_link, &cgrp->css_sets, |
1117 | link = list_entry(cgrp->css_sets.next, | 1107 | cgrp_link_list) { |
1118 | struct cg_cgroup_link, cgrp_link_list); | ||
1119 | list_del(&link->cg_link_list); | 1108 | list_del(&link->cg_link_list); |
1120 | list_del(&link->cgrp_link_list); | 1109 | list_del(&link->cgrp_link_list); |
1121 | kfree(link); | 1110 | kfree(link); |
@@ -1281,18 +1270,14 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) | |||
1281 | } | 1270 | } |
1282 | 1271 | ||
1283 | /* | 1272 | /* |
1284 | * Attach task with pid 'pid' to cgroup 'cgrp'. Call with | 1273 | * Attach task with pid 'pid' to cgroup 'cgrp'. Call with cgroup_mutex |
1285 | * cgroup_mutex, may take task_lock of task | 1274 | * held. May take task_lock of task |
1286 | */ | 1275 | */ |
1287 | static int attach_task_by_pid(struct cgroup *cgrp, char *pidbuf) | 1276 | static int attach_task_by_pid(struct cgroup *cgrp, u64 pid) |
1288 | { | 1277 | { |
1289 | pid_t pid; | ||
1290 | struct task_struct *tsk; | 1278 | struct task_struct *tsk; |
1291 | int ret; | 1279 | int ret; |
1292 | 1280 | ||
1293 | if (sscanf(pidbuf, "%d", &pid) != 1) | ||
1294 | return -EIO; | ||
1295 | |||
1296 | if (pid) { | 1281 | if (pid) { |
1297 | rcu_read_lock(); | 1282 | rcu_read_lock(); |
1298 | tsk = find_task_by_vpid(pid); | 1283 | tsk = find_task_by_vpid(pid); |
@@ -1318,6 +1303,16 @@ static int attach_task_by_pid(struct cgroup *cgrp, char *pidbuf) | |||
1318 | return ret; | 1303 | return ret; |
1319 | } | 1304 | } |
1320 | 1305 | ||
1306 | static int cgroup_tasks_write(struct cgroup *cgrp, struct cftype *cft, u64 pid) | ||
1307 | { | ||
1308 | int ret; | ||
1309 | if (!cgroup_lock_live_group(cgrp)) | ||
1310 | return -ENODEV; | ||
1311 | ret = attach_task_by_pid(cgrp, pid); | ||
1312 | cgroup_unlock(); | ||
1313 | return ret; | ||
1314 | } | ||
1315 | |||
1321 | /* The various types of files and directories in a cgroup file system */ | 1316 | /* The various types of files and directories in a cgroup file system */ |
1322 | enum cgroup_filetype { | 1317 | enum cgroup_filetype { |
1323 | FILE_ROOT, | 1318 | FILE_ROOT, |
@@ -1327,12 +1322,54 @@ enum cgroup_filetype { | |||
1327 | FILE_RELEASE_AGENT, | 1322 | FILE_RELEASE_AGENT, |
1328 | }; | 1323 | }; |
1329 | 1324 | ||
1325 | /** | ||
1326 | * cgroup_lock_live_group - take cgroup_mutex and check that cgrp is alive. | ||
1327 | * @cgrp: the cgroup to be checked for liveness | ||
1328 | * | ||
1329 | * On success, returns true; the lock should be later released with | ||
1330 | * cgroup_unlock(). On failure returns false with no lock held. | ||
1331 | */ | ||
1332 | bool cgroup_lock_live_group(struct cgroup *cgrp) | ||
1333 | { | ||
1334 | mutex_lock(&cgroup_mutex); | ||
1335 | if (cgroup_is_removed(cgrp)) { | ||
1336 | mutex_unlock(&cgroup_mutex); | ||
1337 | return false; | ||
1338 | } | ||
1339 | return true; | ||
1340 | } | ||
1341 | |||
1342 | static int cgroup_release_agent_write(struct cgroup *cgrp, struct cftype *cft, | ||
1343 | const char *buffer) | ||
1344 | { | ||
1345 | BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX); | ||
1346 | if (!cgroup_lock_live_group(cgrp)) | ||
1347 | return -ENODEV; | ||
1348 | strcpy(cgrp->root->release_agent_path, buffer); | ||
1349 | cgroup_unlock(); | ||
1350 | return 0; | ||
1351 | } | ||
1352 | |||
1353 | static int cgroup_release_agent_show(struct cgroup *cgrp, struct cftype *cft, | ||
1354 | struct seq_file *seq) | ||
1355 | { | ||
1356 | if (!cgroup_lock_live_group(cgrp)) | ||
1357 | return -ENODEV; | ||
1358 | seq_puts(seq, cgrp->root->release_agent_path); | ||
1359 | seq_putc(seq, '\n'); | ||
1360 | cgroup_unlock(); | ||
1361 | return 0; | ||
1362 | } | ||
1363 | |||
1364 | /* A buffer size big enough for numbers or short strings */ | ||
1365 | #define CGROUP_LOCAL_BUFFER_SIZE 64 | ||
1366 | |||
1330 | static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft, | 1367 | static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft, |
1331 | struct file *file, | 1368 | struct file *file, |
1332 | const char __user *userbuf, | 1369 | const char __user *userbuf, |
1333 | size_t nbytes, loff_t *unused_ppos) | 1370 | size_t nbytes, loff_t *unused_ppos) |
1334 | { | 1371 | { |
1335 | char buffer[64]; | 1372 | char buffer[CGROUP_LOCAL_BUFFER_SIZE]; |
1336 | int retval = 0; | 1373 | int retval = 0; |
1337 | char *end; | 1374 | char *end; |
1338 | 1375 | ||
@@ -1361,68 +1398,39 @@ static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft, | |||
1361 | return retval; | 1398 | return retval; |
1362 | } | 1399 | } |
1363 | 1400 | ||
1364 | static ssize_t cgroup_common_file_write(struct cgroup *cgrp, | 1401 | static ssize_t cgroup_write_string(struct cgroup *cgrp, struct cftype *cft, |
1365 | struct cftype *cft, | 1402 | struct file *file, |
1366 | struct file *file, | 1403 | const char __user *userbuf, |
1367 | const char __user *userbuf, | 1404 | size_t nbytes, loff_t *unused_ppos) |
1368 | size_t nbytes, loff_t *unused_ppos) | ||
1369 | { | 1405 | { |
1370 | enum cgroup_filetype type = cft->private; | 1406 | char local_buffer[CGROUP_LOCAL_BUFFER_SIZE]; |
1371 | char *buffer; | ||
1372 | int retval = 0; | 1407 | int retval = 0; |
1408 | size_t max_bytes = cft->max_write_len; | ||
1409 | char *buffer = local_buffer; | ||
1373 | 1410 | ||
1374 | if (nbytes >= PATH_MAX) | 1411 | if (!max_bytes) |
1412 | max_bytes = sizeof(local_buffer) - 1; | ||
1413 | if (nbytes >= max_bytes) | ||
1375 | return -E2BIG; | 1414 | return -E2BIG; |
1376 | 1415 | /* Allocate a dynamic buffer if we need one */ | |
1377 | /* +1 for nul-terminator */ | 1416 | if (nbytes >= sizeof(local_buffer)) { |
1378 | buffer = kmalloc(nbytes + 1, GFP_KERNEL); | 1417 | buffer = kmalloc(nbytes + 1, GFP_KERNEL); |
1379 | if (buffer == NULL) | 1418 | if (buffer == NULL) |
1380 | return -ENOMEM; | 1419 | return -ENOMEM; |
1381 | 1420 | } | |
1382 | if (copy_from_user(buffer, userbuf, nbytes)) { | 1421 | if (nbytes && copy_from_user(buffer, userbuf, nbytes)) { |
1383 | retval = -EFAULT; | 1422 | retval = -EFAULT; |
1384 | goto out1; | 1423 | goto out; |
1385 | } | 1424 | } |
1386 | buffer[nbytes] = 0; /* nul-terminate */ | ||
1387 | strstrip(buffer); /* strip -just- trailing whitespace */ | ||
1388 | 1425 | ||
1389 | mutex_lock(&cgroup_mutex); | 1426 | buffer[nbytes] = 0; /* nul-terminate */ |
1390 | 1427 | strstrip(buffer); | |
1391 | /* | 1428 | retval = cft->write_string(cgrp, cft, buffer); |
1392 | * This was already checked for in cgroup_file_write(), but | 1429 | if (!retval) |
1393 | * check again now we're holding cgroup_mutex. | ||
1394 | */ | ||
1395 | if (cgroup_is_removed(cgrp)) { | ||
1396 | retval = -ENODEV; | ||
1397 | goto out2; | ||
1398 | } | ||
1399 | |||
1400 | switch (type) { | ||
1401 | case FILE_TASKLIST: | ||
1402 | retval = attach_task_by_pid(cgrp, buffer); | ||
1403 | break; | ||
1404 | case FILE_NOTIFY_ON_RELEASE: | ||
1405 | clear_bit(CGRP_RELEASABLE, &cgrp->flags); | ||
1406 | if (simple_strtoul(buffer, NULL, 10) != 0) | ||
1407 | set_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags); | ||
1408 | else | ||
1409 | clear_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags); | ||
1410 | break; | ||
1411 | case FILE_RELEASE_AGENT: | ||
1412 | BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX); | ||
1413 | strcpy(cgrp->root->release_agent_path, buffer); | ||
1414 | break; | ||
1415 | default: | ||
1416 | retval = -EINVAL; | ||
1417 | goto out2; | ||
1418 | } | ||
1419 | |||
1420 | if (retval == 0) | ||
1421 | retval = nbytes; | 1430 | retval = nbytes; |
1422 | out2: | 1431 | out: |
1423 | mutex_unlock(&cgroup_mutex); | 1432 | if (buffer != local_buffer) |
1424 | out1: | 1433 | kfree(buffer); |
1425 | kfree(buffer); | ||
1426 | return retval; | 1434 | return retval; |
1427 | } | 1435 | } |
1428 | 1436 | ||
@@ -1438,6 +1446,8 @@ static ssize_t cgroup_file_write(struct file *file, const char __user *buf, | |||
1438 | return cft->write(cgrp, cft, file, buf, nbytes, ppos); | 1446 | return cft->write(cgrp, cft, file, buf, nbytes, ppos); |
1439 | if (cft->write_u64 || cft->write_s64) | 1447 | if (cft->write_u64 || cft->write_s64) |
1440 | return cgroup_write_X64(cgrp, cft, file, buf, nbytes, ppos); | 1448 | return cgroup_write_X64(cgrp, cft, file, buf, nbytes, ppos); |
1449 | if (cft->write_string) | ||
1450 | return cgroup_write_string(cgrp, cft, file, buf, nbytes, ppos); | ||
1441 | if (cft->trigger) { | 1451 | if (cft->trigger) { |
1442 | int ret = cft->trigger(cgrp, (unsigned int)cft->private); | 1452 | int ret = cft->trigger(cgrp, (unsigned int)cft->private); |
1443 | return ret ? ret : nbytes; | 1453 | return ret ? ret : nbytes; |
@@ -1450,7 +1460,7 @@ static ssize_t cgroup_read_u64(struct cgroup *cgrp, struct cftype *cft, | |||
1450 | char __user *buf, size_t nbytes, | 1460 | char __user *buf, size_t nbytes, |
1451 | loff_t *ppos) | 1461 | loff_t *ppos) |
1452 | { | 1462 | { |
1453 | char tmp[64]; | 1463 | char tmp[CGROUP_LOCAL_BUFFER_SIZE]; |
1454 | u64 val = cft->read_u64(cgrp, cft); | 1464 | u64 val = cft->read_u64(cgrp, cft); |
1455 | int len = sprintf(tmp, "%llu\n", (unsigned long long) val); | 1465 | int len = sprintf(tmp, "%llu\n", (unsigned long long) val); |
1456 | 1466 | ||
@@ -1462,56 +1472,13 @@ static ssize_t cgroup_read_s64(struct cgroup *cgrp, struct cftype *cft, | |||
1462 | char __user *buf, size_t nbytes, | 1472 | char __user *buf, size_t nbytes, |
1463 | loff_t *ppos) | 1473 | loff_t *ppos) |
1464 | { | 1474 | { |
1465 | char tmp[64]; | 1475 | char tmp[CGROUP_LOCAL_BUFFER_SIZE]; |
1466 | s64 val = cft->read_s64(cgrp, cft); | 1476 | s64 val = cft->read_s64(cgrp, cft); |
1467 | int len = sprintf(tmp, "%lld\n", (long long) val); | 1477 | int len = sprintf(tmp, "%lld\n", (long long) val); |
1468 | 1478 | ||
1469 | return simple_read_from_buffer(buf, nbytes, ppos, tmp, len); | 1479 | return simple_read_from_buffer(buf, nbytes, ppos, tmp, len); |
1470 | } | 1480 | } |
1471 | 1481 | ||
1472 | static ssize_t cgroup_common_file_read(struct cgroup *cgrp, | ||
1473 | struct cftype *cft, | ||
1474 | struct file *file, | ||
1475 | char __user *buf, | ||
1476 | size_t nbytes, loff_t *ppos) | ||
1477 | { | ||
1478 | enum cgroup_filetype type = cft->private; | ||
1479 | char *page; | ||
1480 | ssize_t retval = 0; | ||
1481 | char *s; | ||
1482 | |||
1483 | if (!(page = (char *)__get_free_page(GFP_KERNEL))) | ||
1484 | return -ENOMEM; | ||
1485 | |||
1486 | s = page; | ||
1487 | |||
1488 | switch (type) { | ||
1489 | case FILE_RELEASE_AGENT: | ||
1490 | { | ||
1491 | struct cgroupfs_root *root; | ||
1492 | size_t n; | ||
1493 | mutex_lock(&cgroup_mutex); | ||
1494 | root = cgrp->root; | ||
1495 | n = strnlen(root->release_agent_path, | ||
1496 | sizeof(root->release_agent_path)); | ||
1497 | n = min(n, (size_t) PAGE_SIZE); | ||
1498 | strncpy(s, root->release_agent_path, n); | ||
1499 | mutex_unlock(&cgroup_mutex); | ||
1500 | s += n; | ||
1501 | break; | ||
1502 | } | ||
1503 | default: | ||
1504 | retval = -EINVAL; | ||
1505 | goto out; | ||
1506 | } | ||
1507 | *s++ = '\n'; | ||
1508 | |||
1509 | retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page); | ||
1510 | out: | ||
1511 | free_page((unsigned long)page); | ||
1512 | return retval; | ||
1513 | } | ||
1514 | |||
1515 | static ssize_t cgroup_file_read(struct file *file, char __user *buf, | 1482 | static ssize_t cgroup_file_read(struct file *file, char __user *buf, |
1516 | size_t nbytes, loff_t *ppos) | 1483 | size_t nbytes, loff_t *ppos) |
1517 | { | 1484 | { |
@@ -1560,7 +1527,7 @@ static int cgroup_seqfile_show(struct seq_file *m, void *arg) | |||
1560 | return cft->read_seq_string(state->cgroup, cft, m); | 1527 | return cft->read_seq_string(state->cgroup, cft, m); |
1561 | } | 1528 | } |
1562 | 1529 | ||
1563 | int cgroup_seqfile_release(struct inode *inode, struct file *file) | 1530 | static int cgroup_seqfile_release(struct inode *inode, struct file *file) |
1564 | { | 1531 | { |
1565 | struct seq_file *seq = file->private_data; | 1532 | struct seq_file *seq = file->private_data; |
1566 | kfree(seq->private); | 1533 | kfree(seq->private); |
@@ -1569,6 +1536,7 @@ int cgroup_seqfile_release(struct inode *inode, struct file *file) | |||
1569 | 1536 | ||
1570 | static struct file_operations cgroup_seqfile_operations = { | 1537 | static struct file_operations cgroup_seqfile_operations = { |
1571 | .read = seq_read, | 1538 | .read = seq_read, |
1539 | .write = cgroup_file_write, | ||
1572 | .llseek = seq_lseek, | 1540 | .llseek = seq_lseek, |
1573 | .release = cgroup_seqfile_release, | 1541 | .release = cgroup_seqfile_release, |
1574 | }; | 1542 | }; |
@@ -1756,15 +1724,11 @@ int cgroup_add_files(struct cgroup *cgrp, | |||
1756 | int cgroup_task_count(const struct cgroup *cgrp) | 1724 | int cgroup_task_count(const struct cgroup *cgrp) |
1757 | { | 1725 | { |
1758 | int count = 0; | 1726 | int count = 0; |
1759 | struct list_head *l; | 1727 | struct cg_cgroup_link *link; |
1760 | 1728 | ||
1761 | read_lock(&css_set_lock); | 1729 | read_lock(&css_set_lock); |
1762 | l = cgrp->css_sets.next; | 1730 | list_for_each_entry(link, &cgrp->css_sets, cgrp_link_list) { |
1763 | while (l != &cgrp->css_sets) { | ||
1764 | struct cg_cgroup_link *link = | ||
1765 | list_entry(l, struct cg_cgroup_link, cgrp_link_list); | ||
1766 | count += atomic_read(&link->cg->ref.refcount); | 1731 | count += atomic_read(&link->cg->ref.refcount); |
1767 | l = l->next; | ||
1768 | } | 1732 | } |
1769 | read_unlock(&css_set_lock); | 1733 | read_unlock(&css_set_lock); |
1770 | return count; | 1734 | return count; |
@@ -2227,6 +2191,18 @@ static u64 cgroup_read_notify_on_release(struct cgroup *cgrp, | |||
2227 | return notify_on_release(cgrp); | 2191 | return notify_on_release(cgrp); |
2228 | } | 2192 | } |
2229 | 2193 | ||
2194 | static int cgroup_write_notify_on_release(struct cgroup *cgrp, | ||
2195 | struct cftype *cft, | ||
2196 | u64 val) | ||
2197 | { | ||
2198 | clear_bit(CGRP_RELEASABLE, &cgrp->flags); | ||
2199 | if (val) | ||
2200 | set_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags); | ||
2201 | else | ||
2202 | clear_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags); | ||
2203 | return 0; | ||
2204 | } | ||
2205 | |||
2230 | /* | 2206 | /* |
2231 | * for the common functions, 'private' gives the type of file | 2207 | * for the common functions, 'private' gives the type of file |
2232 | */ | 2208 | */ |
@@ -2235,7 +2211,7 @@ static struct cftype files[] = { | |||
2235 | .name = "tasks", | 2211 | .name = "tasks", |
2236 | .open = cgroup_tasks_open, | 2212 | .open = cgroup_tasks_open, |
2237 | .read = cgroup_tasks_read, | 2213 | .read = cgroup_tasks_read, |
2238 | .write = cgroup_common_file_write, | 2214 | .write_u64 = cgroup_tasks_write, |
2239 | .release = cgroup_tasks_release, | 2215 | .release = cgroup_tasks_release, |
2240 | .private = FILE_TASKLIST, | 2216 | .private = FILE_TASKLIST, |
2241 | }, | 2217 | }, |
@@ -2243,15 +2219,16 @@ static struct cftype files[] = { | |||
2243 | { | 2219 | { |
2244 | .name = "notify_on_release", | 2220 | .name = "notify_on_release", |
2245 | .read_u64 = cgroup_read_notify_on_release, | 2221 | .read_u64 = cgroup_read_notify_on_release, |
2246 | .write = cgroup_common_file_write, | 2222 | .write_u64 = cgroup_write_notify_on_release, |
2247 | .private = FILE_NOTIFY_ON_RELEASE, | 2223 | .private = FILE_NOTIFY_ON_RELEASE, |
2248 | }, | 2224 | }, |
2249 | }; | 2225 | }; |
2250 | 2226 | ||
2251 | static struct cftype cft_release_agent = { | 2227 | static struct cftype cft_release_agent = { |
2252 | .name = "release_agent", | 2228 | .name = "release_agent", |
2253 | .read = cgroup_common_file_read, | 2229 | .read_seq_string = cgroup_release_agent_show, |
2254 | .write = cgroup_common_file_write, | 2230 | .write_string = cgroup_release_agent_write, |
2231 | .max_write_len = PATH_MAX, | ||
2255 | .private = FILE_RELEASE_AGENT, | 2232 | .private = FILE_RELEASE_AGENT, |
2256 | }; | 2233 | }; |
2257 | 2234 | ||
@@ -2391,7 +2368,7 @@ static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
2391 | return cgroup_create(c_parent, dentry, mode | S_IFDIR); | 2368 | return cgroup_create(c_parent, dentry, mode | S_IFDIR); |
2392 | } | 2369 | } |
2393 | 2370 | ||
2394 | static inline int cgroup_has_css_refs(struct cgroup *cgrp) | 2371 | static int cgroup_has_css_refs(struct cgroup *cgrp) |
2395 | { | 2372 | { |
2396 | /* Check the reference count on each subsystem. Since we | 2373 | /* Check the reference count on each subsystem. Since we |
2397 | * already established that there are no tasks in the | 2374 | * already established that there are no tasks in the |
@@ -2869,16 +2846,17 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks) | |||
2869 | * cgroup_clone - clone the cgroup the given subsystem is attached to | 2846 | * cgroup_clone - clone the cgroup the given subsystem is attached to |
2870 | * @tsk: the task to be moved | 2847 | * @tsk: the task to be moved |
2871 | * @subsys: the given subsystem | 2848 | * @subsys: the given subsystem |
2849 | * @nodename: the name for the new cgroup | ||
2872 | * | 2850 | * |
2873 | * Duplicate the current cgroup in the hierarchy that the given | 2851 | * Duplicate the current cgroup in the hierarchy that the given |
2874 | * subsystem is attached to, and move this task into the new | 2852 | * subsystem is attached to, and move this task into the new |
2875 | * child. | 2853 | * child. |
2876 | */ | 2854 | */ |
2877 | int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys) | 2855 | int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys, |
2856 | char *nodename) | ||
2878 | { | 2857 | { |
2879 | struct dentry *dentry; | 2858 | struct dentry *dentry; |
2880 | int ret = 0; | 2859 | int ret = 0; |
2881 | char nodename[MAX_CGROUP_TYPE_NAMELEN]; | ||
2882 | struct cgroup *parent, *child; | 2860 | struct cgroup *parent, *child; |
2883 | struct inode *inode; | 2861 | struct inode *inode; |
2884 | struct css_set *cg; | 2862 | struct css_set *cg; |
@@ -2903,8 +2881,6 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys) | |||
2903 | cg = tsk->cgroups; | 2881 | cg = tsk->cgroups; |
2904 | parent = task_cgroup(tsk, subsys->subsys_id); | 2882 | parent = task_cgroup(tsk, subsys->subsys_id); |
2905 | 2883 | ||
2906 | snprintf(nodename, MAX_CGROUP_TYPE_NAMELEN, "%d", tsk->pid); | ||
2907 | |||
2908 | /* Pin the hierarchy */ | 2884 | /* Pin the hierarchy */ |
2909 | atomic_inc(&parent->root->sb->s_active); | 2885 | atomic_inc(&parent->root->sb->s_active); |
2910 | 2886 | ||
@@ -3078,27 +3054,24 @@ static void cgroup_release_agent(struct work_struct *work) | |||
3078 | while (!list_empty(&release_list)) { | 3054 | while (!list_empty(&release_list)) { |
3079 | char *argv[3], *envp[3]; | 3055 | char *argv[3], *envp[3]; |
3080 | int i; | 3056 | int i; |
3081 | char *pathbuf; | 3057 | char *pathbuf = NULL, *agentbuf = NULL; |
3082 | struct cgroup *cgrp = list_entry(release_list.next, | 3058 | struct cgroup *cgrp = list_entry(release_list.next, |
3083 | struct cgroup, | 3059 | struct cgroup, |
3084 | release_list); | 3060 | release_list); |
3085 | list_del_init(&cgrp->release_list); | 3061 | list_del_init(&cgrp->release_list); |
3086 | spin_unlock(&release_list_lock); | 3062 | spin_unlock(&release_list_lock); |
3087 | pathbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 3063 | pathbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
3088 | if (!pathbuf) { | 3064 | if (!pathbuf) |
3089 | spin_lock(&release_list_lock); | 3065 | goto continue_free; |
3090 | continue; | 3066 | if (cgroup_path(cgrp, pathbuf, PAGE_SIZE) < 0) |
3091 | } | 3067 | goto continue_free; |
3092 | 3068 | agentbuf = kstrdup(cgrp->root->release_agent_path, GFP_KERNEL); | |
3093 | if (cgroup_path(cgrp, pathbuf, PAGE_SIZE) < 0) { | 3069 | if (!agentbuf) |
3094 | kfree(pathbuf); | 3070 | goto continue_free; |
3095 | spin_lock(&release_list_lock); | ||
3096 | continue; | ||
3097 | } | ||
3098 | 3071 | ||
3099 | i = 0; | 3072 | i = 0; |
3100 | argv[i++] = cgrp->root->release_agent_path; | 3073 | argv[i++] = agentbuf; |
3101 | argv[i++] = (char *)pathbuf; | 3074 | argv[i++] = pathbuf; |
3102 | argv[i] = NULL; | 3075 | argv[i] = NULL; |
3103 | 3076 | ||
3104 | i = 0; | 3077 | i = 0; |
@@ -3112,8 +3085,10 @@ static void cgroup_release_agent(struct work_struct *work) | |||
3112 | * be a slow process */ | 3085 | * be a slow process */ |
3113 | mutex_unlock(&cgroup_mutex); | 3086 | mutex_unlock(&cgroup_mutex); |
3114 | call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); | 3087 | call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); |
3115 | kfree(pathbuf); | ||
3116 | mutex_lock(&cgroup_mutex); | 3088 | mutex_lock(&cgroup_mutex); |
3089 | continue_free: | ||
3090 | kfree(pathbuf); | ||
3091 | kfree(agentbuf); | ||
3117 | spin_lock(&release_list_lock); | 3092 | spin_lock(&release_list_lock); |
3118 | } | 3093 | } |
3119 | spin_unlock(&release_list_lock); | 3094 | spin_unlock(&release_list_lock); |