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 | |
| 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>
| -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; |
