[kernel] Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735)

Josh Boyer jwboyer at fedoraproject.org
Thu Dec 8 15:15:07 UTC 2011


commit 9f7d284a10af2b8d633628b57781b58f43cb0766
Author: Josh Boyer <jwboyer at redhat.com>
Date:   Thu Dec 8 10:14:55 2011 -0500

    Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735)

 kernel.spec              |   11 +++-
 nfs-client-freezer.patch |  197 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 207 insertions(+), 1 deletions(-)
---
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 <jwboyer at redhat.com>
+- Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735)
+
 * Wed Dec 07 2011 Dave Jones <davej at redhat.com> - 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 <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();						\
+ })


More information about the scm-commits mailing list