summaryrefslogtreecommitdiff
path: root/fs/cifs/transport.c
diff options
context:
space:
mode:
authorShyam Prasad N <sprasad@microsoft.com>2021-10-25 05:44:10 +0000
committerSteve French <stfrench@microsoft.com>2022-01-07 20:09:23 -0600
commitbda487ac4bebf871255cc6f23e16f702cea0ca7c (patch)
treec9002fe22f2e9294726411f82e012835ffef95ac /fs/cifs/transport.c
parent73f9bfbe3d818bb52266d5c9f3ba57d97842ffe7 (diff)
cifs: avoid race during socket reconnect between send and recv
When a TCP connection gets reestablished by the sender in cifs_reconnect, There is a chance for race condition with demultiplex thread waiting in cifs_readv_from_socket on the old socket. It will now return -ECONNRESET. This condition is handled by comparing socket pointer before and after sock_recvmsg. If the socket pointer has changed, we should not call cifs_reconnect again, but instead retry with new socket. Also fixed another bug in my prev mchan commits. We should always reestablish session (even if binding) on a channel that needs reconnection. Signed-off-by: Shyam Prasad N <sprasad@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs/transport.c')
-rw-r--r--fs/cifs/transport.c13
1 files changed, 2 insertions, 11 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 1c400ca26383..93f0e8c1ea23 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -1057,18 +1057,9 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
if (!ses)
return NULL;
- spin_lock(&ses->chan_lock);
/* round robin */
-pick_another:
- if (ses->chan_count > 1 &&
- !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
- index = (uint)atomic_inc_return(&ses->chan_seq);
- index %= ses->chan_count;
-
- if (CIFS_CHAN_NEEDS_RECONNECT(ses, index))
- goto pick_another;
- }
- spin_unlock(&ses->chan_lock);
+ index = (uint)atomic_inc_return(&ses->chan_seq);
+ index %= ses->chan_count;
return ses->chans[index].server;
}