vserver 1.9.5.x5
[linux-2.6.git] / fs / cifs / connect.c
index befbff5..ff8a4df 100644 (file)
 #include <linux/string.h>
 #include <linux/list.h>
 #include <linux/wait.h>
-#include <linux/version.h>
 #include <linux/ipv6.h>
 #include <linux/pagemap.h>
 #include <linux/ctype.h>
 #include <linux/utsname.h>
+#include <linux/mempool.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 #include "cifspdu.h"
@@ -49,21 +49,29 @@ extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
                         unsigned char *p24);
 extern int cifs_inet_pton(int, const char *, void *dst);
 
+extern mempool_t *cifs_req_poolp;
+
 struct smb_vol {
        char *username;
        char *password;
        char *domainname;
        char *UNC;
        char *UNCip;
+       char *in6_addr;  /* ipv6 address as human readable form of in6_addr */
        char *iocharset;  /* local code page for mapping to and from Unicode */
        char source_rfc1001_name[16]; /* netbios name of client */
        uid_t linux_uid;
        gid_t linux_gid;
        mode_t file_mode;
        mode_t dir_mode;
-       int rw:1;
-       int retry:1;
-       int intr:1;
+       unsigned rw:1;
+       unsigned retry:1;
+       unsigned intr:1;
+       unsigned setuids:1;
+       unsigned noperm:1;
+       unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
+       unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
+       unsigned direct_io:1;
        unsigned int rsize;
        unsigned int wsize;
        unsigned int sockopt;
@@ -175,7 +183,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
                        if(server->tcpStatus != CifsExiting)
                                server->tcpStatus = CifsGood;
                        spin_unlock(&GlobalMid_Lock);
-                       atomic_set(&server->inFlight,0);
+       /*              atomic_set(&server->inFlight,0);*/
                        wake_up(&server->response_q);
                }
        }
@@ -189,8 +197,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
        unsigned int pdu_length, total_read;
        struct smb_hdr *smb_buffer = NULL;
        struct msghdr smb_msg;
-       mm_segment_t temp_fs;
-       struct iovec iov;
+       struct kvec iov;
        struct socket *csocket = server->ssocket;
        struct list_head *tmp;
        struct cifsSesInfo *ses;
@@ -203,9 +210,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
        current->flags |= PF_MEMALLOC;
        server->tsk = current;  /* save process info to wake at shutdown */
        cFYI(1, ("Demultiplex PID: %d", current->pid));
-
-       temp_fs = get_fs();     /* we must turn off socket api parm checking */
-       set_fs(get_ds());
+       write_lock(&GlobalSMBSeslock);
+       atomic_inc(&tcpSesAllocCount);
+       length = tcpSesAllocCount.counter;
+       write_unlock(&GlobalSMBSeslock);
+       if(length  > 1) {
+               mempool_resize(cifs_req_poolp,
+                       length + cifs_min_rcv,
+                       GFP_KERNEL);
+       }
 
        while (server->tcpStatus != CifsExiting) {
                if (smb_buffer == NULL)
@@ -222,16 +235,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                iov.iov_base = smb_buffer;
                iov.iov_len = sizeof (struct smb_hdr) - 1;      
         /* 1 byte less above since wct is not always returned in error cases */
-               smb_msg.msg_iov = &iov;
-               smb_msg.msg_iovlen = 1;
                smb_msg.msg_control = NULL;
                smb_msg.msg_controllen = 0;
 
                length =
-                   sock_recvmsg(csocket, &smb_msg,
-                                sizeof (struct smb_hdr) -
-                                1 /* RFC1001 header and SMB header */ ,
-                                MSG_PEEK /* flags see socket.h */ );
+                   kernel_recvmsg(csocket, &smb_msg,
+                                  &iov, 1,
+                                  sizeof (struct smb_hdr) -
+                                  1 /* RFC1001 header and SMB header */ ,
+                                  MSG_PEEK /* flags see socket.h */ );
 
                if(server->tcpStatus == CifsExiting) {
                        break;
@@ -241,7 +253,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                        cFYI(1,("call to reconnect done"));
                        csocket = server->ssocket;
                        continue;
-               } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
+               } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)
+                               || ((length > 0) && (length <= 3)) ) {
                        set_current_state(TASK_INTERRUPTIBLE);
                        schedule_timeout(1); /* minimum sleep to prevent looping
                                allowing socket to clear and app threads to set
@@ -253,13 +266,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                                /* some servers kill tcp session rather than returning
                                        smb negprot error in which case reconnecting here is
                                        not going to help - return error to mount */
-                               spin_lock(&GlobalMid_Lock);
-                               server->tcpStatus = CifsExiting;
-                               spin_unlock(&GlobalMid_Lock);
-                               wake_up(&server->response_q);
                                break;
                        }
-
+                       if(length == -EINTR) { 
+                               cFYI(1,("cifsd thread killed"));
+                               break;
+                       }
                        cFYI(1,("Reconnecting after unexpected peek error %d",length));
                        cifs_reconnect(server);
                        csocket = server->ssocket;
@@ -268,7 +280,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                }
 
                pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
-               /* Ony read pdu_length after below checks for too short (due
+               /* Only read pdu_length after below checks for too short (due
                   to e.g. int overflow) and too long ie beyond end of buf */
                cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
 
@@ -277,12 +289,14 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                        if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
                                iov.iov_base = smb_buffer;
                                iov.iov_len = 4;
-                               length = sock_recvmsg(csocket, &smb_msg, 4, 0);
+                               length = kernel_recvmsg(csocket, &smb_msg,
+                                                       &iov, 1, 4, 0);
                                cFYI(0,("Received 4 byte keep alive packet"));
                        } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
