diff options
| author | Jeff Layton <jlayton@redhat.com> | 2011-12-01 22:44:39 +0100 | 
|---|---|---|
| committer | Rafael J. Wysocki <rjw@sisk.pl> | 2011-12-06 22:12:27 +0100 | 
| commit | d310310cbff18ec385c6ab4d58f33b100192a96a (patch) | |
| tree | 801dbbef1552256e7cefc7ec08dcd41b30a9930b | |
| parent | 62c9ea6b120688d800b4d892eaf737c20a73e86b (diff) | |
| download | olio-linux-3.10-d310310cbff18ec385c6ab4d58f33b100192a96a.tar.xz olio-linux-3.10-d310310cbff18ec385c6ab4d58f33b100192a96a.zip  | |
Freezer / sunrpc / NFS: don't allow TASK_KILLABLE sleeps to block the freezer
Allow the freezer to skip wait_on_bit_killable sleeps in the sunrpc
layer. This should allow suspend and hibernate events to proceed, even
when there are RPC's pending on the wire.
Also, wrap the TASK_KILLABLE sleeps in NFS layer in freezer_do_not_count
and freezer_count calls. This allows the freezer to skip tasks that are
sleeping while looping on EJUKEBOX or NFS4ERR_DELAY sorts of errors.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
| -rw-r--r-- | fs/nfs/inode.c | 3 | ||||
| -rw-r--r-- | fs/nfs/nfs3proc.c | 3 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 5 | ||||
| -rw-r--r-- | fs/nfs/proc.c | 3 | ||||
| -rw-r--r-- | include/linux/freezer.h | 28 | ||||
| -rw-r--r-- | net/sunrpc/sched.c | 3 | 
6 files changed, 39 insertions, 6 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 50a15fa8cf9..bf3a57bbbfc 100644 --- a/fs/nfs/inode.c +++ b/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;  } diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index d4bc9ed9174..91943953a37 100644 --- a/fs/nfs/nfs3proc.c +++ b/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; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index be2bbac1381..b28bb19b04f 100644 --- a/fs/nfs/nfs4proc.c +++ b/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; diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index f48125da198..0c672588fe5 100644 --- a/fs/nfs/proc.c +++ b/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; diff --git a/include/linux/freezer.h b/include/linux/freezer.h index c1ee2833655..30f06c22046 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h @@ -105,6 +105,29 @@ static inline int freezer_should_skip(struct task_struct *p)  }  /* + * 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> @@ -163,6 +186,11 @@ static inline void freezer_count(void) {}  static inline int freezer_should_skip(struct task_struct *p) { return 0; }  static inline void set_freezable(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) diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index d12ffa54581..5317b9341b5 100644 --- a/net/sunrpc/sched.c +++ b/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;  }  |