aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/freezer.h
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 /include/linux/freezer.h
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 'include/linux/freezer.h')
-rw-r--r--include/linux/freezer.h48
1 files changed, 46 insertions, 2 deletions
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index db5423eae24d..c9435252e8e4 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -81,7 +81,49 @@ static inline int try_to_freeze(void)
81 return 0; 81 return 0;
82} 82}
83 83
84extern void thaw_some_processes(int all); 84/*
85 * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it
86 * calls wait_for_completion(&vfork) and reset right after it returns from this
87 * function. Next, the parent should call try_to_freeze() to freeze itself
88 * appropriately in case the child has exited before the freezing of tasks is
89 * complete. However, we don't want kernel threads to be frozen in unexpected
90 * places, so we allow them to block freeze_processes() instead or to set
91 * PF_NOFREEZE if needed and PF_FREEZER_SKIP is only set for userland vfork
92 * parents. Fortunately, in the ____call_usermodehelper() case the parent won't
93 * really block freeze_processes(), since ____call_usermodehelper() (the child)
94 * does a little before exec/exit and it can't be frozen before waking up the
95 * parent.
96 */
97
98/*
99 * If the current task is a user space one, tell the freezer not to count it as
100 * freezable.
101 */
102static inline void freezer_do_not_count(void)
103{
104 if (current->mm)
105 current->flags |= PF_FREEZER_SKIP;
106}
107
108/*
109 * If the current task is a user space one, tell the freezer to count it as
110 * freezable again and try to freeze it.
111 */
112static inline void freezer_count(void)
113{
114 if (current->mm) {
115 current->flags &= ~PF_FREEZER_SKIP;
116 try_to_freeze();
117 }
118}
119
120/*
121 * Check if the task should be counted as freezeable by the freezer
122 */
123static inline int freezer_should_skip(struct task_struct *p)
124{
125 return !!(p->flags & PF_FREEZER_SKIP);
126}
85 127
86#else 128#else
87static inline int frozen(struct task_struct *p) { return 0; } 129static inline int frozen(struct task_struct *p) { return 0; }
@@ -96,5 +138,7 @@ static inline void thaw_processes(void) {}
96 138
97static inline int try_to_freeze(void) { return 0; } 139static inline int try_to_freeze(void) { return 0; }
98 140
99 141static inline void freezer_do_not_count(void) {}
142static inline void freezer_count(void) {}
143static inline int freezer_should_skip(struct task_struct *p) { return 0; }
100#endif 144#endif