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/connect.c | |
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/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 25 |
1 files changed, 20 insertions, 5 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 | } |