diff options
author | Steve French <sfrench@us.ibm.com> | 2005-08-18 12:37:34 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2005-08-18 12:37:34 -0400 |
commit | f191401f5906f4d942fac87ebeb4671faf1ba7d6 (patch) | |
tree | 5d918edb41604cde78668e3fba2cfd9fb4f11641 /fs/cifs/connect.c | |
parent | 1982c344f1bf08118f7c224958b30c64e162009e (diff) |
[CIFS] rmmod cifs can oops if done soon after the last cifs unmount
Signed-off-by: Shaggy (shaggy@austin.ibm.com)
Signed-off-by: Steve French (sfrench@us.ibm.com)
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 9e8256003f73..ef0432c44482 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
30 | #include <linux/mempool.h> | 30 | #include <linux/mempool.h> |
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/completion.h> | ||
32 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
33 | #include <asm/processor.h> | 34 | #include <asm/processor.h> |
34 | #include "cifspdu.h" | 35 | #include "cifspdu.h" |
@@ -44,6 +45,8 @@ | |||
44 | #define CIFS_PORT 445 | 45 | #define CIFS_PORT 445 |
45 | #define RFC1001_PORT 139 | 46 | #define RFC1001_PORT 139 |
46 | 47 | ||
48 | static DECLARE_COMPLETION(cifsd_complete); | ||
49 | |||
47 | extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, | 50 | extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, |
48 | unsigned char *p24); | 51 | unsigned char *p24); |
49 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, | 52 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, |
@@ -339,6 +342,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
339 | atomic_inc(&tcpSesAllocCount); | 342 | atomic_inc(&tcpSesAllocCount); |
340 | length = tcpSesAllocCount.counter; | 343 | length = tcpSesAllocCount.counter; |
341 | write_unlock(&GlobalSMBSeslock); | 344 | write_unlock(&GlobalSMBSeslock); |
345 | complete(&cifsd_complete); | ||
342 | if(length > 1) { | 346 | if(length > 1) { |
343 | mempool_resize(cifs_req_poolp, | 347 | mempool_resize(cifs_req_poolp, |
344 | length + cifs_min_rcv, | 348 | length + cifs_min_rcv, |
@@ -676,7 +680,7 @@ multi_t2_fnd: | |||
676 | msleep(125); | 680 | msleep(125); |
677 | } | 681 | } |
678 | 682 | ||
679 | if (list_empty(&server->pending_mid_q)) { | 683 | if (!list_empty(&server->pending_mid_q)) { |
680 | /* mpx threads have not exited yet give them | 684 | /* mpx threads have not exited yet give them |
681 | at least the smb send timeout time for long ops */ | 685 | at least the smb send timeout time for long ops */ |
682 | /* due to delays on oplock break requests, we need | 686 | /* due to delays on oplock break requests, we need |
@@ -713,7 +717,7 @@ multi_t2_fnd: | |||
713 | GFP_KERNEL); | 717 | GFP_KERNEL); |
714 | } | 718 | } |
715 | 719 | ||
716 | msleep(250); | 720 | complete_and_exit(&cifsd_complete, 0); |
717 | return 0; | 721 | return 0; |
718 | } | 722 | } |
719 | 723 | ||
@@ -1617,8 +1621,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1617 | kfree(volume_info.password); | 1621 | kfree(volume_info.password); |
1618 | FreeXid(xid); | 1622 | FreeXid(xid); |
1619 | return rc; | 1623 | return rc; |
1620 | } else | 1624 | } |
1621 | rc = 0; | 1625 | wait_for_completion(&cifsd_complete); |
1626 | rc = 0; | ||
1622 | memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); | 1627 | memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); |
1623 | srvTcp->sequence_number = 0; | 1628 | srvTcp->sequence_number = 0; |
1624 | } | 1629 | } |
@@ -1759,8 +1764,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1759 | spin_lock(&GlobalMid_Lock); | 1764 | spin_lock(&GlobalMid_Lock); |
1760 | srvTcp->tcpStatus = CifsExiting; | 1765 | srvTcp->tcpStatus = CifsExiting; |
1761 | spin_unlock(&GlobalMid_Lock); | 1766 | spin_unlock(&GlobalMid_Lock); |
1762 | if(srvTcp->tsk) | 1767 | if(srvTcp->tsk) { |
1763 | send_sig(SIGKILL,srvTcp->tsk,1); | 1768 | send_sig(SIGKILL,srvTcp->tsk,1); |
1769 | wait_for_completion(&cifsd_complete); | ||
1770 | } | ||
1764 | } | 1771 | } |
1765 | /* If find_unc succeeded then rc == 0 so we can not end */ | 1772 | /* If find_unc succeeded then rc == 0 so we can not end */ |
1766 | if (tcon) /* up accidently freeing someone elses tcon struct */ | 1773 | if (tcon) /* up accidently freeing someone elses tcon struct */ |
@@ -1773,8 +1780,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1773 | temp_rc = CIFSSMBLogoff(xid, pSesInfo); | 1780 | temp_rc = CIFSSMBLogoff(xid, pSesInfo); |
1774 | /* if the socketUseCount is now zero */ | 1781 | /* if the socketUseCount is now zero */ |
1775 | if((temp_rc == -ESHUTDOWN) && | 1782 | if((temp_rc == -ESHUTDOWN) && |
1776 | (pSesInfo->server->tsk)) | 1783 | (pSesInfo->server->tsk)) { |
1777 | send_sig(SIGKILL,pSesInfo->server->tsk,1); | 1784 | send_sig(SIGKILL,pSesInfo->server->tsk,1); |
1785 | wait_for_completion(&cifsd_complete); | ||
1786 | } | ||
1778 | } else | 1787 | } else |
1779 | cFYI(1, ("No session or bad tcon")); | 1788 | cFYI(1, ("No session or bad tcon")); |
1780 | sesInfoFree(pSesInfo); | 1789 | sesInfoFree(pSesInfo); |
@@ -3241,8 +3250,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
3241 | return 0; | 3250 | return 0; |
3242 | } else if (rc == -ESHUTDOWN) { | 3251 | } else if (rc == -ESHUTDOWN) { |
3243 | cFYI(1,("Waking up socket by sending it signal")); | 3252 | cFYI(1,("Waking up socket by sending it signal")); |
3244 | if(cifsd_task) | 3253 | if(cifsd_task) { |
3245 | send_sig(SIGKILL,cifsd_task,1); | 3254 | send_sig(SIGKILL,cifsd_task,1); |
3255 | wait_for_completion(&cifsd_complete); | ||
3256 | } | ||
3246 | rc = 0; | 3257 | rc = 0; |
3247 | } /* else - we have an smb session | 3258 | } /* else - we have an smb session |
3248 | left on this socket do not kill cifsd */ | 3259 | left on this socket do not kill cifsd */ |