diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 41 |
1 files changed, 28 insertions, 13 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index f51b79a67e1..71b7661e226 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -750,6 +750,7 @@ multi_t2_fnd: | |||
750 | write_unlock(&GlobalSMBSeslock); | 750 | write_unlock(&GlobalSMBSeslock); |
751 | 751 | ||
752 | kfree(server->hostname); | 752 | kfree(server->hostname); |
753 | task_to_wake = xchg(&server->tsk, NULL); | ||
753 | kfree(server); | 754 | kfree(server); |
754 | 755 | ||
755 | length = atomic_dec_return(&tcpSesAllocCount); | 756 | length = atomic_dec_return(&tcpSesAllocCount); |
@@ -757,6 +758,16 @@ multi_t2_fnd: | |||
757 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, | 758 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, |
758 | GFP_KERNEL); | 759 | GFP_KERNEL); |
759 | 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 | |||
760 | return 0; | 771 | return 0; |
761 | } | 772 | } |
762 | 773 | ||
@@ -1846,6 +1857,16 @@ convert_delimiter(char *path, char delim) | |||
1846 | } | 1857 | } |
1847 | } | 1858 | } |
1848 | 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 | |||
1849 | int | 1870 | int |
1850 | 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, |
1851 | char *mount_data, const char *devname) | 1872 | char *mount_data, const char *devname) |
@@ -2233,7 +2254,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2233 | spin_lock(&GlobalMid_Lock); | 2254 | spin_lock(&GlobalMid_Lock); |
2234 | srvTcp->tcpStatus = CifsExiting; | 2255 | srvTcp->tcpStatus = CifsExiting; |
2235 | spin_unlock(&GlobalMid_Lock); | 2256 | spin_unlock(&GlobalMid_Lock); |
2236 | force_sig(SIGKILL, srvTcp->tsk); | 2257 | kill_cifsd(srvTcp); |
2237 | } | 2258 | } |
2238 | /* 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 */ |
2239 | if (tcon) /* up accidently freeing someone elses tcon struct */ | 2260 | if (tcon) /* up accidently freeing someone elses tcon struct */ |
@@ -2246,19 +2267,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2246 | temp_rc = CIFSSMBLogoff(xid, pSesInfo); | 2267 | temp_rc = CIFSSMBLogoff(xid, pSesInfo); |
2247 | /* if the socketUseCount is now zero */ | 2268 | /* if the socketUseCount is now zero */ |
2248 | if ((temp_rc == -ESHUTDOWN) && | 2269 | if ((temp_rc == -ESHUTDOWN) && |
2249 | (pSesInfo->server) && | 2270 | (pSesInfo->server)) |
2250 | (pSesInfo->server->tsk)) | 2271 | kill_cifsd(pSesInfo->server); |
2251 | force_sig(SIGKILL, | ||
2252 | pSesInfo->server->tsk); | ||
2253 | } else { | 2272 | } else { |
2254 | cFYI(1, ("No session or bad tcon")); | 2273 | cFYI(1, ("No session or bad tcon")); |
2255 | if ((pSesInfo->server) && | 2274 | if (pSesInfo->server) { |
2256 | (pSesInfo->server->tsk)) { | ||
2257 | spin_lock(&GlobalMid_Lock); | 2275 | spin_lock(&GlobalMid_Lock); |
2258 | srvTcp->tcpStatus = CifsExiting; | 2276 | srvTcp->tcpStatus = CifsExiting; |
2259 | spin_unlock(&GlobalMid_Lock); | 2277 | spin_unlock(&GlobalMid_Lock); |
2260 | force_sig(SIGKILL, | 2278 | kill_cifsd(pSesInfo->server); |
2261 | pSesInfo->server->tsk); | ||
2262 | } | 2279 | } |
2263 | } | 2280 | } |
2264 | sesInfoFree(pSesInfo); | 2281 | sesInfoFree(pSesInfo); |
@@ -3545,7 +3562,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
3545 | int rc = 0; | 3562 | int rc = 0; |
3546 | int xid; | 3563 | int xid; |
3547 | struct cifsSesInfo *ses = NULL; | 3564 | struct cifsSesInfo *ses = NULL; |
3548 | struct task_struct *cifsd_task; | ||
3549 | char *tmp; | 3565 | char *tmp; |
3550 | 3566 | ||
3551 | xid = GetXid(); | 3567 | xid = GetXid(); |
@@ -3561,7 +3577,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
3561 | tconInfoFree(cifs_sb->tcon); | 3577 | tconInfoFree(cifs_sb->tcon); |
3562 | if ((ses) && (ses->server)) { | 3578 | if ((ses) && (ses->server)) { |
3563 | /* save off task so we do not refer to ses later */ | 3579 | /* save off task so we do not refer to ses later */ |
3564 | cifsd_task = ses->server->tsk; | ||
3565 | cFYI(1, ("About to do SMBLogoff ")); | 3580 | cFYI(1, ("About to do SMBLogoff ")); |
3566 | rc = CIFSSMBLogoff(xid, ses); | 3581 | rc = CIFSSMBLogoff(xid, ses); |
3567 | if (rc == -EBUSY) { | 3582 | if (rc == -EBUSY) { |
@@ -3569,8 +3584,8 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
3569 | return 0; | 3584 | return 0; |
3570 | } else if (rc == -ESHUTDOWN) { | 3585 | } else if (rc == -ESHUTDOWN) { |
3571 | cFYI(1, ("Waking up socket by sending signal")); | 3586 | cFYI(1, ("Waking up socket by sending signal")); |
3572 | if (cifsd_task) | 3587 | if (ses->server) |
3573 | force_sig(SIGKILL, cifsd_task); | 3588 | kill_cifsd(ses->server); |
3574 | rc = 0; | 3589 | rc = 0; |
3575 | } /* else - we have an smb session | 3590 | } /* else - we have an smb session |
3576 | left on this socket do not kill cifsd */ | 3591 | left on this socket do not kill cifsd */ |