diff options
| -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 f51b79a67e1b..71b7661e2260 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 */ |
