[RFC][PATCH 2/2] Freezer: Try to handle killable tasks

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Rafael J. Wysocki <rjw@xxxxxxx>

The introduction of TASK_KILLABLE allows the freezer to work in some situation
that it could not handle before.

Make the freezer handle killable tasks and add try_to_freeze() in some places
where it is safe to freeze a (killable) task.  Introduce the
wait_event_killable_freezable() macro to be used wherever the freezing of
a waiting killable task is desirable.

Signed-off-by: Rafael J. Wysocki <rjw@xxxxxxx>
---
 fs/nfs/inode.c          |    2 ++
 fs/nfs/nfs3proc.c       |    2 ++
 fs/nfs/nfs4proc.c       |    4 ++++
 fs/nfs/pagelist.c       |    8 ++++++--
 fs/smbfs/request.c      |    2 ++
 include/linux/freezer.h |   20 +++++++++++++++++---
 kernel/mutex.c          |    3 +++
 kernel/power/process.c  |    6 ++++--
 kernel/sched.c          |    2 ++
 net/sunrpc/sched.c      |    2 ++
 10 files changed, 44 insertions(+), 7 deletions(-)

Index: linux-2.6/fs/nfs/nfs3proc.c
===================================================================
--- linux-2.6.orig/fs/nfs/nfs3proc.c
+++ linux-2.6/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"
@@ -33,6 +34,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, 
 		if (res != -EJUKEBOX)
 			break;
 		schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME);
+		try_to_freeze();
 		res = -ERESTARTSYS;
 	} while (!fatal_signal_pending(current));
 	return res;
Index: linux-2.6/fs/nfs/nfs4proc.c
===================================================================
--- linux-2.6.orig/fs/nfs/nfs4proc.c
+++ linux-2.6/fs/nfs/nfs4proc.c
@@ -48,6 +48,7 @@
 #include <linux/smp_lock.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
+#include <linux/freezer.h>
 
 #include "nfs4_fs.h"
 #include "delegation.h"
@@ -2788,6 +2789,7 @@ static int nfs4_wait_bit_killable(void *
 	if (fatal_signal_pending(current))
 		return -ERESTARTSYS;
 	schedule();
+	try_to_freeze();
 	return 0;
 }
 
@@ -2819,6 +2821,8 @@ static int nfs4_delay(struct rpc_clnt *c
 	schedule_timeout_killable(*timeout);
 	if (fatal_signal_pending(current))
 		res = -ERESTARTSYS;
+	else
+		try_to_freeze();
 	*timeout <<= 1;
 	return res;
 }
Index: linux-2.6/fs/nfs/pagelist.c
===================================================================
--- linux-2.6.orig/fs/nfs/pagelist.c
+++ linux-2.6/fs/nfs/pagelist.c
@@ -18,6 +18,7 @@
 #include <linux/nfs_page.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_mount.h>
+#include <linux/freezer.h>
 
 #include "internal.h"
 
@@ -68,6 +69,7 @@ nfs_create_request(struct nfs_open_conte
 
 		if (fatal_signal_pending(current))
 			return ERR_PTR(-ERESTARTSYS);
+		try_to_freeze();
 		yield();
 	}
 
@@ -180,10 +182,12 @@ static int nfs_wait_bit_killable(void *w
 {
 	int ret = 0;
 
-	if (fatal_signal_pending(current))
+	if (fatal_signal_pending(current)) {
 		ret = -ERESTARTSYS;
-	else
+	} else {
 		schedule();
+		try_to_freeze();
+	}
 	return ret;
 }
 
Index: linux-2.6/fs/smbfs/request.c
===================================================================
--- linux-2.6.orig/fs/smbfs/request.c
+++ linux-2.6/fs/smbfs/request.c
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/net.h>
 #include <linux/sched.h>
+#include <linux/freezer.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smbno.h>
@@ -109,6 +110,7 @@ struct smb_request *smb_alloc_request(st
 			return ERR_PTR(-ERESTARTSYS);
 		current->policy = SCHED_YIELD;
 		schedule();
+		try_to_freeze();
 #else
 		/* FIXME: we want something like nfs does above, but that
 		   requires changes to all callers and can wait. */
Index: linux-2.6/include/linux/freezer.h
===================================================================
--- linux-2.6.orig/include/linux/freezer.h
+++ linux-2.6/include/linux/freezer.h
@@ -137,8 +137,9 @@ static inline void set_freezable_with_si
 }
 
 /*
- * 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_interruptible_timeout(), wait_event_killable(),
+ * originally defined in <linux/wait.h>
  */
 
 #define wait_event_freezable(wq, condition)				\
@@ -155,7 +156,6 @@ static inline void set_freezable_with_si
 	__retval;							\
 })
 