-                                       iov.iov_base = smb_buffer;
-                                       iov.iov_len = 4;
-                                       length = sock_recvmsg(csocket, &smb_msg, 4, 0);
+                               iov.iov_base = smb_buffer;
+                               iov.iov_len = 4;
+                               length = kernel_recvmsg(csocket, &smb_msg,
+                                                       &iov, 1, 4, 0);
                                        cFYI(1,("Good RFC 1002 session rsp"));
                        } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE)
                                   && (length == 5)) {
@@ -292,11 +306,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                                        /* if nack on negprot (rather than 
                                        ret of smb negprot error) reconnecting
                                        not going to help, ret error to mount */
-                                       spin_lock(&GlobalMid_Lock);
-                                       server->tcpStatus = CifsExiting;
-                                       spin_unlock(&GlobalMid_Lock);
-                                       /* wake up thread doing negprot */
-                                       wake_up(&server->response_q);
                                        break;
                                } else {
                                        /* give server a second to
@@ -308,7 +317,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                                        connected to port 139 (the NACK is 
                                        since we do not begin with RFC1001
                                        session initialize frame) */
-                                       server->addr.sockAddr.sin_port = CIFS_PORT;
+                                       server->addr.sockAddr.sin_port = htons(CIFS_PORT);
                                        cifs_reconnect(server);
                                        csocket = server->ssocket;
                                        wake_up(&server->response_q);
@@ -321,18 +330,24 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                                csocket = server->ssocket;
                                continue;
                        } else {
-                               if ((length != sizeof (struct smb_hdr) - 1)
-                                   || (pdu_length >
-                                       CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)
+                               if (length < 16) {
+                                       /* We can not validate the SMB unless 
+                                       at least this much of SMB available
+                                       so give the socket time to copy
+                                       a few more bytes and retry */ 
+                                       set_current_state(TASK_INTERRUPTIBLE);
+                                       schedule_timeout(10);
+                                       continue;
+                               } else if( (pdu_length >
+                                       CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
                                    || (pdu_length <
                                        sizeof (struct smb_hdr) - 1)
-                                   ||
-                                   (checkSMBhdr
+                                   || (checkSMBhdr
                                     (smb_buffer, smb_buffer->Mid))) {
                                        cERROR(1,
-                                           ("Invalid size or format for SMB found with length %d and pdu_lenght %d",
+                                           ("Invalid size or format for SMB found with length %d and pdu_length %d",
                                                length, pdu_length));
-                                       cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
+                                       cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)+3);
                                        /* could we fix this network corruption by finding next 
                                                smb header (instead of killing the session) and
                                                restart reading from next valid SMB found? */
@@ -347,7 +362,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                                        for (total_read = 0; 
                                             total_read < pdu_length;
                                             total_read += length) {    
-                                               length = sock_recvmsg(csocket, &smb_msg, 
+                                               length = kernel_recvmsg(csocket, &smb_msg, 
+                                                       &iov, 1,
                                                        pdu_length - total_read, 0);
                                                if (length == 0) {
                                                        cERROR(1,
@@ -398,7 +414,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                             ("Frame less than four bytes received  %d bytes long.",
                              length));
                        if (length > 0) {
-                               length = sock_recvmsg(csocket, &smb_msg, length, 0);    /* throw away junk frame */
+                               length = kernel_recvmsg(csocket, &smb_msg,
+                                       &iov, 1,
+                                       length, 0);     /* throw away junk frame */
                                cFYI(1,
                                     (" with junk  0x%x in it ",
                                      *(__u32 *) smb_buffer));
@@ -407,20 +425,23 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
        }
        spin_lock(&GlobalMid_Lock);
        server->tcpStatus = CifsExiting;
-       spin_unlock(&GlobalMid_Lock);
+       server->tsk = NULL;
        atomic_set(&server->inFlight, 0);
+       spin_unlock(&GlobalMid_Lock);
        /* Although there should not be any requests blocked on 
        this queue it can not hurt to be paranoid and try to wake up requests
        that may haven been blocked when more than 50 at time were on the wire 
        to the same server - they now will see the session is in exit state
        and get out of SendReceive.  */
-       wake_up_all(&server->request_q);   
-       server->tsk = NULL;
+       wake_up_all(&server->request_q);
+       /* give those requests time to exit */
+       set_current_state(TASK_INTERRUPTIBLE);
+       schedule_timeout(HZ/8);
+
        if(server->ssocket) {
                sock_release(csocket);
                server->ssocket = NULL;
        }
-       set_fs(temp_fs);
        if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
                cifs_buf_release(smb_buffer);
 
@@ -453,7 +474,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                spin_unlock(&GlobalMid_Lock);
                read_unlock(&GlobalSMBSeslock);
                set_current_state(TASK_INTERRUPTIBLE);
-               /* 1/8th of sec should be more than enough time for them to exit */
+               /* 1/8th of sec is more than enough time for them to exit */
                schedule_timeout(HZ/8); 
        }
 
@@ -468,7 +489,18 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
        }
        kfree(server);
 
-       cFYI(1, ("About to exit from demultiplex thread"));
+       write_lock(&GlobalSMBSeslock);
+       atomic_dec(&tcpSesAllocCount);
+       length = tcpSesAllocCount.counter;
+       write_unlock(&GlobalSMBSeslock);
+       if(length  > 0) {
+               mempool_resize(cifs_req_poolp,
+                       length + cifs_min_rcv,
+                       GFP_KERNEL);
+       }
+
+       set_current_state(TASK_INTERRUPTIBLE);
+       schedule_timeout(HZ/4);
        return 0;
 }
 
@@ -483,7 +515,7 @@ cifs_kcalloc(size_t size, int type)
 }
 
 static int
-cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
+cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
 {
        char *value;
        char *data;
@@ -670,7 +702,12 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
                                vol->file_mode =
                                        simple_strtoul(value, &value, 0);
                        }
-               } else if (strnicmp(data, "dir_mode", 3) == 0) {
+               } else if (strnicmp(data, "dir_mode", 4) == 0) {
+                       if (value && *value) {
+                               vol->dir_mode =
+                                       simple_strtoul(value, &value, 0);
+                       }
+               } else if (strnicmp(data, "dirmode", 4) == 0) {
                        if (value && *value) {
                                vol->dir_mode =
                                        simple_strtoul(value, &value, 0);
@@ -716,8 +753,12 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
                                if((i==15) && (value[i] != 0))
                                        printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
                        }
+               } else if (strnicmp(data, "credentials", 4) == 0) {
+                       /* ignore */
                } else if (strnicmp(data, "version", 3) == 0) {
                        /* ignore */
+               } else if (strnicmp(data, "guest",5) == 0) {
+                       /* ignore */
                } else if (strnicmp(data, "rw", 2) == 0) {
                        vol->rw = TRUE;
                } else if ((strnicmp(data, "suid", 4) == 0) ||
@@ -740,6 +781,14 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
                        vol->retry = 1;
                } else if (strnicmp(data, "soft", 4) == 0) {
                        vol->retry = 0;
+               } else if (strnicmp(data, "perm", 4) == 0) {
+                       vol->noperm = 0;
+               } else if (strnicmp(data, "noperm", 6) == 0) {
+                       vol->noperm = 1;
+               } else if (strnicmp(data, "setuids", 7) == 0) {
+                       vol->setuids = 1;
+               } else if (strnicmp(data, "nosetuids", 9) == 0) {
+                       vol->setuids = 0;
                } else if (strnicmp(data, "nohard", 6) == 0) {
                        vol->retry = 0;
                } else if (strnicmp(data, "nosoft", 6) == 0) {
@@ -748,6 +797,27 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
                        vol->intr = 0;
                } else if (strnicmp(data, "intr", 4) == 0) {
                        vol->intr = 1;
+               } else if (strnicmp(data, "serverino",7) == 0) {
+                       vol->server_ino = 1;
+               } else if (strnicmp(data, "noserverino",9) == 0) {
+                       vol->server_ino = 0;
+               } else if (strnicmp(data, "acl",3) == 0) {
+                       vol->no_psx_acl = 0;
+               } else if (strnicmp(data, "noacl",5) == 0) {
+                       vol->no_psx_acl = 1;
+               } else if (strnicmp(data, "direct",6) == 0) {
+                       vol->direct_io = 1;
+               } else if (strnicmp(data, "forcedirectio",13) == 0) {
+                       vol->direct_io = 1;
+               } else if (strnicmp(data, "in6_addr",8) == 0) {
+                       if (!value || !*value) {
+                               vol->in6_addr = NULL;
+                       } else if (strnlen(value, 49) == 48) {
+                               vol->in6_addr = value;
+                       } else {
+                               printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
+                               return 1;
+                       }
                } else if (strnicmp(data, "noac", 4) == 0) {
                        printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
                } else
@@ -782,19 +852,23 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
 }
 
 static struct cifsSesInfo *
-cifs_find_tcp_session(__u32 new_target_ip_addr,
+cifs_find_tcp_session(struct in_addr * target_ip_addr, 
+               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);
+
        list_for_each(tmp, &GlobalSMBSessionList) {
                ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
                if (ses->server) {
-                       if (ses->server->addr.sockAddr.sin_addr.s_addr ==
-                           new_target_ip_addr) {
+                       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?? */
                                *psrvTcp = ses->server; /* found a match on the TCP session */
                                /* BB check if reconnection needed */
@@ -813,7 +887,7 @@ cifs_find_tcp_session(__u32 new_target_ip_addr,
 }
 
 static struct cifsTconInfo *
-find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
+find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
 {
        struct list_head *tmp;
        struct cifsTconInfo *tcon;
@@ -932,7 +1006,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
 {
        int rc = 0;
        int connected = 0;
-       unsigned short int orig_port = 0;
+       __be16 orig_port = 0;
 
        if(*csocket == NULL) {
                rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
@@ -997,7 +1071,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
 
        /* send RFC1001 sessinit */
 
-       if(psin_server->sin_port == htons(139)) {
+       if(psin_server->sin_port == htons(RFC1001_PORT)) {
                /* some servers require RFC1001 sessinit before sending
                negprot - BB check reconnection in case where second 
                sessinit is sent but no second negprot */
@@ -1040,6 +1114,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
 {
        int rc = 0;
        int connected = 0;
+       __be16 orig_port = 0;
 
        if(*csocket == NULL) {
                rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
@@ -1065,6 +1140,10 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
        } 
 
        if(!connected) {
+               /* save original port so we can retry user specified port  
+                       later if fall back ports fail this time  */
+
+               orig_port = psin_server->sin6_port;
                /* do not retry on the same port we just failed on */
                if(psin_server->sin6_port != htons(CIFS_PORT)) {
                        psin_server->sin6_port = htons(CIFS_PORT);
@@ -1087,6 +1166,8 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
        /* give up here - unless we want to retry on different
                protocol families some day */
        if (!connected) {
+               if(orig_port)
+                       psin_server->sin6_port = orig_port;
                cFYI(1,("Error %d connecting to server via ipv6",rc));
                sock_release(*csocket);
                *csocket = NULL;
@@ -1106,6 +1187,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 {
        int rc = 0;
        int xid;
+       int address_type = AF_INET;
        struct socket *csocket = NULL;
        struct sockaddr_in sin_server;
        struct sockaddr_in6 sin_server6;
@@ -1147,12 +1229,16 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
        if (volume_info.UNCip && volume_info.UNC) {
                rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
 
-               if(rc == 0) {
+               if(rc <= 0) {
                        /* not ipv4 address, try ipv6 */
                        rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u); 
-               } 
+                       if(rc > 0)
+                               address_type = AF_INET6;
+               } else {
+                       address_type = AF_INET;
+               }
        
-               if(rc != 1) {
+               if(rc <= 0) {
                        /* we failed translating address */
                        if(volume_info.UNC)
                                kfree(volume_info.UNC);
@@ -1202,9 +1288,24 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                }
        }
 
-       existingCifsSes =
-           cifs_find_tcp_session(sin_server.sin_addr.s_addr,
-                            volume_info.username, &srvTcp);
+       if(address_type == AF_INET)
+               existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
+                       NULL /* no ipv6 addr */,
+                       volume_info.username, &srvTcp);
+       else if(address_type == AF_INET6)
+               existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
+                       &sin_server6.sin6_addr,
+                       volume_info.username, &srvTcp);
+       else {
+               if(volume_info.UNC)
+                       kfree(volume_info.UNC);
+               if(volume_info.password)
+                       kfree(volume_info.password);
+               FreeXid(xid);
+               return -EINVAL;
+       }
+
+
        if (srvTcp) {
                cFYI(1, ("Existing tcp session with server found "));                
        } else {        /* create socket */
@@ -1251,8 +1352,19 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        so no need to spinlock this init of tcpStatus */
                        srvTcp->tcpStatus = CifsNew;
                        init_MUTEX(&srvTcp->tcpSem);
-                       kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
+                       rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
                                      CLONE_FS | CLONE_FILES | CLONE_VM);
+                       if(rc < 0) {
+                               rc = -ENOMEM;
+                               sock_release(csocket);
+                               if(volume_info.UNC)
+                                       kfree(volume_info.UNC);
+                               if(volume_info.password)
+                                       kfree(volume_info.password);
+                               FreeXid(xid);
+                               return rc;
+                       } else
+                               rc = 0;
                        memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
                }
        }
@@ -1314,6 +1426,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                cifs_sb->mnt_file_mode = volume_info.file_mode;
                cifs_sb->mnt_dir_mode = volume_info.dir_mode;
                cFYI(1,("file mode: 0x%x  dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
+
+               if(volume_info.noperm)
+                       cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
+               if(volume_info.setuids)
+                       cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
+               if(volume_info.server_ino)
+                       cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
+               if(volume_info.direct_io) {
+                       cERROR(1,("mounting share using direct i/o"));
+                       cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
+               }
+
                tcon =
                    find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
                             volume_info.username);
@@ -1357,31 +1481,39 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        }
                }
        }
-       if (pSesInfo->capabilities & CAP_LARGE_FILES) {
-               cFYI(0, ("Large files supported "));
-               sb->s_maxbytes = (u64) 1 << 63;
-       } else
-               sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
+       if(pSesInfo) {
+               if (pSesInfo->capabilities & CAP_LARGE_FILES) {
+                       sb->s_maxbytes = (u64) 1 << 63;
+               } else
+                       sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
+       }
+
+       sb->s_time_gran = 100;
 
 /* on error free sesinfo and tcon struct if needed */
        if (rc) {
+               /* if session setup failed, use count is zero but
+               we still need to free cifsd thread */
                if(atomic_read(&srvTcp->socketUseCount) == 0) {
                        spin_lock(&GlobalMid_Lock);
                        srvTcp->tcpStatus = CifsExiting;
                        spin_unlock(&GlobalMid_Lock);
+                       if(srvTcp->tsk)
+                               send_sig(SIGKILL,srvTcp->tsk,1);
                }
                 /* If find_unc succeeded then rc == 0 so we can not end */
-               if (tcon)  /* up here accidently freeing someone elses tcon struct */
+               if (tcon)  /* up accidently freeing someone elses tcon struct */
                        tconInfoFree(tcon);
                if (existingCifsSes == 0) {
                        if (pSesInfo) {
-                               if (pSesInfo->server) {
-                                       if (pSesInfo->Suid)
-                                               CIFSSMBLogoff(xid, pSesInfo);
-                                       if(pSesInfo->server->tsk)
+                               if ((pSesInfo->server) && 
+                                   (pSesInfo->status == CifsGood)) {
+                                       int temp_rc;
+                                       temp_rc = CIFSSMBLogoff(xid, pSesInfo);
+                                       /* if the socketUseCount is now zero */
+                                       if((temp_rc == -ESHUTDOWN) &&
+                                          (pSesInfo->server->tsk))
                                                send_sig(SIGKILL,pSesInfo->server->tsk,1);
-                                       set_current_state(TASK_INTERRUPTIBLE);
-                                       schedule_timeout(HZ / 4);       /* give captive thread time to exit */
                                } else
                                        cFYI(1, ("No session or bad tcon"));
                                sesInfoFree(pSesInfo);
@@ -1396,8 +1528,16 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                /* do not care if following two calls succeed - informational only */
                CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
                CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
-               if (tcon->ses->capabilities & CAP_UNIX)
-                       CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls);
+               if (tcon->ses->capabilities & CAP_UNIX) {
+                       if(!CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls)) {
+                               if(!volume_info.no_psx_acl) {
+                                       if(CIFS_UNIX_POSIX_ACL_CAP & 
+                                          le64_to_cpu(tcon->fsUnixInfo.Capability))
+                                               cFYI(1,("server negotiated posix acl support"));
+                                               sb->s_flags |= MS_POSIXACL;
+                               }
+                       }
+               }
        }
 
        /* volume_info.password is freed above when existing session found
@@ -1420,15 +1560,20 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
        SESSION_SETUP_ANDX *pSMB;
        SESSION_SETUP_ANDX *pSMBr;
        char *bcc_ptr;
-       char *user = ses->userName;
-       char *domain = ses->domainName;
+       char *user;
+       char *domain;
        int rc = 0;
        int remaining_words = 0;
        int bytes_returned = 0;
        int len;
+       __u32 capabilities;
+       __u16 count;
 
        cFYI(1, ("In sesssetup "));
-
+       if(ses == NULL)
+               return -EINVAL;
+       user = ses->userName;
+       domain = ses->domainName;
        smb_buffer = cifs_buf_get();
        if (smb_buffer == 0) {
                return -ENOMEM;
@@ -1438,7 +1583,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 
        /* send SMBsessionSetup here */
        header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
-                       0 /* no tCon exists yet */ , 13 /* wct */ );
+                       NULL /* no tCon exists yet */ , 13 /* wct */ );
 
        pSMB->req_no_secext.AndXCommand = 0xFF;
        pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
@@ -1447,30 +1592,29 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
        if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
                smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
-       pSMB->req_no_secext.Capabilities =
-           CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
+       capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
        if (ses->capabilities & CAP_UNICODE) {
                smb_buffer->Flags2 |= SMBFLG2_UNICODE;
-               pSMB->req_no_secext.Capabilities |= CAP_UNICODE;
+               capabilities |= CAP_UNICODE;
        }
        if (ses->capabilities & CAP_STATUS32) {
                smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-               pSMB->req_no_secext.Capabilities |= CAP_STATUS32;
+               capabilities |= CAP_STATUS32;
        }
        if (ses->capabilities & CAP_DFS) {
                smb_buffer->Flags2 |= SMBFLG2_DFS;
-               pSMB->req_no_secext.Capabilities |= CAP_DFS;
+               capabilities |= CAP_DFS;
        }
-       pSMB->req_no_secext.Capabilities =
-           cpu_to_le32(pSMB->req_no_secext.Capabilities);
-       /* pSMB->req_no_secext.CaseInsensitivePasswordLength =
-          CIFS_SESSION_KEY_SIZE; */
-       pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
+       pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
+
+       pSMB->req_no_secext.CaseInsensitivePasswordLength = 
+               cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+
        pSMB->req_no_secext.CaseSensitivePasswordLength =
            cpu_to_le16(CIFS_SESSION_KEY_SIZE);
        bcc_ptr = pByteArea(smb_buffer);
-       /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE);
-          bcc_ptr += CIFS_SESSION_KEY_SIZE; */
+       memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
+       bcc_ptr += CIFS_SESSION_KEY_SIZE;
        memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
        bcc_ptr += CIFS_SESSION_KEY_SIZE;
 
@@ -1502,7 +1646,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                  32, nls_codepage);
                bcc_ptr += 2 * bytes_returned;
                bytes_returned =
-                   cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
+                   cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
                                  nls_codepage);
                bcc_ptr += 2 * bytes_returned;
                bcc_ptr += 2;
@@ -1529,14 +1673,14 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                }
                strcpy(bcc_ptr, "Linux version ");
                bcc_ptr += strlen("Linux version ");
-               strcpy(bcc_ptr, UTS_RELEASE);
-               bcc_ptr += strlen(UTS_RELEASE) + 1;
+               strcpy(bcc_ptr, system_utsname.release);
+               bcc_ptr += strlen(system_utsname.release) + 1;
                strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
                bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
        }
-       BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-       smb_buffer->smb_buf_length += BCC(smb_buffer);
-       BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+       count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+       smb_buffer->smb_buf_length += count;
+       pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
 
        rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
                         &bytes_returned, 1);
@@ -1544,114 +1688,106 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
        } else if ((smb_buffer_response->WordCount == 3)
                   || (smb_buffer_response->WordCount == 4)) {
-               pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
-               if (pSMBr->resp.Action & GUEST_LOGIN)
+               __u16 action = le16_to_cpu(pSMBr->resp.Action);
+               __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+               if (action & GUEST_LOGIN)
                        cFYI(1, (" Guest login"));      /* do we want to mark SesInfo struct ? */
-               if (ses) {
-                       ses->Suid = smb_buffer_response->Uid;   /* UID left in wire format (le) */
-                       cFYI(1, ("UID = %d ", ses->Suid));
+               ses->Suid = smb_buffer_response->Uid;   /* UID left in wire format (le) */
+               cFYI(1, ("UID = %d ", ses->Suid));
          /* response can have either 3 or 4 word count - Samba sends 3 */
-                       bcc_ptr = pByteArea(smb_buffer_response);       
-                       if ((pSMBr->resp.hdr.WordCount == 3)
-                           || ((pSMBr->resp.hdr.WordCount == 4)
-                               && (pSMBr->resp.SecurityBlobLength <
-                                   pSMBr->resp.ByteCount))) {
-                               if (pSMBr->resp.hdr.WordCount == 4)
-                                       bcc_ptr +=
-                                           pSMBr->resp.SecurityBlobLength;
-
-                               if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
-                                       if ((long) (bcc_ptr) % 2) {
-                                               remaining_words =
-                                                   (BCC(smb_buffer_response)
-                                                    - 1) / 2;
-                                               bcc_ptr++;      /* Unicode strings must be word aligned */
-                                       } else {
-                                               remaining_words =
-                                                   BCC
-                                                   (smb_buffer_response) / 2;
-                                       }
-                                       len =
-                                           UniStrnlen((wchar_t *) bcc_ptr,
-                                                      remaining_words - 1);
+               bcc_ptr = pByteArea(smb_buffer_response);       
+               if ((pSMBr->resp.hdr.WordCount == 3)
+                   || ((pSMBr->resp.hdr.WordCount == 4)
+                       && (blob_len < pSMBr->resp.ByteCount))) {
+                       if (pSMBr->resp.hdr.WordCount == 4)
+                               bcc_ptr += blob_len;
+
+                       if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
+                               if ((long) (bcc_ptr) % 2) {
+                                       remaining_words =
+                                           (BCC(smb_buffer_response) - 1) /2;
+                                       bcc_ptr++;      /* Unicode strings must be word aligned */
+                               } else {
+                                       remaining_words =
+                                               BCC(smb_buffer_response) / 2;
+                               }
+                               len =
+                                   UniStrnlen((wchar_t *) bcc_ptr,
+                                              remaining_words - 1);
 /* We look for obvious messed up bcc or strings in response so we do not go off
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
-                                       ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
-                                       cifs_strfromUCS_le(ses->serverOS,
-                                                          (wchar_t *)bcc_ptr, len,nls_codepage);
+                               ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+                               cifs_strfromUCS_le(ses->serverOS,
+                                          (wchar_t *)bcc_ptr, len,nls_codepage);
+                               bcc_ptr += 2 * (len + 1);
+                               remaining_words -= len + 1;
+                               ses->serverOS[2 * len] = 0;
+                               ses->serverOS[1 + (2 * len)] = 0;
+                               if (remaining_words > 0) {
+                                       len = UniStrnlen((wchar_t *)bcc_ptr,
+                                                        remaining_words-1);
+                                       ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
+                                       cifs_strfromUCS_le(ses->serverNOS,
+                                                          (wchar_t *)bcc_ptr,len,nls_codepage);
                                        bcc_ptr += 2 * (len + 1);
+                                       ses->serverNOS[2 * len] = 0;
+                                       ses->serverNOS[1 + (2 * len)] = 0;
                                        remaining_words -= len + 1;
-                                       ses->serverOS[2 * len] = 0;
-                                       ses->serverOS[1 + (2 * len)] = 0;
                                        if (remaining_words > 0) {
-                                               len = UniStrnlen((wchar_t *)bcc_ptr,
-                                                                remaining_words
-                                                                - 1);
-                                               ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
-                                               cifs_strfromUCS_le(ses->serverNOS,
-                                                                  (wchar_t *)bcc_ptr,len,nls_codepage);
-                                               bcc_ptr += 2 * (len + 1);
-                                               ses->serverNOS[2 * len] = 0;
-                                               ses->serverNOS[1 + (2 * len)] = 0;
-                                               remaining_words -= len + 1;
-                                               if (remaining_words > 0) {
-                                                       len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 
+                                               len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 
           /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
-                                                       ses->serverDomain =
-                                                           cifs_kcalloc(2*(len+1),GFP_KERNEL);
-                                                       cifs_strfromUCS_le(ses->serverDomain,
-                                                            (wchar_t *)bcc_ptr,len,nls_codepage);
-                                                       bcc_ptr += 2 * (len + 1);
-                                                       ses->serverDomain[2*len] = 0;
-                                                       ses->serverDomain[1+(2*len)] = 0;
-                                               } /* else no more room so create dummy domain string */
-                                               else
-                                                       ses->serverDomain =
-                                                           cifs_kcalloc(2,
-                                                                   GFP_KERNEL);
-                                       } else {        /* no room so create dummy domain and NOS string */
                                                ses->serverDomain =
-                                                   cifs_kcalloc(2, GFP_KERNEL);
-                                               ses->serverNOS =
-                                                   cifs_kcalloc(2, GFP_KERNEL);
-                                       }
-                               } else {        /* ASCII */
-                                       len = strnlen(bcc_ptr, 1024);
-                                       if (((long) bcc_ptr + len) - (long)
-                                           pByteArea(smb_buffer_response)
+                                                   cifs_kcalloc(2*(len+1),GFP_KERNEL);
+                                               cifs_strfromUCS_le(ses->serverDomain,
+                                                    (wchar_t *)bcc_ptr,len,nls_codepage);
+                                               bcc_ptr += 2 * (len + 1);
+                                               ses->serverDomain[2*len] = 0;
+                                               ses->serverDomain[1+(2*len)] = 0;
+                                       } /* else no more room so create dummy domain string */
+                                       else
+                                               ses->serverDomain =
+                                                   cifs_kcalloc(2,
+                                                           GFP_KERNEL);
+                               } else {        /* no room so create dummy domain and NOS string */
+                                       ses->serverDomain =
+                                           cifs_kcalloc(2, GFP_KERNEL);
+                                       ses->serverNOS =
+                                           cifs_kcalloc(2, GFP_KERNEL);
+                               }
+                       } else {        /* ASCII */
+                               len = strnlen(bcc_ptr, 1024);
+                               if (((long) bcc_ptr + len) - (long)
+                                   pByteArea(smb_buffer_response)
                                            <= BCC(smb_buffer_response)) {
-                                               ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
-                                               strncpy(ses->serverOS,bcc_ptr, len);
+                                       ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+                                       strncpy(ses->serverOS,bcc_ptr, len);
 
-                                               bcc_ptr += len;
-                                               bcc_ptr[0] = 0; /* null terminate the string */
-                                               bcc_ptr++;
+                                       bcc_ptr += len;
+                                       bcc_ptr[0] = 0; /* null terminate the string */
+                                       bcc_ptr++;
 
-                                               len = strnlen(bcc_ptr, 1024);
-                                               ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
-                                               strncpy(ses->serverNOS, bcc_ptr, len);
-                                               bcc_ptr += len;
-                                               bcc_ptr[0] = 0;
-                                               bcc_ptr++;
+                                       len = strnlen(bcc_ptr, 1024);
+                                       ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+                                       strncpy(ses->serverNOS, bcc_ptr, len);
+                                       bcc_ptr += len;
+                                       bcc_ptr[0] = 0;
+                                       bcc_ptr++;
 
-                                               len = strnlen(bcc_ptr, 1024);
-                                               ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
-                                               strncpy(ses->serverDomain, bcc_ptr, len);
-                                               bcc_ptr += len;
-                                               bcc_ptr[0] = 0;
-                                               bcc_ptr++;
-                                       } else
-                                               cFYI(1,
-                                                    ("Variable field of length %d extends beyond end of smb ",
-                                                     len));
-                               }
-                       } else {
-                               cERROR(1,
-                                      (" Security Blob Length extends beyond end of SMB"));
+                                       len = strnlen(bcc_ptr, 1024);
+                                       ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
+                                       strncpy(ses->serverDomain, bcc_ptr, len);
+                                       bcc_ptr += len;
+                                       bcc_ptr[0] = 0;
+                                       bcc_ptr++;
+                               } else
+                                       cFYI(1,
+                                            ("Variable field of length %d extends beyond end of smb ",
+                                             len));
                        }
                } else {
-                       cERROR(1, ("No session structure passed in."));
+                       cERROR(1,
+                              (" Security Blob Length extends beyond end of SMB"));
                }
        } else {
                cERROR(1,
@@ -1676,14 +1812,20 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
        SESSION_SETUP_ANDX *pSMB;
        SESSION_SETUP_ANDX *pSMBr;
        char *bcc_ptr;
-       char *user = ses->userName;
-       char *domain = ses->domainName;
+       char *user;
+       char *domain;
        int rc = 0;
        int remaining_words = 0;
        int bytes_returned = 0;
        int len;
+       __u32 capabilities;
+       __u16 count;
 
        cFYI(1, ("In spnego sesssetup "));
+       if(ses == NULL)
+               return -EINVAL;
+       user = ses->userName;
+       domain = ses->domainName;
 
        smb_buffer = cifs_buf_get();
        if (smb_buffer == 0) {
@@ -1694,7 +1836,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 
        /* send SMBsessionSetup here */
        header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
-                       0 /* no tCon exists yet */ , 12 /* wct */ );
+                       NULL /* no tCon exists yet */ , 12 /* wct */ );
        pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
        pSMB->req.AndXCommand = 0xFF;
        pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
@@ -1703,22 +1845,21 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
        if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
                smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
-       pSMB->req.Capabilities =
-           CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+       capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
            CAP_EXTENDED_SECURITY;
        if (ses->capabilities & CAP_UNICODE) {
                smb_buffer->Flags2 |= SMBFLG2_UNICODE;
-               pSMB->req.Capabilities |= CAP_UNICODE;
+               capabilities |= CAP_UNICODE;
        }
        if (ses->capabilities & CAP_STATUS32) {
                smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-               pSMB->req.Capabilities |= CAP_STATUS32;
+               capabilities |= CAP_STATUS32;
        }
        if (ses->capabilities & CAP_DFS) {
                smb_buffer->Flags2 |= SMBFLG2_DFS;
-               pSMB->req.Capabilities |= CAP_DFS;
+               capabilities |= CAP_DFS;
        }
-       pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
+       pSMB->req.Capabilities = cpu_to_le32(capabilities);
 
        pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
        bcc_ptr = pByteArea(smb_buffer);
@@ -1749,7 +1890,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                  32, nls_codepage);
                bcc_ptr += 2 * bytes_returned;
                bytes_returned =
