]> Pileus Git - ~andy/linux/commitdiff
[CIFS] rmmod cifs can oops if done soon after the last cifs unmount
authorSteve French <sfrench@us.ibm.com>
Thu, 18 Aug 2005 16:37:34 +0000 (09:37 -0700)
committerSteve French <sfrench@us.ibm.com>
Thu, 18 Aug 2005 16:37:34 +0000 (09:37 -0700)
Signed-off-by: Shaggy (shaggy@austin.ibm.com)
Signed-off-by: Steve French (sfrench@us.ibm.com)
fs/cifs/cifsfs.c
fs/cifs/connect.c

index 8cc23e7d0d5d34e69924e7752e3a816dd6297cfc..7fda0f7d9c004d1b91a8cfb23f77712c209d9746 100644 (file)
@@ -834,8 +834,8 @@ static int cifs_oplock_thread(void * dummyarg)
                                spin_unlock(&GlobalMid_Lock);
                }
        } while(!signal_pending(current));
-       complete_and_exit (&cifs_oplock_exited, 0);
        oplockThread = NULL;
+       complete_and_exit (&cifs_oplock_exited, 0);
 }
 
 static int __init
index 9e8256003f7315d01c473252abdb1f5f7e44e172..ef0432c4448226ff6616a6435da9110df1bfa53a 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/utsname.h>
 #include <linux/mempool.h>
 #include <linux/delay.h>
+#include <linux/completion.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 #include "cifspdu.h"
@@ -44,6 +45,8 @@
 #define CIFS_PORT 445
 #define RFC1001_PORT 139
 
+static DECLARE_COMPLETION(cifsd_complete);
+
 extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
                       unsigned char *p24);
 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
@@ -339,6 +342,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
        atomic_inc(&tcpSesAllocCount);
        length = tcpSesAllocCount.counter;
        write_unlock(&GlobalSMBSeslock);
+       complete(&cifsd_complete);
        if(length  > 1) {
                mempool_resize(cifs_req_poolp,
                        length + cifs_min_rcv,
@@ -676,7 +680,7 @@ multi_t2_fnd:
                msleep(125);
        }
 
-       if (list_empty(&server->pending_mid_q)) {
+       if (!list_empty(&server->pending_mid_q)) {
                /* mpx threads have not exited yet give them 
                at least the smb send timeout time for long ops */
                /* due to delays on oplock break requests, we need
@@ -713,7 +717,7 @@ multi_t2_fnd:
                        GFP_KERNEL);
        }
        
-       msleep(250);
+       complete_and_exit(&cifsd_complete, 0);
        return 0;
 }
 
@@ -1617,8 +1621,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                                        kfree(volume_info.password);
                                FreeXid(xid);
                                return rc;
-                       } else
-                               rc = 0;
+                       }
+                       wait_for_completion(&cifsd_complete);
+                       rc = 0;
                        memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
                        srvTcp->sequence_number = 0;
                }
@@ -1759,8 +1764,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        spin_lock(&GlobalMid_Lock);
                        srvTcp->tcpStatus = CifsExiting;
                        spin_unlock(&GlobalMid_Lock);
-                       if(srvTcp->tsk)
+                       if(srvTcp->tsk) {
                                send_sig(SIGKILL,srvTcp->tsk,1);
+                               wait_for_completion(&cifsd_complete);
+                       }
                }
                 /* If find_unc succeeded then rc == 0 so we can not end */
                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,
                                        temp_rc = CIFSSMBLogoff(xid, pSesInfo);
                                        /* if the socketUseCount is now zero */
                                        if((temp_rc == -ESHUTDOWN) &&
-                                          (pSesInfo->server->tsk))
+                                          (pSesInfo->server->tsk)) {
                                                send_sig(SIGKILL,pSesInfo->server->tsk,1);
+                                               wait_for_completion(&cifsd_complete);
+                                       }
                                } else
                                        cFYI(1, ("No session or bad tcon"));
                                sesInfoFree(pSesInfo);
@@ -3241,8 +3250,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
                                return 0;
                        } else if (rc == -ESHUTDOWN) {
                                cFYI(1,("Waking up socket by sending it signal"));
-                               if(cifsd_task)
+                               if(cifsd_task) {
                                        send_sig(SIGKILL,cifsd_task,1);
+                                       wait_for_completion(&cifsd_complete);
+                               }
                                rc = 0;
                        } /* else - we have an smb session
                                left on this socket do not kill cifsd */