-
 #define wait_event_freezable_timeout(wq, condition, timeout)		\
 ({									\
 	long __retval = timeout;					\
@@ -166,6 +166,20 @@ static inline void set_freezable_with_si
 	} while (try_to_freeze());					\
 	__retval;							\
 })
+
+#define wait_event_killable_freezable(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;							\
+})
 #else /* !CONFIG_PM_SLEEP */
 static inline int frozen(struct task_struct *p) { return 0; }
 static inline int freezing(struct task_struct *p) { return 0; }
Index: linux-2.6/kernel/mutex.c
===================================================================
--- linux-2.6.orig/kernel/mutex.c
+++ linux-2.6/kernel/mutex.c
@@ -18,6 +18,7 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/debug_locks.h>
+#include <linux/freezer.h>
 
 /*
  * In the DEBUG case we are using the "NULL fastpath" for mutexes,
@@ -182,6 +183,8 @@ __mutex_lock_common(struct mutex *lock, 
 		/* didnt get the lock, go to sleep: */
 		spin_unlock_mutex(&lock->wait_lock, flags);
 		schedule();
+		if (state == TASK_KILLABLE)
+			try_to_freeze();
 		spin_lock_mutex(&lock->wait_lock, flags);
 	}
 
Index: linux-2.6/kernel/sched.c
===================================================================
--- linux-2.6.orig/kernel/sched.c
+++ linux-2.6/kernel/sched.c
@@ -4769,6 +4769,8 @@ do_wait_for_common(struct completion *x,
 			__set_current_state(state);
 			spin_unlock_irq(&x->wait.lock);
 			timeout = schedule_timeout(timeout);
+			if (state == TASK_KILLABLE)
+				try_to_freeze();
 			spin_lock_irq(&x->wait.lock);
 			if (!timeout) {
 				__remove_wait_queue(&x->wait, &wait);
Index: linux-2.6/net/sunrpc/sched.c
===================================================================
--- linux-2.6.orig/net/sunrpc/sched.c
+++ linux-2.6/net/sunrpc/sched.c
@@ -19,6 +19,7 @@
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
+#include <linux/freezer.h>
 
 #include <linux/sunrpc/clnt.h>
 
@@ -227,6 +228,7 @@ static int rpc_wait_bit_killable(void *w
 	if (fatal_signal_pending(current))
 		return -ERESTARTSYS;
 	schedule();
+	try_to_freeze();
 	return 0;
 }
 
Index: linux-2.6/fs/nfs/inode.c
===================================================================
--- linux-2.6.orig/fs/nfs/inode.c
+++ linux-2.6/fs/nfs/inode.c
@@ -37,6 +37,7 @@
 #include <linux/vfs.h>
 #include <linux/inet.h>
 #include <linux/nfs_xdr.h>
+#include <linux/freezer.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -426,6 +427,7 @@ static int nfs_wait_schedule(void *word)
 	if (signal_pending(current))
 		return -ERESTARTSYS;
 	schedule();
+	try_to_freeze();
 	return 0;
 }
 
Index: linux-2.6/kernel/power/process.c
===================================================================
--- linux-2.6.orig/kernel/power/process.c
+++ linux-2.6/kernel/power/process.c
@@ -77,7 +77,9 @@ static void fake_signal_wake_up(struct t
 	unsigned long flags;
 
 	spin_lock_irqsave(&p->sighand->siglock, flags);
-	signal_wake_up(p, 0);
+	set_tsk_thread_flag(p, TIF_SIGPENDING);
+	if (!wake_up_state(p, TASK_INTERRUPTIBLE | TASK_KILLABLE))
+		kick_process(p);
 	spin_unlock_irqrestore(&p->sighand->siglock, flags);
 }
 
@@ -124,7 +126,7 @@ static bool freeze_task(struct task_stru
 	} else if (sig_only) {
 		return false;
 	} else {
-		wake_up_state(p, TASK_INTERRUPTIBLE);
+		wake_up_state(p, TASK_INTERRUPTIBLE | TASK_KILLABLE);
 	}
 
 	return true;
_______________________________________________
linux-pm mailing list
linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux