If an RPC task is signaled while it is running and the transport is not connected, it will never sleep and never be terminated. This can happen when a RPC transport is shut down: the remaining tasks are signalled, but the transport is disconnected. Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> --- include/linux/sunrpc/sched.h | 3 ++- net/sunrpc/sched.c | 14 ++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index df696efdd675..9f5e48f154c5 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h @@ -170,7 +170,8 @@ struct rpc_task_setup { #define RPC_IS_ACTIVATED(t) test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate) -#define RPC_SIGNALLED(t) test_bit(RPC_TASK_SIGNALLED, &(t)->tk_runstate) +#define RPC_SIGNALLED(t) \ + unlikely(test_bit(RPC_TASK_SIGNALLED, &(t)->tk_runstate) != 0) /* * Task priorities. diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 7eba20a88438..99b7b834a110 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -912,6 +912,12 @@ static void __rpc_execute(struct rpc_task *task) trace_rpc_task_run_action(task, do_action); do_action(task); + if (RPC_SIGNALLED(task)) { + task->tk_rpc_status = -ERESTARTSYS; + rpc_exit(task, -ERESTARTSYS); + break; + } + /* * Lockless check for whether task is sleeping or not. */ @@ -919,14 +925,6 @@ static void __rpc_execute(struct rpc_task *task) continue; /* - * Signalled tasks should exit rather than sleep. - */ - if (RPC_SIGNALLED(task)) { - task->tk_rpc_status = -ERESTARTSYS; - rpc_exit(task, -ERESTARTSYS); - } - - /* * The queue->lock protects against races with * rpc_make_runnable(). *