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

Josh Boyer jwboyer at fedoraproject.org
Thu Dec 15 15:55:51 UTC 2011


commit 504b3ab58dc196aad81f68e697d39da568277726
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              |    9 ++
 nfs-client-freezer.patch |  299 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 308 insertions(+), 0 deletions(-)
---
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 <jwboyer at redhat.com>
+- Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735)
+
 * Thu Dec 15 2011 Dave Jones <davej at redhat.com> - 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 <linux/wait.h>
+ #include <linux/net.h>
+ #include <linux/delay.h>
++#include <linux/freezer.h>
+ #include <asm/uaccess.h>
+ #include <asm/processor.h>
+ #include <linux/mempool.h>
+@@ -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 <linux/wait.h>
++ * Freezer-friendly wrappers around wait_event_interruptible(),
++ * wait_event_killable() and wait_event_interruptible_timeout(), originally
++ * defined in <linux/wait.h>
+  */
+ 
++#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 <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"
+@@ -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 <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	
+@@ -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 <linux/wait.h>
+@@ -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 <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	
+@@ -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();						\
+ })


More information about the scm-commits mailing list