summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2023-05-10 12:28:00 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-05-30 14:03:17 +0100
commit0d97634ad49888f1cea7362191cd9e8ee3ddde0c (patch)
tree019a9e5177176d9ea8dcaf40558a476abf572037 /net
parent40599969ff5859e00d30308da6980600bd64a813 (diff)
downloadlinux-stable-0d97634ad49888f1cea7362191cd9e8ee3ddde0c.tar.gz
linux-stable-0d97634ad49888f1cea7362191cd9e8ee3ddde0c.tar.bz2
linux-stable-0d97634ad49888f1cea7362191cd9e8ee3ddde0c.zip
SUNRPC: Don't change task->tk_status after the call to rpc_exit_task
commit d180891fba995bd54e25b089b1ec98d134873586 upstream. Some calls to rpc_exit_task() may deliberately change the value of task->tk_status, for instance because it gets checked by the RPC call's rpc_release() callback. That makes it wrong to reset the value to task->tk_rpc_status. In particular this causes a bug where the rpc_call_done() callback tries to fail over a set of pNFS/flexfiles writes to a different IP address, but the reset of task->tk_status causes nfs_commit_release_pages() to immediately mark the file as having a fatal error. Fixes: 39494194f93b ("SUNRPC: Fix races with rpc_killall_tasks()") Cc: stable@vger.kernel.org # 6.1.x Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/sched.c5
1 files changed, 2 insertions, 3 deletions
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index c8321de341ee..6debf4fd42d4 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -927,11 +927,10 @@ static void __rpc_execute(struct rpc_task *task)
*/
do_action = task->tk_action;
/* Tasks with an RPC error status should exit */
- if (do_action != rpc_exit_task &&
+ if (do_action && do_action != rpc_exit_task &&
(status = READ_ONCE(task->tk_rpc_status)) != 0) {
task->tk_status = status;
- if (do_action != NULL)
- do_action = rpc_exit_task;
+ do_action = rpc_exit_task;
}
/* Callbacks override all actions */
if (task->tk_callback) {