diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifs_debug.c | 2 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 3 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 17 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 18 | ||||
-rw-r--r-- | fs/cifs/connect.c | 205 |
6 files changed, 96 insertions, 150 deletions
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index ba8723d95996..40b5108fb4f9 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
@@ -144,7 +144,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
144 | seq_printf(m, "TCP status: %d\n\tLocal Users To " | 144 | seq_printf(m, "TCP status: %d\n\tLocal Users To " |
145 | "Server: %d SecMode: 0x%x Req On Wire: %d", | 145 | "Server: %d SecMode: 0x%x Req On Wire: %d", |
146 | ses->server->tcpStatus, | 146 | ses->server->tcpStatus, |
147 | atomic_read(&ses->server->socketUseCount), | 147 | ses->server->srv_count, |
148 | ses->server->secMode, | 148 | ses->server->secMode, |
149 | atomic_read(&ses->server->inFlight)); | 149 | atomic_read(&ses->server->inFlight)); |
150 | 150 | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index af16a2406b1c..2946dab0718f 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -1059,7 +1059,7 @@ init_cifs(void) | |||
1059 | { | 1059 | { |
1060 | int rc = 0; | 1060 | int rc = 0; |
1061 | cifs_proc_init(); | 1061 | cifs_proc_init(); |
1062 | INIT_LIST_HEAD(&global_cifs_sock_list); | 1062 | INIT_LIST_HEAD(&cifs_tcp_ses_list); |
1063 | INIT_LIST_HEAD(&GlobalSMBSessionList); /* BB to be removed by jl */ | 1063 | INIT_LIST_HEAD(&GlobalSMBSessionList); /* BB to be removed by jl */ |
1064 | INIT_LIST_HEAD(&GlobalTreeConnectionList); /* BB to be removed by jl */ | 1064 | INIT_LIST_HEAD(&GlobalTreeConnectionList); /* BB to be removed by jl */ |
1065 | INIT_LIST_HEAD(&GlobalOplock_Q); | 1065 | INIT_LIST_HEAD(&GlobalOplock_Q); |
@@ -1089,6 +1089,7 @@ init_cifs(void) | |||
1089 | GlobalMaxActiveXid = 0; | 1089 | GlobalMaxActiveXid = 0; |
1090 | memset(Local_System_Name, 0, 15); | 1090 | memset(Local_System_Name, 0, 15); |
1091 | rwlock_init(&GlobalSMBSeslock); | 1091 | rwlock_init(&GlobalSMBSeslock); |
1092 | rwlock_init(&cifs_tcp_ses_lock); | ||
1092 | spin_lock_init(&GlobalMid_Lock); | 1093 | spin_lock_init(&GlobalMid_Lock); |
1093 | 1094 | ||
1094 | if (cifs_max_pending < 2) { | 1095 | if (cifs_max_pending < 2) { |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 13dc48414a78..313f7bfedec7 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -123,6 +123,7 @@ struct cifs_cred { | |||
123 | struct TCP_Server_Info { | 123 | struct TCP_Server_Info { |
124 | struct list_head tcp_ses_list; | 124 | struct list_head tcp_ses_list; |
125 | struct list_head smb_ses_list; | 125 | struct list_head smb_ses_list; |
126 | int srv_count; /* reference counter */ | ||
126 | /* 15 character server name + 0x20 16th byte indicating type = srv */ | 127 | /* 15 character server name + 0x20 16th byte indicating type = srv */ |
127 | char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; | 128 | char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; |
128 | char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; | 129 | char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; |
@@ -144,7 +145,6 @@ struct TCP_Server_Info { | |||
144 | bool svlocal:1; /* local server or remote */ | 145 | bool svlocal:1; /* local server or remote */ |
145 | bool noblocksnd; /* use blocking sendmsg */ | 146 | bool noblocksnd; /* use blocking sendmsg */ |
146 | bool noautotune; /* do not autotune send buf sizes */ | 147 | bool noautotune; /* do not autotune send buf sizes */ |
147 | atomic_t socketUseCount; /* number of open cifs sessions on socket */ | ||
148 | atomic_t inFlight; /* number of requests on the wire to server */ | 148 | atomic_t inFlight; /* number of requests on the wire to server */ |
149 | #ifdef CONFIG_CIFS_STATS2 | 149 | #ifdef CONFIG_CIFS_STATS2 |
150 | atomic_t inSend; /* requests trying to send */ | 150 | atomic_t inSend; /* requests trying to send */ |
@@ -591,13 +591,18 @@ require use of the stronger protocol */ | |||
591 | #define GLOBAL_EXTERN extern | 591 | #define GLOBAL_EXTERN extern |
592 | #endif | 592 | #endif |
593 | 593 | ||
594 | 594 | /* | |
595 | /* the list of TCP_Server_Info structures, ie each of the sockets | 595 | * the list of TCP_Server_Info structures, ie each of the sockets |
596 | * connecting our client to a distinct server (ip address), is | 596 | * connecting our client to a distinct server (ip address), is |
597 | * chained together by global_cifs_sock_list. The list of all our SMB | 597 | * chained together by cifs_tcp_ses_list. The list of all our SMB |
598 | * sessions (and from that the tree connections) can be found | 598 | * sessions (and from that the tree connections) can be found |
599 | * by iterating over global_cifs_sock_list */ | 599 | * by iterating over cifs_tcp_ses_list |
600 | GLOBAL_EXTERN struct list_head global_cifs_sock_list; | 600 | */ |
601 | GLOBAL_EXTERN struct list_head cifs_tcp_ses_list; | ||
602 | |||
603 | /* protects cifs_tcp_ses_list and srv_count for each tcp session */ | ||
604 | GLOBAL_EXTERN rwlock_t cifs_tcp_ses_lock; | ||
605 | |||
601 | GLOBAL_EXTERN struct list_head GlobalSMBSessionList; /* BB to be removed by jl*/ | 606 | GLOBAL_EXTERN struct list_head GlobalSMBSessionList; /* BB to be removed by jl*/ |
602 | GLOBAL_EXTERN struct list_head GlobalTreeConnectionList; /* BB to be removed */ | 607 | GLOBAL_EXTERN struct list_head GlobalTreeConnectionList; /* BB to be removed */ |
603 | GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */ | 608 | GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */ |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 6f21ecb85ce5..0250a994c6e6 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -102,6 +102,7 @@ extern void acl_to_uid_mode(struct inode *inode, const char *path, | |||
102 | const __u16 *pfid); | 102 | const __u16 *pfid); |
103 | extern int mode_to_acl(struct inode *inode, const char *path, __u64); | 103 | extern int mode_to_acl(struct inode *inode, const char *path, __u64); |
104 | 104 | ||
105 | extern void cifs_put_tcp_session(struct TCP_Server_Info *server); | ||
105 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, | 106 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, |
106 | const char *); | 107 | const char *); |
107 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); | 108 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 7f0651b69573..cd9e9a145e4d 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -664,8 +664,9 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
664 | rc = -EIO; | 664 | rc = -EIO; |
665 | goto neg_err_exit; | 665 | goto neg_err_exit; |
666 | } | 666 | } |
667 | 667 | read_lock(&cifs_tcp_ses_lock); | |
668 | if (server->socketUseCount.counter > 1) { | 668 | if (server->srv_count > 1) { |
669 | read_unlock(&cifs_tcp_ses_lock); | ||
669 | if (memcmp(server->server_GUID, | 670 | if (memcmp(server->server_GUID, |
670 | pSMBr->u.extended_response. | 671 | pSMBr->u.extended_response. |
671 | GUID, 16) != 0) { | 672 | GUID, 16) != 0) { |
@@ -674,9 +675,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
674 | pSMBr->u.extended_response.GUID, | 675 | pSMBr->u.extended_response.GUID, |
675 | 16); | 676 | 16); |
676 | } | 677 | } |
677 | } else | 678 | } else { |
679 | read_unlock(&cifs_tcp_ses_lock); | ||
678 | memcpy(server->server_GUID, | 680 | memcpy(server->server_GUID, |
679 | pSMBr->u.extended_response.GUID, 16); | 681 | pSMBr->u.extended_response.GUID, 16); |
682 | } | ||
680 | 683 | ||
681 | if (count == 16) { | 684 | if (count == 16) { |
682 | server->secType = RawNTLMSSP; | 685 | server->secType = RawNTLMSSP; |
@@ -830,12 +833,9 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
830 | pSMB->AndXCommand = 0xFF; | 833 | pSMB->AndXCommand = 0xFF; |
831 | rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); | 834 | rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); |
832 | session_already_dead: | 835 | session_already_dead: |
833 | atomic_dec(&ses->server->socketUseCount); | 836 | if (ses->server) { |
834 | if (atomic_read(&ses->server->socketUseCount) == 0) { | 837 | cifs_put_tcp_session(ses->server); |
835 | spin_lock(&GlobalMid_Lock); | 838 | rc = 0; |
836 | ses->server->tcpStatus = CifsExiting; | ||
837 | spin_unlock(&GlobalMid_Lock); | ||
838 | rc = -ESHUTDOWN; | ||
839 | } | 839 | } |
840 | up(&ses->sesSem); | 840 | up(&ses->sesSem); |
841 | 841 | ||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 30ab8dc68e17..a0314259f94d 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -659,6 +659,11 @@ multi_t2_fnd: | |||
659 | } | 659 | } |
660 | } /* end while !EXITING */ | 660 | } /* end while !EXITING */ |
661 | 661 | ||
662 | /* take it off the list, if it's not already */ | ||
663 | write_lock(&cifs_tcp_ses_lock); | ||
664 | list_del_init(&server->tcp_ses_list); | ||
665 | write_unlock(&cifs_tcp_ses_lock); | ||
666 | |||
662 | spin_lock(&GlobalMid_Lock); | 667 | spin_lock(&GlobalMid_Lock); |
663 | server->tcpStatus = CifsExiting; | 668 | server->tcpStatus = CifsExiting; |
664 | spin_unlock(&GlobalMid_Lock); | 669 | spin_unlock(&GlobalMid_Lock); |
@@ -1357,92 +1362,66 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1357 | return 0; | 1362 | return 0; |
1358 | } | 1363 | } |
1359 | 1364 | ||
1360 | static struct cifsSesInfo * | 1365 | static struct TCP_Server_Info * |
1361 | cifs_find_tcp_session(struct in_addr *target_ip_addr, | 1366 | cifs_find_tcp_session(struct sockaddr *addr) |
1362 | struct in6_addr *target_ip6_addr, | ||
1363 | char *userName, struct TCP_Server_Info **psrvTcp) | ||
1364 | { | 1367 | { |
1365 | struct list_head *tmp; | 1368 | struct list_head *tmp; |
1366 | struct cifsSesInfo *ses; | 1369 | struct TCP_Server_Info *server; |
1367 | 1370 | struct sockaddr_in *addr4 = (struct sockaddr_in *) addr; | |
1368 | *psrvTcp = NULL; | 1371 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr; |
1369 | 1372 | ||
1370 | read_lock(&GlobalSMBSeslock); | 1373 | write_lock(&cifs_tcp_ses_lock); |
1371 | list_for_each(tmp, &GlobalSMBSessionList) { | 1374 | list_for_each(tmp, &cifs_tcp_ses_list) { |
1372 | ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); | 1375 | server = list_entry(tmp, struct TCP_Server_Info, |
1373 | if (!ses->server) | 1376 | tcp_ses_list); |
1377 | |||
1378 | /* | ||
1379 | * the demux thread can exit on its own while still in CifsNew | ||
1380 | * so don't accept any sockets in that state. Since the | ||
1381 | * tcpStatus never changes back to CifsNew it's safe to check | ||
1382 | * for this without a lock. | ||
1383 | */ | ||
1384 | if (server->tcpStatus == CifsNew) | ||
1374 | continue; | 1385 | continue; |
1375 | 1386 | ||
1376 | if (target_ip_addr && | 1387 | if (addr->sa_family == AF_INET && |
1377 | ses->server->addr.sockAddr.sin_addr.s_addr != target_ip_addr->s_addr) | 1388 | (addr4->sin_addr.s_addr != |
1378 | continue; | 1389 | server->addr.sockAddr.sin_addr.s_addr)) |
1379 | else if (target_ip6_addr && | 1390 | continue; |
1380 | memcmp(&ses->server->addr.sockAddr6.sin6_addr, | 1391 | else if (addr->sa_family == AF_INET6 && |
1381 | target_ip6_addr, sizeof(*target_ip6_addr))) | 1392 | memcmp(&server->addr.sockAddr6.sin6_addr, |
1382 | continue; | 1393 | &addr6->sin6_addr, sizeof(addr6->sin6_addr))) |
1383 | /* BB lock server and tcp session; increment use count here?? */ | 1394 | continue; |
1384 | |||
1385 | /* found a match on the TCP session */ | ||
1386 | *psrvTcp = ses->server; | ||
1387 | 1395 | ||
1388 | /* BB check if reconnection needed */ | 1396 | ++server->srv_count; |
1389 | if (strncmp(ses->userName, userName, MAX_USERNAME_SIZE) == 0) { | 1397 | write_unlock(&cifs_tcp_ses_lock); |
1390 | read_unlock(&GlobalSMBSeslock); | 1398 | return server; |
1391 | /* Found exact match on both TCP and | ||
1392 | SMB sessions */ | ||
1393 | return ses; | ||
1394 | } | ||
1395 | /* else tcp and smb sessions need reconnection */ | ||
1396 | } | 1399 | } |
1397 | read_unlock(&GlobalSMBSeslock); | 1400 | write_unlock(&cifs_tcp_ses_lock); |
1398 | |||
1399 | return NULL; | 1401 | return NULL; |
1400 | } | 1402 | } |
1401 | 1403 | ||
1402 | static struct cifsTconInfo * | 1404 | void |
1403 | find_unc(__be32 new_target_ip_addr, char *uncName, char *userName) | 1405 | cifs_put_tcp_session(struct TCP_Server_Info *server) |
1404 | { | 1406 | { |
1405 | struct list_head *tmp; | 1407 | struct task_struct *task; |
1406 | struct cifsTconInfo *tcon; | ||
1407 | __be32 old_ip; | ||
1408 | |||
1409 | read_lock(&GlobalSMBSeslock); | ||
1410 | |||
1411 | list_for_each(tmp, &GlobalTreeConnectionList) { | ||
1412 | cFYI(1, ("Next tcon")); | ||
1413 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); | ||
1414 | if (!tcon->ses || !tcon->ses->server) | ||
1415 | continue; | ||
1416 | |||
1417 | old_ip = tcon->ses->server->addr.sockAddr.sin_addr.s_addr; | ||
1418 | cFYI(1, ("old ip addr: %x == new ip %x ?", | ||
1419 | old_ip, new_target_ip_addr)); | ||
1420 | |||
1421 | if (old_ip != new_target_ip_addr) | ||
1422 | continue; | ||
1423 | |||
1424 | /* BB lock tcon, server, tcp session and increment use count? */ | ||
1425 | /* found a match on the TCP session */ | ||
1426 | /* BB check if reconnection needed */ | ||
1427 | cFYI(1, ("IP match, old UNC: %s new: %s", | ||
1428 | tcon->treeName, uncName)); | ||
1429 | 1408 | ||
1430 | if (strncmp(tcon->treeName, uncName, MAX_TREE_SIZE)) | 1409 | write_lock(&cifs_tcp_ses_lock); |
1431 | continue; | 1410 | if (--server->srv_count > 0) { |
1411 | write_unlock(&cifs_tcp_ses_lock); | ||
1412 | return; | ||
1413 | } | ||
1432 | 1414 | ||
1433 | cFYI(1, ("and old usr: %s new: %s", | 1415 | list_del_init(&server->tcp_ses_list); |
1434 | tcon->treeName, uncName)); | 1416 | write_unlock(&cifs_tcp_ses_lock); |
1435 | 1417 | ||
1436 | if (strncmp(tcon->ses->userName, userName, MAX_USERNAME_SIZE)) | 1418 | spin_lock(&GlobalMid_Lock); |
1437 | continue; | 1419 | server->tcpStatus = CifsExiting; |
1438 | 1420 | spin_unlock(&GlobalMid_Lock); | |
1439 | /* matched smb session (user name) */ | ||
1440 | read_unlock(&GlobalSMBSeslock); | ||
1441 | return tcon; | ||
1442 | } | ||
1443 | 1421 | ||
1444 | read_unlock(&GlobalSMBSeslock); | 1422 | task = xchg(&server->tsk, NULL); |
1445 | return NULL; | 1423 | if (task) |
1424 | force_sig(SIGKILL, task); | ||
1446 | } | 1425 | } |
1447 | 1426 | ||
1448 | int | 1427 | int |
@@ -1881,16 +1860,6 @@ convert_delimiter(char *path, char delim) | |||
1881 | } | 1860 | } |
1882 | } | 1861 | } |
1883 | 1862 | ||
1884 | static void | ||
1885 | kill_cifsd(struct TCP_Server_Info *server) | ||
1886 | { | ||
1887 | struct task_struct *task; | ||
1888 | |||
1889 | task = xchg(&server->tsk, NULL); | ||
1890 | if (task) | ||
1891 | force_sig(SIGKILL, task); | ||
1892 | } | ||
1893 | |||
1894 | static void setup_cifs_sb(struct smb_vol *pvolume_info, | 1863 | static void setup_cifs_sb(struct smb_vol *pvolume_info, |
1895 | struct cifs_sb_info *cifs_sb) | 1864 | struct cifs_sb_info *cifs_sb) |
1896 | { | 1865 | { |
@@ -2069,21 +2038,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2069 | } | 2038 | } |
2070 | } | 2039 | } |
2071 | 2040 | ||
2072 | if (addr.sa_family == AF_INET) | 2041 | srvTcp = cifs_find_tcp_session(&addr); |
2073 | existingCifsSes = cifs_find_tcp_session(&sin_server->sin_addr, | 2042 | if (srvTcp) { |
2074 | NULL /* no ipv6 addr */, | 2043 | cFYI(1, ("Existing tcp session with server found")); |
2075 | volume_info.username, &srvTcp); | 2044 | } else { /* create socket */ |
2076 | else if (addr.sa_family == AF_INET6) { | ||
2077 | cFYI(1, ("looking for ipv6 address")); | ||
2078 | existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */, | ||
2079 | &sin_server6->sin6_addr, | ||
2080 | volume_info.username, &srvTcp); | ||
2081 | } else { | ||
2082 | rc = -EINVAL; | ||
2083 | goto out; | ||
2084 | } | ||
2085 | |||
2086 | if (!srvTcp) { | ||
2087 | if (addr.sa_family == AF_INET6) { | 2045 | if (addr.sa_family == AF_INET6) { |
2088 | cFYI(1, ("attempting ipv6 connect")); | 2046 | cFYI(1, ("attempting ipv6 connect")); |
2089 | /* BB should we allow ipv6 on port 139? */ | 2047 | /* BB should we allow ipv6 on port 139? */ |
@@ -2153,6 +2111,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2153 | memcpy(srvTcp->server_RFC1001_name, | 2111 | memcpy(srvTcp->server_RFC1001_name, |
2154 | volume_info.target_rfc1001_name, 16); | 2112 | volume_info.target_rfc1001_name, 16); |
2155 | srvTcp->sequence_number = 0; | 2113 | srvTcp->sequence_number = 0; |
2114 | INIT_LIST_HEAD(&srvTcp->tcp_ses_list); | ||
2115 | ++srvTcp->srv_count; | ||
2116 | write_lock(&cifs_tcp_ses_lock); | ||
2117 | list_add(&srvTcp->tcp_ses_list, | ||
2118 | &cifs_tcp_ses_list); | ||
2119 | write_unlock(&cifs_tcp_ses_lock); | ||
2156 | } | 2120 | } |
2157 | } | 2121 | } |
2158 | 2122 | ||
@@ -2204,8 +2168,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2204 | rc = cifs_setup_session(xid, pSesInfo, | 2168 | rc = cifs_setup_session(xid, pSesInfo, |
2205 | cifs_sb->local_nls); | 2169 | cifs_sb->local_nls); |
2206 | up(&pSesInfo->sesSem); | 2170 | up(&pSesInfo->sesSem); |
2207 | if (!rc) | ||
2208 | atomic_inc(&srvTcp->socketUseCount); | ||
2209 | } | 2171 | } |
2210 | } | 2172 | } |
2211 | 2173 | ||
@@ -2213,9 +2175,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2213 | if (!rc) { | 2175 | if (!rc) { |
2214 | setup_cifs_sb(&volume_info, cifs_sb); | 2176 | setup_cifs_sb(&volume_info, cifs_sb); |
2215 | 2177 | ||
2216 | tcon = | ||
2217 | find_unc(sin_server->sin_addr.s_addr, volume_info.UNC, | ||
2218 | volume_info.username); | ||
2219 | if (tcon) { | 2178 | if (tcon) { |
2220 | cFYI(1, ("Found match on UNC path")); | 2179 | cFYI(1, ("Found match on UNC path")); |
2221 | if (tcon->seal != volume_info.seal) | 2180 | if (tcon->seal != volume_info.seal) |
@@ -2278,35 +2237,21 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2278 | /* on error free sesinfo and tcon struct if needed */ | 2237 | /* on error free sesinfo and tcon struct if needed */ |
2279 | mount_fail_check: | 2238 | mount_fail_check: |
2280 | if (rc) { | 2239 | if (rc) { |
2281 | /* if session setup failed, use count is zero but | 2240 | /* If find_unc succeeded then rc == 0 so we can not end */ |
2282 | we still need to free cifsd thread */ | 2241 | /* up accidently freeing someone elses tcon struct */ |
2283 | if (atomic_read(&srvTcp->socketUseCount) == 0) { | 2242 | if (tcon) |
2284 | spin_lock(&GlobalMid_Lock); | ||
2285 | srvTcp->tcpStatus = CifsExiting; | ||
2286 | spin_unlock(&GlobalMid_Lock); | ||
2287 | kill_cifsd(srvTcp); | ||
2288 | } | ||
2289 | /* If find_unc succeeded then rc == 0 so we can not end */ | ||
2290 | if (tcon) /* up accidently freeing someone elses tcon struct */ | ||
2291 | tconInfoFree(tcon); | 2243 | tconInfoFree(tcon); |
2244 | |||
2292 | if (existingCifsSes == NULL) { | 2245 | if (existingCifsSes == NULL) { |
2293 | if (pSesInfo) { | 2246 | if (pSesInfo) { |
2294 | if ((pSesInfo->server) && | 2247 | if ((pSesInfo->server) && |
2295 | (pSesInfo->status == CifsGood)) { | 2248 | (pSesInfo->status == CifsGood)) |
2296 | int temp_rc; | 2249 | CIFSSMBLogoff(xid, pSesInfo); |
2297 | temp_rc = CIFSSMBLogoff(xid, pSesInfo); | 2250 | else { |
2298 | /* if the socketUseCount is now zero */ | ||
2299 | if ((temp_rc == -ESHUTDOWN) && | ||
2300 | (pSesInfo->server)) | ||
2301 | kill_cifsd(pSesInfo->server); | ||
2302 | } else { | ||
2303 | cFYI(1, ("No session or bad tcon")); | 2251 | cFYI(1, ("No session or bad tcon")); |
2304 | if (pSesInfo->server) { | 2252 | if (pSesInfo->server) |
2305 | spin_lock(&GlobalMid_Lock); | 2253 | cifs_put_tcp_session( |
2306 | srvTcp->tcpStatus = CifsExiting; | 2254 | pSesInfo->server); |
2307 | spin_unlock(&GlobalMid_Lock); | ||
2308 | kill_cifsd(pSesInfo->server); | ||
2309 | } | ||
2310 | } | 2255 | } |
2311 | sesInfoFree(pSesInfo); | 2256 | sesInfoFree(pSesInfo); |
2312 | /* pSesInfo = NULL; */ | 2257 | /* pSesInfo = NULL; */ |
@@ -3613,13 +3558,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
3613 | if (rc == -EBUSY) { | 3558 | if (rc == -EBUSY) { |
3614 | FreeXid(xid); | 3559 | FreeXid(xid); |
3615 | return 0; | 3560 | return 0; |
3616 | } else if (rc == -ESHUTDOWN) { | 3561 | } |
3617 | cFYI(1, ("Waking up socket by sending signal")); | ||
3618 | if (ses->server) | ||
3619 | kill_cifsd(ses->server); | ||
3620 | rc = 0; | ||
3621 | } /* else - we have an smb session | ||
3622 | left on this socket do not kill cifsd */ | ||
3623 | } else | 3562 | } else |
3624 | cFYI(1, ("No session or bad tcon")); | 3563 | cFYI(1, ("No session or bad tcon")); |
3625 | } | 3564 | } |