Merge branch 'linus' into x86/urgent
[safe/jmp/linux-2.6] / fs / cifs / connect.c
index 957998e..f428bf3 100644 (file)
@@ -348,7 +348,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
        int reconnect;
 
        current->flags |= PF_MEMALLOC;
-       server->tsk = current;  /* save process info to wake at shutdown */
        cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
        write_lock(&GlobalSMBSeslock);
        atomic_inc(&tcpSesAllocCount);
@@ -651,10 +650,20 @@ multi_t2_fnd:
 
        spin_lock(&GlobalMid_Lock);
        server->tcpStatus = CifsExiting;
-       server->tsk = NULL;
+       spin_unlock(&GlobalMid_Lock);
+
+       /* don't exit until kthread_stop is called */
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       while (!kthread_should_stop()) {
+               schedule();
+               set_current_state(TASK_UNINTERRUPTIBLE);
+       }
+       set_current_state(TASK_RUNNING);
+
        /* check if we have blocked requests that need to free */
        /* Note that cifs_max_pending is normally 50, but
        can be set at module install time to as little as two */
+       spin_lock(&GlobalMid_Lock);
        if (atomic_read(&server->inFlight) >= cifs_max_pending)
                atomic_set(&server->inFlight, cifs_max_pending - 1);
        /* We do not want to set the max_pending too low or we
@@ -1302,6 +1311,9 @@ cifs_parse_mount_options(char *options, const char *devname,
                                                    "begin with // or \\\\ \n");
                                return 1;
                        }
+                       value = strpbrk(vol->UNC+2, "/\\");
+                       if (value)
+                               *value = '\\';
                } else {
                        printk(KERN_WARNING "CIFS: UNC name too long\n");
                        return 1;
@@ -1315,42 +1327,43 @@ cifs_parse_mount_options(char *options, const char *devname,
 
 static struct cifsSesInfo *
 cifs_find_tcp_session(struct in_addr *target_ip_addr,
-               struct in6_addr *target_ip6_addr,
-                char *userName, struct TCP_Server_Info **psrvTcp)
+                     struct in6_addr *target_ip6_addr,
+                     char *userName, struct TCP_Server_Info **psrvTcp)
 {
        struct list_head *tmp;
        struct cifsSesInfo *ses;
+
        *psrvTcp = NULL;
-       read_lock(&GlobalSMBSeslock);
 
+       read_lock(&GlobalSMBSeslock);
        list_for_each(tmp, &GlobalSMBSessionList) {
                ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
-               if (ses->server) {
-                       if ((target_ip_addr &&
-                               (ses->server->addr.sockAddr.sin_addr.s_addr
-                                 == target_ip_addr->s_addr)) || (target_ip6_addr
-                               && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
-                                       target_ip6_addr, sizeof(*target_ip6_addr)))) {
-                               /* BB lock server and tcp session and increment
-                                     use count here?? */
-
-                               /* found a match on the TCP session */
-                               *psrvTcp = ses->server;
-
-                               /* BB check if reconnection needed */
-                               if (strncmp
-                                   (ses->userName, userName,
-                                    MAX_USERNAME_SIZE) == 0){
-                                       read_unlock(&GlobalSMBSeslock);
-                                       /* Found exact match on both TCP and
-                                          SMB sessions */
-                                       return ses;
-                               }
-                       }
+               if (!ses->server)
+                       continue;
+
+               if (target_ip_addr &&
+                   ses->server->addr.sockAddr.sin_addr.s_addr != target_ip_addr->s_addr)
+                               continue;
+               else if (target_ip6_addr &&
+                        memcmp(&ses->server->addr.sockAddr6.sin6_addr,
+                               target_ip6_addr, sizeof(*target_ip6_addr)))
+                               continue;
+               /* BB lock server and tcp session; increment use count here?? */
+
+               /* found a match on the TCP session */
+               *psrvTcp = ses->server;
+
+               /* BB check if reconnection needed */
+               if (strncmp(ses->userName, userName, MAX_USERNAME_SIZE) == 0) {
+                       read_unlock(&GlobalSMBSeslock);
+                       /* Found exact match on both TCP and
+                          SMB sessions */
+                       return ses;
                }
                /* else tcp and smb sessions need reconnection */
        }
        read_unlock(&GlobalSMBSeslock);
+
        return NULL;
 }
 
@@ -2183,15 +2196,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        srvTcp->tcpStatus = CifsExiting;
                        spin_unlock(&GlobalMid_Lock);
                        if (srvTcp->tsk) {
-                               struct task_struct *tsk;
                                /* If we could verify that kthread_stop would
                                   always wake up processes blocked in
                                   tcp in recv_mesg then we could remove the
                                   send_sig call */
                                force_sig(SIGKILL, srvTcp->tsk);
-                               tsk = srvTcp->tsk;
-                               if (tsk)
-                                       kthread_stop(tsk);
+                               kthread_stop(srvTcp->tsk);
                        }
                }
                 /* If find_unc succeeded then rc == 0 so we can not end */
@@ -2207,23 +2217,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                                        if ((temp_rc == -ESHUTDOWN) &&
                                            (pSesInfo->server) &&
                                            (pSesInfo->server->tsk)) {
-                                               struct task_struct *tsk;
                                                force_sig(SIGKILL,
                                                        pSesInfo->server->tsk);
-                                               tsk = pSesInfo->server->tsk;
-                                               if (tsk)
-                                                       kthread_stop(tsk);
+                                               kthread_stop(pSesInfo->server->tsk);
                                        }
                                } else {
                                        cFYI(1, ("No session or bad tcon"));
                                        if ((pSesInfo->server) &&
                                            (pSesInfo->server->tsk)) {
-                                               struct task_struct *tsk;
                                                force_sig(SIGKILL,
                                                        pSesInfo->server->tsk);
-                                               tsk = pSesInfo->server->tsk;
-                                               if (tsk)
-                                                       kthread_stop(tsk);
+                                               kthread_stop(pSesInfo->server->tsk);
                                        }
                                }
                                sesInfoFree(pSesInfo);