-                   cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
+                   cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
                                  nls_codepage);
                bcc_ptr += 2 * bytes_returned;
                bcc_ptr += 2;
@@ -1774,14 +1915,14 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                }
                strcpy(bcc_ptr, "Linux version ");
                bcc_ptr += strlen("Linux version ");
-               strcpy(bcc_ptr, UTS_RELEASE);
-               bcc_ptr += strlen(UTS_RELEASE) + 1;
+               strcpy(bcc_ptr, system_utsname.release);
+               bcc_ptr += strlen(system_utsname.release) + 1;
                strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
                bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
        }
-       BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-       smb_buffer->smb_buf_length += BCC(smb_buffer);
-       BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+       count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+       smb_buffer->smb_buf_length += count;
+       pSMB->req.ByteCount = cpu_to_le16(count);
 
        rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
                         &bytes_returned, 1);
@@ -1789,10 +1930,10 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 /*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
        } else if ((smb_buffer_response->WordCount == 3)
                   || (smb_buffer_response->WordCount == 4)) {
-               pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
-               pSMBr->resp.SecurityBlobLength =
+               __u16 action = le16_to_cpu(pSMBr->resp.Action);
+               __u16 blob_len =
                    le16_to_cpu(pSMBr->resp.SecurityBlobLength);
-               if (pSMBr->resp.Action & GUEST_LOGIN)
+               if (action & GUEST_LOGIN)
                        cFYI(1, (" Guest login"));      /* BB do we want to set anything in SesInfo struct ? */
                if (ses) {
                        ses->Suid = smb_buffer_response->Uid;   /* UID left in wire format (le) */
@@ -1803,14 +1944,14 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 
                        if ((pSMBr->resp.hdr.WordCount == 3)
                            || ((pSMBr->resp.hdr.WordCount == 4)
-                               && (pSMBr->resp.SecurityBlobLength <
+                               && (blob_len <
                                    pSMBr->resp.ByteCount))) {
                                if (pSMBr->resp.hdr.WordCount == 4) {
                                        bcc_ptr +=
-                                           pSMBr->resp.SecurityBlobLength;
+                                           blob_len;
                                        cFYI(1,
                                             ("Security Blob Length %d ",
-                                             pSMBr->resp.SecurityBlobLength));
+                                             blob_len));
                                }
 
                                if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
@@ -1935,7 +2076,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
        SESSION_SETUP_ANDX *pSMB;
        SESSION_SETUP_ANDX *pSMBr;
        char *bcc_ptr;
-       char *domain = ses->domainName;
+       char *domain;
        int rc = 0;
        int remaining_words = 0;
        int bytes_returned = 0;
@@ -1943,8 +2084,13 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
        int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
        PNEGOTIATE_MESSAGE SecurityBlob;
        PCHALLENGE_MESSAGE SecurityBlob2;
+       __u32 negotiate_flags, capabilities;
+       __u16 count;
 
        cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
+       if(ses == NULL)
+               return -EINVAL;
+       domain = ses->domainName;
        *pNTLMv2_flag = FALSE;
        smb_buffer = cifs_buf_get();
        if (smb_buffer == 0) {
@@ -1956,7 +2102,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 
        /* send SMBsessionSetup here */
        header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
-                       0 /* no tCon exists yet */ , 12 /* wct */ );
+                       NULL /* no tCon exists yet */ , 12 /* wct */ );
        pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
        pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
 
