diff options
author | Tejun Heo <tj@kernel.org> | 2014-05-13 12:11:00 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2014-05-13 12:11:00 -0400 |
commit | 7d331fa985d3a39d5b8cb60caf016d3e53e57c91 (patch) | |
tree | 91521a5c39556347262c2b41c05428236e6ced46 /kernel/cgroup.c | |
parent | d37167ab7b3d67d53519585a44c47416e6758ed2 (diff) |
cgroup: use restart_syscall() for retries after offline waits in cgroup_subtree_control_write()
After waiting for a child to finish offline,
cgroup_subtree_control_write() jumps up to retry from after the input
parsing and active protection breaking. This retry makes the
scheduled locking update - removal of cgroup_tree_mutex - more
difficult. Let's simplify it by returning with restart_syscall() for
retries.
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.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 250def0694b4..3251cc9070fa 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -2535,7 +2535,7 @@ out_finish: | |||
2535 | static int cgroup_subtree_control_write(struct cgroup_subsys_state *dummy_css, | 2535 | static int cgroup_subtree_control_write(struct cgroup_subsys_state *dummy_css, |
2536 | struct cftype *cft, char *buffer) | 2536 | struct cftype *cft, char *buffer) |
2537 | { | 2537 | { |
2538 | unsigned int enable_req = 0, disable_req = 0, enable, disable; | 2538 | unsigned int enable = 0, disable = 0; |
2539 | struct cgroup *cgrp = dummy_css->cgroup, *child; | 2539 | struct cgroup *cgrp = dummy_css->cgroup, *child; |
2540 | struct cgroup_subsys *ss; | 2540 | struct cgroup_subsys *ss; |
2541 | char *tok, *p; | 2541 | char *tok, *p; |
@@ -2554,11 +2554,11 @@ static int cgroup_subtree_control_write(struct cgroup_subsys_state *dummy_css, | |||
2554 | continue; | 2554 | continue; |
2555 | 2555 | ||
2556 | if (*tok == '+') { | 2556 | if (*tok == '+') { |
2557 | enable_req |= 1 << ssid; | 2557 | enable |= 1 << ssid; |
2558 | disable_req &= ~(1 << ssid); | 2558 | disable &= ~(1 << ssid); |
2559 | } else if (*tok == '-') { | 2559 | } else if (*tok == '-') { |
2560 | disable_req |= 1 << ssid; | 2560 | disable |= 1 << ssid; |
2561 | enable_req &= ~(1 << ssid); | 2561 | enable &= ~(1 << ssid); |
2562 | } else { | 2562 | } else { |
2563 | return -EINVAL; | 2563 | return -EINVAL; |
2564 | } | 2564 | } |
@@ -2576,9 +2576,6 @@ static int cgroup_subtree_control_write(struct cgroup_subsys_state *dummy_css, | |||
2576 | */ | 2576 | */ |
2577 | cgroup_get(cgrp); | 2577 | cgroup_get(cgrp); |
2578 | kernfs_break_active_protection(cgrp->control_kn); | 2578 | kernfs_break_active_protection(cgrp->control_kn); |
2579 | retry: | ||
2580 | enable = enable_req; | ||
2581 | disable = disable_req; | ||
2582 | 2579 | ||
2583 | mutex_lock(&cgroup_tree_mutex); | 2580 | mutex_lock(&cgroup_tree_mutex); |
2584 | 2581 | ||
@@ -2608,7 +2605,9 @@ retry: | |||
2608 | schedule(); | 2605 | schedule(); |
2609 | finish_wait(&child->offline_waitq, &wait); | 2606 | finish_wait(&child->offline_waitq, &wait); |
2610 | cgroup_put(child); | 2607 | cgroup_put(child); |
2611 | goto retry; | 2608 | |
2609 | ret = restart_syscall(); | ||
2610 | goto out_unbreak; | ||
2612 | } | 2611 | } |
2613 | 2612 | ||
2614 | /* unavailable or not enabled on the parent? */ | 2613 | /* unavailable or not enabled on the parent? */ |
@@ -2692,6 +2691,7 @@ out_unlock: | |||
2692 | mutex_unlock(&cgroup_mutex); | 2691 | mutex_unlock(&cgroup_mutex); |
2693 | out_unlock_tree: | 2692 | out_unlock_tree: |
2694 | mutex_unlock(&cgroup_tree_mutex); | 2693 | mutex_unlock(&cgroup_tree_mutex); |
2694 | out_unbreak: | ||
2695 | kernfs_unbreak_active_protection(cgrp->control_kn); | 2695 | kernfs_unbreak_active_protection(cgrp->control_kn); |
2696 | cgroup_put(cgrp); | 2696 | cgroup_put(cgrp); |
2697 | return ret; | 2697 | return ret; |