diff options
author | Josh Boyer <jwboyer@redhat.com> | 2011-12-08 10:14:55 -0500 |
---|---|---|
committer | Josh Boyer <jwboyer@redhat.com> | 2011-12-08 10:14:55 -0500 |
commit | 9f7d284a10af2b8d633628b57781b58f43cb0766 (patch) | |
tree | e0c132ad202b58ded088584f3c0b4e74d010f6c4 /nfs-client-freezer.patch | |
parent | e29397a0ab3fac4a32e8f51a92cff8ff108a77c2 (diff) | |
download | kernel-9f7d284a10af2b8d633628b57781b58f43cb0766.tar.gz kernel-9f7d284a10af2b8d633628b57781b58f43cb0766.tar.xz kernel-9f7d284a10af2b8d633628b57781b58f43cb0766.zip |
Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735)
Diffstat (limited to 'nfs-client-freezer.patch')
-rw-r--r-- | nfs-client-freezer.patch | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/nfs-client-freezer.patch b/nfs-client-freezer.patch new file mode 100644 index 000000000..5f5b0836e --- /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 <linux/nfs_xdr.h> + #include <linux/slab.h> + #include <linux/compat.h> ++#include <linux/freezer.h> + + #include <asm/system.h> + #include <asm/uaccess.h> +@@ -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 <linux/nfs_page.h> + #include <linux/lockd/bind.h> + #include <linux/nfs_mount.h> ++#include <linux/freezer.h> + + #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 <linux/sunrpc/bc_xprt.h> + #include <linux/xattr.h> + #include <linux/utsname.h> ++#include <linux/freezer.h> + + #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 <linux/nfs_fs.h> + #include <linux/nfs_page.h> + #include <linux/lockd/bind.h> ++#include <linux/freezer.h> + #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 <linux/wait.h> +@@ -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 <linux/smp.h> + #include <linux/spinlock.h> + #include <linux/mutex.h> ++#include <linux/freezer.h> + + #include <linux/sunrpc/clnt.h> + +@@ -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(); \ + }) |