@@ -1967,35 +2113,34 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
        if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
                smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
-       pSMB->req.Capabilities =
-           CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+       capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
            CAP_EXTENDED_SECURITY;
        if (ses->capabilities & CAP_UNICODE) {
                smb_buffer->Flags2 |= SMBFLG2_UNICODE;
-               pSMB->req.Capabilities |= CAP_UNICODE;
+               capabilities |= CAP_UNICODE;
        }
        if (ses->capabilities & CAP_STATUS32) {
                smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-               pSMB->req.Capabilities |= CAP_STATUS32;
+               capabilities |= CAP_STATUS32;
        }
        if (ses->capabilities & CAP_DFS) {
                smb_buffer->Flags2 |= SMBFLG2_DFS;
-               pSMB->req.Capabilities |= CAP_DFS;
+               capabilities |= CAP_DFS;
        }
-       pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
+       pSMB->req.Capabilities = cpu_to_le32(capabilities);
 
        bcc_ptr = (char *) &pSMB->req.SecurityBlob;
        SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
        strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
        SecurityBlob->MessageType = NtLmNegotiate;
-       SecurityBlob->NegotiateFlags =
+       negotiate_flags =
            NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
            NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
            /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
        if(sign_CIFS_PDUs)
-               SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
+               negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
        if(ntlmv2_support)
