summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTrond Myklebust2018-12-02 05:18:00 +0100
committerGreg Kroah-Hartman2018-12-21 14:15:17 +0100
commit20595815b058dc7d7ae9d16169e20407f71be2d6 (patch)
tree0b6289c29dec3e5a9e7dba0f9b0c09fa0f084b44 /net
parentnfs: don't dirty kernel pages read by direct-io (diff)
downloadkernel-qcow2-linux-20595815b058dc7d7ae9d16169e20407f71be2d6.tar.gz
kernel-qcow2-linux-20595815b058dc7d7ae9d16169e20407f71be2d6.tar.xz
kernel-qcow2-linux-20595815b058dc7d7ae9d16169e20407f71be2d6.zip
SUNRPC: Fix a potential race in xprt_connect()
[ Upstream commit 0a9a4304f3614e25d9de9b63502ca633c01c0d70 ] If an asynchronous connection attempt completes while another task is in xprt_connect(), then the call to rpc_sleep_on() could end up racing with the call to xprt_wake_pending_tasks(). So add a second test of the connection state after we've put the task to sleep and set the XPRT_CONNECTING flag, when we know that there can be no asynchronous connection attempts still in progress. Fixes: 0b9e79431377d ("SUNRPC: Move the test for XPRT_CONNECTING into...") Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/xprt.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index a8db2e3f8904..d066aae3cb6d 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -781,8 +781,15 @@ void xprt_connect(struct rpc_task *task)
return;
if (xprt_test_and_set_connecting(xprt))
return;
- xprt->stat.connect_start = jiffies;
- xprt->ops->connect(xprt, task);
+ /* Race breaker */
+ if (!xprt_connected(xprt)) {
+ xprt->stat.connect_start = jiffies;
+ xprt->ops->connect(xprt, task);
+ } else {
+ xprt_clear_connecting(xprt);
+ task->tk_status = 0;
+ rpc_wake_up_queued_task(&xprt->pending, task);
+ }
}
xprt_release_write(xprt, task);
}