aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c94
1 files changed, 55 insertions, 39 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4c13bcdb92a5..71b7661e2260 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -90,6 +90,8 @@ struct smb_vol {
90 bool nocase:1; /* request case insensitive filenames */ 90 bool nocase:1; /* request case insensitive filenames */
91 bool nobrl:1; /* disable sending byte range locks to srv */ 91 bool nobrl:1; /* disable sending byte range locks to srv */
92 bool seal:1; /* request transport encryption on share */ 92 bool seal:1; /* request transport encryption on share */
93 bool nodfs:1; /* Do not request DFS, even if available */
94 bool local_lease:1; /* check leases only on local system, not remote */
93 unsigned int rsize; 95 unsigned int rsize;
94 unsigned int wsize; 96 unsigned int wsize;
95 unsigned int sockopt; 97 unsigned int sockopt;
@@ -124,7 +126,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
124 struct mid_q_entry *mid_entry; 126 struct mid_q_entry *mid_entry;
125 127
126 spin_lock(&GlobalMid_Lock); 128 spin_lock(&GlobalMid_Lock);
127 if (kthread_should_stop()) { 129 if (server->tcpStatus == CifsExiting) {
128 /* the demux thread will exit normally 130 /* the demux thread will exit normally
129 next time through the loop */ 131 next time through the loop */
130 spin_unlock(&GlobalMid_Lock); 132 spin_unlock(&GlobalMid_Lock);
@@ -184,7 +186,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
184 spin_unlock(&GlobalMid_Lock); 186 spin_unlock(&GlobalMid_Lock);
185 up(&server->tcpSem); 187 up(&server->tcpSem);
186 188
187 while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) { 189 while ((server->tcpStatus != CifsExiting) &&
190 (server->tcpStatus != CifsGood)) {
188 try_to_freeze(); 191 try_to_freeze();
189 if (server->protocolType == IPV6) { 192 if (server->protocolType == IPV6) {
190 rc = ipv6_connect(&server->addr.sockAddr6, 193 rc = ipv6_connect(&server->addr.sockAddr6,
@@ -201,7 +204,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
201 } else { 204 } else {
202 atomic_inc(&tcpSesReconnectCount); 205 atomic_inc(&tcpSesReconnectCount);
203 spin_lock(&GlobalMid_Lock); 206 spin_lock(&GlobalMid_Lock);
204 if (!kthread_should_stop()) 207 if (server->tcpStatus != CifsExiting)
205 server->tcpStatus = CifsGood; 208 server->tcpStatus = CifsGood;
206 server->sequence_number = 0; 209 server->sequence_number = 0;
207 spin_unlock(&GlobalMid_Lock); 210 spin_unlock(&GlobalMid_Lock);
@@ -356,7 +359,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
356 GFP_KERNEL); 359 GFP_KERNEL);
357 360
358 set_freezable(); 361 set_freezable();
359 while (!kthread_should_stop()) { 362 while (server->tcpStatus != CifsExiting) {
360 if (try_to_freeze()) 363 if (try_to_freeze())
361 continue; 364 continue;
362 if (bigbuf == NULL) { 365 if (bigbuf == NULL) {
@@ -397,7 +400,7 @@ incomplete_rcv:
397 kernel_recvmsg(csocket, &smb_msg, 400 kernel_recvmsg(csocket, &smb_msg,
398 &iov, 1, pdu_length, 0 /* BB other flags? */); 401 &iov, 1, pdu_length, 0 /* BB other flags? */);
399 402
400 if (kthread_should_stop()) { 403 if (server->tcpStatus == CifsExiting) {
401 break; 404 break;
402 } else if (server->tcpStatus == CifsNeedReconnect) { 405 } else if (server->tcpStatus == CifsNeedReconnect) {
403 cFYI(1, ("Reconnect after server stopped responding")); 406 cFYI(1, ("Reconnect after server stopped responding"));
@@ -522,7 +525,7 @@ incomplete_rcv:
522 total_read += length) { 525 total_read += length) {
523 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, 526 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
524 pdu_length - total_read, 0); 527 pdu_length - total_read, 0);
525 if (kthread_should_stop() || 528 if ((server->tcpStatus == CifsExiting) ||
526 (length == -EINTR)) { 529 (length == -EINTR)) {
527 /* then will exit */ 530 /* then will exit */
528 reconnect = 2; 531 reconnect = 2;
@@ -651,14 +654,6 @@ multi_t2_fnd:
651 spin_unlock(&GlobalMid_Lock); 654 spin_unlock(&GlobalMid_Lock);
652 wake_up_all(&server->response_q); 655 wake_up_all(&server->response_q);
653 656
654 /* don't exit until kthread_stop is called */
655 set_current_state(TASK_UNINTERRUPTIBLE);
656 while (!kthread_should_stop()) {
657 schedule();
658 set_current_state(TASK_UNINTERRUPTIBLE);
659 }
660 set_current_state(TASK_RUNNING);
661
662 /* check if we have blocked requests that need to free */ 657 /* check if we have blocked requests that need to free */
663 /* Note that cifs_max_pending is normally 50, but 658 /* Note that cifs_max_pending is normally 50, but
664 can be set at module install time to as little as two */ 659 can be set at module install time to as little as two */
@@ -755,6 +750,7 @@ multi_t2_fnd:
755 write_unlock(&GlobalSMBSeslock); 750 write_unlock(&GlobalSMBSeslock);
756 751
757 kfree(server->hostname); 752 kfree(server->hostname);
753 task_to_wake = xchg(&server->tsk, NULL);
758 kfree(server); 754 kfree(server);
759 755
760 length = atomic_dec_return(&tcpSesAllocCount); 756 length = atomic_dec_return(&tcpSesAllocCount);
@@ -762,6 +758,16 @@ multi_t2_fnd:
762 mempool_resize(cifs_req_poolp, length + cifs_min_rcv, 758 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
763 GFP_KERNEL); 759 GFP_KERNEL);
764 760
761 /* if server->tsk was NULL then wait for a signal before exiting */
762 if (!task_to_wake) {
763 set_current_state(TASK_INTERRUPTIBLE);
764 while (!signal_pending(current)) {
765 schedule();
766 set_current_state(TASK_INTERRUPTIBLE);
767 }
768 set_current_state(TASK_RUNNING);
769 }
770
765 return 0; 771 return 0;
766} 772}
767 773
@@ -1218,6 +1224,8 @@ cifs_parse_mount_options(char *options, const char *devname,
1218 vol->sfu_emul = 1; 1224 vol->sfu_emul = 1;
1219 } else if (strnicmp(data, "nosfu", 5) == 0) { 1225 } else if (strnicmp(data, "nosfu", 5) == 0) {
1220 vol->sfu_emul = 0; 1226 vol->sfu_emul = 0;
1227 } else if (strnicmp(data, "nodfs", 5) == 0) {
1228 vol->nodfs = 1;
1221 } else if (strnicmp(data, "posixpaths", 10) == 0) { 1229 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1222 vol->posix_paths = 1; 1230 vol->posix_paths = 1;
1223 } else if (strnicmp(data, "noposixpaths", 12) == 0) { 1231 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
@@ -1268,6 +1276,10 @@ cifs_parse_mount_options(char *options, const char *devname,
1268 vol->no_psx_acl = 0; 1276 vol->no_psx_acl = 0;
1269 } else if (strnicmp(data, "noacl", 5) == 0) { 1277 } else if (strnicmp(data, "noacl", 5) == 0) {
1270 vol->no_psx_acl = 1; 1278 vol->no_psx_acl = 1;
1279#ifdef CONFIG_CIFS_EXPERIMENTAL
1280 } else if (strnicmp(data, "locallease", 6) == 0) {
1281 vol->local_lease = 1;
1282#endif
1271 } else if (strnicmp(data, "sign", 4) == 0) { 1283 } else if (strnicmp(data, "sign", 4) == 0) {
1272 vol->secFlg |= CIFSSEC_MUST_SIGN; 1284 vol->secFlg |= CIFSSEC_MUST_SIGN;
1273 } else if (strnicmp(data, "seal", 4) == 0) { 1285 } else if (strnicmp(data, "seal", 4) == 0) {
@@ -1845,6 +1857,16 @@ convert_delimiter(char *path, char delim)
1845 } 1857 }
1846} 1858}
1847 1859
1860static void
1861kill_cifsd(struct TCP_Server_Info *server)
1862{
1863 struct task_struct *task;
1864
1865 task = xchg(&server->tsk, NULL);
1866 if (task)
1867 force_sig(SIGKILL, task);
1868}
1869
1848int 1870int
1849cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, 1871cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1850 char *mount_data, const char *devname) 1872 char *mount_data, const char *devname)
@@ -2166,6 +2188,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2166 for the retry flag is used */ 2188 for the retry flag is used */
2167 tcon->retry = volume_info.retry; 2189 tcon->retry = volume_info.retry;
2168 tcon->nocase = volume_info.nocase; 2190 tcon->nocase = volume_info.nocase;
2191 tcon->local_lease = volume_info.local_lease;
2169 if (tcon->seal != volume_info.seal) 2192 if (tcon->seal != volume_info.seal)
2170 cERROR(1, ("transport encryption setting " 2193 cERROR(1, ("transport encryption setting "
2171 "conflicts with existing tid")); 2194 "conflicts with existing tid"));
@@ -2197,6 +2220,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2197 volume_info.UNC, 2220 volume_info.UNC,
2198 tcon, cifs_sb->local_nls); 2221 tcon, cifs_sb->local_nls);
2199 cFYI(1, ("CIFS Tcon rc = %d", rc)); 2222 cFYI(1, ("CIFS Tcon rc = %d", rc));
2223 if (volume_info.nodfs) {
2224 tcon->Flags &=
2225 ~SMB_SHARE_IS_IN_DFS;
2226 cFYI(1, ("DFS disabled (%d)",
2227 tcon->Flags));
2228 }
2200 } 2229 }
2201 if (!rc) { 2230 if (!rc) {
2202 atomic_inc(&pSesInfo->inUse); 2231 atomic_inc(&pSesInfo->inUse);
@@ -2225,14 +2254,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2225 spin_lock(&GlobalMid_Lock); 2254 spin_lock(&GlobalMid_Lock);
2226 srvTcp->tcpStatus = CifsExiting; 2255 srvTcp->tcpStatus = CifsExiting;
2227 spin_unlock(&GlobalMid_Lock); 2256 spin_unlock(&GlobalMid_Lock);
2228 if (srvTcp->tsk) { 2257 kill_cifsd(srvTcp);
2229 /* If we could verify that kthread_stop would
2230 always wake up processes blocked in
2231 tcp in recv_mesg then we could remove the
2232 send_sig call */
2233 force_sig(SIGKILL, srvTcp->tsk);
2234 kthread_stop(srvTcp->tsk);
2235 }
2236 } 2258 }
2237 /* If find_unc succeeded then rc == 0 so we can not end */ 2259 /* If find_unc succeeded then rc == 0 so we can not end */
2238 if (tcon) /* up accidently freeing someone elses tcon struct */ 2260 if (tcon) /* up accidently freeing someone elses tcon struct */
@@ -2245,19 +2267,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2245 temp_rc = CIFSSMBLogoff(xid, pSesInfo); 2267 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
2246 /* if the socketUseCount is now zero */ 2268 /* if the socketUseCount is now zero */
2247 if ((temp_rc == -ESHUTDOWN) && 2269 if ((temp_rc == -ESHUTDOWN) &&
2248 (pSesInfo->server) && 2270 (pSesInfo->server))
2249 (pSesInfo->server->tsk)) { 2271 kill_cifsd(pSesInfo->server);
2250 force_sig(SIGKILL,
2251 pSesInfo->server->tsk);
2252 kthread_stop(pSesInfo->server->tsk);
2253 }
2254 } else { 2272 } else {
2255 cFYI(1, ("No session or bad tcon")); 2273 cFYI(1, ("No session or bad tcon"));
2256 if ((pSesInfo->server) && 2274 if (pSesInfo->server) {
2257 (pSesInfo->server->tsk)) { 2275 spin_lock(&GlobalMid_Lock);
2258 force_sig(SIGKILL, 2276 srvTcp->tcpStatus = CifsExiting;
2259 pSesInfo->server->tsk); 2277 spin_unlock(&GlobalMid_Lock);
2260 kthread_stop(pSesInfo->server->tsk); 2278 kill_cifsd(pSesInfo->server);
2261 } 2279 }
2262 } 2280 }
2263 sesInfoFree(pSesInfo); 2281 sesInfoFree(pSesInfo);
@@ -3544,7 +3562,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3544 int rc = 0; 3562 int rc = 0;
3545 int xid; 3563 int xid;
3546 struct cifsSesInfo *ses = NULL; 3564 struct cifsSesInfo *ses = NULL;
3547 struct task_struct *cifsd_task;
3548 char *tmp; 3565 char *tmp;
3549 3566
3550 xid = GetXid(); 3567 xid = GetXid();
@@ -3560,7 +3577,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3560 tconInfoFree(cifs_sb->tcon); 3577 tconInfoFree(cifs_sb->tcon);
3561 if ((ses) && (ses->server)) { 3578 if ((ses) && (ses->server)) {
3562 /* save off task so we do not refer to ses later */ 3579 /* save off task so we do not refer to ses later */
3563 cifsd_task = ses->server->tsk;
3564 cFYI(1, ("About to do SMBLogoff ")); 3580 cFYI(1, ("About to do SMBLogoff "));
3565 rc = CIFSSMBLogoff(xid, ses); 3581 rc = CIFSSMBLogoff(xid, ses);
3566 if (rc == -EBUSY) { 3582 if (rc == -EBUSY) {
@@ -3568,10 +3584,8 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3568 return 0; 3584 return 0;
3569 } else if (rc == -ESHUTDOWN) { 3585 } else if (rc == -ESHUTDOWN) {
3570 cFYI(1, ("Waking up socket by sending signal")); 3586 cFYI(1, ("Waking up socket by sending signal"));
3571 if (cifsd_task) { 3587 if (ses->server)
3572 force_sig(SIGKILL, cifsd_task); 3588 kill_cifsd(ses->server);
3573 kthread_stop(cifsd_task);
3574 }
3575 rc = 0; 3589 rc = 0;
3576 } /* else - we have an smb session 3590 } /* else - we have an smb session
3577 left on this socket do not kill cifsd */ 3591 left on this socket do not kill cifsd */
@@ -3701,7 +3715,9 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3701 cERROR(1, ("Send error in SessSetup = %d", rc)); 3715 cERROR(1, ("Send error in SessSetup = %d", rc));
3702 } else { 3716 } else {
3703 cFYI(1, ("CIFS Session Established successfully")); 3717 cFYI(1, ("CIFS Session Established successfully"));
3718 spin_lock(&GlobalMid_Lock);
3704 pSesInfo->status = CifsGood; 3719 pSesInfo->status = CifsGood;
3720 spin_unlock(&GlobalMid_Lock);
3705 } 3721 }
3706 3722
3707ss_err_exit: 3723ss_err_exit: