freezer: add unsafe versions of freezable helpers for CIFS
authorColin Cross <ccross@android.com>
Tue, 7 May 2013 17:52:05 +0000 (17:52 +0000)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Sun, 12 May 2013 12:16:21 +0000 (14:16 +0200)
CIFS calls wait_event_freezekillable_unsafe with a VFS lock 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).  CIFS shouldn't be doing this, but
it has long-running syscalls that must hold a lock but also
shouldn't block suspend.  Until CIFS freeze handling is rewritten
to use a signal to exit out of the critical section, add a new
wait_event_freezekillable_unsafe helper that will not run the
lockdep test when 6aa9707 is reapplied, and call it from CIFS.

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.

Acked-by: Pavel Machek <pavel@ucw.cz>
Acked-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Colin Cross <ccross@android.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
fs/cifs/transport.c
include/linux/freezer.h

index bfbf4700d160f8a4d54f7cc0446a35c4de8c747d..b70aa7c913940c3766263b67e564a053883f9f32 100644 (file)
@@ -447,7 +447,7 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
 {
        int error;
 
-       error = wait_event_freezekillable(server->response_q,
+       error = wait_event_freezekillable_unsafe(server->response_q,
                                    midQ->mid_state != MID_REQUEST_SUBMITTED);
        if (error < 0)
                return -ERESTARTSYS;
index 5b31e21c485f4ac7ecf5cd6b43cbdece997ca5f1..d3c038ec9a88051c3ed1b71dcd3941ef9951d50d 100644 (file)
@@ -212,6 +212,16 @@ static inline bool freezer_should_skip(struct task_struct *p)
        __retval;                                                       \
 })
 
+/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */
+#define wait_event_freezekillable_unsafe(wq, condition)                        \
+({                                                                     \
+       int __retval;                                                   \
+       freezer_do_not_count();                                         \
+       __retval = wait_event_killable(wq, (condition));                \
+       freezer_count_unsafe();                                         \
+       __retval;                                                       \
+})
+
 #define wait_event_freezable(wq, condition)                            \
 ({                                                                     \
        int __retval;                                                   \
@@ -277,6 +287,9 @@ static inline void set_freezable(void) {}
 #define wait_event_freezekillable(wq, condition)               \
                wait_event_killable(wq, condition)
 
+#define wait_event_freezekillable_unsafe(wq, condition)                        \
+               wait_event_killable(wq, condition)
+
 #endif /* !CONFIG_FREEZER */
 
 #endif /* FREEZER_H_INCLUDED */