diff options
author | Shyam Prasad N <sprasad@microsoft.com> | 2021-10-25 08:44:10 +0300 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2022-01-08 05:09:23 +0300 |
commit | bda487ac4bebf871255cc6f23e16f702cea0ca7c (patch) | |
tree | c9002fe22f2e9294726411f82e012835ffef95ac /fs/cifs/transport.c | |
parent | 73f9bfbe3d818bb52266d5c9f3ba57d97842ffe7 (diff) | |
download | linux-bda487ac4bebf871255cc6f23e16f702cea0ca7c.tar.xz |
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.c | 13 |
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; } |