From 4a6e9e2ce822c9f597b3036887f6cf5fa3a79375 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 30 Aug 2007 16:10:22 -0400 Subject: Use wake_up_locked() in eventpoll Replace the uses of __wake_up_locked with wake_up_locked Signed-off-by: Matthew Wilcox --- fs/eventpoll.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 34f68f3a069a..81c04abfb1aa 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -656,8 +656,7 @@ is_linked: * wait list. */ if (waitqueue_active(&ep->wq)) - __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE | - TASK_INTERRUPTIBLE); + wake_up_locked(&ep->wq); if (waitqueue_active(&ep->poll_wait)) pwake++; @@ -780,7 +779,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, /* Notify waiting tasks that events are available */ if (waitqueue_active(&ep->wq)) - __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE); + wake_up_locked(&ep->wq); if (waitqueue_active(&ep->poll_wait)) pwake++; } @@ -854,8 +853,7 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even /* Notify waiting tasks that events are available */ if (waitqueue_active(&ep->wq)) - __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE | - TASK_INTERRUPTIBLE); + wake_up_locked(&ep->wq); if (waitqueue_active(&ep->poll_wait)) pwake++; } @@ -978,8 +976,7 @@ errxit: * wait list (delayed after we release the lock). */ if (waitqueue_active(&ep->wq)) - __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE | - TASK_INTERRUPTIBLE); + wake_up_locked(&ep->wq); if (waitqueue_active(&ep->poll_wait)) pwake++; } -- cgit From 92a1f4bc7af13949d2185449307088cf98b4755d Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 10:55:25 -0500 Subject: Add macros to replace direct uses of TASK_ flags With the changes to support TASK_KILLABLE, ->state becomes a bitmask, and moving these tests to convenience macros will fix all the users. Signed-off-by: Matthew Wilcox --- include/linux/sched.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/sched.h b/include/linux/sched.h index ac3d496fbd20..69233c7fe28d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -178,6 +178,22 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) /* in tsk->state again */ #define TASK_DEAD 64 +/* Convenience macros for the sake of wake_up */ +#define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE) +#define TASK_ALL (TASK_NORMAL | TASK_STOPPED | TASK_TRACED) + +/* get_task_state() */ +#define TASK_REPORT (TASK_RUNNING | TASK_INTERRUPTIBLE | \ + TASK_UNINTERRUPTIBLE | TASK_STOPPED | \ + TASK_TRACED) + +#define task_is_traced(task) ((task->state & TASK_TRACED) != 0) +#define task_is_stopped(task) ((task->state & TASK_STOPPED) != 0) +#define task_is_stopped_or_traced(task) \ + ((task->state & (TASK_STOPPED | TASK_TRACED)) != 0) +#define task_contributes_to_load(task) \ + ((task->state & TASK_UNINTERRUPTIBLE) != 0) + #define __set_task_state(tsk, state_value) \ do { (tsk)->state = (state_value); } while (0) #define set_task_state(tsk, state_value) \ -- cgit From 21498223daad359d048b35b0ee4d1b93300ef258 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 11:02:55 -0500 Subject: perfmon: Use task_is_* Signed-off-by: Matthew Wilcox --- arch/ia64/kernel/perfmon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 73e7c2e40b54..5ae177f557d8 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -2631,7 +2631,7 @@ pfm_task_incompatible(pfm_context_t *ctx, struct task_struct *task) */ if (task == current) return 0; - if ((task->state != TASK_STOPPED) && (task->state != TASK_TRACED)) { + if (!task_is_stopped_or_traced(task)) { DPRINT(("cannot attach to non-stopped task [%d] state=%ld\n", task_pid_nr(task), task->state)); return -EBUSY; } @@ -4792,7 +4792,7 @@ recheck: * the task must be stopped. */ if (PFM_CMD_STOPPED(cmd)) { - if ((task->state != TASK_STOPPED) && (task->state != TASK_TRACED)) { + if (!task_is_stopped_or_traced(task)) { DPRINT(("[%d] task not in stopped state\n", task_pid_nr(task))); return -EBUSY; } -- cgit From 1587e2b1880632d959db6ac9e79cb1d99a73c656 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 11:03:36 -0500 Subject: proc/array.c: Use TASK_REPORT Signed-off-by: Matthew Wilcox --- fs/proc/array.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/fs/proc/array.c b/fs/proc/array.c index 65c62e1bfd6f..5be663e5dad1 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -141,12 +141,7 @@ static const char *task_state_array[] = { static inline const char *get_task_state(struct task_struct *tsk) { - unsigned int state = (tsk->state & (TASK_RUNNING | - TASK_INTERRUPTIBLE | - TASK_UNINTERRUPTIBLE | - TASK_STOPPED | - TASK_TRACED)) | - tsk->exit_state; + unsigned int state = (tsk->state & TASK_REPORT) | tsk->exit_state; const char **p = &task_state_array[0]; while (state) { -- cgit From 6d8982d9b8f4b771754335f1398e406cc72003c3 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 11:04:01 -0500 Subject: proc/base.c: Use task_is_* Signed-off-by: Matthew Wilcox --- fs/proc/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 02a63ac04178..e88ee1a0323a 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -199,7 +199,7 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf (task == current || \ (task->parent == current && \ (task->ptrace & PT_PTRACED) && \ - (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \ + (task_is_stopped_or_traced(task)) && \ security_ptrace(current,task) == 0)) static int proc_pid_cmdline(struct task_struct *task, char * buffer) -- cgit From e64d66c8edf11629aa203328daf898775ee27dd4 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 17:34:36 -0500 Subject: wait: Use TASK_NORMAL Also move wake_up_locked() to be with the related functions Signed-off-by: Matthew Wilcox --- include/linux/wait.h | 11 ++++++----- kernel/wait.c | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/linux/wait.h b/include/linux/wait.h index 0e686280450b..0a410a449258 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -152,14 +152,15 @@ int FASTCALL(out_of_line_wait_on_bit(void *, int, int (*)(void *), unsigned)); int FASTCALL(out_of_line_wait_on_bit_lock(void *, int, int (*)(void *), unsigned)); wait_queue_head_t *FASTCALL(bit_waitqueue(void *, int)); -#define wake_up(x) __wake_up(x, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1, NULL) -#define wake_up_nr(x, nr) __wake_up(x, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, nr, NULL) -#define wake_up_all(x) __wake_up(x, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 0, NULL) +#define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL) +#define wake_up_nr(x, nr) __wake_up(x, TASK_NORMAL, nr, NULL) +#define wake_up_all(x) __wake_up(x, TASK_NORMAL, 0, NULL) +#define wake_up_locked(x) __wake_up_locked((x), TASK_NORMAL) + #define wake_up_interruptible(x) __wake_up(x, TASK_INTERRUPTIBLE, 1, NULL) #define wake_up_interruptible_nr(x, nr) __wake_up(x, TASK_INTERRUPTIBLE, nr, NULL) #define wake_up_interruptible_all(x) __wake_up(x, TASK_INTERRUPTIBLE, 0, NULL) -#define wake_up_locked(x) __wake_up_locked((x), TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE) -#define wake_up_interruptible_sync(x) __wake_up_sync((x),TASK_INTERRUPTIBLE, 1) +#define wake_up_interruptible_sync(x) __wake_up_sync((x), TASK_INTERRUPTIBLE, 1) #define __wait_event(wq, condition) \ do { \ diff --git a/kernel/wait.c b/kernel/wait.c index 444ddbfaefc4..f9876888a569 100644 --- a/kernel/wait.c +++ b/kernel/wait.c @@ -215,7 +215,7 @@ void fastcall __wake_up_bit(wait_queue_head_t *wq, void *word, int bit) { struct wait_bit_key key = __WAIT_BIT_KEY_INITIALIZER(word, bit); if (waitqueue_active(wq)) - __wake_up(wq, TASK_INTERRUPTIBLE|TASK_UNINTERRUPTIBLE, 1, &key); + __wake_up(wq, TASK_NORMAL, 1, &key); } EXPORT_SYMBOL(__wake_up_bit); -- cgit From d2f60e5faa9aef9a08d0abaee2007e5a0800d2c5 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 11:06:01 -0500 Subject: power: Use task_is_* Signed-off-by: Matthew Wilcox --- kernel/power/process.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/power/process.c b/kernel/power/process.c index 6533923e711b..7c2118f9597f 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -86,9 +86,9 @@ static void fake_signal_wake_up(struct task_struct *p, int resume) static void send_fake_signal(struct task_struct *p) { - if (p->state == TASK_STOPPED) + if (task_is_stopped(p)) force_sig_specific(SIGSTOP, p); - fake_signal_wake_up(p, p->state == TASK_STOPPED); + fake_signal_wake_up(p, task_is_stopped(p)); } static int has_mm(struct task_struct *p) @@ -182,7 +182,7 @@ static int try_to_freeze_tasks(int freeze_user_space) if (frozen(p) || !freezeable(p)) continue; - if (p->state == TASK_TRACED && frozen(p->parent)) { + if (task_is_traced(p) && frozen(p->parent)) { cancel_freezing(p); continue; } -- cgit From 6618a3e275519e10001a2ac4669f46141d4c108b Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 11:06:16 -0500 Subject: ptrace: Use task_is_* Signed-off-by: Matthew Wilcox --- kernel/ptrace.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 7c76f2ffaeaa..26f9923baddc 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -51,7 +51,7 @@ void __ptrace_link(struct task_struct *child, struct task_struct *new_parent) void ptrace_untrace(struct task_struct *child) { spin_lock(&child->sighand->siglock); - if (child->state == TASK_TRACED) { + if (task_is_traced(child)) { if (child->signal->flags & SIGNAL_STOP_STOPPED) { child->state = TASK_STOPPED; } else { @@ -79,7 +79,7 @@ void __ptrace_unlink(struct task_struct *child) add_parent(child); } - if (child->state == TASK_TRACED) + if (task_is_traced(child)) ptrace_untrace(child); } @@ -103,9 +103,9 @@ int ptrace_check_attach(struct task_struct *child, int kill) && child->signal != NULL) { ret = 0; spin_lock_irq(&child->sighand->siglock); - if (child->state == TASK_STOPPED) { + if (task_is_stopped(child)) { child->state = TASK_TRACED; - } else if (child->state != TASK_TRACED && !kill) { + } else if (!task_is_traced(child) && !kill) { ret = -ESRCH; } spin_unlock_irq(&child->sighand->siglock); -- cgit From d9514f6c6b95b5a747ba902858eff577281e8659 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 11:07:07 -0500 Subject: sched: Use task_contributes_to_load, TASK_ALL and TASK_NORMAL Signed-off-by: Matthew Wilcox --- kernel/sched.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 67d9d1799d86..50a0faae585f 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -992,7 +992,7 @@ static int effective_prio(struct task_struct *p) */ static void activate_task(struct rq *rq, struct task_struct *p, int wakeup) { - if (p->state == TASK_UNINTERRUPTIBLE) + if (task_contributes_to_load(p)) rq->nr_uninterruptible--; enqueue_task(rq, p, wakeup); @@ -1004,7 +1004,7 @@ static void activate_task(struct rq *rq, struct task_struct *p, int wakeup) */ static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep) { - if (p->state == TASK_UNINTERRUPTIBLE) + if (task_contributes_to_load(p)) rq->nr_uninterruptible++; dequeue_task(rq, p, sleep); @@ -1646,8 +1646,7 @@ out: int fastcall wake_up_process(struct task_struct *p) { - return try_to_wake_up(p, TASK_STOPPED | TASK_TRACED | - TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE, 0); + return try_to_wake_up(p, TASK_ALL, 0); } EXPORT_SYMBOL(wake_up_process); @@ -3857,8 +3856,7 @@ void complete(struct completion *x) spin_lock_irqsave(&x->wait.lock, flags); x->done++; - __wake_up_common(&x->wait, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, - 1, 0, NULL); + __wake_up_common(&x->wait, TASK_NORMAL, 1, 0, NULL); spin_unlock_irqrestore(&x->wait.lock, flags); } EXPORT_SYMBOL(complete); @@ -3869,8 +3867,7 @@ void complete_all(struct completion *x) spin_lock_irqsave(&x->wait.lock, flags); x->done += UINT_MAX/2; - __wake_up_common(&x->wait, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, - 0, 0, NULL); + __wake_up_common(&x->wait, TASK_NORMAL, 0, 0, NULL); spin_unlock_irqrestore(&x->wait.lock, flags); } EXPORT_SYMBOL(complete_all); -- cgit From e1abb39c60971590b6580c0d3a12119dcbad9c50 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 11:07:35 -0500 Subject: signal: Use task_is_* Signed-off-by: Matthew Wilcox --- kernel/signal.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c index afa4f781f924..c5a401aa715c 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -838,7 +838,7 @@ static inline int wants_signal(int sig, struct task_struct *p) return 0; if (sig == SIGKILL) return 1; - if (p->state & (TASK_STOPPED | TASK_TRACED)) + if (task_is_stopped_or_traced(p)) return 0; return task_curr(p) || !signal_pending(p); } @@ -1441,7 +1441,7 @@ void do_notify_parent(struct task_struct *tsk, int sig) BUG_ON(sig == -1); /* do_notify_parent_cldstop should have been called instead. */ - BUG_ON(tsk->state & (TASK_STOPPED|TASK_TRACED)); + BUG_ON(task_is_stopped_or_traced(tsk)); BUG_ON(!tsk->ptrace && (tsk->group_leader != tsk || !thread_group_empty(tsk))); @@ -1729,7 +1729,7 @@ static int do_signal_stop(int signr) * so this check has no races. */ if (!t->exit_state && - !(t->state & (TASK_STOPPED|TASK_TRACED))) { + !task_is_stopped_or_traced(t)) { stop_count++; signal_wake_up(t, 0); } -- cgit From 338077e54e17e656da470a84724b773816207316 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 11:09:35 -0500 Subject: exit: Use task_is_* Also restructure the loop in do_wait() Signed-off-by: Matthew Wilcox --- kernel/exit.c | 88 ++++++++++++++++++++++++++--------------------------------- 1 file changed, 39 insertions(+), 49 deletions(-) diff --git a/kernel/exit.c b/kernel/exit.c index 549c0558ba68..bfb1c0e940e8 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -249,7 +249,7 @@ static int has_stopped_jobs(struct pid *pgrp) struct task_struct *p; do_each_pid_task(pgrp, PIDTYPE_PGID, p) { - if (p->state != TASK_STOPPED) + if (!task_is_stopped(p)) continue; retval = 1; break; @@ -614,7 +614,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced) p->parent = p->real_parent; add_parent(p); - if (p->state == TASK_TRACED) { + if (task_is_traced(p)) { /* * If it was at a trace stop, turn it into * a normal stop since it's no longer being @@ -1563,60 +1563,51 @@ repeat: } allowed = 1; - switch (p->state) { - case TASK_TRACED: - /* - * When we hit the race with PTRACE_ATTACH, - * we will not report this child. But the - * race means it has not yet been moved to - * our ptrace_children list, so we need to - * set the flag here to avoid a spurious ECHILD - * when the race happens with the only child. - */ - flag = 1; - if (!my_ptrace_child(p)) - continue; - /*FALLTHROUGH*/ - case TASK_STOPPED: + if (task_is_stopped_or_traced(p)) { /* * It's stopped now, so it might later * continue, exit, or stop again. + * + * When we hit the race with PTRACE_ATTACH, we + * will not report this child. But the race + * means it has not yet been moved to our + * ptrace_children list, so we need to set the + * flag here to avoid a spurious ECHILD when + * the race happens with the only child. */ flag = 1; - if (!(options & WUNTRACED) && - !my_ptrace_child(p)) - continue; + + if (!my_ptrace_child(p)) { + if (task_is_traced(p)) + continue; + if (!(options & WUNTRACED)) + continue; + } + retval = wait_task_stopped(p, ret == 2, - (options & WNOWAIT), - infop, - stat_addr, ru); + (options & WNOWAIT), infop, + stat_addr, ru); if (retval == -EAGAIN) goto repeat; if (retval != 0) /* He released the lock. */ goto end; - break; - default: - // case EXIT_DEAD: - if (p->exit_state == EXIT_DEAD) + } else if (p->exit_state == EXIT_DEAD) { + continue; + } else if (p->exit_state == EXIT_ZOMBIE) { + /* + * Eligible but we cannot release it yet: + */ + if (ret == 2) + goto check_continued; + if (!likely(options & WEXITED)) continue; - // case EXIT_ZOMBIE: - if (p->exit_state == EXIT_ZOMBIE) { - /* - * Eligible but we cannot release - * it yet: - */ - if (ret == 2) - goto check_continued; - if (!likely(options & WEXITED)) - continue; - retval = wait_task_zombie( - p, (options & WNOWAIT), - infop, stat_addr, ru); - /* He released the lock. */ - if (retval != 0) - goto end; - break; - } + retval = wait_task_zombie(p, + (options & WNOWAIT), infop, + stat_addr, ru); + /* He released the lock. */ + if (retval != 0) + goto end; + } else { check_continued: /* * It's running now, so it might later @@ -1625,12 +1616,11 @@ check_continued: flag = 1; if (!unlikely(options & WCONTINUED)) continue; - retval = wait_task_continued( - p, (options & WNOWAIT), - infop, stat_addr, ru); + retval = wait_task_continued(p, + (options & WNOWAIT), infop, + stat_addr, ru); if (retval != 0) /* He released the lock. */ goto end; - break; } } if (!flag) { -- cgit From f021a3c2b14d0dd082c2cee890c204d9e1dee52b Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 11:13:16 -0500 Subject: Add TASK_WAKEKILL Set TASK_WAKEKILL for TASK_STOPPED and TASK_TRACED, add TASK_KILLABLE and use TASK_WAKEKILL in signal_wake_up() Signed-off-by: Matthew Wilcox --- include/linux/sched.h | 22 ++++++++++++++-------- kernel/signal.c | 8 ++++---- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 69233c7fe28d..70d87f2fd23e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -170,27 +170,33 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 #define TASK_UNINTERRUPTIBLE 2 -#define TASK_STOPPED 4 -#define TASK_TRACED 8 +#define __TASK_STOPPED 4 +#define __TASK_TRACED 8 /* in tsk->exit_state */ #define EXIT_ZOMBIE 16 #define EXIT_DEAD 32 /* in tsk->state again */ #define TASK_DEAD 64 +#define TASK_WAKEKILL 128 + +/* Convenience macros for the sake of set_task_state */ +#define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE) +#define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED) +#define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED) /* Convenience macros for the sake of wake_up */ #define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE) -#define TASK_ALL (TASK_NORMAL | TASK_STOPPED | TASK_TRACED) +#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED) /* get_task_state() */ #define TASK_REPORT (TASK_RUNNING | TASK_INTERRUPTIBLE | \ - TASK_UNINTERRUPTIBLE | TASK_STOPPED | \ - TASK_TRACED) + TASK_UNINTERRUPTIBLE | __TASK_STOPPED | \ + __TASK_TRACED) -#define task_is_traced(task) ((task->state & TASK_TRACED) != 0) -#define task_is_stopped(task) ((task->state & TASK_STOPPED) != 0) +#define task_is_traced(task) ((task->state & __TASK_TRACED) != 0) +#define task_is_stopped(task) ((task->state & __TASK_STOPPED) != 0) #define task_is_stopped_or_traced(task) \ - ((task->state & (TASK_STOPPED | TASK_TRACED)) != 0) + ((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0) #define task_contributes_to_load(task) \ ((task->state & TASK_UNINTERRUPTIBLE) != 0) diff --git a/kernel/signal.c b/kernel/signal.c index c5a401aa715c..fd4797f30628 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -456,15 +456,15 @@ void signal_wake_up(struct task_struct *t, int resume) set_tsk_thread_flag(t, TIF_SIGPENDING); /* - * For SIGKILL, we want to wake it up in the stopped/traced case. - * We don't check t->state here because there is a race with it + * For SIGKILL, we want to wake it up in the stopped/traced/killable + * case. We don't check t->state here because there is a race with it * executing another processor and just now entering stopped state. * By using wake_up_state, we ensure the process will wake up and * handle its death signal. */ mask = TASK_INTERRUPTIBLE; if (resume) - mask |= TASK_STOPPED | TASK_TRACED; + mask |= TASK_WAKEKILL; if (!wake_up_state(t, mask)) kick_process(t); } @@ -620,7 +620,7 @@ static void handle_stop_signal(int sig, struct task_struct *p) * Wake up the stopped thread _after_ setting * TIF_SIGPENDING */ - state = TASK_STOPPED; + state = __TASK_STOPPED; if (sig_user_defined(t, SIGCONT) && !sigismember(&t->blocked, SIGCONT)) { set_tsk_thread_flag(t, TIF_SIGPENDING); state |= TASK_INTERRUPTIBLE; -- cgit From f776d12dd16da1b0cd55a1240002c1b31f315d5d Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 11:15:50 -0500 Subject: Add fatal_signal_pending Like signal_pending, but it's only true for signals which are fatal to this process Signed-off-by: Matthew Wilcox --- include/linux/sched.h | 9 ++++++++- kernel/signal.c | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 70d87f2fd23e..95395c143bab 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1872,7 +1872,14 @@ static inline int signal_pending(struct task_struct *p) { return unlikely(test_tsk_thread_flag(p,TIF_SIGPENDING)); } - + +extern int FASTCALL(__fatal_signal_pending(struct task_struct *p)); + +static inline int fatal_signal_pending(struct task_struct *p) +{ + return signal_pending(p) && __fatal_signal_pending(p); +} + static inline int need_resched(void) { return unlikely(test_thread_flag(TIF_NEED_RESCHED)); diff --git a/kernel/signal.c b/kernel/signal.c index fd4797f30628..657aa16d97cb 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -994,6 +994,11 @@ void zap_other_threads(struct task_struct *p) } } +int fastcall __fatal_signal_pending(struct task_struct *tsk) +{ + return sigismember(&tsk->pending.signal, SIGKILL); +} + /* * Must be called under rcu_read_lock() or with tasklist_lock read-held. */ -- cgit From 2687a3569e40b1302f96698bcd6329aeb0ce3dd2 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 11:18:49 -0500 Subject: Add lock_page_killable This routine is like lock_page, but can be interrupted by a fatal signal Signed-off-by: Matthew Wilcox --- include/linux/pagemap.h | 14 ++++++++++++++ mm/filemap.c | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index db8a410ae9e1..4b62a105622b 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -157,6 +157,7 @@ static inline pgoff_t linear_page_index(struct vm_area_struct *vma, } extern void FASTCALL(__lock_page(struct page *page)); +extern int FASTCALL(__lock_page_killable(struct page *page)); extern void FASTCALL(__lock_page_nosync(struct page *page)); extern void FASTCALL(unlock_page(struct page *page)); @@ -170,6 +171,19 @@ static inline void lock_page(struct page *page) __lock_page(page); } +/* + * lock_page_killable is like lock_page but can be interrupted by fatal + * signals. It returns 0 if it locked the page and -EINTR if it was + * killed while waiting. + */ +static inline int lock_page_killable(struct page *page) +{ + might_sleep(); + if (TestSetPageLocked(page)) + return __lock_page_killable(page); + return 0; +} + /* * lock_page_nosync should only be used if we can't pin the page's inode. * Doesn't play quite so well with block device plugging. diff --git a/mm/filemap.c b/mm/filemap.c index 188cf5fd3e8d..ac8f690d2885 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -173,6 +173,12 @@ static int sync_page(void *word) return 0; } +static int sync_page_killable(void *word) +{ + sync_page(word); + return fatal_signal_pending(current) ? -EINTR : 0; +} + /** * __filemap_fdatawrite_range - start writeback on mapping dirty pages in range * @mapping: address space structure to write @@ -577,6 +583,14 @@ void fastcall __lock_page(struct page *page) } EXPORT_SYMBOL(__lock_page); +int fastcall __lock_page_killable(struct page *page) +{ + DEFINE_WAIT_BIT(wait, &page->flags, PG_locked); + + return __wait_on_bit_lock(page_waitqueue(page), &wait, + sync_page_killable, TASK_KILLABLE); +} + /* * Variant of lock_page that does not require the caller to hold a reference * on the page's mapping. -- cgit From 0b94e97a25d9b06ef17fca8da23169200bead1e2 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 11:19:57 -0500 Subject: Use lock_page_killable Replacing lock_page with lock_page_killable in do_generic_mapping_read() allows us to kill `cat' of a file on an NFS-mounted filesystem Signed-off-by: Matthew Wilcox --- mm/filemap.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index ac8f690d2885..455119cc7f40 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -982,7 +982,8 @@ page_ok: page_not_up_to_date: /* Get exclusive access to the page ... */ - lock_page(page); + if (lock_page_killable(page)) + goto readpage_eio; /* Did it get truncated before we got the lock? */ if (!page->mapping) { @@ -1010,7 +1011,8 @@ readpage: } if (!PageUptodate(page)) { - lock_page(page); + if (lock_page_killable(page)) + goto readpage_eio; if (!PageUptodate(page)) { if (page->mapping == NULL) { /* @@ -1021,15 +1023,16 @@ readpage: goto find_page; } unlock_page(page); - error = -EIO; shrink_readahead_size_eio(filp, ra); - goto readpage_error; + goto readpage_eio; } unlock_page(page); } goto page_ok; +readpage_eio: + error = -EIO; readpage_error: /* UHHUH! A synchronous read error occurred. Report it */ desc->error = error; -- cgit From ad776537cc6b4b936cfd11893e7b698dfa072666 Mon Sep 17 00:00:00 2001 From: "Liam R. Howlett" Date: Thu, 6 Dec 2007 17:37:59 -0500 Subject: Add mutex_lock_killable Similar to mutex_lock_interruptible, it can be interrupted by a fatal signal only. Signed-off-by: Liam R. Howlett Acked-by: Ingo Molnar Signed-off-by: Matthew Wilcox --- include/linux/mutex.h | 5 +++++ kernel/mutex.c | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/include/linux/mutex.h b/include/linux/mutex.h index 601479772b98..05c590352dd7 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -125,15 +125,20 @@ static inline int fastcall mutex_is_locked(struct mutex *lock) extern void mutex_lock_nested(struct mutex *lock, unsigned int subclass); extern int __must_check mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass); +extern int __must_check mutex_lock_killable_nested(struct mutex *lock, + unsigned int subclass); #define mutex_lock(lock) mutex_lock_nested(lock, 0) #define mutex_lock_interruptible(lock) mutex_lock_interruptible_nested(lock, 0) +#define mutex_lock_killable(lock) mutex_lock_killable_nested(lock, 0) #else extern void fastcall mutex_lock(struct mutex *lock); extern int __must_check fastcall mutex_lock_interruptible(struct mutex *lock); +extern int __must_check fastcall mutex_lock_killable(struct mutex *lock); # define mutex_lock_nested(lock, subclass) mutex_lock(lock) # define mutex_lock_interruptible_nested(lock, subclass) mutex_lock_interruptible(lock) +# define mutex_lock_killable_nested(lock, subclass) mutex_lock_killable(lock) #endif /* diff --git a/kernel/mutex.c b/kernel/mutex.c index d7fe50cc556f..d9ec9b666250 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -166,9 +166,12 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, * got a signal? (This code gets eliminated in the * TASK_UNINTERRUPTIBLE case.) */ - if (unlikely(state == TASK_INTERRUPTIBLE && - signal_pending(task))) { - mutex_remove_waiter(lock, &waiter, task_thread_info(task)); + if (unlikely((state == TASK_INTERRUPTIBLE && + signal_pending(task)) || + (state == TASK_KILLABLE && + fatal_signal_pending(task)))) { + mutex_remove_waiter(lock, &waiter, + task_thread_info(task)); mutex_release(&lock->dep_map, 1, ip); spin_unlock_mutex(&lock->wait_lock, flags); @@ -210,6 +213,14 @@ mutex_lock_nested(struct mutex *lock, unsigned int subclass) EXPORT_SYMBOL_GPL(mutex_lock_nested); +int __sched +mutex_lock_killable_nested(struct mutex *lock, unsigned int subclass) +{ + might_sleep(); + return __mutex_lock_common(lock, TASK_KILLABLE, subclass, _RET_IP_); +} +EXPORT_SYMBOL_GPL(mutex_lock_killable_nested); + int __sched mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass) { @@ -272,6 +283,9 @@ __mutex_unlock_slowpath(atomic_t *lock_count) * mutex_lock_interruptible() and mutex_trylock(). */ static int fastcall noinline __sched +__mutex_lock_killable_slowpath(atomic_t *lock_count); + +static noinline int fastcall __sched __mutex_lock_interruptible_slowpath(atomic_t *lock_count); /*** @@ -294,6 +308,14 @@ int fastcall __sched mutex_lock_interruptible(struct mutex *lock) EXPORT_SYMBOL(mutex_lock_interruptible); +int fastcall __sched mutex_lock_killable(struct mutex *lock) +{ + might_sleep(); + return __mutex_fastpath_lock_retval + (&lock->count, __mutex_lock_killable_slowpath); +} +EXPORT_SYMBOL(mutex_lock_killable); + static void fastcall noinline __sched __mutex_lock_slowpath(atomic_t *lock_count) { @@ -303,6 +325,14 @@ __mutex_lock_slowpath(atomic_t *lock_count) } static int fastcall noinline __sched +__mutex_lock_killable_slowpath(atomic_t *lock_count) +{ + struct mutex *lock = container_of(lock_count, struct mutex, count); + + return __mutex_lock_common(lock, TASK_KILLABLE, 0, _RET_IP_); +} + +static noinline int fastcall __sched __mutex_lock_interruptible_slowpath(atomic_t *lock_count) { struct mutex *lock = container_of(lock_count, struct mutex, count); -- cgit From da78451190bdaae0e67d6c96b1ec3366abc45474 Mon Sep 17 00:00:00 2001 From: "Liam R. Howlett" Date: Thu, 6 Dec 2007 17:39:54 -0500 Subject: Use mutex_lock_killable in vfs_readdir Signed-off-by: Liam R. Howlett Acked-by: Ingo Molnar Signed-off-by: Matthew Wilcox --- fs/readdir.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/readdir.c b/fs/readdir.c index efe52e676577..4e026e5407fb 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -30,7 +30,10 @@ int vfs_readdir(struct file *file, filldir_t filler, void *buf) if (res) goto out; - mutex_lock(&inode->i_mutex); + res = mutex_lock_killable(&inode->i_mutex); + if (res) + goto out; + res = -ENOENT; if (!IS_DEADDIR(inode)) { res = file->f_op->readdir(file, buf, filler); -- cgit From 294d5cc233d81ec4aec77ebc60dc5752a3d0082a Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 11:59:46 -0500 Subject: Add schedule_timeout_killable Signed-off-by: Matthew Wilcox --- include/linux/sched.h | 1 + kernel/timer.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/include/linux/sched.h b/include/linux/sched.h index 95395c143bab..e4921aad4063 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -314,6 +314,7 @@ extern int in_sched_functions(unsigned long addr); #define MAX_SCHEDULE_TIMEOUT LONG_MAX extern signed long FASTCALL(schedule_timeout(signed long timeout)); extern signed long schedule_timeout_interruptible(signed long timeout); +extern signed long schedule_timeout_killable(signed long timeout); extern signed long schedule_timeout_uninterruptible(signed long timeout); asmlinkage void schedule(void); diff --git a/kernel/timer.c b/kernel/timer.c index a05817c021d6..66d7d8bca1a3 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1100,6 +1100,13 @@ signed long __sched schedule_timeout_interruptible(signed long timeout) } EXPORT_SYMBOL(schedule_timeout_interruptible); +signed long __sched schedule_timeout_killable(signed long timeout) +{ + __set_current_state(TASK_KILLABLE); + return schedule_timeout(timeout); +} +EXPORT_SYMBOL(schedule_timeout_killable); + signed long __sched schedule_timeout_uninterruptible(signed long timeout) { __set_current_state(TASK_UNINTERRUPTIBLE); -- cgit From 1411d5a7fbe7dce1568b6f0a94c7cbc69eed1bfe Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 12:00:00 -0500 Subject: Add wait_event_killable Signed-off-by: Matthew Wilcox --- include/linux/wait.h | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/include/linux/wait.h b/include/linux/wait.h index 0a410a449258..1f4fb0a81ecd 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -346,6 +346,47 @@ do { \ __ret; \ }) +#define __wait_event_killable(wq, condition, ret) \ +do { \ + DEFINE_WAIT(__wait); \ + \ + for (;;) { \ + prepare_to_wait(&wq, &__wait, TASK_KILLABLE); \ + if (condition) \ + break; \ + if (!fatal_signal_pending(current)) { \ + schedule(); \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + finish_wait(&wq, &__wait); \ +} while (0) + +/** + * wait_event_killable - sleep until a condition gets true + * @wq: the waitqueue to wait on + * @condition: a C expression for the event to wait for + * + * The process is put to sleep (TASK_KILLABLE) until the + * @condition evaluates to true or a signal is received. + * The @condition is checked each time the waitqueue @wq is woken up. + * + * wake_up() has to be called after changing any variable that could + * change the result of the wait condition. + * + * The function will return -ERESTARTSYS if it was interrupted by a + * signal and 0 if @condition evaluated to true. + */ +#define wait_event_killable(wq, condition) \ +({ \ + int __ret = 0; \ + if (!(condition)) \ + __wait_event_killable(wq, condition, __ret); \ + __ret; \ +}) + /* * Must be called with the spinlock in the wait_queue_head_t held. */ -- cgit From 009e577e079656d51d0fe9b15e61e41b00816c29 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 12:29:54 -0500 Subject: Add wait_for_completion_killable Signed-off-by: Matthew Wilcox --- include/linux/completion.h | 1 + kernel/sched.c | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/linux/completion.h b/include/linux/completion.h index 33d6aaf94447..d2961b66d53d 100644 --- a/include/linux/completion.h +++ b/include/linux/completion.h @@ -44,6 +44,7 @@ static inline void init_completion(struct completion *x) extern void wait_for_completion(struct completion *); extern int wait_for_completion_interruptible(struct completion *x); +extern int wait_for_completion_killable(struct completion *x); extern unsigned long wait_for_completion_timeout(struct completion *x, unsigned long timeout); extern unsigned long wait_for_completion_interruptible_timeout( diff --git a/kernel/sched.c b/kernel/sched.c index 50a0faae585f..d2f77fab0f46 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3881,8 +3881,10 @@ do_wait_for_common(struct completion *x, long timeout, int state) wait.flags |= WQ_FLAG_EXCLUSIVE; __add_wait_queue_tail(&x->wait, &wait); do { - if (state == TASK_INTERRUPTIBLE && - signal_pending(current)) { + if ((state == TASK_INTERRUPTIBLE && + signal_pending(current)) || + (state == TASK_KILLABLE && + fatal_signal_pending(current))) { __remove_wait_queue(&x->wait, &wait); return -ERESTARTSYS; } @@ -3942,6 +3944,15 @@ wait_for_completion_interruptible_timeout(struct completion *x, } EXPORT_SYMBOL(wait_for_completion_interruptible_timeout); +int __sched wait_for_completion_killable(struct completion *x) +{ + long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_KILLABLE); + if (t == -ERESTARTSYS) + return t; + return 0; +} +EXPORT_SYMBOL(wait_for_completion_killable); + static long __sched sleep_on_common(wait_queue_head_t *q, int state, long timeout) { -- cgit From 150030b78a454ba50d5e267b0dcf01b162809192 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 16:24:39 -0500 Subject: NFS: Switch from intr mount option to TASK_KILLABLE By using the TASK_KILLABLE infrastructure, we can get rid of the 'intr' mount option. We have to use _killable everywhere instead of _interruptible as we get rid of rpc_clnt_sigmask/sigunmask. Signed-off-by: Liam R. Howlett Signed-off-by: Matthew Wilcox --- fs/nfs/client.c | 6 +----- fs/nfs/direct.c | 10 +--------- fs/nfs/inode.c | 6 +----- fs/nfs/mount_clnt.c | 2 +- fs/nfs/nfs3proc.c | 7 ++----- fs/nfs/nfs4proc.c | 27 +++++++------------------ fs/nfs/nfsroot.c | 3 --- fs/nfs/pagelist.c | 18 +++++------------ fs/nfs/read.c | 5 ----- fs/nfs/super.c | 4 ---- fs/nfs/write.c | 7 +------ include/linux/nfs_fs.h | 9 +-------- include/linux/nfs_mount.h | 2 +- include/linux/sunrpc/clnt.h | 2 -- include/linux/sunrpc/sched.h | 2 -- net/sunrpc/clnt.c | 47 ++------------------------------------------ net/sunrpc/rpcb_clnt.c | 3 +-- net/sunrpc/sched.c | 15 ++++++-------- net/sunrpc/sunrpc_syms.c | 2 -- 19 files changed, 30 insertions(+), 147 deletions(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 70587f383f10..310fa2f4cbb8 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -302,7 +302,7 @@ found_client: if (new) nfs_free_client(new); - error = wait_event_interruptible(nfs_client_active_wq, + error = wait_event_killable(nfs_client_active_wq, clp->cl_cons_state != NFS_CS_INITING); if (error < 0) { nfs_put_client(clp); @@ -494,10 +494,6 @@ static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t if (server->flags & NFS_MOUNT_SOFT) server->client->cl_softrtry = 1; - server->client->cl_intr = 0; - if (server->flags & NFS4_MOUNT_INTR) - server->client->cl_intr = 1; - return 0; } diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 5e8d82f6666b..7b994b2fa593 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -193,7 +193,7 @@ static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq) if (dreq->iocb) goto out; - result = wait_for_completion_interruptible(&dreq->completion); + result = wait_for_completion_killable(&dreq->completion); if (!result) result = dreq->error; @@ -391,9 +391,7 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { ssize_t result = 0; - sigset_t oldset; struct inode *inode = iocb->ki_filp->f_mapping->host; - struct rpc_clnt *clnt = NFS_CLIENT(inode); struct nfs_direct_req *dreq; dreq = nfs_direct_req_alloc(); @@ -405,11 +403,9 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, if (!is_sync_kiocb(iocb)) dreq->iocb = iocb; - rpc_clnt_sigmask(clnt, &oldset); result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos); if (!result) result = nfs_direct_wait(dreq); - rpc_clnt_sigunmask(clnt, &oldset); nfs_direct_req_release(dreq); return result; @@ -767,9 +763,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, size_t count) { ssize_t result = 0; - sigset_t oldset; struct inode *inode = iocb->ki_filp->f_mapping->host; - struct rpc_clnt *clnt = NFS_CLIENT(inode); struct nfs_direct_req *dreq; size_t wsize = NFS_SERVER(inode)->wsize; int sync = 0; @@ -787,11 +781,9 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, if (!is_sync_kiocb(iocb)) dreq->iocb = iocb; - rpc_clnt_sigmask(clnt, &oldset); result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync); if (!result) result = nfs_direct_wait(dreq); - rpc_clnt_sigunmask(clnt, &oldset); nfs_direct_req_release(dreq); return result; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index db5d96dc6107..f68c22215b14 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -433,15 +433,11 @@ static int nfs_wait_schedule(void *word) */ static int nfs_wait_on_inode(struct inode *inode) { - struct rpc_clnt *clnt = NFS_CLIENT(inode); struct nfs_inode *nfsi = NFS_I(inode); - sigset_t oldmask; int error; - rpc_clnt_sigmask(clnt, &oldmask); error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING, - nfs_wait_schedule, TASK_INTERRUPTIBLE); - rpc_clnt_sigunmask(clnt, &oldmask); + nfs_wait_schedule, TASK_KILLABLE); return error; } diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 8afd9f7e7a97..49c7cd0502cc 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c @@ -56,7 +56,7 @@ int nfs_mount(struct sockaddr *addr, size_t len, char *hostname, char *path, .program = &mnt_program, .version = version, .authflavor = RPC_AUTH_UNIX, - .flags = RPC_CLNT_CREATE_INTR, + .flags = 0, }; struct rpc_clnt *mnt_clnt; int status; diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 4cdc2361a669..5ae96340f2c2 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -27,17 +27,14 @@ static int nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) { - sigset_t oldset; int res; - rpc_clnt_sigmask(clnt, &oldset); do { res = rpc_call_sync(clnt, msg, flags); if (res != -EJUKEBOX) break; - schedule_timeout_interruptible(NFS_JUKEBOX_RETRY_TIME); + schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); res = -ERESTARTSYS; - } while (!signalled()); - rpc_clnt_sigunmask(clnt, &oldset); + } while (!fatal_signal_pending(current)); return res; } diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index f03d9d5f5ba4..c4faa43b36de 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -316,12 +316,9 @@ static void nfs4_opendata_put(struct nfs4_opendata *p) static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task) { - sigset_t oldset; int ret; - rpc_clnt_sigmask(task->tk_client, &oldset); ret = rpc_wait_for_completion_task(task); - rpc_clnt_sigunmask(task->tk_client, &oldset); return ret; } @@ -2806,9 +2803,9 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) return 0; } -static int nfs4_wait_bit_interruptible(void *word) +static int nfs4_wait_bit_killable(void *word) { - if (signal_pending(current)) + if (fatal_signal_pending(current)) return -ERESTARTSYS; schedule(); return 0; @@ -2816,18 +2813,14 @@ static int nfs4_wait_bit_interruptible(void *word) static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp) { - sigset_t oldset; int res; might_sleep(); rwsem_acquire(&clp->cl_sem.dep_map, 0, 0, _RET_IP_); - rpc_clnt_sigmask(clnt, &oldset); res = wait_on_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER, - nfs4_wait_bit_interruptible, - TASK_INTERRUPTIBLE); - rpc_clnt_sigunmask(clnt, &oldset); + nfs4_wait_bit_killable, TASK_KILLABLE); rwsem_release(&clp->cl_sem.dep_map, 1, _RET_IP_); return res; @@ -2835,7 +2828,6 @@ static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp) static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) { - sigset_t oldset; int res = 0; might_sleep(); @@ -2844,14 +2836,9 @@ 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; - rpc_clnt_sigmask(clnt, &oldset); - if (clnt->cl_intr) { - schedule_timeout_interruptible(*timeout); - if (signalled()) - res = -ERESTARTSYS; - } else - schedule_timeout_uninterruptible(*timeout); - rpc_clnt_sigunmask(clnt, &oldset); + schedule_timeout_killable(*timeout); + if (fatal_signal_pending(current)) + res = -ERESTARTSYS; *timeout <<= 1; return res; } @@ -3085,7 +3072,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_interruptible(timeout); + schedule_timeout_killable(timeout); timeout <<= 1; if (timeout > NFS4_LOCK_MAXTIMEOUT) return NFS4_LOCK_MAXTIMEOUT; diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index 4b0334590ee5..531379d36823 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c @@ -228,10 +228,7 @@ static int __init root_nfs_parse(char *name, char *buf) nfs_data.flags &= ~NFS_MOUNT_SOFT; break; case Opt_intr: - nfs_data.flags |= NFS_MOUNT_INTR; - break; case Opt_nointr: - nfs_data.flags &= ~NFS_MOUNT_INTR; break; case Opt_posix: nfs_data.flags |= NFS_MOUNT_POSIX; diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 345bb9b4765b..2dff469f04fe 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -67,7 +67,7 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode, if (req != NULL) break; - if (signalled() && (server->flags & NFS_MOUNT_INTR)) + if (fatal_signal_pending(current)) return ERR_PTR(-ERESTARTSYS); yield(); } @@ -175,11 +175,11 @@ void nfs_release_request(struct nfs_page *req) kref_put(&req->wb_kref, nfs_free_request); } -static int nfs_wait_bit_interruptible(void *word) +static int nfs_wait_bit_killable(void *word) { int ret = 0; - if (signal_pending(current)) + if (fatal_signal_pending(current)) ret = -ERESTARTSYS; else schedule(); @@ -190,26 +190,18 @@ static int nfs_wait_bit_interruptible(void *word) * nfs_wait_on_request - Wait for a request to complete. * @req: request to wait upon. * - * Interruptible by signals only if mounted with intr flag. + * Interruptible by fatal signals only. * The user is responsible for holding a count on the request. */ int nfs_wait_on_request(struct nfs_page *req) { - struct rpc_clnt *clnt = NFS_CLIENT(req->wb_context->path.dentry->d_inode); - sigset_t oldmask; int ret = 0; if (!test_bit(PG_BUSY, &req->wb_flags)) goto out; - /* - * Note: the call to rpc_clnt_sigmask() suffices to ensure that we - * are not interrupted if intr flag is not set - */ - rpc_clnt_sigmask(clnt, &oldmask); ret = out_of_line_wait_on_bit(&req->wb_flags, PG_BUSY, - nfs_wait_bit_interruptible, TASK_INTERRUPTIBLE); - rpc_clnt_sigunmask(clnt, &oldmask); + nfs_wait_bit_killable, TASK_KILLABLE); out: return ret; } diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 4587a86adaac..3dcaa6a73261 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -212,12 +212,7 @@ nfs_async_read_error(struct list_head *head) */ static void nfs_execute_read(struct nfs_read_data *data) { - struct rpc_clnt *clnt = NFS_CLIENT(data->inode); - sigset_t oldset; - - rpc_clnt_sigmask(clnt, &oldset); rpc_execute(&data->task); - rpc_clnt_sigunmask(clnt, &oldset); } /* diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 2426e713b77f..5b6339f70a4c 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -424,7 +424,6 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, const char *nostr; } nfs_info[] = { { NFS_MOUNT_SOFT, ",soft", ",hard" }, - { NFS_MOUNT_INTR, ",intr", ",nointr" }, { NFS_MOUNT_NOCTO, ",nocto", "" }, { NFS_MOUNT_NOAC, ",noac", "" }, { NFS_MOUNT_NONLM, ",nolock", "" }, @@ -624,10 +623,7 @@ static int nfs_parse_mount_options(char *raw, mnt->flags &= ~NFS_MOUNT_SOFT; break; case Opt_intr: - mnt->flags |= NFS_MOUNT_INTR; - break; case Opt_nointr: - mnt->flags &= ~NFS_MOUNT_INTR; break; case Opt_posix: mnt->flags |= NFS_MOUNT_POSIX; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 51cc1bd6a116..60e3e870ada4 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -490,7 +490,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req) /* * Wait for a request to complete. * - * Interruptible by signals only if mounted with intr flag. + * Interruptible by fatal signals only. */ static int nfs_wait_on_requests_locked(struct inode *inode, pgoff_t idx_start, unsigned int npages) { @@ -816,12 +816,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req, static void nfs_execute_write(struct nfs_write_data *data) { - struct rpc_clnt *clnt = NFS_CLIENT(data->inode); - sigset_t oldset; - - rpc_clnt_sigmask(clnt, &oldset); rpc_execute(&data->task); - rpc_clnt_sigunmask(clnt, &oldset); } /* diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 2d15d4aac094..2814bd40edf6 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -516,14 +516,7 @@ extern void * nfs_root_data(void); #define nfs_wait_event(clnt, wq, condition) \ ({ \ - int __retval = 0; \ - if (clnt->cl_intr) { \ - sigset_t oldmask; \ - rpc_clnt_sigmask(clnt, &oldmask); \ - __retval = wait_event_interruptible(wq, condition); \ - rpc_clnt_sigunmask(clnt, &oldmask); \ - } else \ - wait_event(wq, condition); \ + int __retval = wait_event_killable(wq, condition); \ __retval; \ }) diff --git a/include/linux/nfs_mount.h b/include/linux/nfs_mount.h index a3ade89a64d2..df7c6b7a7ebb 100644 --- a/include/linux/nfs_mount.h +++ b/include/linux/nfs_mount.h @@ -48,7 +48,7 @@ struct nfs_mount_data { /* bits in the flags field */ #define NFS_MOUNT_SOFT 0x0001 /* 1 */ -#define NFS_MOUNT_INTR 0x0002 /* 1 */ +#define NFS_MOUNT_INTR 0x0002 /* 1 */ /* now unused, but ABI */ #define NFS_MOUNT_SECURE 0x0004 /* 1 */ #define NFS_MOUNT_POSIX 0x0008 /* 1 */ #define NFS_MOUNT_NOCTO 0x0010 /* 1 */ diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index d9d5c5ad826c..01879365f4ec 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h @@ -41,7 +41,6 @@ struct rpc_clnt { struct rpc_iostats * cl_metrics; /* per-client statistics */ unsigned int cl_softrtry : 1,/* soft timeouts */ - cl_intr : 1,/* interruptible */ cl_discrtry : 1,/* disconnect before retry */ cl_autobind : 1;/* use getport() */ @@ -109,7 +108,6 @@ struct rpc_create_args { /* Values for "flags" field */ #define RPC_CLNT_CREATE_HARDRTRY (1UL << 0) -#define RPC_CLNT_CREATE_INTR (1UL << 1) #define RPC_CLNT_CREATE_AUTOBIND (1UL << 2) #define RPC_CLNT_CREATE_NONPRIVPORT (1UL << 3) #define RPC_CLNT_CREATE_NOPING (1UL << 4) diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 8ea077db0099..19160e63d6ad 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h @@ -128,7 +128,6 @@ struct rpc_call_ops { #define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */ #define RPC_TASK_KILLED 0x0100 /* task was killed */ #define RPC_TASK_SOFT 0x0200 /* Use soft timeouts */ -#define RPC_TASK_NOINTR 0x0400 /* uninterruptible task */ #define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC) #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) @@ -136,7 +135,6 @@ struct rpc_call_ops { #define RPC_ASSASSINATED(t) ((t)->tk_flags & RPC_TASK_KILLED) #define RPC_DO_CALLBACK(t) ((t)->tk_callback != NULL) #define RPC_IS_SOFT(t) ((t)->tk_flags & RPC_TASK_SOFT) -#define RPC_TASK_UNINTERRUPTIBLE(t) ((t)->tk_flags & RPC_TASK_NOINTR) #define RPC_TASK_RUNNING 0 #define RPC_TASK_QUEUED 1 diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 76be83ee4b04..a99729ff450e 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -281,7 +281,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) return clnt; if (!(args->flags & RPC_CLNT_CREATE_NOPING)) { - int err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR); + int err = rpc_ping(clnt, RPC_TASK_SOFT); if (err != 0) { rpc_shutdown_client(clnt); return ERR_PTR(err); @@ -292,8 +292,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) if (args->flags & RPC_CLNT_CREATE_HARDRTRY) clnt->cl_softrtry = 0; - if (args->flags & RPC_CLNT_CREATE_INTR) - clnt->cl_intr = 1; if (args->flags & RPC_CLNT_CREATE_AUTOBIND) clnt->cl_autobind = 1; if (args->flags & RPC_CLNT_CREATE_DISCRTRY) @@ -459,7 +457,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, clnt->cl_prog = program->number; clnt->cl_vers = version->number; clnt->cl_stats = program->stats; - err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR); + err = rpc_ping(clnt, RPC_TASK_SOFT); if (err != 0) { rpc_shutdown_client(clnt); clnt = ERR_PTR(err); @@ -480,44 +478,6 @@ static const struct rpc_call_ops rpc_default_ops = { .rpc_call_done = rpc_default_callback, }; -/* - * Export the signal mask handling for synchronous code that - * sleeps on RPC calls - */ -#define RPC_INTR_SIGNALS (sigmask(SIGHUP) | sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTERM)) - -static void rpc_save_sigmask(sigset_t *oldset, int intr) -{ - unsigned long sigallow = sigmask(SIGKILL); - sigset_t sigmask; - - /* Block all signals except those listed in sigallow */ - if (intr) - sigallow |= RPC_INTR_SIGNALS; - siginitsetinv(&sigmask, sigallow); - sigprocmask(SIG_BLOCK, &sigmask, oldset); -} - -static inline void rpc_task_sigmask(struct rpc_task *task, sigset_t *oldset) -{ - rpc_save_sigmask(oldset, !RPC_TASK_UNINTERRUPTIBLE(task)); -} - -static inline void rpc_restore_sigmask(sigset_t *oldset) -{ - sigprocmask(SIG_SETMASK, oldset, NULL); -} - -void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset) -{ - rpc_save_sigmask(oldset, clnt->cl_intr); -} - -void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset) -{ - rpc_restore_sigmask(oldset); -} - static struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt, struct rpc_message *msg, @@ -526,7 +486,6 @@ struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt, void *data) { struct rpc_task *task, *ret; - sigset_t oldset; task = rpc_new_task(clnt, flags, ops, data); if (task == NULL) { @@ -535,7 +494,6 @@ struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt, } /* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */ - rpc_task_sigmask(task, &oldset); if (msg != NULL) { rpc_call_setup(task, msg, 0); if (task->tk_status != 0) { @@ -548,7 +506,6 @@ struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt, rpc_execute(task); ret = task; out: - rpc_restore_sigmask(&oldset); return ret; } diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index a05493aedb68..c35b6e7fc680 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -172,8 +172,7 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, .program = &rpcb_program, .version = version, .authflavor = RPC_AUTH_UNIX, - .flags = (RPC_CLNT_CREATE_NOPING | - RPC_CLNT_CREATE_INTR), + .flags = RPC_CLNT_CREATE_NOPING, }; switch (srvaddr->sa_family) { diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index c98873f39aec..4b22910b4461 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -245,9 +245,9 @@ void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname) } EXPORT_SYMBOL(rpc_init_wait_queue); -static int rpc_wait_bit_interruptible(void *word) +static int rpc_wait_bit_killable(void *word) { - if (signal_pending(current)) + if (fatal_signal_pending(current)) return -ERESTARTSYS; schedule(); return 0; @@ -299,9 +299,9 @@ static void rpc_mark_complete_task(struct rpc_task *task) int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *)) { if (action == NULL) - action = rpc_wait_bit_interruptible; + action = rpc_wait_bit_killable; return wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, - action, TASK_INTERRUPTIBLE); + action, TASK_KILLABLE); } EXPORT_SYMBOL(__rpc_wait_for_completion_task); @@ -690,10 +690,9 @@ static void __rpc_execute(struct rpc_task *task) /* sync task: sleep here */ dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid); - /* Note: Caller should be using rpc_clnt_sigmask() */ status = out_of_line_wait_on_bit(&task->tk_runstate, - RPC_TASK_QUEUED, rpc_wait_bit_interruptible, - TASK_INTERRUPTIBLE); + RPC_TASK_QUEUED, rpc_wait_bit_killable, + TASK_KILLABLE); if (status == -ERESTARTSYS) { /* * When a sync task receives a signal, it exits with @@ -837,8 +836,6 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons kref_get(&clnt->cl_kref); if (clnt->cl_softrtry) task->tk_flags |= RPC_TASK_SOFT; - if (!clnt->cl_intr) - task->tk_flags |= RPC_TASK_NOINTR; } BUG_ON(task->tk_ops == NULL); diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 33d89e842c85..1fd3aa81938a 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c @@ -38,8 +38,6 @@ EXPORT_SYMBOL(rpc_killall_tasks); EXPORT_SYMBOL(rpc_call_sync); EXPORT_SYMBOL(rpc_call_async); EXPORT_SYMBOL(rpc_call_setup); -EXPORT_SYMBOL(rpc_clnt_sigmask); -EXPORT_SYMBOL(rpc_clnt_sigunmask); EXPORT_SYMBOL(rpc_delay); EXPORT_SYMBOL(rpc_restart_call); EXPORT_SYMBOL(rpc_setbufsize); -- cgit From 2dfe485a2c8afa54cb069fcf48476f6c90ea3fdf Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 6 Dec 2007 16:25:30 -0500 Subject: Remove commented-out code copied from NFS This is a false positive when grepping ... change it to be what the NFS code looks like now. Signed-off-by: Matthew Wilcox --- fs/smbfs/request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c index ca4b2d59c0ca..45f45933e862 100644 --- a/fs/smbfs/request.c +++ b/fs/smbfs/request.c @@ -105,7 +105,7 @@ struct smb_request *smb_alloc_request(struct smb_sb_info *server, int bufsize) if (nfs_try_to_free_pages(server)) continue; - if (signalled() && (server->flags & NFS_MOUNT_INTR)) + if (fatal_signal_pending(current)) return ERR_PTR(-ERESTARTSYS); current->policy = SCHED_YIELD; schedule(); -- cgit