aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/freezer.h
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2013-05-06 19:50:06 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-05-12 08:16:21 -0400
commit416ad3c9c0066405b83ec875b75496523549be09 (patch)
tree393d8c261cf9b79c18197d3173e0b8aa8874ca35 /include/linux/freezer.h
parentf722406faae2d073cc1d01063d1123c35425939e (diff)
freezer: add unsafe versions of freezable helpers for NFS
NFS calls the freezable helpers with locks held, which is unsafe and will cause lockdep warnings when 6aa9707 "lockdep: check that no locks held at freeze time" is reapplied (it was reverted in dbf520a). NFS shouldn't be doing this, but it has long-running syscalls that must hold a lock but also shouldn't block suspend. Until NFS freeze handling is rewritten to use a signal to exit out of the critical section, add new *_unsafe versions of the helpers that will not run the lockdep test when 6aa9707 is reapplied, and call them from NFS. In practice the likley result of holding the lock while freezing is that a second task blocked on the lock will never freeze, aborting suspend, but it is possible to manufacture a case using the cgroup freezer, the lock, and the suspend freezer to create a deadlock. Silencing the lockdep warning here will allow problems to be found in other drivers that may have a more serious deadlock risk, and prevent new problems from being added. Signed-off-by: Colin Cross <ccross@android.com> Acked-by: Pavel Machek <pavel@ucw.cz> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'include/linux/freezer.h')
-rw-r--r--include/linux/freezer.h42
1 files changed, 41 insertions, 1 deletions
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index e70df40d84f6..5b31e21c485f 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -46,7 +46,11 @@ extern int freeze_kernel_threads(void);
46extern void thaw_processes(void); 46extern void thaw_processes(void);
47extern void thaw_kernel_threads(void); 47extern void thaw_kernel_threads(void);
48 48
49static inline bool try_to_freeze(void) 49/*
50 * DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION
51 * If try_to_freeze causes a lockdep warning it means the caller may deadlock
52 */
53static inline bool try_to_freeze_unsafe(void)
50{ 54{
51 might_sleep(); 55 might_sleep();
52 if (likely(!freezing(current))) 56 if (likely(!freezing(current)))
@@ -54,6 +58,11 @@ static inline bool try_to_freeze(void)
54 return __refrigerator(false); 58 return __refrigerator(false);
55} 59}
56 60
61static inline bool try_to_freeze(void)
62{
63 return try_to_freeze_unsafe();
64}
65
57extern bool freeze_task(struct task_struct *p); 66extern bool freeze_task(struct task_struct *p);
58extern bool set_freezable(void); 67extern bool set_freezable(void);
59 68
@@ -115,6 +124,14 @@ static inline void freezer_count(void)
115 try_to_freeze(); 124 try_to_freeze();
116} 125}
117 126
127/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */
128static inline void freezer_count_unsafe(void)
129{
130 current->flags &= ~PF_FREEZER_SKIP;
131 smp_mb();
132 try_to_freeze_unsafe();
133}
134
118/** 135/**
119 * freezer_should_skip - whether to skip a task when determining frozen 136 * freezer_should_skip - whether to skip a task when determining frozen
120 * state is reached 137 * state is reached
@@ -152,6 +169,14 @@ static inline bool freezer_should_skip(struct task_struct *p)
152 freezer_count(); \ 169 freezer_count(); \
153}) 170})
154 171
172/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */
173#define freezable_schedule_unsafe() \
174({ \
175 freezer_do_not_count(); \
176 schedule(); \
177 freezer_count_unsafe(); \
178})
179
155/* Like schedule_timeout_killable(), but should not block the freezer. */ 180/* Like schedule_timeout_killable(), but should not block the freezer. */
156#define freezable_schedule_timeout_killable(timeout) \ 181#define freezable_schedule_timeout_killable(timeout) \
157({ \ 182({ \
@@ -162,6 +187,16 @@ static inline bool freezer_should_skip(struct task_struct *p)
162 __retval; \ 187 __retval; \
163}) 188})
164 189
190/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */
191#define freezable_schedule_timeout_killable_unsafe(timeout) \
192({ \
193 long __retval; \
194 freezer_do_not_count(); \
195 __retval = schedule_timeout_killable(timeout); \
196 freezer_count_unsafe(); \
197 __retval; \
198})
199
165/* 200/*
166 * Freezer-friendly wrappers around wait_event_interruptible(), 201 * Freezer-friendly wrappers around wait_event_interruptible(),
167 * wait_event_killable() and wait_event_interruptible_timeout(), originally 202 * wait_event_killable() and wait_event_interruptible_timeout(), originally
@@ -225,9 +260,14 @@ static inline void set_freezable(void) {}
225 260
226#define freezable_schedule() schedule() 261#define freezable_schedule() schedule()
227 262
263#define freezable_schedule_unsafe() schedule()
264
228#define freezable_schedule_timeout_killable(timeout) \ 265#define freezable_schedule_timeout_killable(timeout) \
229 schedule_timeout_killable(timeout) 266 schedule_timeout_killable(timeout)
230 267
268#define freezable_schedule_timeout_killable_unsafe(timeout) \
269 schedule_timeout_killable(timeout)
270
231#define wait_event_freezable(wq, condition) \ 271#define wait_event_freezable(wq, condition) \
232 wait_event_interruptible(wq, condition) 272 wait_event_interruptible(wq, condition)
233 273