-               SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
+               negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
        /* setup pointers to domain name and workstation name */
        bcc_ptr += SecurityBlobLength;
 
@@ -2008,20 +2153,20 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                SecurityBlob->DomainName.Length = 0;
                SecurityBlob->DomainName.MaximumLength = 0;
        } else {
-               SecurityBlob->NegotiateFlags |=
-                   NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
+               __u16 len;
+               negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
                strncpy(bcc_ptr, domain, 63);
-               SecurityBlob->DomainName.Length = strnlen(domain, 64);
+               len = strnlen(domain, 64);
                SecurityBlob->DomainName.MaximumLength =
-                   cpu_to_le16(SecurityBlob->DomainName.Length);
+                   cpu_to_le16(len);
                SecurityBlob->DomainName.Buffer =
                    cpu_to_le32((long) &SecurityBlob->
                                DomainString -
                                (long) &SecurityBlob->Signature);
-               bcc_ptr += SecurityBlob->DomainName.Length;
-               SecurityBlobLength += SecurityBlob->DomainName.Length;
+               bcc_ptr += len;
+               SecurityBlobLength += len;
                SecurityBlob->DomainName.Length =
-                   cpu_to_le16(SecurityBlob->DomainName.Length);
+                   cpu_to_le16(len);
        }
        if (ses->capabilities & CAP_UNICODE) {
                if ((long) bcc_ptr % 2) {
@@ -2034,7 +2179,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                  32, nls_codepage);
                bcc_ptr += 2 * bytes_returned;
                bytes_returned =
-                   cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
+                   cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
                                  nls_codepage);
                bcc_ptr += 2 * bytes_returned;
                bcc_ptr += 2;   /* null terminate Linux version */
