diff options
author | Shirish Pargaonkar <shirishpargaonkar@gmail.com> | 2013-10-12 11:06:03 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2013-11-02 13:52:35 -0400 |
commit | 7f48558e6489d032b1584b0cc9ac4bb11072c034 (patch) | |
tree | 54c6b7529085229d53cae09cada37d548f848f26 /fs/cifs | |
parent | 3d378d3fd82a759d59c60d89b4559bf325d7e668 (diff) |
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>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/connect.c | 25 | ||||
-rw-r--r-- | fs/cifs/smb2transport.c | 10 | ||||
-rw-r--r-- | fs/cifs/transport.c | 11 |
3 files changed, 37 insertions, 9 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a279ffc0bc29..62a55147400a 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -2242,6 +2242,8 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol) | |||
2242 | 2242 | ||
2243 | spin_lock(&cifs_tcp_ses_lock); | 2243 | spin_lock(&cifs_tcp_ses_lock); |
2244 | list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { | 2244 | list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { |
2245 | if (ses->status == CifsExiting) | ||
2246 | continue; | ||
2245 | if (!match_session(ses, vol)) | 2247 | if (!match_session(ses, vol)) |
2246 | continue; | 2248 | continue; |
2247 | ++ses->ses_count; | 2249 | ++ses->ses_count; |
@@ -2255,24 +2257,37 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol) | |||
2255 | static void | 2257 | static void |
2256 | cifs_put_smb_ses(struct cifs_ses *ses) | 2258 | cifs_put_smb_ses(struct cifs_ses *ses) |
2257 | { | 2259 | { |
2258 | unsigned int xid; | 2260 | unsigned int rc, xid; |
2259 | struct TCP_Server_Info *server = ses->server; | 2261 | struct TCP_Server_Info *server = ses->server; |
2260 | 2262 | ||
2261 | cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count); | 2263 | cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count); |
2264 | |||
2262 | spin_lock(&cifs_tcp_ses_lock); | 2265 | spin_lock(&cifs_tcp_ses_lock); |
2266 | if (ses->status == CifsExiting) { | ||
2267 | spin_unlock(&cifs_tcp_ses_lock); | ||
2268 | return; | ||
2269 | } | ||
2263 | if (--ses->ses_count > 0) { | 2270 | if (--ses->ses_count > 0) { |
2264 | spin_unlock(&cifs_tcp_ses_lock); | 2271 | spin_unlock(&cifs_tcp_ses_lock); |
2265 | return; | 2272 | return; |
2266 | } | 2273 | } |
2267 | 2274 | if (ses->status == CifsGood) | |
2268 | list_del_init(&ses->smb_ses_list); | 2275 | ses->status = CifsExiting; |
2269 | spin_unlock(&cifs_tcp_ses_lock); | 2276 | spin_unlock(&cifs_tcp_ses_lock); |
2270 | 2277 | ||
2271 | if (ses->status == CifsGood && server->ops->logoff) { | 2278 | if (ses->status == CifsExiting && server->ops->logoff) { |
2272 | xid = get_xid(); | 2279 | xid = get_xid(); |
2273 | server->ops->logoff(xid, ses); | 2280 | rc = server->ops->logoff(xid, ses); |
2281 | if (rc) | ||
2282 | cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n", | ||
2283 | __func__, rc); | ||
2274 | _free_xid(xid); | 2284 | _free_xid(xid); |
2275 | } | 2285 | } |
2286 | |||
2287 | spin_lock(&cifs_tcp_ses_lock); | ||
2288 | list_del_init(&ses->smb_ses_list); | ||
2289 | spin_unlock(&cifs_tcp_ses_lock); | ||
2290 | |||
2276 | sesInfoFree(ses); | 2291 | sesInfoFree(ses); |
2277 | cifs_put_tcp_session(server); | 2292 | cifs_put_tcp_session(server); |
2278 | } | 2293 | } |
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index c523617eade2..59c748ce872f 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c | |||
@@ -516,13 +516,19 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf, | |||
516 | return -EAGAIN; | 516 | return -EAGAIN; |
517 | } | 517 | } |
518 | 518 | ||
519 | if (ses->status != CifsGood) { | 519 | if (ses->status == CifsNew) { |
520 | /* check if SMB2 session is bad because we are setting it up */ | ||
521 | if ((buf->Command != SMB2_SESSION_SETUP) && | 520 | if ((buf->Command != SMB2_SESSION_SETUP) && |
522 | (buf->Command != SMB2_NEGOTIATE)) | 521 | (buf->Command != SMB2_NEGOTIATE)) |
523 | return -EAGAIN; | 522 | return -EAGAIN; |
524 | /* else ok - we are setting up session */ | 523 | /* else ok - we are setting up session */ |
525 | } | 524 | } |
525 | |||
526 | if (ses->status == CifsExiting) { | ||
527 | if (buf->Command != SMB2_LOGOFF) | ||
528 | return -EAGAIN; | ||
529 | /* else ok - we are shutting down the session */ | ||
530 | } | ||
531 | |||
526 | *mid = smb2_mid_entry_alloc(buf, ses->server); | 532 | *mid = smb2_mid_entry_alloc(buf, ses->server); |
527 | if (*mid == NULL) | 533 | if (*mid == NULL) |
528 | return -ENOMEM; | 534 | return -ENOMEM; |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 0ee6d249ef6f..b37570952846 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -431,13 +431,20 @@ static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, | |||
431 | return -EAGAIN; | 431 | return -EAGAIN; |
432 | } | 432 | } |
433 | 433 | ||
434 | if (ses->status != CifsGood) { | 434 | if (ses->status == CifsNew) { |
435 | /* check if SMB session is bad because we are setting it up */ | ||
436 | if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && | 435 | if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && |
437 | (in_buf->Command != SMB_COM_NEGOTIATE)) | 436 | (in_buf->Command != SMB_COM_NEGOTIATE)) |
438 | return -EAGAIN; | 437 | return -EAGAIN; |
439 | /* else ok - we are setting up session */ | 438 | /* else ok - we are setting up session */ |
440 | } | 439 | } |
440 | |||
441 | if (ses->status == CifsExiting) { | ||
442 | /* check if SMB session is bad because we are setting it up */ | ||
443 | if (in_buf->Command != SMB_COM_LOGOFF_ANDX) | ||
444 | return -EAGAIN; | ||
445 | /* else ok - we are shutting down session */ | ||
446 | } | ||
447 | |||
441 | *ppmidQ = AllocMidQEntry(in_buf, ses->server); | 448 | *ppmidQ = AllocMidQEntry(in_buf, ses->server); |
442 | if (*ppmidQ == NULL) | 449 | if (*ppmidQ == NULL) |
443 | return -ENOMEM; | 450 | return -ENOMEM; |