From 2f58967979409ea3ec799343aa35e9007f735a3b Mon Sep 17 00:00:00 2001 From: Aurelien Aptel Date: Fri, 24 Apr 2020 16:55:31 +0200 Subject: cifs: multichannel: try to rebind when reconnecting a channel first steps in trying to make channels properly reconnect. * add cifs_ses_find_chan() function to find the enclosing cifs_chan struct it belongs to * while we have the session lock and are redoing negprot and sess.setup in smb2_reconnect() redo the binding of channels. Signed-off-by: Aurelien Aptel Signed-off-by: Steve French --- fs/cifs/cifsproto.h | 2 ++ fs/cifs/sess.c | 16 ++++++++++++++++ fs/cifs/smb2pdu.c | 16 ++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index a25a46237f9f..bd92070ca30c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -593,6 +593,8 @@ void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc); extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page, unsigned int *len, unsigned int *offset); +struct cifs_chan * +cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server); int cifs_try_adding_channels(struct cifs_ses *ses); int cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface); diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 1ffdd7dadc55..5d05bd2822d2 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -150,6 +150,22 @@ int cifs_try_adding_channels(struct cifs_ses *ses) return ses->chan_count - old_chan_count; } +/* + * If server is a channel of ses, return the corresponding enclosing + * cifs_chan otherwise return NULL. + */ +struct cifs_chan * +cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server) +{ + int i; + + for (i = 0; i < ses->chan_count; i++) { + if (ses->chans[i].server == server) + return &ses->chans[i]; + } + return NULL; +} + int cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface) { diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 2497e0e428ac..ded96b529a4d 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -375,15 +375,31 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, goto out; } + /* + * If we are reconnecting an extra channel, bind + */ + if (server->is_channel) { + ses->binding = true; + ses->binding_chan = cifs_ses_find_chan(ses, server); + } + rc = cifs_negotiate_protocol(0, tcon->ses); if (!rc && tcon->ses->need_reconnect) { rc = cifs_setup_session(0, tcon->ses, nls_codepage); if ((rc == -EACCES) && !tcon->retry) { rc = -EHOSTDOWN; + ses->binding = false; + ses->binding_chan = NULL; mutex_unlock(&tcon->ses->session_mutex); goto failed; } } + /* + * End of channel binding + */ + ses->binding = false; + ses->binding_chan = NULL; + if (rc || !tcon->need_reconnect) { mutex_unlock(&tcon->ses->session_mutex); goto out; -- cgit v1.2.3