diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index fa80a23f9fcf..9ee5856d63cc 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -169,6 +169,7 @@ static void cifs_resolve_server(struct work_struct *work) */ static void cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server) { + unsigned int num_sessions = 0; struct cifs_ses *ses; struct cifs_tcon *tcon; struct mid_q_entry *mid, *nmid; @@ -201,6 +202,8 @@ static void cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server if (!CIFS_ALL_CHANS_NEED_RECONNECT(ses)) goto next_session; + num_sessions++; + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) tcon->need_reconnect = true; if (ses->tcon_ipc) @@ -211,6 +214,14 @@ next_session: } spin_unlock(&cifs_tcp_ses_lock); + if (num_sessions == 0) + return; + /* + * before reconnecting the tcp session, mark the smb session (uid) + * and the tid bad so they are not used until reconnected + */ + cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n", + __func__); /* do not want to be sending data on a socket we are freeing */ cifs_dbg(FYI, "%s: tearing down socket\n", __func__); mutex_lock(&server->srv_mutex); @@ -2005,7 +2016,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) spin_unlock(&ses->chan_lock); cifs_dbg(FYI, "Session needs reconnect\n"); - rc = cifs_negotiate_protocol(xid, ses); + rc = cifs_negotiate_protocol(xid, ses, server); if (rc) { mutex_unlock(&ses->session_mutex); /* problem -- put our ses reference */ @@ -2014,7 +2025,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) return ERR_PTR(rc); } - rc = cifs_setup_session(xid, ses, + rc = cifs_setup_session(xid, ses, server, ctx->local_nls); if (rc) { mutex_unlock(&ses->session_mutex); @@ -2086,9 +2097,9 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) ses->chans_need_reconnect = 1; spin_unlock(&ses->chan_lock); - rc = cifs_negotiate_protocol(xid, ses); + rc = cifs_negotiate_protocol(xid, ses, server); if (!rc) - rc = cifs_setup_session(xid, ses, ctx->local_nls); + rc = cifs_setup_session(xid, ses, server, ctx->local_nls); /* each channel uses a different signing key */ memcpy(ses->chans[0].signkey, ses->smb3signingkey, @@ -3820,10 +3831,10 @@ cifs_umount(struct cifs_sb_info *cifs_sb) } int -cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses) +cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses, + struct TCP_Server_Info *server) { int rc = 0; - struct TCP_Server_Info *server = cifs_ses_server(ses); if (!server->ops->need_neg || !server->ops->negotiate) return -ENOSYS; @@ -3832,7 +3843,7 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses) if (!server->ops->need_neg(server)) return 0; - rc = server->ops->negotiate(xid, ses); + rc = server->ops->negotiate(xid, ses, server); if (rc == 0) { spin_lock(&GlobalMid_Lock); if (server->tcpStatus == CifsNeedNegotiate) @@ -3847,12 +3858,17 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses) int cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, + struct TCP_Server_Info *server, struct nls_table *nls_info) { int rc = -ENOSYS; - struct TCP_Server_Info *server = cifs_ses_server(ses); + bool is_binding = false; + + spin_lock(&ses->chan_lock); + is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses); + spin_unlock(&ses->chan_lock); - if (!ses->binding) { + if (!is_binding) { ses->capabilities = server->capabilities; if (!linuxExtEnabled) ses->capabilities &= (~server->vals->cap_unix); @@ -3870,7 +3886,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, server->sec_mode, server->capabilities, server->timeAdj); if (server->ops->sess_setup) - rc = server->ops->sess_setup(xid, ses, nls_info); + rc = server->ops->sess_setup(xid, ses, server, nls_info); if (rc) cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc); |