summaryrefslogtreecommitdiffstats
path: root/nfs-client-freezer.patch
diff options
context:
space:
mode:
authorJosh Boyer <jwboyer@redhat.com>2011-12-08 10:14:55 -0500
committerJosh Boyer <jwboyer@redhat.com>2011-12-08 10:14:55 -0500
commit9f7d284a10af2b8d633628b57781b58f43cb0766 (patch)
treee0c132ad202b58ded088584f3c0b4e74d010f6c4 /nfs-client-freezer.patch
parente29397a0ab3fac4a32e8f51a92cff8ff108a77c2 (diff)
downloadkernel-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.patch197
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(); \
+ })