diff --git a/kernel.spec b/kernel.spec index 0099e9e..57a348e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -731,6 +731,9 @@ Patch21030: alps.patch # rhbz 736815 Patch21040: x86-code-dump-fix-truncation.patch +#rhbz 717735 +Patch21045: nfs-client-freezer.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-add-module_usb_driver-and-module_platform_driver.patch @@ -1411,6 +1414,9 @@ ApplyPatch alps.patch # rhbz 736815 ApplyPatch x86-code-dump-fix-truncation.patch +#rhbz 717735 +ApplyPatch nfs-client-freezer.patch + # END OF PATCH APPLICATIONS %endif @@ -2219,6 +2225,9 @@ fi # ||----w | # || || %changelog +* Thu Dec 08 2011 Josh Boyer +- Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735) + * Wed Dec 07 2011 Dave Jones - 3.2.0-0.rc4.git5.2 - Linux 3.2-rc4-git5 (77a7300abad7fe01891b400e88d746f97307ee5a) diff --git a/nfs-client-freezer.patch b/nfs-client-freezer.patch new file mode 100644 index 0000000..5f5b083 --- /dev/null +++ b/nfs-client-freezer.patch @@ -0,0 +1,197 @@ +@@ -, +, @@ + 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" +@@ -241,7 +242,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; +@@ -3950,7 +3951,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 +@@ -135,6 +135,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 +@@ -194,6 +217,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 +@@ -141,18 +141,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(); \ + })