From: Zhang Xiaoxu zhangxiaoxu5@huawei.com
mainline inclusion from mainline-v5.14 commit fcb170a9d825d7db4a3fb870b0300f5a40a8d096 category: bugfix bugzilla: 51898 CVE: NA
---------------------------
The 'queue->nr' will wraparound from 0 to 255 when only current priority queue has tasks. 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. When non-privileged task complete and release the slot, a non-privileged maybe picked out. It maybe allocate slot failed when the session on draining.
If the 'queue->nr' has wraparound to 255, and no enough slot to service it, then the privileged delegreturn will lost to wake up.
So we should avoid the wraparound on 'queue->nr'.
Reported-by: Hulk Robot hulkci@huawei.com Fixes: 5fcdfacc01f3 ("NFSv4: Return delegations synchronously in evict_inode") Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Zhang Xiaoxu zhangxiaoxu5@huawei.com Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/sched.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 8d204d5a76187..8cffcf58e6386 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -506,7 +506,8 @@ static struct rpc_task *__rpc_find_next_queued_priority(struct rpc_wait_queue *q * Service a batch of tasks from a single owner. */ q = &queue->tasks[queue->priority]; - if (!list_empty(q) && --queue->nr) { + if (!list_empty(q) && queue->nr) { + queue->nr--; task = list_first_entry(q, struct rpc_task, u.tk_wait.list); goto out; }
From: Zhang Xiaoxu zhangxiaoxu5@huawei.com
mainline inclusion from mainline-v5.14 commit 5483b904bf336948826594610af4c9bbb0d9e3aa category: bugfix bugzilla: 51898 CVE: NA
---------------------------
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 Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/sched.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 8cffcf58e6386..5af838a329e14 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -502,6 +502,15 @@ static struct rpc_task *__rpc_find_next_queued_priority(struct rpc_wait_queue *q struct list_head *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. */