@@ -2051,35 +2196,34 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
        } else {                /* ASCII */
                strcpy(bcc_ptr, "Linux version ");
                bcc_ptr += strlen("Linux version ");
-               strcpy(bcc_ptr, UTS_RELEASE);
-               bcc_ptr += strlen(UTS_RELEASE) + 1;
+               strcpy(bcc_ptr, system_utsname.release);
+               bcc_ptr += strlen(system_utsname.release) + 1;
                strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
                bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
                bcc_ptr++;      /* empty domain field */
                *bcc_ptr = 0;
        }
-       SecurityBlob->NegotiateFlags =
-           cpu_to_le32(SecurityBlob->NegotiateFlags);
+       SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
        pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
-       BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-       smb_buffer->smb_buf_length += BCC(smb_buffer);
-       BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+       count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+       smb_buffer->smb_buf_length += count;
+       pSMB->req.ByteCount = cpu_to_le16(count);
 
        rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
                         &bytes_returned, 1);
 
        if (smb_buffer_response->Status.CifsError ==
-           (NT_STATUS_MORE_PROCESSING_REQUIRED))
+           cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
                rc = 0;
 
        if (rc) {
 /*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
        } else if ((smb_buffer_response->WordCount == 3)
                   || (smb_buffer_response->WordCount == 4)) {
-               pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
-               pSMBr->resp.SecurityBlobLength =
-                   le16_to_cpu(pSMBr->resp.SecurityBlobLength);
-               if (pSMBr->resp.Action & GUEST_LOGIN)
+               __u16 action = le16_to_cpu(pSMBr->resp.Action);
+               __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+
+               if (action & GUEST_LOGIN)
                        cFYI(1, (" Guest login"));      
         /* Do we want to set anything in SesInfo struct when guest login? */
 
@@ -2096,14 +2240,14 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                        cFYI(1, ("UID = %d ", ses->Suid));
                        if ((pSMBr->resp.hdr.WordCount == 3)
                            || ((pSMBr->resp.hdr.WordCount == 4)
-                               && (pSMBr->resp.SecurityBlobLength <
+                               && (blob_len <
                                    pSMBr->resp.ByteCount))) {
+
                                if (pSMBr->resp.hdr.WordCount == 4) {
-                                       bcc_ptr +=
-                                           pSMBr->resp.SecurityBlobLength;
+                                       bcc_ptr += blob_len;
                                        cFYI(1,
                                             ("Security Blob Length %d ",
-                                             pSMBr->resp.SecurityBlobLength));
+                                             blob_len));
                                }
 
                                cFYI(1, ("NTLMSSP Challenge rcvd "));
@@ -2111,16 +2255,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                memcpy(ses->server->cryptKey,
                                       SecurityBlob2->Challenge,
                                       CIFS_CRYPTO_KEY_SIZE);
-                               if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
+                               if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
                                        *pNTLMv2_flag = TRUE;
 
                                if((SecurityBlob2->NegotiateFlags & 
-                                       NTLMSSP_NEGOTIATE_ALWAYS_SIGN
+                                       cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
                                        || (sign_CIFS_PDUs > 1))
                                                ses->server->secMode |= 
                                                        SECMODE_SIGN_REQUIRED;  
                                if ((SecurityBlob2->NegotiateFlags & 
-                                       NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
+                                       cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
                                                ses->server->secMode |= 
                                                        SECMODE_SIGN_ENABLED;
 
@@ -2264,7 +2408,6 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 
        return rc;
 }
-
 static int
 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                char *ntlm_session_key, int ntlmv2_flag,
@@ -2275,17 +2418,22 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
        SESSION_SETUP_ANDX *pSMB;
        SESSION_SETUP_ANDX *pSMBr;
        char *bcc_ptr;
-       char *user = ses->userName;
-       char *domain = ses->domainName;
+       char *user;
+       char *domain;
        int rc = 0;
        int remaining_words = 0;
        int bytes_returned = 0;
        int len;
        int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
        PAUTHENTICATE_MESSAGE SecurityBlob;
+       __u32 negotiate_flags, capabilities;
+       __u16 count;
 
        cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
-
+       if(ses == NULL)
+               return -EINVAL;
+       user = ses->userName;
+       domain = ses->domainName;
        smb_buffer = cifs_buf_get();
        if (smb_buffer == 0) {
                return -ENOMEM;
@@ -2296,7 +2444,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 
        /* send SMBsessionSetup here */
        header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
-                       0 /* no tCon exists yet */ , 12 /* wct */ );
+                       NULL /* no tCon exists yet */ , 12 /* wct */ );
        pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
        pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
        pSMB->req.AndXCommand = 0xFF;
@@ -2308,36 +2456,35 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
        if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
                smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
-       pSMB->req.Capabilities =
-           CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+       capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
            CAP_EXTENDED_SECURITY;
        if (ses->capabilities & CAP_UNICODE) {
                smb_buffer->Flags2 |= SMBFLG2_UNICODE;
-               pSMB->req.Capabilities |= CAP_UNICODE;
+               capabilities |= CAP_UNICODE;
        }
        if (ses->capabilities & CAP_STATUS32) {
                smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-               pSMB->req.Capabilities |= CAP_STATUS32;
+               capabilities |= CAP_STATUS32;
        }
        if (ses->capabilities & CAP_DFS) {
                smb_buffer->Flags2 |= SMBFLG2_DFS;
-               pSMB->req.Capabilities |= CAP_DFS;
+               capabilities |= CAP_DFS;
        }
-       pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
+       pSMB->req.Capabilities = cpu_to_le32(capabilities);
 
        bcc_ptr = (char *) &pSMB->req.SecurityBlob;
        SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
        strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
        SecurityBlob->MessageType = NtLmAuthenticate;
        bcc_ptr += SecurityBlobLength;
-       SecurityBlob->NegotiateFlags =
+       negotiate_flags = 
            NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
            NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
            0x80000000 | NTLMSSP_NEGOTIATE_128;
        if(sign_CIFS_PDUs)
-               SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
+               negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
        if(ntlmv2_flag)
-               SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
+               negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
 
 /* setup pointers to domain name and workstation name */
 
@@ -2368,36 +2515,36 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                        SecurityBlob->DomainName.Length = 0;
                        SecurityBlob->DomainName.MaximumLength = 0;
                } else {
-                       SecurityBlob->DomainName.Length =
+                       __u16 len =
                            cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
                                          nls_codepage);
-                       SecurityBlob->DomainName.Length *= 2;
+                       len *= 2;
                        SecurityBlob->DomainName.MaximumLength =
-                           cpu_to_le16(SecurityBlob->DomainName.Length);
+                           cpu_to_le16(len);
                        SecurityBlob->DomainName.Buffer =
                            cpu_to_le32(SecurityBlobLength);
-                       bcc_ptr += SecurityBlob->DomainName.Length;
-                       SecurityBlobLength += SecurityBlob->DomainName.Length;
+                       bcc_ptr += len;
+                       SecurityBlobLength += len;
                        SecurityBlob->DomainName.Length =
-                           cpu_to_le16(SecurityBlob->DomainName.Length);
+                           cpu_to_le16(len);
                }
                if (user == NULL) {
                        SecurityBlob->UserName.Buffer = 0;
                        SecurityBlob->UserName.Length = 0;
                        SecurityBlob->UserName.MaximumLength = 0;
                } else {
-                       SecurityBlob->UserName.Length =
+                       __u16 len =
                            cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
                                          nls_codepage);
