diff options
Diffstat (limited to 'net/sunrpc/sched.c')
-rw-r--r-- | net/sunrpc/sched.c | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 28956c70100a..3d6cb91ba598 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -759,8 +759,7 @@ static void | |||
759 | rpc_reset_task_statistics(struct rpc_task *task) | 759 | rpc_reset_task_statistics(struct rpc_task *task) |
760 | { | 760 | { |
761 | task->tk_timeouts = 0; | 761 | task->tk_timeouts = 0; |
762 | task->tk_flags &= ~(RPC_CALL_MAJORSEEN|RPC_TASK_KILLED|RPC_TASK_SENT); | 762 | task->tk_flags &= ~(RPC_CALL_MAJORSEEN|RPC_TASK_SENT); |
763 | |||
764 | rpc_init_task_statistics(task); | 763 | rpc_init_task_statistics(task); |
765 | } | 764 | } |
766 | 765 | ||
@@ -773,7 +772,6 @@ void rpc_exit_task(struct rpc_task *task) | |||
773 | if (task->tk_ops->rpc_call_done != NULL) { | 772 | if (task->tk_ops->rpc_call_done != NULL) { |
774 | task->tk_ops->rpc_call_done(task, task->tk_calldata); | 773 | task->tk_ops->rpc_call_done(task, task->tk_calldata); |
775 | if (task->tk_action != NULL) { | 774 | if (task->tk_action != NULL) { |
776 | WARN_ON(RPC_ASSASSINATED(task)); | ||
777 | /* Always release the RPC slot and buffer memory */ | 775 | /* Always release the RPC slot and buffer memory */ |
778 | xprt_release(task); | 776 | xprt_release(task); |
779 | rpc_reset_task_statistics(task); | 777 | rpc_reset_task_statistics(task); |
@@ -781,6 +779,19 @@ void rpc_exit_task(struct rpc_task *task) | |||
781 | } | 779 | } |
782 | } | 780 | } |
783 | 781 | ||
782 | void rpc_signal_task(struct rpc_task *task) | ||
783 | { | ||
784 | struct rpc_wait_queue *queue; | ||
785 | |||
786 | if (!RPC_IS_ACTIVATED(task)) | ||
787 | return; | ||
788 | set_bit(RPC_TASK_SIGNALLED, &task->tk_runstate); | ||
789 | smp_mb__after_atomic(); | ||
790 | queue = READ_ONCE(task->tk_waitqueue); | ||
791 | if (queue) | ||
792 | rpc_wake_up_queued_task_set_status(queue, task, -ERESTARTSYS); | ||
793 | } | ||
794 | |||
784 | void rpc_exit(struct rpc_task *task, int status) | 795 | void rpc_exit(struct rpc_task *task, int status) |
785 | { | 796 | { |
786 | task->tk_status = status; | 797 | task->tk_status = status; |
@@ -836,6 +847,13 @@ static void __rpc_execute(struct rpc_task *task) | |||
836 | */ | 847 | */ |
837 | if (!RPC_IS_QUEUED(task)) | 848 | if (!RPC_IS_QUEUED(task)) |
838 | continue; | 849 | continue; |
850 | |||
851 | /* | ||
852 | * Signalled tasks should exit rather than sleep. | ||
853 | */ | ||
854 | if (RPC_SIGNALLED(task)) | ||
855 | rpc_exit(task, -ERESTARTSYS); | ||
856 | |||
839 | /* | 857 | /* |
840 | * The queue->lock protects against races with | 858 | * The queue->lock protects against races with |
841 | * rpc_make_runnable(). | 859 | * rpc_make_runnable(). |
@@ -861,7 +879,7 @@ static void __rpc_execute(struct rpc_task *task) | |||
861 | status = out_of_line_wait_on_bit(&task->tk_runstate, | 879 | status = out_of_line_wait_on_bit(&task->tk_runstate, |
862 | RPC_TASK_QUEUED, rpc_wait_bit_killable, | 880 | RPC_TASK_QUEUED, rpc_wait_bit_killable, |
863 | TASK_KILLABLE); | 881 | TASK_KILLABLE); |
864 | if (status == -ERESTARTSYS) { | 882 | if (status < 0) { |
865 | /* | 883 | /* |
866 | * When a sync task receives a signal, it exits with | 884 | * When a sync task receives a signal, it exits with |
867 | * -ERESTARTSYS. In order to catch any callbacks that | 885 | * -ERESTARTSYS. In order to catch any callbacks that |
@@ -869,7 +887,7 @@ static void __rpc_execute(struct rpc_task *task) | |||
869 | * break the loop here, but go around once more. | 887 | * break the loop here, but go around once more. |
870 | */ | 888 | */ |
871 | dprintk("RPC: %5u got signal\n", task->tk_pid); | 889 | dprintk("RPC: %5u got signal\n", task->tk_pid); |
872 | task->tk_flags |= RPC_TASK_KILLED; | 890 | set_bit(RPC_TASK_SIGNALLED, &task->tk_runstate); |
873 | rpc_exit(task, -ERESTARTSYS); | 891 | rpc_exit(task, -ERESTARTSYS); |
874 | } | 892 | } |
875 | dprintk("RPC: %5u sync task resuming\n", task->tk_pid); | 893 | dprintk("RPC: %5u sync task resuming\n", task->tk_pid); |