cifs: Send a logoff request before removing a smb session
Send a smb session logoff request before removing smb session off of the list. On a signed smb session, remvoing a session off of the list before sending a logoff request results in server returning an error for lack of smb signature. Never seen an error during smb logoff, so as per MS-SMB2 3.2.5.1, not sure how an error during logoff should be retried. So for now, if a server returns an error to a logoff request, log the error and remove the session off of the list. Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:
committed by
Steve French
parent
3d378d3fd8
commit
7f48558e64
@@ -2242,6 +2242,8 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
|
|||||||
|
|
||||||
spin_lock(&cifs_tcp_ses_lock);
|
spin_lock(&cifs_tcp_ses_lock);
|
||||||
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
|
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
|
||||||
|
if (ses->status == CifsExiting)
|
||||||
|
continue;
|
||||||
if (!match_session(ses, vol))
|
if (!match_session(ses, vol))
|
||||||
continue;
|
continue;
|
||||||
++ses->ses_count;
|
++ses->ses_count;
|
||||||
@@ -2255,24 +2257,37 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
|
|||||||
static void
|
static void
|
||||||
cifs_put_smb_ses(struct cifs_ses *ses)
|
cifs_put_smb_ses(struct cifs_ses *ses)
|
||||||
{
|
{
|
||||||
unsigned int xid;
|
unsigned int rc, xid;
|
||||||
struct TCP_Server_Info *server = ses->server;
|
struct TCP_Server_Info *server = ses->server;
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
|
cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
|
||||||
|
|
||||||
spin_lock(&cifs_tcp_ses_lock);
|
spin_lock(&cifs_tcp_ses_lock);
|
||||||
|
if (ses->status == CifsExiting) {
|
||||||
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (--ses->ses_count > 0) {
|
if (--ses->ses_count > 0) {
|
||||||
spin_unlock(&cifs_tcp_ses_lock);
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (ses->status == CifsGood)
|
||||||
|
ses->status = CifsExiting;
|
||||||
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
|
|
||||||
|
if (ses->status == CifsExiting && server->ops->logoff) {
|
||||||
|
xid = get_xid();
|
||||||
|
rc = server->ops->logoff(xid, ses);
|
||||||
|
if (rc)
|
||||||
|
cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
|
||||||
|
__func__, rc);
|
||||||
|
_free_xid(xid);
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock(&cifs_tcp_ses_lock);
|
||||||
list_del_init(&ses->smb_ses_list);
|
list_del_init(&ses->smb_ses_list);
|
||||||
spin_unlock(&cifs_tcp_ses_lock);
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
|
|
||||||
if (ses->status == CifsGood && server->ops->logoff) {
|
|
||||||
xid = get_xid();
|
|
||||||
server->ops->logoff(xid, ses);
|
|
||||||
_free_xid(xid);
|
|
||||||
}
|
|
||||||
sesInfoFree(ses);
|
sesInfoFree(ses);
|
||||||
cifs_put_tcp_session(server);
|
cifs_put_tcp_session(server);
|
||||||
}
|
}
|
||||||
|
@@ -516,13 +516,19 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf,
|
|||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ses->status != CifsGood) {
|
if (ses->status == CifsNew) {
|
||||||
/* check if SMB2 session is bad because we are setting it up */
|
|
||||||
if ((buf->Command != SMB2_SESSION_SETUP) &&
|
if ((buf->Command != SMB2_SESSION_SETUP) &&
|
||||||
(buf->Command != SMB2_NEGOTIATE))
|
(buf->Command != SMB2_NEGOTIATE))
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
/* else ok - we are setting up session */
|
/* else ok - we are setting up session */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ses->status == CifsExiting) {
|
||||||
|
if (buf->Command != SMB2_LOGOFF)
|
||||||
|
return -EAGAIN;
|
||||||
|
/* else ok - we are shutting down the session */
|
||||||
|
}
|
||||||
|
|
||||||
*mid = smb2_mid_entry_alloc(buf, ses->server);
|
*mid = smb2_mid_entry_alloc(buf, ses->server);
|
||||||
if (*mid == NULL)
|
if (*mid == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@@ -431,13 +431,20 @@ static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
|
|||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ses->status != CifsGood) {
|
if (ses->status == CifsNew) {
|
||||||
/* check if SMB session is bad because we are setting it up */
|
|
||||||
if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
|
if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
|
||||||
(in_buf->Command != SMB_COM_NEGOTIATE))
|
(in_buf->Command != SMB_COM_NEGOTIATE))
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
/* else ok - we are setting up session */
|
/* else ok - we are setting up session */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ses->status == CifsExiting) {
|
||||||
|
/* check if SMB session is bad because we are setting it up */
|
||||||
|
if (in_buf->Command != SMB_COM_LOGOFF_ANDX)
|
||||||
|
return -EAGAIN;
|
||||||
|
/* else ok - we are shutting down session */
|
||||||
|
}
|
||||||
|
|
||||||
*ppmidQ = AllocMidQEntry(in_buf, ses->server);
|
*ppmidQ = AllocMidQEntry(in_buf, ses->server);
|
||||||
if (*ppmidQ == NULL)
|
if (*ppmidQ == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
Reference in New Issue
Block a user