-                       SecurityBlob->UserName.Length *= 2;
+                       len *= 2;
                        SecurityBlob->UserName.MaximumLength =
-                           cpu_to_le16(SecurityBlob->UserName.Length);
+                           cpu_to_le16(len);
                        SecurityBlob->UserName.Buffer =
                            cpu_to_le32(SecurityBlobLength);
-                       bcc_ptr += SecurityBlob->UserName.Length;
-                       SecurityBlobLength += SecurityBlob->UserName.Length;
+                       bcc_ptr += len;
+                       SecurityBlobLength += len;
                        SecurityBlob->UserName.Length =
-                           cpu_to_le16(SecurityBlob->UserName.Length);
+                           cpu_to_le16(len);
                }
 
                /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
@@ -2417,7 +2564,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                  32, nls_codepage);
                bcc_ptr += 2 * bytes_returned;
                bytes_returned =
-                   cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
+                   cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
                                  nls_codepage);
                bcc_ptr += 2 * bytes_returned;
                bcc_ptr += 2;   /* null term version string */
@@ -2437,52 +2584,50 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                        SecurityBlob->DomainName.Length = 0;
                        SecurityBlob->DomainName.MaximumLength = 0;
                } else {
-                       SecurityBlob->NegotiateFlags |=
-                           NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
+                       __u16 len;
+                       negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
                        strncpy(bcc_ptr, domain, 63);
-                       SecurityBlob->DomainName.Length = strnlen(domain, 64);
+                       len = strnlen(domain, 64);
                        SecurityBlob->DomainName.MaximumLength =
-                           cpu_to_le16(SecurityBlob->DomainName.Length);
+                           cpu_to_le16(len);
                        SecurityBlob->DomainName.Buffer =
                            cpu_to_le32(SecurityBlobLength);
-                       bcc_ptr += SecurityBlob->DomainName.Length;
-                       SecurityBlobLength += SecurityBlob->DomainName.Length;
-                       SecurityBlob->DomainName.Length =
-                           cpu_to_le16(SecurityBlob->DomainName.Length);
+                       bcc_ptr += len;
+                       SecurityBlobLength += len;
+                       SecurityBlob->DomainName.Length = cpu_to_le16(len);
                }
                if (user == NULL) {
                        SecurityBlob->UserName.Buffer = 0;
                        SecurityBlob->UserName.Length = 0;
                        SecurityBlob->UserName.MaximumLength = 0;
                } else {
+                       __u16 len;
                        strncpy(bcc_ptr, user, 63);
-                       SecurityBlob->UserName.Length = strnlen(user, 64);
+                       len = strnlen(user, 64);
                        SecurityBlob->UserName.MaximumLength =
-                           cpu_to_le16(SecurityBlob->UserName.Length);
+                           cpu_to_le16(len);
                        SecurityBlob->UserName.Buffer =
                            cpu_to_le32(SecurityBlobLength);
-                       bcc_ptr += SecurityBlob->UserName.Length;
-                       SecurityBlobLength += SecurityBlob->UserName.Length;
-                       SecurityBlob->UserName.Length =
-                           cpu_to_le16(SecurityBlob->UserName.Length);
+                       bcc_ptr += len;
+                       SecurityBlobLength += len;
+                       SecurityBlob->UserName.Length = cpu_to_le16(len);
                }
                /* BB fill in our workstation name if known BB */
 
                strcpy(bcc_ptr, "Linux version ");
                bcc_ptr += strlen("Linux version ");
