From 504b3ab58dc196aad81f68e697d39da568277726 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Dec 15 2011 15:11:53 +0000 Subject: Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735) --- diff --git a/kernel.spec b/kernel.spec index 77c3d3b..675487d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -709,6 +709,9 @@ Patch21225: pci-Rework-ASPM-disable-code.patch #rhbz #757839 Patch21230: net-sky2-88e8059-fix-link-speed.patch +#rhbz 717735 +Patch21045: nfs-client-freezer.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1312,6 +1315,9 @@ ApplyPatch pci-Rework-ASPM-disable-code.patch #rhbz #757839 ApplyPatch net-sky2-88e8059-fix-link-speed.patch +#rhbz 717735 +ApplyPatch nfs-client-freezer.patch + # END OF PATCH APPLICATIONS %endif @@ -1959,6 +1965,9 @@ fi # and build. %changelog +* Thu Dec 15 2011 Josh Boyer +- Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735) + * Thu Dec 15 2011 Dave Jones - 2.6.41.5-3 - Disable Intel IOMMU by default. diff --git a/nfs-client-freezer.patch b/nfs-client-freezer.patch new file mode 100644 index 0000000..6b4d34d --- /dev/null +++ b/nfs-client-freezer.patch @@ -0,0 +1,299 @@ +@@ -, +, @@ + fs/cifs/transport.c | 3 ++- + include/linux/freezer.h | 19 +++++++++++++++++-- + 2 files changed, 19 insertions(+), 3 deletions(-) +--- a/fs/cifs/transport.c ++++ a/fs/cifs/transport.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -324,7 +325,7 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) + { + int error; + +- error = wait_event_killable(server->response_q, ++ error = wait_event_freezekillable(server->response_q, + midQ->midState != MID_REQUEST_SUBMITTED); + if (error < 0) + return -ERESTARTSYS; +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -134,10 +134,25 @@ static inline void set_freezable_with_signal(void) + } + + /* +- * Freezer-friendly wrappers around wait_event_interruptible() and +- * wait_event_interruptible_timeout(), originally defined in ++ * Freezer-friendly wrappers around wait_event_interruptible(), ++ * wait_event_killable() and wait_event_interruptible_timeout(), originally ++ * defined in + */ + ++#define wait_event_freezekillable(wq, condition) \ ++({ \ ++ int __retval; \ ++ do { \ ++ __retval = wait_event_killable(wq, \ ++ (condition) || freezing(current)); \ ++ if (__retval && !freezing(current)) \ ++ break; \ ++ else if (!(condition)) \ ++ __retval = -ERESTARTSYS; \ ++ } while (try_to_freeze()); \ ++ __retval; \ ++}) ++ + #define wait_event_freezable(wq, condition) \ + ({ \ + int __retval; \ + include/linux/freezer.h | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -143,7 +143,7 @@ static inline void set_freezable_with_signal(void) + ({ \ + int __retval; \ + do { \ +- __retval = wait_event_killable(wq, \ ++ __retval = wait_event_killable(wq, \ + (condition) || freezing(current)); \ + if (__retval && !freezing(current)) \ + break; \ + include/linux/freezer.h | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -203,6 +203,9 @@ static inline void set_freezable_with_signal(void) {} + #define wait_event_freezable_timeout(wq, condition, timeout) \ + wait_event_interruptible_timeout(wq, condition, timeout) + ++#define wait_event_freezekillable(wq, condition) \ ++ wait_event_killable(wq, condition) ++ + #endif /* !CONFIG_FREEZER */ + + #endif /* FREEZER_H_INCLUDED */ + description on Rafael's request.] + include/linux/freezer.h | 11 +++-------- + 1 files changed, 3 insertions(+), 8 deletions(-) +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -142,14 +142,9 @@ static inline void set_freezable_with_signal(void) + #define wait_event_freezekillable(wq, condition) \ + ({ \ + int __retval; \ +- do { \ +- __retval = wait_event_killable(wq, \ +- (condition) || freezing(current)); \ +- if (__retval && !freezing(current)) \ +- break; \ +- else if (!(condition)) \ +- __retval = -ERESTARTSYS; \ +- } while (try_to_freeze()); \ ++ freezer_do_not_count(); \ ++ __retval = wait_event_killable(wq, (condition)); \ ++ freezer_count(); \ + __retval; \ + }) + + fs/nfs/inode.c | 3 ++- + fs/nfs/nfs3proc.c | 3 ++- + fs/nfs/nfs4proc.c | 5 +++-- + fs/nfs/proc.c | 3 ++- + include/linux/freezer.h | 28 ++++++++++++++++++++++++++++ + net/sunrpc/sched.c | 3 ++- + 6 files changed, 39 insertions(+), 6 deletions(-) +--- a/fs/nfs/inode.c ++++ a/fs/nfs/inode.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -77,7 +78,7 @@ int nfs_wait_bit_killable(void *word) + { + if (fatal_signal_pending(current)) + return -ERESTARTSYS; +- schedule(); ++ freezable_schedule(); + return 0; + } + +--- a/fs/nfs/nfs3proc.c ++++ a/fs/nfs/nfs3proc.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + #include "iostat.h" + #include "internal.h" +@@ -32,7 +33,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) + res = rpc_call_sync(clnt, msg, flags); + if (res != -EJUKEBOX && res != -EKEYEXPIRED) + break; +- schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); ++ freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); + res = -ERESTARTSYS; + } while (!fatal_signal_pending(current)); + return res; +--- a/fs/nfs/nfs4proc.c ++++ a/fs/nfs/nfs4proc.c +@@ -53,6 +53,7 @@ + #include + #include + #include ++#include + + #include "nfs4_fs.h" + #include "delegation.h" +@@ -244,7 +245,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) + *timeout = NFS4_POLL_RETRY_MIN; + if (*timeout > NFS4_POLL_RETRY_MAX) + *timeout = NFS4_POLL_RETRY_MAX; +- schedule_timeout_killable(*timeout); ++ freezable_schedule_timeout_killable(*timeout); + if (fatal_signal_pending(current)) + res = -ERESTARTSYS; + *timeout <<= 1; +@@ -3970,7 +3971,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 + static unsigned long + nfs4_set_lock_task_retry(unsigned long timeout) + { +- schedule_timeout_killable(timeout); ++ freezable_schedule_timeout_killable(timeout); + timeout <<= 1; + if (timeout > NFS4_LOCK_MAXTIMEOUT) + return NFS4_LOCK_MAXTIMEOUT; +--- a/fs/nfs/proc.c ++++ a/fs/nfs/proc.c +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + #include "internal.h" + + #define NFSDBG_FACILITY NFSDBG_PROC +@@ -59,7 +60,7 @@ nfs_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) + res = rpc_call_sync(clnt, msg, flags); + if (res != -EKEYEXPIRED) + break; +- schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); ++ freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); + res = -ERESTARTSYS; + } while (!fatal_signal_pending(current)); + return res; +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -134,6 +134,29 @@ static inline void set_freezable_with_signal(void) + } + + /* ++ * These macros are intended to be used whenever you want allow a task that's ++ * sleeping in TASK_UNINTERRUPTIBLE or TASK_KILLABLE state to be frozen. Note ++ * that neither return any clear indication of whether a freeze event happened ++ * while in this function. ++ */ ++ ++/* Like schedule(), but should not block the freezer. */ ++#define freezable_schedule() \ ++({ \ ++ freezer_do_not_count(); \ ++ schedule(); \ ++ freezer_count(); \ ++}) ++ ++/* Like schedule_timeout_killable(), but should not block the freezer. */ ++#define freezable_schedule_timeout_killable(timeout) \ ++({ \ ++ freezer_do_not_count(); \ ++ schedule_timeout_killable(timeout); \ ++ freezer_count(); \ ++}) ++ ++/* + * Freezer-friendly wrappers around wait_event_interruptible(), + * wait_event_killable() and wait_event_interruptible_timeout(), originally + * defined in +@@ -192,6 +215,11 @@ static inline int freezer_should_skip(struct task_struct *p) { return 0; } + static inline void set_freezable(void) {} + static inline void set_freezable_with_signal(void) {} + ++#define freezable_schedule() schedule() ++ ++#define freezable_schedule_timeout_killable(timeout) \ ++ schedule_timeout_killable(timeout) ++ + #define wait_event_freezable(wq, condition) \ + wait_event_interruptible(wq, condition) + +--- a/net/sunrpc/sched.c ++++ a/net/sunrpc/sched.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include + +@@ -231,7 +232,7 @@ static int rpc_wait_bit_killable(void *word) + { + if (fatal_signal_pending(current)) + return -ERESTARTSYS; +- schedule(); ++ freezable_schedule(); + return 0; + } + + include/linux/freezer.h | 21 ++++++++++++++++++--- + 1 files changed, 18 insertions(+), 3 deletions(-) +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -140,18 +140,33 @@ static inline void set_freezable_with_signal(void) + * while in this function. + */ + +-/* Like schedule(), but should not block the freezer. */ ++/* ++ * Like schedule(), but should not block the freezer. It may return immediately ++ * if it ends up racing with the freezer. Callers must be able to deal with ++ * spurious wakeups. ++ */ + #define freezable_schedule() \ + ({ \ + freezer_do_not_count(); \ +- schedule(); \ ++ if (!try_to_freeze()) \ ++ schedule(); \ + freezer_count(); \ + }) + +-/* Like schedule_timeout_killable(), but should not block the freezer. */ ++/* ++ * Like schedule_timeout_killable(), but should not block the freezer. It may ++ * end up returning immediately if it ends up racing with the freezer. Callers ++ * must be able to deal with the loose wakeup timing that can occur when the ++ * freezer races in. When that occurs, this function will return the timeout ++ * value instead of 0. ++ */ + #define freezable_schedule_timeout_killable(timeout) \ + ({ \ + freezer_do_not_count(); \ ++ if (try_to_freeze()) { \ ++ freezer_count(); \ ++ return timeout; \ ++ } \ + schedule_timeout_killable(timeout); \ + freezer_count(); \ + })