diff options
author | Shyam Prasad N <sprasad@microsoft.com> | 2021-07-19 12:46:53 +0000 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2022-01-02 20:38:46 -0600 |
commit | d1a931ce2e3b7761d293ba8e0bde2b0180f456e9 (patch) | |
tree | 1de9314a0edcfd133b19d83dc9cddc6772a77c2d /fs/cifs/sess.c | |
parent | 0b66fa776c361824a700793e34f866bf479dac92 (diff) | |
download | lwn-d1a931ce2e3b7761d293ba8e0bde2b0180f456e9.tar.gz lwn-d1a931ce2e3b7761d293ba8e0bde2b0180f456e9.zip |
cifs: track individual channel status using chans_need_reconnect
We needed a way to identify the channels under the smb session
which are in reconnect, so that the traffic to other channels
can continue. So I replaced the bool need_reconnect with
a bitmask identifying all the channels that need reconnection
(named chans_need_reconnect). When a channel needs reconnection,
the bit corresponding to the index of the server in ses->chans
is used to set this bitmask. Checking if no channels or all
the channels need reconnect then becomes very easy.
Also wrote some helper macros for checking and setting the bits.
Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs/sess.c')
-rw-r--r-- | fs/cifs/sess.c | 67 |
1 files changed, 65 insertions, 2 deletions
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 035dc3e245dc..ba8543ccb298 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -65,6 +65,53 @@ bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface) return false; } +unsigned int +cifs_ses_get_chan_index(struct cifs_ses *ses, + struct TCP_Server_Info *server) +{ + unsigned int i; + + for (i = 0; i < ses->chan_count; i++) { + if (ses->chans[i].server == server) + return i; + } + + /* If we didn't find the channel, it is likely a bug */ + WARN_ON(1); + return 0; +} + +void +cifs_chan_set_need_reconnect(struct cifs_ses *ses, + struct TCP_Server_Info *server) +{ + unsigned int chan_index = cifs_ses_get_chan_index(ses, server); + + set_bit(chan_index, &ses->chans_need_reconnect); + cifs_dbg(FYI, "Set reconnect bitmask for chan %u; now 0x%lx\n", + chan_index, ses->chans_need_reconnect); +} + +void +cifs_chan_clear_need_reconnect(struct cifs_ses *ses, + struct TCP_Server_Info *server) +{ + unsigned int chan_index = cifs_ses_get_chan_index(ses, server); + + clear_bit(chan_index, &ses->chans_need_reconnect); + cifs_dbg(FYI, "Cleared reconnect bitmask for chan %u; now 0x%lx\n", + chan_index, ses->chans_need_reconnect); +} + +bool +cifs_chan_needs_reconnect(struct cifs_ses *ses, + struct TCP_Server_Info *server) +{ + unsigned int chan_index = cifs_ses_get_chan_index(ses, server); + + return CIFS_CHAN_NEEDS_RECONNECT(ses, chan_index); +} + /* returns number of channels added */ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses) { @@ -306,11 +353,21 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, spin_lock(&ses->chan_lock); ses->chan_count++; atomic_set(&ses->chan_seq, 0); + + /* Mark this channel as needing connect/setup */ + cifs_chan_set_need_reconnect(ses, chan->server); spin_unlock(&ses->chan_lock); out: ses->binding = false; ses->binding_chan = NULL; + + if (rc && chan->server) { + /* we rely on all bits beyond chan_count to be clear */ + cifs_chan_clear_need_reconnect(ses, chan->server); + ses->chan_count--; + } + mutex_unlock(&ses->session_mutex); if (rc && chan->server) @@ -998,9 +1055,15 @@ sess_establish_session(struct sess_data *sess_data) mutex_unlock(&ses->server->srv_mutex); cifs_dbg(FYI, "CIFS session established successfully\n"); + if (ses->binding) + cifs_chan_clear_need_reconnect(ses, ses->binding_chan->server); + else + cifs_chan_clear_need_reconnect(ses, ses->server); + + /* keep existing ses state if binding */ spin_lock(&GlobalMid_Lock); - ses->status = CifsGood; - ses->need_reconnect = false; + if (!ses->binding) + ses->status = CifsGood; spin_unlock(&GlobalMid_Lock); return 0; |