-               strcpy(bcc_ptr, UTS_RELEASE);
-               bcc_ptr += strlen(UTS_RELEASE) + 1;
+               strcpy(bcc_ptr, system_utsname.release);
+               bcc_ptr += strlen(system_utsname.release) + 1;
                strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
                bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
                bcc_ptr++;      /* null domain */
                *bcc_ptr = 0;
        }
-       SecurityBlob->NegotiateFlags =
-           cpu_to_le32(SecurityBlob->NegotiateFlags);
+       SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
        pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
-       BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-       smb_buffer->smb_buf_length += BCC(smb_buffer);
-       BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+       count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+       smb_buffer->smb_buf_length += count;
+       pSMB->req.ByteCount = cpu_to_le16(count);
 
        rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
                         &bytes_returned, 1);
@@ -2490,10 +2635,10 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 /*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
        } else if ((smb_buffer_response->WordCount == 3)
                   || (smb_buffer_response->WordCount == 4)) {
-               pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
-               pSMBr->resp.SecurityBlobLength =
+               __u16 action = le16_to_cpu(pSMBr->resp.Action);
+               __u16 blob_len =
                    le16_to_cpu(pSMBr->resp.SecurityBlobLength);
-               if (pSMBr->resp.Action & GUEST_LOGIN)
+               if (action & GUEST_LOGIN)
                        cFYI(1, (" Guest login"));      /* BB do we want to set anything in SesInfo struct ? */
 /*        if(SecurityBlob2->MessageType != NtLm??){                               
                  cFYI("Unexpected message type on auth response is %d ")); 
@@ -2507,14 +2652,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
             /* response can have either 3 or 4 word count - Samba sends 3 */
                        if ((pSMBr->resp.hdr.WordCount == 3)
                            || ((pSMBr->resp.hdr.WordCount == 4)
-                               && (pSMBr->resp.SecurityBlobLength <
+                               && (blob_len <
                                    pSMBr->resp.ByteCount))) {
                                if (pSMBr->resp.hdr.WordCount == 4) {
                                        bcc_ptr +=
-                                           pSMBr->resp.SecurityBlobLength;
+                                           blob_len;
                                        cFYI(1,
                                             ("Security Blob Length %d ",
-                                             pSMBr->resp.SecurityBlobLength));
+                                             blob_len));
                                }
 
                                cFYI(1,
@@ -2655,9 +2800,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
        struct smb_hdr *smb_buffer_response;
        TCONX_REQ *pSMB;
        TCONX_RSP *pSMBr;
-       char *bcc_ptr;
+       unsigned char *bcc_ptr;
        int rc = 0;
        int length;
+       __u16 count;
 
        if (ses == NULL)
                return -EIO;
@@ -2669,7 +2815,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
        smb_buffer_response = smb_buffer;
 
        header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
-                       0 /*no tid */ , 4 /*wct */ );
+                       NULL /*no tid */ , 4 /*wct */ );
        smb_buffer->Uid = ses->Suid;
        pSMB = (TCONX_REQ *) smb_buffer;
        pSMBr = (TCONX_RSP *) smb_buffer_response;
@@ -2677,7 +2823,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
        pSMB->AndXCommand = 0xFF;
        pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
        pSMB->PasswordLength = cpu_to_le16(1);  /* minimum */
-       bcc_ptr = &(pSMB->Password[0]);
+       bcc_ptr = &pSMB->Password[0];
        bcc_ptr++;              /* skip password */
 
        if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
@@ -2703,16 +2849,16 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
        strcpy(bcc_ptr, "?????");
        bcc_ptr += strlen("?????");
        bcc_ptr += 1;
-       BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-       smb_buffer->smb_buf_length += BCC(smb_buffer);
-       BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+       count = bcc_ptr - &pSMB->Password[0];
+       pSMB->hdr.smb_buf_length += count;
+       pSMB->ByteCount = cpu_to_le16(count);
 
        rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
 
        /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
        /* above now done in SendReceive */
        if ((rc == 0) && (tcon != NULL)) {
-        tcon->tidStatus = CifsGood;
+               tcon->tidStatus = CifsGood;
                tcon->tid = smb_buffer_response->Tid;
                bcc_ptr = pByteArea(smb_buffer_response);
                length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
@@ -2721,8 +2867,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
                if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
                        length = UniStrnlen((wchar_t *) bcc_ptr, 512);
-                       if (((long) bcc_ptr + (2 * length)) -
-                           (long) pByteArea(smb_buffer_response) <=
+                       if ((bcc_ptr + (2 * length)) -
+                            pByteArea(smb_buffer_response) <=
                            BCC(smb_buffer_response)) {
                                if(tcon->nativeFileSystem)
                                        kfree(tcon->nativeFileSystem);
@@ -2739,8 +2885,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                        /* else do not bother copying these informational fields */
                } else {
                        length = strnlen(bcc_ptr, 1024);
-                       if (((long) bcc_ptr + length) -
-                           (long) pByteArea(smb_buffer_response) <=
+                       if ((bcc_ptr + length) -
+                           pByteArea(smb_buffer_response) <=
                            BCC(smb_buffer_response)) {
                                if(tcon->nativeFileSystem)
                                        kfree(tcon->nativeFileSystem);
@@ -2769,6 +2915,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
        int rc = 0;
        int xid;
        struct cifsSesInfo *ses = NULL;
+       struct task_struct *cifsd_task;
 
        xid = GetXid();
 
@@ -2781,19 +2928,19 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
                }
                tconInfoFree(cifs_sb->tcon);
                if ((ses) && (ses->server)) {
+                       /* save off task so we do not refer to ses later */
+                       cifsd_task = ses->server->tsk;
                        cFYI(1, ("About to do SMBLogoff "));
                        rc = CIFSSMBLogoff(xid, ses);
                        if (rc == -EBUSY) {
                                FreeXid(xid);
                                return 0;
-                       }
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(HZ / 4);       /* give captive thread time to exit */
-                       if((ses->server) && (ses->server->ssocket)) {            
-                               cFYI(1,("Waking up socket by sending it signal "));
-                               send_sig(SIGKILL,ses->server->tsk,1);
-                       }
+                       } else if (rc == -ESHUTDOWN) {
+                               cFYI(1,("Waking up socket by sending it signal"));
+                               send_sig(SIGKILL,cifsd_task,1);
+                               rc = 0;
+                       } /* else - we have an smb session
+                               left on this socket do not kill cifsd */
                } else
                        cFYI(1, ("No session or bad tcon"));
        }