aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2007-05-23 16:57:25 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-23 23:14:11 -0400
commitba96a0c88098697a63e80157718b7440414ed24d (patch)
treebdd999761eed452cc162f5b63166d1014aaf2e3e /kernel
parent33e1c288da62a6a5aa9077a6b7bfa690b1b02cf4 (diff)
freezer: fix vfork problem
Currently try_to_freeze_tasks() has to wait until all of the vforked processes exit and for this reason every user can make it fail. To fix this problem we can introduce the additional process flag PF_FREEZER_SKIP to be used by tasks that do not want to be counted as freezable by the freezer and want to have TIF_FREEZE set nevertheless. Then, this flag can be set by tasks using sys_vfork() before they call wait_for_completion(&vfork) and cleared after they have woken up. After clearing it, the tasks should call try_to_freeze() as soon as possible. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Cc: Gautham R Shenoy <ego@in.ibm.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Cc: Pavel Machek <pavel@ucw.cz> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/fork.c3
-rw-r--r--kernel/power/process.c29
2 files changed, 12 insertions, 20 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index 87069cfc18a1..73ad5cda1bcd 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -45,6 +45,7 @@
45#include <linux/acct.h> 45#include <linux/acct.h>
46#include <linux/tsacct_kern.h> 46#include <linux/tsacct_kern.h>
47#include <linux/cn_proc.h> 47#include <linux/cn_proc.h>
48#include <linux/freezer.h>
48#include <linux/delayacct.h> 49#include <linux/delayacct.h>
49#include <linux/taskstats_kern.h> 50#include <linux/taskstats_kern.h>
50#include <linux/random.h> 51#include <linux/random.h>
@@ -1405,7 +1406,9 @@ long do_fork(unsigned long clone_flags,
1405 } 1406 }
1406 1407
1407 if (clone_flags & CLONE_VFORK) { 1408 if (clone_flags & CLONE_VFORK) {
1409 freezer_do_not_count();
1408 wait_for_completion(&vfork); 1410 wait_for_completion(&vfork);
1411 freezer_count();
1409 if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) { 1412 if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) {
1410 current->ptrace_message = nr; 1413 current->ptrace_message = nr;
1411 ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP); 1414 ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 02e490e311eb..eefca8581fa0 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -120,22 +120,12 @@ static unsigned int try_to_freeze_tasks(int freeze_user_space)
120 cancel_freezing(p); 120 cancel_freezing(p);
121 continue; 121 continue;
122 } 122 }
123 if (is_user_space(p)) { 123 if (is_user_space(p) == !freeze_user_space)
124 if (!freeze_user_space) 124 continue;
125 continue; 125
126 126 freeze_process(p);
127 /* Freeze the task unless there is a vfork 127 if (!freezer_should_skip(p))
128 * completion pending 128 todo++;
129 */
130 if (!p->vfork_done)
131 freeze_process(p);
132 } else {
133 if (freeze_user_space)
134 continue;
135
136 freeze_process(p);
137 }
138 todo++;
139 } while_each_thread(g, p); 129 } while_each_thread(g, p);
140 read_unlock(&tasklist_lock); 130 read_unlock(&tasklist_lock);
141 yield(); /* Yield is okay here */ 131 yield(); /* Yield is okay here */
@@ -161,7 +151,8 @@ static unsigned int try_to_freeze_tasks(int freeze_user_space)
161 continue; 151 continue;
162 152
163 task_lock(p); 153 task_lock(p);
164 if (freezeable(p) && !frozen(p)) 154 if (freezeable(p) && !frozen(p) &&
155 !freezer_should_skip(p))
165 printk(KERN_ERR " %s\n", p->comm); 156 printk(KERN_ERR " %s\n", p->comm);
166 157
167 cancel_freezing(p); 158 cancel_freezing(p);
@@ -210,9 +201,7 @@ static void thaw_tasks(int thaw_user_space)
210 if (is_user_space(p) == !thaw_user_space) 201 if (is_user_space(p) == !thaw_user_space)
211 continue; 202 continue;
212 203
213 if (!thaw_process(p)) 204 thaw_process(p);
214 printk(KERN_WARNING " Strange, %s not stopped\n",
215 p->comm );
216 } while_each_thread(g, p); 205 } while_each_thread(g, p);
217 read_unlock(&tasklist_lock); 206 read_unlock(&tasklist_lock);
218} 207}