diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-23 13:43:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-23 13:43:36 -0400 |
commit | db563fc2e80534f98c7f9121a6f7dfe41f177a79 (patch) | |
tree | c97acbb983530b070e28c70825e0eedbbdb97ab2 /fs/cifs/connect.c | |
parent | eb81071584bed0b04adcaf57e525638d0f92e1e1 (diff) | |
parent | b1c8d2b421376bc941823ee93e36cb491609b02c (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
cifs: handle the TCP_Server_Info->tsk field more carefully
cifs: fix unlinking of rename target when server doesn't support open file renames
[CIFS] improve setlease handling
[CIFS] fix saving of resume key before CIFSFindNext
cifs: make cifs_rename handle -EACCES errors
[CIFS] fix build error
[CIFS] undo changes in cifs_rename_pending_delete if it errors out
cifs: track DeletePending flag in cifsInodeInfo
cifs: don't use CREATE_DELETE_ON_CLOSE in cifs_rename_pending_delete
[CIFS] eliminate usage of kthread_stop for cifsd
[CIFS] Add nodfs mount option
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 94 |
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 | ||
1860 | static void | ||
1861 | kill_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 | |||
1848 | int | 1870 | int |
1849 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | 1871 | cifs_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 | ||
3707 | ss_err_exit: | 3723 | ss_err_exit: |