summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorZhang Xiaoxu <zhangxiaoxu5@huawei.com>2021-06-26 15:50:42 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-07-20 16:17:29 +0200
commit96ee5b4c5591868dd4f83dc77ebef4499fd23d5a (patch)
tree42eadddee2a5387038ac805de236b91eb40a8244 /net
parent98c887fafa40fa6d65ce04110b8020d12907d64f (diff)
downloadlinux-stable-96ee5b4c5591868dd4f83dc77ebef4499fd23d5a.tar.gz
linux-stable-96ee5b4c5591868dd4f83dc77ebef4499fd23d5a.tar.bz2
linux-stable-96ee5b4c5591868dd4f83dc77ebef4499fd23d5a.zip
SUNRPC: Should wake up the privileged task firstly.
commit 5483b904bf336948826594610af4c9bbb0d9e3aa upstream. When find a task from wait queue to wake up, a non-privileged task may be found out, rather than the privileged. This maybe lead a deadlock same as commit dfe1fe75e00e ("NFSv4: Fix deadlock between nfs4_evict_inode() and nfs4_opendata_get_inode()"): Privileged delegreturn task is queued to privileged list because all the slots are assigned. If there has no enough slot to wake up the non-privileged batch tasks(session less than 8 slot), then the privileged delegreturn task maybe lost waked up because the found out task can't get slot since the session is on draining. So we should treate the privileged task as the emergency task, and execute it as for as we can. Reported-by: Hulk Robot <hulkci@huawei.com> Fixes: 5fcdfacc01f3 ("NFSv4: Return delegations synchronously in evict_inode") Cc: stable@vger.kernel.org Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/sched.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 41fd80dc9a20..253132130c42 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -487,6 +487,15 @@ static struct rpc_task *__rpc_find_next_queued_priority(struct rpc_wait_queue *q
struct rpc_task *task;
/*
+ * Service the privileged queue.
+ */
+ q = &queue->tasks[RPC_NR_PRIORITY - 1];
+ if (queue->maxpriority > RPC_PRIORITY_PRIVILEGED && !list_empty(q)) {
+ task = list_first_entry(q, struct rpc_task, u.tk_wait.list);
+ goto out;
+ }
+
+ /*
* Service a batch of tasks from a single owner.
*/
q = &queue->tasks[queue->priority];