diff options
| -rw-r--r-- | fs/proc/base.c | 39 | ||||
| -rw-r--r-- | include/linux/cgroup.h | 26 | ||||
| -rw-r--r-- | include/linux/cpuset.h | 3 | ||||
| -rw-r--r-- | kernel/cgroup.c | 184 | ||||
| -rw-r--r-- | kernel/cpuset.c | 15 | ||||
| -rw-r--r-- | kernel/events/core.c | 7 | ||||
| -rw-r--r-- | mm/memory-failure.c | 2 |
7 files changed, 71 insertions, 205 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 4c542b907754..950100e326a1 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -376,37 +376,6 @@ static const struct file_operations proc_lstats_operations = { | |||
| 376 | 376 | ||
| 377 | #endif | 377 | #endif |
| 378 | 378 | ||
| 379 | #ifdef CONFIG_CGROUPS | ||
| 380 | static int cgroup_open(struct inode *inode, struct file *file) | ||
| 381 | { | ||
| 382 | struct pid *pid = PROC_I(inode)->pid; | ||
| 383 | return single_open(file, proc_cgroup_show, pid); | ||
| 384 | } | ||
| 385 | |||
| 386 | static const struct file_operations proc_cgroup_operations = { | ||
| 387 | .open = cgroup_open, | ||
| 388 | .read = seq_read, | ||
| 389 | .llseek = seq_lseek, | ||
| 390 | .release = single_release, | ||
| 391 | }; | ||
| 392 | #endif | ||
| 393 | |||
| 394 | #ifdef CONFIG_PROC_PID_CPUSET | ||
| 395 | |||
| 396 | static int cpuset_open(struct inode *inode, struct file *file) | ||
| 397 | { | ||
| 398 | struct pid *pid = PROC_I(inode)->pid; | ||
| 399 | return single_open(file, proc_cpuset_show, pid); | ||
| 400 | } | ||
| 401 | |||
| 402 | static const struct file_operations proc_cpuset_operations = { | ||
| 403 | .open = cpuset_open, | ||
| 404 | .read = seq_read, | ||
| 405 | .llseek = seq_lseek, | ||
| 406 | .release = single_release, | ||
| 407 | }; | ||
| 408 | #endif | ||
| 409 | |||
| 410 | static int proc_oom_score(struct seq_file *m, struct pid_namespace *ns, | 379 | static int proc_oom_score(struct seq_file *m, struct pid_namespace *ns, |
| 411 | struct pid *pid, struct task_struct *task) | 380 | struct pid *pid, struct task_struct *task) |
| 412 | { | 381 | { |
| @@ -2579,10 +2548,10 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
| 2579 | REG("latency", S_IRUGO, proc_lstats_operations), | 2548 | REG("latency", S_IRUGO, proc_lstats_operations), |
| 2580 | #endif | 2549 | #endif |
| 2581 | #ifdef CONFIG_PROC_PID_CPUSET | 2550 | #ifdef CONFIG_PROC_PID_CPUSET |
| 2582 | REG("cpuset", S_IRUGO, proc_cpuset_operations), | 2551 | ONE("cpuset", S_IRUGO, proc_cpuset_show), |
| 2583 | #endif | 2552 | #endif |
| 2584 | #ifdef CONFIG_CGROUPS | 2553 | #ifdef CONFIG_CGROUPS |
| 2585 | REG("cgroup", S_IRUGO, proc_cgroup_operations), | 2554 | ONE("cgroup", S_IRUGO, proc_cgroup_show), |
| 2586 | #endif | 2555 | #endif |
| 2587 | ONE("oom_score", S_IRUGO, proc_oom_score), | 2556 | ONE("oom_score", S_IRUGO, proc_oom_score), |
| 2588 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adj_operations), | 2557 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adj_operations), |
| @@ -2925,10 +2894,10 @@ static const struct pid_entry tid_base_stuff[] = { | |||
| 2925 | REG("latency", S_IRUGO, proc_lstats_operations), | 2894 | REG("latency", S_IRUGO, proc_lstats_operations), |
| 2926 | #endif | 2895 | #endif |
| 2927 | #ifdef CONFIG_PROC_PID_CPUSET | 2896 | #ifdef CONFIG_PROC_PID_CPUSET |
| 2928 | REG("cpuset", S_IRUGO, proc_cpuset_operations), | 2897 | ONE("cpuset", S_IRUGO, proc_cpuset_show), |
| 2929 | #endif | 2898 | #endif |
| 2930 | #ifdef CONFIG_CGROUPS | 2899 | #ifdef CONFIG_CGROUPS |
| 2931 | REG("cgroup", S_IRUGO, proc_cgroup_operations), | 2900 | ONE("cgroup", S_IRUGO, proc_cgroup_show), |
| 2932 | #endif | 2901 | #endif |
| 2933 | ONE("oom_score", S_IRUGO, proc_oom_score), | 2902 | ONE("oom_score", S_IRUGO, proc_oom_score), |
| 2934 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adj_operations), | 2903 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adj_operations), |
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index b5223c570eba..1d5196889048 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | 27 | ||
| 28 | struct cgroup_root; | 28 | struct cgroup_root; |
| 29 | struct cgroup_subsys; | 29 | struct cgroup_subsys; |
| 30 | struct inode; | ||
| 31 | struct cgroup; | 30 | struct cgroup; |
| 32 | 31 | ||
| 33 | extern int cgroup_init_early(void); | 32 | extern int cgroup_init_early(void); |
| @@ -38,7 +37,8 @@ extern void cgroup_exit(struct task_struct *p); | |||
| 38 | extern int cgroupstats_build(struct cgroupstats *stats, | 37 | extern int cgroupstats_build(struct cgroupstats *stats, |
| 39 | struct dentry *dentry); | 38 | struct dentry *dentry); |
| 40 | 39 | ||
| 41 | extern int proc_cgroup_show(struct seq_file *, void *); | 40 | extern int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns, |
| 41 | struct pid *pid, struct task_struct *tsk); | ||
| 42 | 42 | ||
| 43 | /* define the enumeration of all cgroup subsystems */ | 43 | /* define the enumeration of all cgroup subsystems */ |
| 44 | #define SUBSYS(_x) _x ## _cgrp_id, | 44 | #define SUBSYS(_x) _x ## _cgrp_id, |
| @@ -161,11 +161,6 @@ static inline void css_put(struct cgroup_subsys_state *css) | |||
| 161 | 161 | ||
| 162 | /* bits in struct cgroup flags field */ | 162 | /* bits in struct cgroup flags field */ |
| 163 | enum { | 163 | enum { |
| 164 | /* | ||
| 165 | * Control Group has previously had a child cgroup or a task, | ||
| 166 | * but no longer (only if CGRP_NOTIFY_ON_RELEASE is set) | ||
| 167 | */ | ||
| 168 | CGRP_RELEASABLE, | ||
| 169 | /* Control Group requires release notifications to userspace */ | 164 | /* Control Group requires release notifications to userspace */ |
| 170 | CGRP_NOTIFY_ON_RELEASE, | 165 | CGRP_NOTIFY_ON_RELEASE, |
| 171 | /* | 166 | /* |
| @@ -235,13 +230,6 @@ struct cgroup { | |||
| 235 | struct list_head e_csets[CGROUP_SUBSYS_COUNT]; | 230 | struct list_head e_csets[CGROUP_SUBSYS_COUNT]; |
| 236 | 231 | ||
| 237 | /* | 232 | /* |
| 238 | * Linked list running through all cgroups that can | ||
| 239 | * potentially be reaped by the release agent. Protected by | ||
| 240 | * release_list_lock | ||
| 241 | */ | ||
| 242 | struct list_head release_list; | ||
| 243 | |||
| 244 | /* | ||
| 245 | * list of pidlists, up to two for each namespace (one for procs, one | 233 | * list of pidlists, up to two for each namespace (one for procs, one |
| 246 | * for tasks); created on demand. | 234 | * for tasks); created on demand. |
| 247 | */ | 235 | */ |
| @@ -250,6 +238,9 @@ struct cgroup { | |||
| 250 | 238 | ||
| 251 | /* used to wait for offlining of csses */ | 239 | /* used to wait for offlining of csses */ |
| 252 | wait_queue_head_t offline_waitq; | 240 | wait_queue_head_t offline_waitq; |
| 241 | |||
| 242 | /* used to schedule release agent */ | ||
| 243 | struct work_struct release_agent_work; | ||
| 253 | }; | 244 | }; |
| 254 | 245 | ||
| 255 | #define MAX_CGROUP_ROOT_NAMELEN 64 | 246 | #define MAX_CGROUP_ROOT_NAMELEN 64 |
| @@ -536,13 +527,10 @@ static inline bool cgroup_has_tasks(struct cgroup *cgrp) | |||
| 536 | return !list_empty(&cgrp->cset_links); | 527 | return !list_empty(&cgrp->cset_links); |
| 537 | } | 528 | } |
| 538 | 529 | ||
| 539 | /* returns ino associated with a cgroup, 0 indicates unmounted root */ | 530 | /* returns ino associated with a cgroup */ |
| 540 | static inline ino_t cgroup_ino(struct cgroup *cgrp) | 531 | static inline ino_t cgroup_ino(struct cgroup *cgrp) |
| 541 | { | 532 | { |
| 542 | if (cgrp->kn) | 533 | return cgrp->kn->ino; |
| 543 | return cgrp->kn->ino; | ||
| 544 | else | ||
| 545 | return 0; | ||
| 546 | } | 534 | } |
| 547 | 535 | ||
| 548 | /* cft/css accessors for cftype->write() operation */ | 536 | /* cft/css accessors for cftype->write() operation */ |
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index 6e39c9bb0dae..2f073db7392e 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h | |||
| @@ -86,7 +86,8 @@ extern void __cpuset_memory_pressure_bump(void); | |||
| 86 | 86 | ||
| 87 | extern void cpuset_task_status_allowed(struct seq_file *m, | 87 | extern void cpuset_task_status_allowed(struct seq_file *m, |
| 88 | struct task_struct *task); | 88 | struct task_struct *task); |
| 89 | extern int proc_cpuset_show(struct seq_file *, void *); | 89 | extern int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns, |
| 90 | struct pid *pid, struct task_struct *tsk); | ||
| 90 | 91 | ||
| 91 | extern int cpuset_mem_spread_node(void); | 92 | extern int cpuset_mem_spread_node(void); |
| 92 | extern int cpuset_slab_spread_node(void); | 93 | extern int cpuset_slab_spread_node(void); |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 3a73f995a81e..cab7dc4284dc 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
| @@ -185,7 +185,6 @@ static int need_forkexit_callback __read_mostly; | |||
| 185 | static struct cftype cgroup_dfl_base_files[]; | 185 | static struct cftype cgroup_dfl_base_files[]; |
| 186 | static struct cftype cgroup_legacy_base_files[]; | 186 | static struct cftype cgroup_legacy_base_files[]; |
| 187 | 187 | ||
| 188 | static void cgroup_put(struct cgroup *cgrp); | ||
| 189 | static int rebind_subsystems(struct cgroup_root *dst_root, | 188 | static int rebind_subsystems(struct cgroup_root *dst_root, |
| 190 | unsigned int ss_mask); | 189 | unsigned int ss_mask); |
| 191 | static int cgroup_destroy_locked(struct cgroup *cgrp); | 190 | static int cgroup_destroy_locked(struct cgroup *cgrp); |
| @@ -195,7 +194,6 @@ static void css_release(struct percpu_ref *ref); | |||
| 195 | static void kill_css(struct cgroup_subsys_state *css); | 194 | static void kill_css(struct cgroup_subsys_state *css); |
| 196 | static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[], | 195 | static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[], |
| 197 | bool is_add); | 196 | bool is_add); |
| 198 | static void cgroup_pidlist_destroy_all(struct cgroup *cgrp); | ||
| 199 | 197 | ||
| 200 | /* IDR wrappers which synchronize using cgroup_idr_lock */ | 198 | /* IDR wrappers which synchronize using cgroup_idr_lock */ |
| 201 | static int cgroup_idr_alloc(struct idr *idr, void *ptr, int start, int end, | 199 | static int cgroup_idr_alloc(struct idr *idr, void *ptr, int start, int end, |
| @@ -331,14 +329,6 @@ bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor) | |||
| 331 | return false; | 329 | return false; |
| 332 | } | 330 | } |
| 333 | 331 | ||
| 334 | static int cgroup_is_releasable(const struct cgroup *cgrp) | ||
| 335 | { | ||
| 336 | const int bits = | ||
| 337 | (1 << CGRP_RELEASABLE) | | ||
| 338 | (1 << CGRP_NOTIFY_ON_RELEASE); | ||
| 339 | return (cgrp->flags & bits) == bits; | ||
| 340 | } | ||
| 341 | |||
| 342 | static int notify_on_release(const struct cgroup *cgrp) | 332 | static int notify_on_release(const struct cgroup *cgrp) |
| 343 | { | 333 | { |
| 344 | return test_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags); | 334 | return test_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags); |
| @@ -394,12 +384,7 @@ static int notify_on_release(const struct cgroup *cgrp) | |||
| 394 | ; \ | 384 | ; \ |
| 395 | else | 385 | else |
| 396 | 386 | ||
| 397 | /* the list of cgroups eligible for automatic release. Protected by | ||
| 398 | * release_list_lock */ | ||
| 399 | static LIST_HEAD(release_list); | ||
| 400 | static DEFINE_RAW_SPINLOCK(release_list_lock); | ||
| 401 | static void cgroup_release_agent(struct work_struct *work); | 387 | static void cgroup_release_agent(struct work_struct *work); |
| 402 | static DECLARE_WORK(release_agent_work, cgroup_release_agent); | ||
| 403 | static void check_for_release(struct cgroup *cgrp); | 388 | static void check_for_release(struct cgroup *cgrp); |
| 404 | 389 | ||
| 405 | /* | 390 | /* |
| @@ -498,7 +483,7 @@ static unsigned long css_set_hash(struct cgroup_subsys_state *css[]) | |||
| 498 | return key; | 483 | return key; |
| 499 | } | 484 | } |
| 500 | 485 | ||
| 501 | static void put_css_set_locked(struct css_set *cset, bool taskexit) | 486 | static void put_css_set_locked(struct css_set *cset) |
| 502 | { | 487 | { |
| 503 | struct cgrp_cset_link *link, *tmp_link; | 488 | struct cgrp_cset_link *link, *tmp_link; |
| 504 | struct cgroup_subsys *ss; | 489 | struct cgroup_subsys *ss; |
| @@ -524,11 +509,7 @@ static void put_css_set_locked(struct css_set *cset, bool taskexit) | |||
| 524 | /* @cgrp can't go away while we're holding css_set_rwsem */ | 509 | /* @cgrp can't go away while we're holding css_set_rwsem */ |
| 525 | if (list_empty(&cgrp->cset_links)) { | 510 | if (list_empty(&cgrp->cset_links)) { |
| 526 | cgroup_update_populated(cgrp, false); | 511 | cgroup_update_populated(cgrp, false); |
| 527 | if (notify_on_release(cgrp)) { | 512 | check_for_release(cgrp); |
| 528 | if (taskexit) | ||
| 529 | set_bit(CGRP_RELEASABLE, &cgrp->flags); | ||
| 530 | check_for_release(cgrp); | ||
| 531 | } | ||
| 532 | } | 513 | } |
| 533 | 514 | ||
| 534 | kfree(link); | 515 | kfree(link); |
| @@ -537,7 +518,7 @@ static void put_css_set_locked(struct css_set *cset, bool taskexit) | |||
| 537 | kfree_rcu(cset, rcu_head); | 518 | kfree_rcu(cset, rcu_head); |
| 538 | } | 519 | } |
| 539 | 520 | ||
| 540 | static void put_css_set(struct css_set *cset, bool taskexit) | 521 | static void put_css_set(struct css_set *cset) |
| 541 | { | 522 | { |
| 542 | /* | 523 | /* |
| 543 | * Ensure that the refcount doesn't hit zero while any readers | 524 | * Ensure that the refcount doesn't hit zero while any readers |
| @@ -548,7 +529,7 @@ static void put_css_set(struct css_set *cset, bool taskexit) | |||
| 548 | return; | 529 | return; |
| 549 | 530 | ||
| 550 | down_write(&css_set_rwsem); | 531 | down_write(&css_set_rwsem); |
| 551 | put_css_set_locked(cset, taskexit); | 532 | put_css_set_locked(cset); |
| 552 | up_write(&css_set_rwsem); | 533 | up_write(&css_set_rwsem); |
| 553 | } | 534 | } |
| 554 | 535 | ||
| @@ -969,14 +950,6 @@ static struct cgroup *task_cgroup_from_root(struct task_struct *task, | |||
| 969 | * knows that the cgroup won't be removed, as cgroup_rmdir() | 950 | * knows that the cgroup won't be removed, as cgroup_rmdir() |
| 970 | * needs that mutex. | 951 | * needs that mutex. |
| 971 | * | 952 | * |
| 972 | * The fork and exit callbacks cgroup_fork() and cgroup_exit(), don't | ||
| 973 | * (usually) take cgroup_mutex. These are the two most performance | ||
| 974 | * critical pieces of code here. The exception occurs on cgroup_exit(), | ||
| 975 | * when a task in a notify_on_release cgroup exits. Then cgroup_mutex | ||
| 976 | * is taken, and if the cgroup count is zero, a usermode call made | ||
| 977 | * to the release agent with the name of the cgroup (path relative to | ||
| 978 | * the root of cgroup file system) as the argument. | ||
| 979 | * | ||
| 980 | * A cgroup can only be deleted if both its 'count' of using tasks | 953 | * A cgroup can only be deleted if both its 'count' of using tasks |
| 981 | * is zero, and its list of 'children' cgroups is empty. Since all | 954 | * is zero, and its list of 'children' cgroups is empty. Since all |
| 982 | * tasks in the system use _some_ cgroup, and since there is always at | 955 | * tasks in the system use _some_ cgroup, and since there is always at |
| @@ -1587,7 +1560,6 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp) | |||
| 1587 | INIT_LIST_HEAD(&cgrp->self.sibling); | 1560 | INIT_LIST_HEAD(&cgrp->self.sibling); |
| 1588 | INIT_LIST_HEAD(&cgrp->self.children); | 1561 | INIT_LIST_HEAD(&cgrp->self.children); |
| 1589 | INIT_LIST_HEAD(&cgrp->cset_links); | 1562 | INIT_LIST_HEAD(&cgrp->cset_links); |
| 1590 | INIT_LIST_HEAD(&cgrp->release_list); | ||
| 1591 | INIT_LIST_HEAD(&cgrp->pidlists); | 1563 | INIT_LIST_HEAD(&cgrp->pidlists); |
| 1592 | mutex_init(&cgrp->pidlist_mutex); | 1564 | mutex_init(&cgrp->pidlist_mutex); |
| 1593 | cgrp->self.cgroup = cgrp; | 1565 | cgrp->self.cgroup = cgrp; |
| @@ -1597,6 +1569,7 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp) | |||
| 1597 | INIT_LIST_HEAD(&cgrp->e_csets[ssid]); | 1569 | INIT_LIST_HEAD(&cgrp->e_csets[ssid]); |
| 1598 | 1570 | ||
| 1599 | init_waitqueue_head(&cgrp->offline_waitq); | 1571 | init_waitqueue_head(&cgrp->offline_waitq); |
| 1572 | INIT_WORK(&cgrp->release_agent_work, cgroup_release_agent); | ||
| 1600 | } | 1573 | } |
| 1601 | 1574 | ||
| 1602 | static void init_cgroup_root(struct cgroup_root *root, | 1575 | static void init_cgroup_root(struct cgroup_root *root, |
| @@ -2052,8 +2025,7 @@ static void cgroup_task_migrate(struct cgroup *old_cgrp, | |||
| 2052 | * task. As trading it for new_cset is protected by cgroup_mutex, | 2025 | * task. As trading it for new_cset is protected by cgroup_mutex, |
| 2053 | * we're safe to drop it here; it will be freed under RCU. | 2026 | * we're safe to drop it here; it will be freed under RCU. |
| 2054 | */ | 2027 | */ |
| 2055 | set_bit(CGRP_RELEASABLE, &old_cgrp->flags); | 2028 | put_css_set_locked(old_cset); |
| 2056 | put_css_set_locked(old_cset, false); | ||
| 2057 | } | 2029 | } |
| 2058 | 2030 | ||
| 2059 | /** | 2031 | /** |
| @@ -2074,7 +2046,7 @@ static void cgroup_migrate_finish(struct list_head *preloaded_csets) | |||
| 2074 | cset->mg_src_cgrp = NULL; | 2046 | cset->mg_src_cgrp = NULL; |
| 2075 | cset->mg_dst_cset = NULL; | 2047 | cset->mg_dst_cset = NULL; |
| 2076 | list_del_init(&cset->mg_preload_node); | 2048 | list_del_init(&cset->mg_preload_node); |
| 2077 | put_css_set_locked(cset, false); | 2049 | put_css_set_locked(cset); |
| 2078 | } | 2050 | } |
| 2079 | up_write(&css_set_rwsem); | 2051 | up_write(&css_set_rwsem); |
| 2080 | } | 2052 | } |
| @@ -2168,8 +2140,8 @@ static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp, | |||
| 2168 | if (src_cset == dst_cset) { | 2140 | if (src_cset == dst_cset) { |
| 2169 | src_cset->mg_src_cgrp = NULL; | 2141 | src_cset->mg_src_cgrp = NULL; |
| 2170 | list_del_init(&src_cset->mg_preload_node); | 2142 | list_del_init(&src_cset->mg_preload_node); |
| 2171 | put_css_set(src_cset, false); | 2143 | put_css_set(src_cset); |
| 2172 | put_css_set(dst_cset, false); | 2144 | put_css_set(dst_cset); |
| 2173 | continue; | 2145 | continue; |
| 2174 | } | 2146 | } |
| 2175 | 2147 | ||
| @@ -2178,7 +2150,7 @@ static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp, | |||
| 2178 | if (list_empty(&dst_cset->mg_preload_node)) | 2150 | if (list_empty(&dst_cset->mg_preload_node)) |
| 2179 | list_add(&dst_cset->mg_preload_node, &csets); | 2151 | list_add(&dst_cset->mg_preload_node, &csets); |
| 2180 | else | 2152 | else |
| 2181 | put_css_set(dst_cset, false); | 2153 | put_css_set(dst_cset); |
| 2182 | } | 2154 | } |
| 2183 | 2155 | ||
| 2184 | list_splice_tail(&csets, preloaded_csets); | 2156 | list_splice_tail(&csets, preloaded_csets); |
| @@ -4173,7 +4145,6 @@ static u64 cgroup_read_notify_on_release(struct cgroup_subsys_state *css, | |||
| 4173 | static int cgroup_write_notify_on_release(struct cgroup_subsys_state *css, | 4145 | static int cgroup_write_notify_on_release(struct cgroup_subsys_state *css, |
| 4174 | struct cftype *cft, u64 val) | 4146 | struct cftype *cft, u64 val) |
| 4175 | { | 4147 | { |
| 4176 | clear_bit(CGRP_RELEASABLE, &css->cgroup->flags); | ||
| 4177 | if (val) | 4148 | if (val) |
| 4178 | set_bit(CGRP_NOTIFY_ON_RELEASE, &css->cgroup->flags); | 4149 | set_bit(CGRP_NOTIFY_ON_RELEASE, &css->cgroup->flags); |
| 4179 | else | 4150 | else |
| @@ -4351,6 +4322,7 @@ static void css_free_work_fn(struct work_struct *work) | |||
| 4351 | /* cgroup free path */ | 4322 | /* cgroup free path */ |
| 4352 | atomic_dec(&cgrp->root->nr_cgrps); | 4323 | atomic_dec(&cgrp->root->nr_cgrps); |
| 4353 | cgroup_pidlist_destroy_all(cgrp); | 4324 | cgroup_pidlist_destroy_all(cgrp); |
| 4325 | cancel_work_sync(&cgrp->release_agent_work); | ||
| 4354 | 4326 | ||
| 4355 | if (cgroup_parent(cgrp)) { | 4327 | if (cgroup_parent(cgrp)) { |
| 4356 | /* | 4328 | /* |
| @@ -4813,19 +4785,12 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) | |||
| 4813 | for_each_css(css, ssid, cgrp) | 4785 | for_each_css(css, ssid, cgrp) |
| 4814 | kill_css(css); | 4786 | kill_css(css); |
| 4815 | 4787 | ||
| 4816 | /* CSS_ONLINE is clear, remove from ->release_list for the last time */ | ||
| 4817 | raw_spin_lock(&release_list_lock); | ||
| 4818 | if (!list_empty(&cgrp->release_list)) | ||
| 4819 | list_del_init(&cgrp->release_list); | ||
| 4820 | raw_spin_unlock(&release_list_lock); | ||
| 4821 | |||
| 4822 | /* | 4788 | /* |
| 4823 | * Remove @cgrp directory along with the base files. @cgrp has an | 4789 | * Remove @cgrp directory along with the base files. @cgrp has an |
| 4824 | * extra ref on its kn. | 4790 | * extra ref on its kn. |
| 4825 | */ | 4791 | */ |
| 4826 | kernfs_remove(cgrp->kn); | 4792 | kernfs_remove(cgrp->kn); |
| 4827 | 4793 | ||
| 4828 | set_bit(CGRP_RELEASABLE, &cgroup_parent(cgrp)->flags); | ||
| 4829 | check_for_release(cgroup_parent(cgrp)); | 4794 | check_for_release(cgroup_parent(cgrp)); |
| 4830 | 4795 | ||
| 4831 | /* put the base reference */ | 4796 | /* put the base reference */ |
| @@ -4842,13 +4807,10 @@ static int cgroup_rmdir(struct kernfs_node *kn) | |||
| 4842 | cgrp = cgroup_kn_lock_live(kn); | 4807 | cgrp = cgroup_kn_lock_live(kn); |
| 4843 | if (!cgrp) | 4808 | if (!cgrp) |
| 4844 | return 0; | 4809 | return 0; |
| 4845 | cgroup_get(cgrp); /* for @kn->priv clearing */ | ||
| 4846 | 4810 | ||
| 4847 | ret = cgroup_destroy_locked(cgrp); | 4811 | ret = cgroup_destroy_locked(cgrp); |
| 4848 | 4812 | ||
| 4849 | cgroup_kn_unlock(kn); | 4813 | cgroup_kn_unlock(kn); |
| 4850 | |||
| 4851 | cgroup_put(cgrp); | ||
| 4852 | return ret; | 4814 | return ret; |
| 4853 | } | 4815 | } |
| 4854 | 4816 | ||
| @@ -5052,12 +5014,9 @@ core_initcall(cgroup_wq_init); | |||
| 5052 | * - Print task's cgroup paths into seq_file, one line for each hierarchy | 5014 | * - Print task's cgroup paths into seq_file, one line for each hierarchy |
| 5053 | * - Used for /proc/<pid>/cgroup. | 5015 | * - Used for /proc/<pid>/cgroup. |
| 5054 | */ | 5016 | */ |
| 5055 | 5017 | int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns, | |
| 5056 | /* TODO: Use a proper seq_file iterator */ | 5018 | struct pid *pid, struct task_struct *tsk) |
| 5057 | int proc_cgroup_show(struct seq_file *m, void *v) | ||
| 5058 | { | 5019 | { |
| 5059 | struct pid *pid; | ||
| 5060 | struct task_struct *tsk; | ||
| 5061 | char *buf, *path; | 5020 | char *buf, *path; |
| 5062 | int retval; | 5021 | int retval; |
| 5063 | struct cgroup_root *root; | 5022 | struct cgroup_root *root; |
| @@ -5067,14 +5026,6 @@ int proc_cgroup_show(struct seq_file *m, void *v) | |||
| 5067 | if (!buf) | 5026 | if (!buf) |
| 5068 | goto out; | 5027 | goto out; |
| 5069 | 5028 | ||
| 5070 | retval = -ESRCH; | ||
| 5071 | pid = m->private; | ||
| 5072 | tsk = get_pid_task(pid, PIDTYPE_PID); | ||
| 5073 | if (!tsk) | ||
| 5074 | goto out_free; | ||
| 5075 | |||
| 5076 | retval = 0; | ||
| 5077 | |||
| 5078 | mutex_lock(&cgroup_mutex); | 5029 | mutex_lock(&cgroup_mutex); |
| 5079 | down_read(&css_set_rwsem); | 5030 | down_read(&css_set_rwsem); |
| 5080 | 5031 | ||
| @@ -5104,11 +5055,10 @@ int proc_cgroup_show(struct seq_file *m, void *v) | |||
| 5104 | seq_putc(m, '\n'); | 5055 | seq_putc(m, '\n'); |
| 5105 | } | 5056 | } |
| 5106 | 5057 | ||
| 5058 | retval = 0; | ||
| 5107 | out_unlock: | 5059 | out_unlock: |
| 5108 | up_read(&css_set_rwsem); | 5060 | up_read(&css_set_rwsem); |
| 5109 | mutex_unlock(&cgroup_mutex); | 5061 | mutex_unlock(&cgroup_mutex); |
| 5110 | put_task_struct(tsk); | ||
| 5111 | out_free: | ||
| 5112 | kfree(buf); | 5062 | kfree(buf); |
| 5113 | out: | 5063 | out: |
| 5114 | return retval; | 5064 | return retval; |
| @@ -5179,7 +5129,7 @@ void cgroup_post_fork(struct task_struct *child) | |||
| 5179 | int i; | 5129 | int i; |
| 5180 | 5130 | ||
| 5181 | /* | 5131 | /* |
| 5182 | * This may race against cgroup_enable_task_cg_links(). As that | 5132 | * This may race against cgroup_enable_task_cg_lists(). As that |
| 5183 | * function sets use_task_css_set_links before grabbing | 5133 | * function sets use_task_css_set_links before grabbing |
| 5184 | * tasklist_lock and we just went through tasklist_lock to add | 5134 | * tasklist_lock and we just went through tasklist_lock to add |
| 5185 | * @child, it's guaranteed that either we see the set | 5135 | * @child, it's guaranteed that either we see the set |
| @@ -5194,7 +5144,7 @@ void cgroup_post_fork(struct task_struct *child) | |||
| 5194 | * when implementing operations which need to migrate all tasks of | 5144 | * when implementing operations which need to migrate all tasks of |
| 5195 | * a cgroup to another. | 5145 | * a cgroup to another. |
| 5196 | * | 5146 | * |
| 5197 | * Note that if we lose to cgroup_enable_task_cg_links(), @child | 5147 | * Note that if we lose to cgroup_enable_task_cg_lists(), @child |
| 5198 | * will remain in init_css_set. This is safe because all tasks are | 5148 | * will remain in init_css_set. This is safe because all tasks are |
| 5199 | * in the init_css_set before cg_links is enabled and there's no | 5149 | * in the init_css_set before cg_links is enabled and there's no |
| 5200 | * operation which transfers all tasks out of init_css_set. | 5150 | * operation which transfers all tasks out of init_css_set. |
| @@ -5278,30 +5228,14 @@ void cgroup_exit(struct task_struct *tsk) | |||
| 5278 | } | 5228 | } |
| 5279 | 5229 | ||
| 5280 | if (put_cset) | 5230 | if (put_cset) |
| 5281 | put_css_set(cset, true); | 5231 | put_css_set(cset); |
| 5282 | } | 5232 | } |
| 5283 | 5233 | ||
| 5284 | static void check_for_release(struct cgroup *cgrp) | 5234 | static void check_for_release(struct cgroup *cgrp) |
| 5285 | { | 5235 | { |
| 5286 | if (cgroup_is_releasable(cgrp) && list_empty(&cgrp->cset_links) && | 5236 | if (notify_on_release(cgrp) && !cgroup_has_tasks(cgrp) && |
| 5287 | !css_has_online_children(&cgrp->self)) { | 5237 | !css_has_online_children(&cgrp->self) && !cgroup_is_dead(cgrp)) |
| 5288 | /* | 5238 | schedule_work(&cgrp->release_agent_work); |
| 5289 | * Control Group is currently removeable. If it's not | ||
| 5290 | * already queued for a userspace notification, queue | ||
| 5291 | * it now | ||
| 5292 | */ | ||
| 5293 | int need_schedule_work = 0; | ||
| 5294 | |||
| 5295 | raw_spin_lock(&release_list_lock); | ||
| 5296 | if (!cgroup_is_dead(cgrp) && | ||
| 5297 | list_empty(&cgrp->release_list)) { | ||
| 5298 | list_add(&cgrp->release_list, &release_list); | ||
| 5299 | need_schedule_work = 1; | ||
| 5300 | } | ||
| 5301 | raw_spin_unlock(&release_list_lock); | ||
| 5302 | if (need_schedule_work) | ||
| 5303 | schedule_work(&release_agent_work); | ||
| 5304 | } | ||
| 5305 | } | 5239 | } |
| 5306 | 5240 | ||
| 5307 | /* | 5241 | /* |
| @@ -5329,52 +5263,39 @@ static void check_for_release(struct cgroup *cgrp) | |||
| 5329 | */ | 5263 | */ |
| 5330 | static void cgroup_release_agent(struct work_struct *work) | 5264 | static void cgroup_release_agent(struct work_struct *work) |
| 5331 | { | 5265 | { |
| 5332 | BUG_ON(work != &release_agent_work); | 5266 | struct cgroup *cgrp = |
| 5267 | container_of(work, struct cgroup, release_agent_work); | ||
| 5268 | char *pathbuf = NULL, *agentbuf = NULL, *path; | ||
| 5269 | char *argv[3], *envp[3]; | ||
| 5270 | |||
| 5333 | mutex_lock(&cgroup_mutex); | 5271 | mutex_lock(&cgroup_mutex); |
| 5334 | raw_spin_lock(&release_list_lock); | 5272 | |
| 5335 | while (!list_empty(&release_list)) { | 5273 | pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); |
| 5336 | char *argv[3], *envp[3]; | 5274 | agentbuf = kstrdup(cgrp->root->release_agent_path, GFP_KERNEL); |
| 5337 | int i; | 5275 | if (!pathbuf || !agentbuf) |
| 5338 | char *pathbuf = NULL, *agentbuf = NULL, *path; | 5276 | goto out; |
| 5339 | struct cgroup *cgrp = list_entry(release_list.next, | 5277 | |
| 5340 | struct cgroup, | 5278 | path = cgroup_path(cgrp, pathbuf, PATH_MAX); |
| 5341 | release_list); | 5279 | if (!path) |
| 5342 | list_del_init(&cgrp->release_list); | 5280 | goto out; |
| 5343 | raw_spin_unlock(&release_list_lock); | 5281 | |
| 5344 | pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); | 5282 | argv[0] = agentbuf; |
| 5345 | if (!pathbuf) | 5283 | argv[1] = path; |
| 5346 | goto continue_free; | 5284 | argv[2] = NULL; |
| 5347 | path = cgroup_path(cgrp, pathbuf, PATH_MAX); | 5285 | |
| 5348 | if (!path) | 5286 | /* minimal command environment */ |
| 5349 | goto continue_free; | 5287 | envp[0] = "HOME=/"; |
| 5350 | agentbuf = kstrdup(cgrp->root->release_agent_path, GFP_KERNEL); | 5288 | envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; |
| 5351 | if (!agentbuf) | 5289 | envp[2] = NULL; |
| 5352 | goto continue_free; | 5290 | |
| 5353 | 5291 | mutex_unlock(&cgroup_mutex); | |
| 5354 | i = 0; | 5292 | call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); |
| 5355 | argv[i++] = agentbuf; | 5293 | goto out_free; |
| 5356 | argv[i++] = path; | 5294 | out: |
| 5357 | argv[i] = NULL; | ||
| 5358 | |||
| 5359 | i = 0; | ||
| 5360 | /* minimal command environment */ | ||
| 5361 | envp[i++] = "HOME=/"; | ||
| 5362 | envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; | ||
| 5363 | envp[i] = NULL; | ||
| 5364 | |||
| 5365 | /* Drop the lock while we invoke the usermode helper, | ||
| 5366 | * since the exec could involve hitting disk and hence | ||
| 5367 | * be a slow process */ | ||
| 5368 | mutex_unlock(&cgroup_mutex); | ||
| 5369 | call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); | ||
| 5370 | mutex_lock(&cgroup_mutex); | ||
| 5371 | continue_free: | ||
| 5372 | kfree(pathbuf); | ||
| 5373 | kfree(agentbuf); | ||
| 5374 | raw_spin_lock(&release_list_lock); | ||
| 5375 | } | ||
| 5376 | raw_spin_unlock(&release_list_lock); | ||
| 5377 | mutex_unlock(&cgroup_mutex); | 5295 | mutex_unlock(&cgroup_mutex); |
| 5296 | out_free: | ||
| 5297 | kfree(agentbuf); | ||
| 5298 | kfree(pathbuf); | ||
| 5378 | } | 5299 | } |
| 5379 | 5300 | ||
| 5380 | static int __init cgroup_disable(char *str) | 5301 | static int __init cgroup_disable(char *str) |
| @@ -5562,7 +5483,8 @@ static int cgroup_css_links_read(struct seq_file *seq, void *v) | |||
| 5562 | 5483 | ||
| 5563 | static u64 releasable_read(struct cgroup_subsys_state *css, struct cftype *cft) | 5484 | static u64 releasable_read(struct cgroup_subsys_state *css, struct cftype *cft) |
| 5564 | { | 5485 | { |
| 5565 | return test_bit(CGRP_RELEASABLE, &css->cgroup->flags); | 5486 | return (!cgroup_has_tasks(css->cgroup) && |
| 5487 | !css_has_online_children(&css->cgroup->self)); | ||
| 5566 | } | 5488 | } |
| 5567 | 5489 | ||
| 5568 | static struct cftype debug_files[] = { | 5490 | static struct cftype debug_files[] = { |
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 52cb04c993b7..1f107c74087b 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
| @@ -2730,10 +2730,9 @@ void __cpuset_memory_pressure_bump(void) | |||
| 2730 | * and we take cpuset_mutex, keeping cpuset_attach() from changing it | 2730 | * and we take cpuset_mutex, keeping cpuset_attach() from changing it |
| 2731 | * anyway. | 2731 | * anyway. |
| 2732 | */ | 2732 | */ |
| 2733 | int proc_cpuset_show(struct seq_file *m, void *unused_v) | 2733 | int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns, |
| 2734 | struct pid *pid, struct task_struct *tsk) | ||
| 2734 | { | 2735 | { |
| 2735 | struct pid *pid; | ||
| 2736 | struct task_struct *tsk; | ||
| 2737 | char *buf, *p; | 2736 | char *buf, *p; |
| 2738 | struct cgroup_subsys_state *css; | 2737 | struct cgroup_subsys_state *css; |
| 2739 | int retval; | 2738 | int retval; |
| @@ -2743,24 +2742,16 @@ int proc_cpuset_show(struct seq_file *m, void *unused_v) | |||
| 2743 | if (!buf) | 2742 | if (!buf) |
| 2744 | goto out; | 2743 | goto out; |
| 2745 | 2744 | ||
| 2746 | retval = -ESRCH; | ||
| 2747 | pid = m->private; | ||
| 2748 | tsk = get_pid_task(pid, PIDTYPE_PID); | ||
| 2749 | if (!tsk) | ||
| 2750 | goto out_free; | ||
| 2751 | |||
| 2752 | retval = -ENAMETOOLONG; | 2745 | retval = -ENAMETOOLONG; |
| 2753 | rcu_read_lock(); | 2746 | rcu_read_lock(); |
| 2754 | css = task_css(tsk, cpuset_cgrp_id); | 2747 | css = task_css(tsk, cpuset_cgrp_id); |
| 2755 | p = cgroup_path(css->cgroup, buf, PATH_MAX); | 2748 | p = cgroup_path(css->cgroup, buf, PATH_MAX); |
| 2756 | rcu_read_unlock(); | 2749 | rcu_read_unlock(); |
| 2757 | if (!p) | 2750 | if (!p) |
| 2758 | goto out_put_task; | 2751 | goto out_free; |
| 2759 | seq_puts(m, p); | 2752 | seq_puts(m, p); |
| 2760 | seq_putc(m, '\n'); | 2753 | seq_putc(m, '\n'); |
| 2761 | retval = 0; | 2754 | retval = 0; |
| 2762 | out_put_task: | ||
| 2763 | put_task_struct(tsk); | ||
| 2764 | out_free: | 2755 | out_free: |
| 2765 | kfree(buf); | 2756 | kfree(buf); |
| 2766 | out: | 2757 | out: |
diff --git a/kernel/events/core.c b/kernel/events/core.c index 963bf139e2b2..b1c663593f5c 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
| @@ -392,14 +392,9 @@ perf_cgroup_match(struct perf_event *event) | |||
| 392 | event->cgrp->css.cgroup); | 392 | event->cgrp->css.cgroup); |
| 393 | } | 393 | } |
| 394 | 394 | ||
| 395 | static inline void perf_put_cgroup(struct perf_event *event) | ||
| 396 | { | ||
| 397 | css_put(&event->cgrp->css); | ||
| 398 | } | ||
| 399 | |||
| 400 | static inline void perf_detach_cgroup(struct perf_event *event) | 395 | static inline void perf_detach_cgroup(struct perf_event *event) |
| 401 | { | 396 | { |
| 402 | perf_put_cgroup(event); | 397 | css_put(&event->cgrp->css); |
| 403 | event->cgrp = NULL; | 398 | event->cgrp = NULL; |
| 404 | } | 399 | } |
| 405 | 400 | ||
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 44c6bd201d3a..8639f6b28746 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
| @@ -148,7 +148,7 @@ static int hwpoison_filter_task(struct page *p) | |||
| 148 | ino = cgroup_ino(css->cgroup); | 148 | ino = cgroup_ino(css->cgroup); |
| 149 | css_put(css); | 149 | css_put(css); |
| 150 | 150 | ||
| 151 | if (!ino || ino != hwpoison_filter_memcg) | 151 | if (ino != hwpoison_filter_memcg) |
| 152 | return -EINVAL; | 152 | return -EINVAL; |
| 153 | 153 | ||
| 154 | return 0; | 154 | return 0; |
