vserver 1.9.5.x5
[linux-2.6.git] / fs / cifs / cifssmb.c
index dc9e0fd..81a6c9e 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/vfs.h>
+#include <linux/posix_acl_xattr.h>
 #include <asm/uaccess.h>
 #include "cifspdu.h"
 #include "cifsglob.h"
@@ -77,6 +78,97 @@ static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
        /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
 }
 
+static int
+small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+        void **request_buf /* returned */)
+{
+       int rc = 0;
+
+       /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
+          check for tcp and smb session status done differently
+          for those three - in the calling routine */
+       if(tcon) {
+               if((tcon->ses) && (tcon->ses->server)){
+                       struct nls_table *nls_codepage;
+                               /* Give Demultiplex thread up to 10 seconds to 
+                                       reconnect, should be greater than cifs socket
+                                       timeout which is 7 seconds */
+                       while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+                               wait_event_interruptible_timeout(tcon->ses->server->response_q,
+                                       (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
+                               if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+                                       /* on "soft" mounts we wait once */
+                                       if((tcon->retry == FALSE) || 
+                                          (tcon->ses->status == CifsExiting)) {
+                                               cFYI(1,("gave up waiting on reconnect in smb_init"));
+                                               return -EHOSTDOWN;
+                                       } /* else "hard" mount - keep retrying until 
+                                       process is killed or server comes back up */
+                               } else /* TCP session is reestablished now */
+                                       break;
+                                
+                       }
+                       
+                       nls_codepage = load_nls_default();
+               /* need to prevent multiple threads trying to
+               simultaneously reconnect the same SMB session */
+                       down(&tcon->ses->sesSem);
+                       if(tcon->ses->status == CifsNeedReconnect)
+                               rc = cifs_setup_session(0, tcon->ses, nls_codepage);
+                       if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
+                               mark_open_files_invalid(tcon);
+                               rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
+                                       nls_codepage);
+                               up(&tcon->ses->sesSem);
+                               if(rc == 0)
+                                       atomic_inc(&tconInfoReconnectCount);
+
+                               cFYI(1, ("reconnect tcon rc = %d", rc));
+                               /* Removed call to reopen open files here - 
+                                       it is safer (and faster) to reopen files
+                                       one at a time as needed in read and write */
+
+                               /* Check if handle based operation so we 
+                                       know whether we can continue or not without
+                                       returning to caller to reset file handle */
+                               switch(smb_command) {
+                                       case SMB_COM_READ_ANDX:
+                                       case SMB_COM_WRITE_ANDX:
+                                       case SMB_COM_CLOSE:
+                                       case SMB_COM_FIND_CLOSE2:
+                                       case SMB_COM_LOCKING_ANDX: {
+                                               unload_nls(nls_codepage);
+                                               return -EAGAIN;
+                                       }
+                               }
+                       } else {
+                               up(&tcon->ses->sesSem);
+                       }
+                       unload_nls(nls_codepage);
+
+               } else {
+                       return -EIO;
+               }
+       }
+       if(rc)
+               return rc;
+
+       *request_buf = cifs_small_buf_get();
+       if (*request_buf == 0) {
+               /* BB should we add a retry in here if not a writepage? */
+               return -ENOMEM;
+       }
+
+       header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
+
+#ifdef CONFIG_CIFS_STATS
+        if(tcon != NULL) {
+                atomic_inc(&tcon->num_smbs_sent);
+        }
+#endif /* CONFIG_CIFS_STATS */
+       return rc;
+}  
+
 static int
 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
         void **request_buf /* returned */ ,
@@ -171,10 +263,42 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
         if(tcon != NULL) {
                 atomic_inc(&tcon->num_smbs_sent);
         }
-#endif
+#endif /* CONFIG_CIFS_STATS */
        return rc;
 }
 
+static int validate_t2(struct smb_t2_rsp * pSMB) 
+{
+       int rc = -EINVAL;
+       int total_size;
+       char * pBCC;
+
+       /* check for plausible wct, bcc and t2 data and parm sizes */
+       /* check for parm and data offset going beyond end of smb */
+       if(pSMB->hdr.WordCount >= 10) {
+               if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
+                  (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
+                       /* check that bcc is at least as big as parms + data */
+                       /* check that bcc is less than negotiated smb buffer */
+                       total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
+                       if(total_size < 512) {
+                               total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
+                               /* BCC le converted in SendReceive */
+                               pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) + 
+                                       (char *)pSMB;
+                               if((total_size <= (*(u16 *)pBCC)) && 
+                                  (total_size < 
+                                       CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
+                                       return 0;
+                               }
+                               
+                       }
+               }
+       }
+       cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
+               sizeof(struct smb_t2_rsp) + 16);
+       return rc;
+}
 int
 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 {
@@ -183,6 +307,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
        int rc = 0;
        int bytes_returned;
        struct TCP_Server_Info * server;
+       u16 count;
 
        if(ses->server)
                server = ses->server;
@@ -199,12 +324,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
        if (extended_security)
                pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
 
-       pSMB->ByteCount = strlen(protocols[0].name) + 1;
+       count = strlen(protocols[0].name) + 1;
        strncpy(pSMB->DialectsArray, protocols[0].name, 30);    
     /* null guaranteed to be at end of source and target buffers anyway */
 
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += count;
+       pSMB->ByteCount = cpu_to_le16(count);
 
        rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -216,7 +341,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                /* probably no need to store and check maxvcs */
                server->maxBuf =
                        min(le32_to_cpu(pSMBr->MaxBufferSize),
-                       (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
+                       (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
                server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
                cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
                GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
@@ -234,10 +359,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 
                /* BB might be helpful to save off the domain of server here */
 
-               if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
-                       if (pSMBr->ByteCount < 16)
+               if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 
+                       (server->capabilities & CAP_EXTENDED_SECURITY)) {
+                       count = pSMBr->ByteCount;
+                       if (count < 16)
                                rc = -EIO;
-                       else if (pSMBr->ByteCount == 16) {
+                       else if (count == 16) {
                                server->secType = RawNTLMSSP;
                                if (server->socketUseCount.counter > 1) {
                                        if (memcmp
@@ -260,8 +387,14 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                                rc = decode_negTokenInit(pSMBr->u.
                                                         extended_response.
                                                         SecurityBlob,
-                                                        pSMBr->ByteCount -
-                                                        16, &server->secType);
+                                                        count - 16,
+                                                        &server->secType);
+                               if(rc == 1) {
+                               /* BB Need to fill struct for sessetup here */
+                                       rc = -EOPNOTSUPP;
+                               } else {
+                                       rc = -EINVAL;
+                               }
                        }
                } else
                        server->capabilities &= ~CAP_EXTENDED_SECURITY;
@@ -285,7 +418,7 @@ int
 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
 {
        struct smb_hdr *smb_buffer;
-       struct smb_hdr *smb_buffer_response;
+       struct smb_hdr *smb_buffer_response; /* BB removeme BB */
        int rc = 0;
        int length;
 
@@ -319,20 +452,20 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
                up(&tcon->tconSem);
                return -EIO;
        }
-
-       rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
-                     (void **) &smb_buffer, (void **) &smb_buffer_response);
+       rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **)&smb_buffer);
        if (rc) {
                up(&tcon->tconSem);
                return rc;
-       }
+       } else {
+               smb_buffer_response = smb_buffer; /* BB removeme BB */
+    }
        rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
                         &length, 0);
        if (rc)
                cFYI(1, (" Tree disconnect failed %d", rc));
 
        if (smb_buffer)
-               cifs_buf_release(smb_buffer);
+               cifs_small_buf_release(smb_buffer);
        up(&tcon->tconSem);
 
        /* No need to return error on this operation if tid invalidated and 
@@ -362,12 +495,14 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
                up(&ses->sesSem);
                return -EBUSY;
        }
-
-       rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL /* no tcon anymore */,
-                (void **) &pSMB, (void **) &smb_buffer_response);
-
-       if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-               pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+       rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
+       smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
+       
+       if(ses->server) {
+               if(ses->server->secMode & 
+                  (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+                       pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+       }
 
        if (rc) {
                up(&ses->sesSem);
@@ -389,7 +524,7 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
                }
        }
        if (pSMB)
-               cifs_buf_release(pSMB);
+               cifs_small_buf_release(pSMB);
        up(&ses->sesSem);
 
        /* if session dead then we do not need to do ulogoff,
@@ -418,22 +553,21 @@ DelFileRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fileName, 530);
+               name_len = strnlen(fileName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->fileName, fileName, name_len);
        }
        pSMB->SearchAttributes =
            cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
-       pSMB->ByteCount = name_len + 1;
        pSMB->BufferFormat = 0x04;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += name_len + 1;
+       pSMB->ByteCount = cpu_to_le16(name_len + 1);
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
@@ -471,21 +605,20 @@ RmDirRetry:
                return rc;
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
+               name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, PATH_MAX
                                /* find define for this maxpathcomponent */
                                , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(dirName, 530);
+               name_len = strnlen(dirName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->DirName, dirName, name_len);
        }
 
-       pSMB->ByteCount = name_len + 1;
        pSMB->BufferFormat = 0x04;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += name_len + 1;
+       pSMB->ByteCount = cpu_to_le16(name_len + 1);
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
@@ -522,21 +655,20 @@ MkDirRetry:
                return rc;
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
+               name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, PATH_MAX
                                         /* find define for this maxpathcomponent */
                                         , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(name, 530);
+               name_len = strnlen(name, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->DirName, name, name_len);
        }
 
-       pSMB->ByteCount = name_len + 1 /* for buf format */ ;
        pSMB->BufferFormat = 0x04;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += name_len + 1;
+       pSMB->ByteCount = cpu_to_le16(name_len + 1);
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
@@ -566,6 +698,7 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
        OPEN_RSP *pSMBr = NULL;
        int bytes_returned;
        int name_len;
+       __u16 count;
 
 openRetry:
        rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
@@ -576,18 +709,18 @@ openRetry:
        pSMB->AndXCommand = 0xFF;       /* none */
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               pSMB->ByteCount = 1;    /* account for one byte pad to word boundary */
+               count = 1;      /* account for one byte pad to word boundary */
                name_len =
                    cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
-                                 fileName, 530
+                                 fileName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
                pSMB->NameLength = cpu_to_le16(name_len);
        } else {                /* BB improve the check for buffer overruns BB */
-               pSMB->ByteCount = 0;    /* no pad */
-               name_len = strnlen(fileName, 530);
+               count = 0;      /* no pad */
+               name_len = strnlen(fileName, PATH_MAX);
                name_len++;     /* trailing null */
                pSMB->NameLength = cpu_to_le16(name_len);
                strncpy(pSMB->fileName, fileName, name_len);
@@ -599,30 +732,29 @@ openRetry:
        }
        pSMB->DesiredAccess = cpu_to_le32(access_flags);
        pSMB->AllocationSize = 0;
-       pSMB->FileAttributes = ATTR_NORMAL;
+       pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
        /* XP does not handle ATTR_POSIX_SEMANTICS */
        /* but it helps speed up case sensitive checks for other
        servers such as Samba */
        if (tcon->ses->capabilities & CAP_UNIX)
-               pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS;
+               pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
 
        /* if ((omode & S_IWUGO) == 0)
-               pSMB->FileAttributes |= ATTR_READONLY;*/
+               pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
        /*  Above line causes problems due to vfs splitting create into two
                pieces - need to set mode after file created not while it is
                being created */
-       pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
        pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
        pSMB->CreateDisposition = cpu_to_le32(openDisposition);
        pSMB->CreateOptions = cpu_to_le32(create_options);
        pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
        pSMB->SecurityFlags =
-           cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
+           SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
 
-       pSMB->ByteCount += name_len;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+       count += name_len;
+       pSMB->hdr.smb_buf_length += count;
 
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->ByteCount = cpu_to_le16(count);
        /* long_op set to 1 to allow for oplock break timeouts */
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 1);
@@ -694,24 +826,24 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
        if (rc) {
                cERROR(1, ("Send error in read = %d", rc));
        } else {
-               pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
-               *nbytes = pSMBr->DataLength;
+               __u16 data_length = le16_to_cpu(pSMBr->DataLength);
+               *nbytes = data_length;
                /*check that DataLength would not go beyond end of SMB */
-               if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE
-                               || (pSMBr->DataLength > count)) {
-                       cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
+               if ((data_length > CIFSMaxBufSize
+                               || (data_length > count)) {
+                       cFYI(1,("bad length %d for count %d",data_length,count));
                        rc = -EIO;
                        *nbytes = 0;
                } else {
                        pReadData =
                            (char *) (&pSMBr->hdr.Protocol) +
                            le16_to_cpu(pSMBr->DataOffset);
-/*                     if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
+/*                     if(rc = copy_to_user(buf, pReadData, data_length)) {
                                cERROR(1,("Faulting on read rc = %d",rc));
                                rc = -EFAULT;
                        }*/ /* can not use copy_to_user when using page cache*/
                        if(*buf)
-                           memcpy(*buf,pReadData,pSMBr->DataLength);
+                           memcpy(*buf,pReadData,data_length);
                }
        }
        if (pSMB) {
@@ -730,12 +862,14 @@ int
 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
             const int netfid, const unsigned int count,
             const __u64 offset, unsigned int *nbytes, const char *buf,
-            const int long_op)
+            const char __user * ubuf, const int long_op)
 {
        int rc = -EACCES;
        WRITE_REQ *pSMB = NULL;
        WRITE_RSP *pSMBr = NULL;
        int bytes_returned;
+       unsigned bytes_sent;
+       __u16 byte_count;
 
        rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -749,22 +883,35 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
        pSMB->Fid = netfid;
        pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
        pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
+       pSMB->Reserved = 0xFFFFFFFF;
+       pSMB->WriteMode = 0;
        pSMB->Remaining = 0;
-       if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
-               pSMB->DataLengthLow =
-                   (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
-       else
-               pSMB->DataLengthLow = count;
+       /* BB can relax this if buffer is big enough in some cases - ie we can 
+       send more  if LARGE_WRITE_X capability returned by the server and if
+       our buffer is big enough or if we convert to iovecs on socket writes
+       and eliminate the copy to the CIFS buffer */
+       bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
+       if (bytes_sent > count)
+               bytes_sent = count;
        pSMB->DataLengthHigh = 0;
        pSMB->DataOffset =
            cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
+    if(buf)
+           memcpy(pSMB->Data,buf,bytes_sent);
+       else if(ubuf)
+               copy_from_user(pSMB->Data,ubuf,bytes_sent);
+    else {
+               /* No buffer */
+               if(pSMB)
+                       cifs_buf_release(pSMB);
+               return -EINVAL;
+       }
 
-       memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
-
-       pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
-       pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       byte_count = bytes_sent + 1 /* pad */ ;
+       pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
+       pSMB->DataLengthHigh = 0;
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
@@ -783,6 +930,66 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
        return rc;
 }
 
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
+            const int netfid, const unsigned int count,
+            const __u64 offset, unsigned int *nbytes, const char __user *buf,
+            const int long_op)
+{
+       int rc = -EACCES;
+       WRITE_REQ *pSMB = NULL;
+       WRITE_RSP *pSMBr = NULL;
+       /*int bytes_returned;*/
+       unsigned bytes_sent;
+       __u16 byte_count;
+
+       rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
+       pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
+    
+    if (rc)
+               return rc;
+       /* tcon and ses pointer are checked in smb_init */
+       if (tcon->ses->server == NULL)
+               return -ECONNABORTED;
+
+       pSMB->AndXCommand = 0xFF; /* none */
+       pSMB->Fid = netfid;
+       pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
+       pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
+       pSMB->Reserved = 0xFFFFFFFF;
+       pSMB->WriteMode = 0;
+       pSMB->Remaining = 0;
+       bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
+       if (bytes_sent > count)
+               bytes_sent = count;
+       pSMB->DataLengthHigh = 0;
+       pSMB->DataOffset =
+           cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
+
+       byte_count = bytes_sent + 1 /* pad */ ;
+       pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
+       pSMB->DataLengthHigh = 0;
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+
+/*     rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                        (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */  /* BB fixme BB */
+       if (rc) {
+               cFYI(1, ("Send error in write2 (large write) = %d", rc));
+               *nbytes = 0;
+       } else
+               *nbytes = le16_to_cpu(pSMBr->Count);
+
+       if (pSMB)
+               cifs_small_buf_release(pSMB);
+
+       /* Note: On -EAGAIN error only caller can retry on handle based calls 
+               since file handle passed in no longer valid */
+
+       return rc;
+}
+#endif /* CIFS_EXPERIMENTAL */
+
 int
 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
            const __u16 smb_file_id, const __u64 len,
@@ -794,7 +1001,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
        LOCK_RSP *pSMBr = NULL;
        int bytes_returned;
        int timeout = 0;
-       __u64 temp;
+       __u16 count;
 
        cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
        rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
@@ -807,33 +1014,31 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
                pSMB->Timeout = 0;
        } else if (waitFlag == TRUE) {
                timeout = 3;  /* blocking operation, no timeout */
-               pSMB->Timeout = -1; /* blocking - do not time out */
+               pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
        } else {
                pSMB->Timeout = 0;
        }
 
-       pSMB->NumberOfLocks = cpu_to_le32(numLock);
-       pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
+       pSMB->NumberOfLocks = cpu_to_le16(numLock);
+       pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
        pSMB->LockType = lockType;
        pSMB->AndXCommand = 0xFF;       /* none */
        pSMB->Fid = smb_file_id; /* netfid stays le */
 
-       if(numLock != 0) {
+       if((numLock != 0) || (numUnlock != 0)) {
                pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
                /* BB where to store pid high? */
-               temp = cpu_to_le64(len);
-               pSMB->Locks[0].LengthLow = (__u32)(temp & 0xFFFFFFFF);
-               pSMB->Locks[0].LengthHigh =  (__u32)(temp>>32);
-               temp = cpu_to_le64(offset);
-               pSMB->Locks[0].OffsetLow = (__u32)(temp & 0xFFFFFFFF);
-               pSMB->Locks[0].OffsetHigh = (__u32)(temp>>32);
-               pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
+               pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
+               pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
+               pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
+               pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
+               count = sizeof(LOCKING_ANDX_RANGE);
        } else {
                /* oplock break */
-               pSMB->ByteCount = 0;
+               count = 0;
        }
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += count;
+       pSMB->ByteCount = cpu_to_le16(count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
@@ -859,8 +1064,8 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
        cFYI(1, ("In CIFSSMBClose"));
 
 /* do not retry on dead session on close */
-       rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
+       rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
+       pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
        if(rc == -EAGAIN)
                return 0;
        if (rc)
@@ -877,8 +1082,9 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
                        cERROR(1, ("Send error in Close = %d", rc));
                }
        }
+
        if (pSMB)
-               cifs_buf_release(pSMB);
+               cifs_small_buf_release(pSMB);
 
        /* Since session is dead, file will be closed on server already */
        if(rc == -EAGAIN)
@@ -897,6 +1103,7 @@ CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
        RENAME_RSP *pSMBr = NULL;
        int bytes_returned;
        int name_len, name_len2;
+       __u16 count;
 
        cFYI(1, ("In CIFSSMBRename"));
 renameRetry:
@@ -912,7 +1119,7 @@ renameRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
@@ -922,15 +1129,15 @@ renameRetry:
                pSMB->OldFileName[name_len + 1] = 0x00;
                name_len2 =
                    cifs_strtoUCS((wchar_t *) & pSMB->
-                                 OldFileName[name_len + 2], toName, 530,
+                                 OldFileName[name_len + 2], toName, PATH_MAX,
                                  nls_codepage);
                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
                name_len2 *= 2; /* convert to bytes */
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fromName, 530);
+               name_len = strnlen(fromName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->OldFileName, fromName, name_len);
-               name_len2 = strnlen(toName, 530);
+               name_len2 = strnlen(toName, PATH_MAX);
                name_len2++;    /* trailing null */
                pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
                strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
@@ -938,9 +1145,9 @@ renameRetry:
                name_len2++;    /* signature byte */
        }
 
-       pSMB->ByteCount = 1 /* 1st signature byte */  + name_len + name_len2;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       count = 1 /* 1st signature byte */  + name_len + name_len2;
+       pSMB->hdr.smb_buf_length += count;
+       pSMB->ByteCount = cpu_to_le16(count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -974,6 +1181,7 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
        int rc = 0;
        int bytes_returned = 0;
        int len_of_str;
+       __u16 params, param_offset, offset, count, byte_count;
 
        cFYI(1, ("Rename to File by handle"));
        rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
@@ -981,28 +1189,27 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
        if (rc)
                return rc;
 
-       pSMB->ParameterCount = 6;
+       params = 6;
        pSMB->MaxSetupCount = 0;
        pSMB->Reserved = 0;
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
-                               Fid) - 4;
-       pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+       param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+       offset = param_offset + params;
 
-       data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+       data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
        rename_info = (struct set_file_rename *) data_offset;
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
-       pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount;
-       pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+       byte_count = 3 /* pad */  + params;
+       pSMB->ParameterCount = cpu_to_le16(params);
        pSMB->TotalParameterCount = pSMB->ParameterCount;
-       pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-       pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
        /* construct random name ".cifs_tmp<inodenum><mid>" */
        rename_info->overwrite = cpu_to_le32(1);
        rename_info->root_fid  = 0;
@@ -1011,19 +1218,19 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
                sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
                len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
        } else {
-               len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
+               len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, PATH_MAX, nls_codepage);
        }
        rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
-       pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
-       pSMB->ByteCount += pSMB->DataCount;
-       pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+       count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
+       byte_count += count;
+       pSMB->DataCount = cpu_to_le16(count);
        pSMB->TotalDataCount = pSMB->DataCount;
        pSMB->Fid = netfid;
        pSMB->InformationLevel =
                cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
        pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
        rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
@@ -1053,6 +1260,7 @@ CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
        COPY_RSP *pSMBr = NULL;
        int bytes_returned;
        int name_len, name_len2;
+       __u16 count;
 
        cFYI(1, ("In CIFSSMBCopy"));
 copyRetry:
@@ -1064,14 +1272,12 @@ copyRetry:
        pSMB->BufferFormat = 0x04;
        pSMB->Tid2 = target_tid;
 
-       if(flags & COPY_TREE)
-               pSMB->Flags |= COPY_TREE;
-       pSMB->Flags = cpu_to_le16(pSMB->Flags);
+       pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, 
                                fromName, 
-                               530 /* find define for this maxpathcomponent */,
+                               PATH_MAX /* find define for this maxpathcomponent */,
                                nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
@@ -1079,15 +1285,15 @@ copyRetry:
                /* protocol requires ASCII signature byte on Unicode string */
                pSMB->OldFileName[name_len + 1] = 0x00;
                name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
-                               OldFileName[name_len + 2], toName, 530,
+                               OldFileName[name_len + 2], toName, PATH_MAX,
                                nls_codepage);
                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
                name_len2 *= 2; /* convert to bytes */
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fromName, 530);
+               name_len = strnlen(fromName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->OldFileName, fromName, name_len);
-               name_len2 = strnlen(toName, 530);
+               name_len2 = strnlen(toName, PATH_MAX);
                name_len2++;    /* trailing null */
                pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
                strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
@@ -1095,15 +1301,15 @@ copyRetry:
                name_len2++;    /* signature byte */
        }
 
-       pSMB->ByteCount = 1 /* 1st signature byte */  + name_len + name_len2;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       count = 1 /* 1st signature byte */  + name_len + name_len2;
+       pSMB->hdr.smb_buf_length += count;
+       pSMB->ByteCount = cpu_to_le16(count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
                cFYI(1, ("Send error in copy = %d with %d files copied",
-                       rc, pSMBr->CopyCount));
+                       rc, le16_to_cpu(pSMBr->CopyCount)));
        }
        if (pSMB)
                cifs_buf_release(pSMB);
@@ -1126,6 +1332,7 @@ CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
        int name_len_target;
        int rc = 0;
        int bytes_returned = 0;
+       __u16 params, param_offset, offset, byte_count;
 
        cFYI(1, ("In Symlink Unix style"));
 createSymLinkRetry:
@@ -1136,59 +1343,58 @@ createSymLinkRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
 
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fromName, 530);
+               name_len = strnlen(fromName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, fromName, name_len);
        }
-       pSMB->ParameterCount = 6 + name_len;
+       params = 6 + name_len;
        pSMB->MaxSetupCount = 0;
        pSMB->Reserved = 0;
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+       param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-       pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+       offset = param_offset + params;
 
-       data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+       data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len_target =
-                   cifs_strtoUCS((wchar_t *) data_offset, toName, 530
+                   cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len_target++;      /* trailing null */
                name_len_target *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len_target = strnlen(toName, 530);
+               name_len_target = strnlen(toName, PATH_MAX);
                name_len_target++;      /* trailing null */
                strncpy(data_offset, toName, name_len_target);
        }
 
-       pSMB->DataCount = name_len_target;
        pSMB->MaxParameterCount = cpu_to_le16(2);
        /* BB find exact max on data count below from sess */
        pSMB->MaxDataCount = cpu_to_le16(1000);
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-       pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-       pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-       pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+       byte_count = 3 /* pad */  + params + name_len_target;
+       pSMB->DataCount = cpu_to_le16(name_len_target);
+       pSMB->ParameterCount = cpu_to_le16(params);
        pSMB->TotalDataCount = pSMB->DataCount;
        pSMB->TotalParameterCount = pSMB->ParameterCount;
-       pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-       pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
        pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
        pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
@@ -1218,6 +1424,7 @@ CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
        int name_len_target;
        int rc = 0;
        int bytes_returned = 0;
+       __u16 params, param_offset, offset, byte_count;
 
        cFYI(1, ("In Create Hard link Unix style"));
 createHardLinkRetry:
@@ -1227,59 +1434,58 @@ createHardLinkRetry:
                return rc;
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
+               name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, PATH_MAX
                                         /* find define for this maxpathcomponent */
                                         , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
 
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(toName, 530);
+               name_len = strnlen(toName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, toName, name_len);
        }
-       pSMB->ParameterCount = 6 + name_len;
+       params = 6 + name_len;
        pSMB->MaxSetupCount = 0;
        pSMB->Reserved = 0;
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+       param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-       pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+       offset = param_offset + params;
 
-       data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+       data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len_target =
-                   cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
+                   cifs_strtoUCS((wchar_t *) data_offset, fromName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len_target++;      /* trailing null */
                name_len_target *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len_target = strnlen(fromName, 530);
+               name_len_target = strnlen(fromName, PATH_MAX);
                name_len_target++;      /* trailing null */
                strncpy(data_offset, fromName, name_len_target);
        }
 
-       pSMB->DataCount = name_len_target;
        pSMB->MaxParameterCount = cpu_to_le16(2);
        /* BB find exact max on data count below from sess*/
        pSMB->MaxDataCount = cpu_to_le16(1000);
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-       pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-       pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+       byte_count = 3 /* pad */  + params + name_len_target;
+       pSMB->ParameterCount = cpu_to_le16(params);
        pSMB->TotalParameterCount = pSMB->ParameterCount;
-       pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+       pSMB->DataCount = cpu_to_le16(name_len_target);
        pSMB->TotalDataCount = pSMB->DataCount;
-       pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-       pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
        pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
        pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
@@ -1304,6 +1510,7 @@ CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
        RENAME_RSP *pSMBr = NULL;
        int bytes_returned;
        int name_len, name_len2;
+       __u16 count;
 
        cFYI(1, ("In CIFSCreateHardLink"));
 winCreateHardLinkRetry:
@@ -1323,7 +1530,7 @@ winCreateHardLinkRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
@@ -1332,15 +1539,15 @@ winCreateHardLinkRetry:
                pSMB->OldFileName[name_len + 1] = 0x04; 
                name_len2 =
                    cifs_strtoUCS((wchar_t *) & pSMB->
-                                 OldFileName[name_len + 2], toName, 530,
+                                 OldFileName[name_len + 2], toName, PATH_MAX,
                                  nls_codepage);
                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
                name_len2 *= 2; /* convert to bytes */
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fromName, 530);
+               name_len = strnlen(fromName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->OldFileName, fromName, name_len);
-               name_len2 = strnlen(toName, 530);
+               name_len2 = strnlen(toName, PATH_MAX);
                name_len2++;    /* trailing null */
                pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
                strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
@@ -1348,9 +1555,9 @@ winCreateHardLinkRetry:
                name_len2++;    /* signature byte */
        }
 
-       pSMB->ByteCount = 1 /* string type byte */  + name_len + name_len2;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       count = 1 /* string type byte */  + name_len + name_len2;
+       pSMB->hdr.smb_buf_length += count;
+       pSMB->ByteCount = cpu_to_le16(count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -1377,6 +1584,7 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
        int rc = 0;
        int bytes_returned;
        int name_len;
+       __u16 params, byte_count;
 
        cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
 
@@ -1388,19 +1596,18 @@ querySymLinkRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, 530);
+               name_len = strnlen(searchName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, searchName, name_len);
        }
 
-       pSMB->TotalParameterCount =
-           2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
+       params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
        pSMB->TotalDataCount = 0;
        pSMB->MaxParameterCount = cpu_to_le16(2);
        /* BB find exact max data count below from sess structure BB */
@@ -1417,38 +1624,42 @@ querySymLinkRetry:
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-       pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-       pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
        pSMB->ParameterCount = pSMB->TotalParameterCount;
        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
        pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
                cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
-       } else {                /* decode response */
-               pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-               pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
-               if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
+       } else {
+               /* decode response */
+
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+               if (rc || (pSMBr->ByteCount < 2))
                /* BB also check enough total bytes returned */
                        rc = -EIO;      /* bad smb */
                else {
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+                       __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+
                        if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
                                name_len = UniStrnlen((wchar_t *) ((char *)
-                                       &pSMBr->hdr.Protocol +pSMBr->DataOffset),
-                                       min_t(const int, buflen,pSMBr->DataCount) / 2);
+                                       &pSMBr->hdr.Protocol +data_offset),
+                                       min_t(const int, buflen,count) / 2);
                                cifs_strfromUCS_le(symlinkinfo,
                                        (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
-                                               pSMBr->DataOffset),
+                                               data_offset),
                                        name_len, nls_codepage);
                        } else {
                                strncpy(symlinkinfo,
                                        (char *) &pSMBr->hdr.Protocol + 
-                                               pSMBr->DataOffset,
-                                       min_t(const int, buflen, pSMBr->DataCount));
+                                               data_offset,
+                                       min_t(const int, buflen, count));
                        }
                        symlinkinfo[buflen] = 0;
        /* just in case so calling code does not go off the end of buffer */
@@ -1505,16 +1716,16 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
        if (rc) {
                cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
        } else {                /* decode response */
-               pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-               pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
-               if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
+               __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
+               __u32 data_count = le32_to_cpu(pSMBr->DataCount);
+               if ((pSMBr->ByteCount < 2) || (data_offset > 512))
                /* BB also check enough total bytes returned */
                        rc = -EIO;      /* bad smb */
                else {
-                       if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
+                       if(data_count && (data_count < 2048)) {
                /* could also validate reparse tag && better check name length */
                                struct reparse_data * reparse_buf = (struct reparse_data *)
-                                       ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
+                                       ((char *)&pSMBr->hdr.Protocol + data_offset);
                                if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
                                        name_len = UniStrnlen((wchar_t *)
                                                        (reparse_buf->LinkNamesBuf + 
@@ -1547,6 +1758,306 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
        return rc;
 }
 
+#ifdef CONFIG_CIFS_POSIX
+
+/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
+static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
+{
+       /* u8 cifs fields do not need le conversion */
+       ace->e_perm = (__u16)cifs_ace->cifs_e_perm; 
+       ace->e_tag  = (__u16)cifs_ace->cifs_e_tag;
+       ace->e_id   = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
+       /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
+
+       return;
+}
+
+/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
+static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const int acl_type,const int size_of_data_area)
+{
+       int size =  0;
+       int i;
+       __u16 count;
+       struct cifs_posix_ace * pACE;
+       struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
+       posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
+
+       if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
+               return -EOPNOTSUPP;
+
+       if(acl_type & ACL_TYPE_ACCESS) {
+               count = le16_to_cpu(cifs_acl->access_entry_count);
+               pACE = &cifs_acl->ace_array[0];
+               size = sizeof(struct cifs_posix_acl);
+               size += sizeof(struct cifs_posix_ace) * count;
+               /* check if we would go beyond end of SMB */
+               if(size_of_data_area < size) {
+                       cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
+                       return -EINVAL;
+               }
+       } else if(acl_type & ACL_TYPE_DEFAULT) {
+               count = le16_to_cpu(cifs_acl->access_entry_count);
+               size = sizeof(struct cifs_posix_acl);
+               size += sizeof(struct cifs_posix_ace) * count;
+/* skip past access ACEs to get to default ACEs */
+               pACE = &cifs_acl->ace_array[count];
+               count = le16_to_cpu(cifs_acl->default_entry_count);
+               size += sizeof(struct cifs_posix_ace) * count;
+               /* check if we would go beyond end of SMB */
+               if(size_of_data_area < size)
+                       return -EINVAL;
+       } else {
+               /* illegal type */
+               return -EINVAL;
+       }
+
+       size = posix_acl_xattr_size(count);
+       if((buflen == 0) || (local_acl == NULL)) {
+               /* used to query ACL EA size */                         
+       } else if(size > buflen) {
+               return -ERANGE;
+       } else /* buffer big enough */ {
+               local_acl->a_version = POSIX_ACL_XATTR_VERSION;
+               for(i = 0;i < count ;i++) {
+                       cifs_convert_ace(&local_acl->a_entries[i],pACE);
+                       pACE ++;
+               }
+       }
+       return size;
+}
+
+__u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
+                       const posix_acl_xattr_entry * local_ace)
+{
+       __u16 rc = 0; /* 0 = ACL converted ok */
+
+       cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
+       cifs_ace->cifs_e_tag =  (__u8)cpu_to_le16(local_ace->e_tag);
+       /* BB is there a better way to handle the large uid? */
+       if(local_ace->e_id == -1) {
+       /* Probably no need to le convert -1 on any arch but can not hurt */
+               cifs_ace->cifs_uid = cpu_to_le64(-1);
+       } else 
+               cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
+        /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
+       return rc;
+}
+
+/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
+__u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
+               const int acl_type)
+{
+       __u16 rc = 0;
+        struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
+        posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
+       int count;
+       int i;
+
+       if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
+               return 0;
+
+       count = posix_acl_xattr_count((size_t)buflen);
+       cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
+               count,buflen,local_acl->a_version));
+       if(local_acl->a_version != 2) {
+               cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
+               return 0;
+       }
+       cifs_acl->version = cpu_to_le16(1);
+       if(acl_type == ACL_TYPE_ACCESS) 
+               cifs_acl->access_entry_count = count;
+       else if(acl_type == ACL_TYPE_DEFAULT)
+               cifs_acl->default_entry_count = count;
+       else {
+               cFYI(1,("unknown ACL type %d",acl_type));
+               return 0;
+       }
+       for(i=0;i<count;i++) {
+               rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
+                                       &local_acl->a_entries[i]);
+               if(rc != 0) {
+                       /* ACE not converted */
+                       break;
+               }
+       }
+       if(rc == 0) {
+               rc = (__u16)(count * sizeof(struct cifs_posix_ace));
+               rc += sizeof(struct cifs_posix_acl);
+               /* BB add check to make sure ACL does not overflow SMB */
+       }
+       return rc;
+}
+
+int
+CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
+                        const unsigned char *searchName,
+                        char *acl_inf, const int buflen, const int acl_type,
+                        const struct nls_table *nls_codepage)
+{
+/* SMB_QUERY_POSIX_ACL */
+       TRANSACTION2_QPI_REQ *pSMB = NULL;
+       TRANSACTION2_QPI_RSP *pSMBr = NULL;
+       int rc = 0;
+       int bytes_returned;
+       int name_len;
+       __u16 params, byte_count;
+                                                                                                                                             
+       cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
+
+queryAclRetry:
+       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+               (void **) &pSMBr);
+       if (rc)
+               return rc;
+                                                                                                                                             
+       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+               name_len =
+                       cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
+                               /* BB fixme find define for this maxpathcomponent */
+                               , nls_codepage);
+               name_len++;     /* trailing null */
+               name_len *= 2;
+               pSMB->FileName[name_len] = 0;
+               pSMB->FileName[name_len+1] = 0;
+       } else {                /* BB improve the check for buffer overruns BB */
+               name_len = strnlen(searchName, PATH_MAX /* BB fixme */);
+               name_len++;     /* trailing null */
+               strncpy(pSMB->FileName, searchName, name_len);
+       }
+
+       params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
+       pSMB->TotalDataCount = 0;
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+        /* BB find exact max data count below from sess structure BB */
+       pSMB->MaxDataCount = cpu_to_le16(4000);
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+       pSMB->Flags = 0;
+       pSMB->Timeout = 0;
+       pSMB->Reserved2 = 0;
+       pSMB->ParameterOffset = cpu_to_le16(
+               offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+       pSMB->DataCount = 0;
+       pSMB->DataOffset = 0;
+       pSMB->SetupCount = 1;
+       pSMB->Reserved3 = 0;
+       pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
+       pSMB->ParameterCount = pSMB->TotalParameterCount;
+       pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
+       pSMB->Reserved4 = 0;
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+
+       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+               (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+       if (rc) {
+               cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
+       } else {
+               /* decode response */
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+               if (rc || (pSMBr->ByteCount < 2))
+               /* BB also check enough total bytes returned */
+                       rc = -EIO;      /* bad smb */
+               else {
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+                       __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+                       rc = cifs_copy_posix_acl(acl_inf,
+                               (char *)&pSMBr->hdr.Protocol+data_offset,
+                               buflen,acl_type,count);
+               }
+       }
+       if (pSMB)
+               cifs_buf_release(pSMB);
+       if (rc == -EAGAIN)
+               goto queryAclRetry;
+       return rc;
+}
+
+int
+CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
+                        const unsigned char *fileName,
+                        const char *local_acl, const int buflen, const int acl_type,
+                        const struct nls_table *nls_codepage)
+{
+       struct smb_com_transaction2_spi_req *pSMB = NULL;
+       struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
+       char *parm_data;
+       int name_len;
+       int rc = 0;
+       int bytes_returned = 0;
+       __u16 params, byte_count, data_count, param_offset, offset;
+
+       cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
+setAclRetry:
+       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+                      (void **) &pSMBr);
+       if (rc)
+               return rc;
+                                                                                                                       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+               name_len =
+                       cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
+                               /* BB fixme find define for this maxpathcomponent */
+                               , nls_codepage);
+               name_len++;     /* trailing null */
+               name_len *= 2;
+       } else {                /* BB improve the check for buffer overruns BB */
+               name_len = strnlen(fileName, PATH_MAX);
+               name_len++;     /* trailing null */
+               strncpy(pSMB->FileName, fileName, name_len);
+       }
+       params = 6 + name_len;
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+       pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+       pSMB->Flags = 0;
+       pSMB->Timeout = 0;
+       pSMB->Reserved2 = 0;
+       param_offset = offsetof(struct smb_com_transaction2_spi_req,
+                                     InformationLevel) - 4;
+       offset = param_offset + params;
+       parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
+
+       /* convert to on the wire format for POSIX ACL */
+       data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
+
+       if(data_count == 0) {
+               rc = -EOPNOTSUPP;
+               goto setACLerrorExit;
+       }
+       pSMB->DataOffset = cpu_to_le16(offset);
+       pSMB->SetupCount = 1;
+       pSMB->Reserved3 = 0;
+       pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+       pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
+       byte_count = 3 /* pad */  + params + data_count;
+       pSMB->DataCount = cpu_to_le16(data_count);
+       pSMB->TotalDataCount = pSMB->DataCount;
+       pSMB->ParameterCount = cpu_to_le16(params);
+       pSMB->TotalParameterCount = pSMB->ParameterCount;
+       pSMB->Reserved4 = 0;
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+       if (rc) {
+               cFYI(1, ("Set POSIX ACL returned %d", rc));
+       }
+
+setACLerrorExit:
+       if (pSMB)
+               cifs_buf_release(pSMB);
+                                                                                                               if (rc == -EAGAIN)
+               goto setAclRetry;
+                                                                                                               return rc;
+}
+
+#endif
+
 int
 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
                 const unsigned char *searchName,
@@ -1559,8 +2070,9 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
        int rc = 0;
        int bytes_returned;
        int name_len;
+       __u16 params, byte_count;
 
-       cFYI(1, ("In QPathInfo path %s", searchName));
+/* cFYI(1, ("In QPathInfo path %s", searchName)); */ /* BB fixme BB */
 QPathInfoRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -1569,19 +2081,18 @@ QPathInfoRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, 530);
+               name_len = strnlen(searchName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, searchName, name_len);
        }
 
-       pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
-           name_len /* includes null */ ;
+       params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
        pSMB->TotalDataCount = 0;
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
@@ -1597,29 +2108,28 @@ QPathInfoRetry:
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-       pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-       pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
        pSMB->ParameterCount = pSMB->TotalParameterCount;
        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
        pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
                cFYI(1, ("Send error in QPathInfo = %d", rc));
        } else {                /* decode response */
-               pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-               /* BB also check enough total bytes returned */
-               /* BB we need to improve the validity checking
-               of these trans2 responses */
-               if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) 
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+               if (rc || (pSMBr->ByteCount < 40)) 
                        rc = -EIO;      /* bad smb */
                else if (pFindData){
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
                        memcpy((char *) pFindData,
                               (char *) &pSMBr->hdr.Protocol +
-                              pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
+                              data_offset, sizeof (FILE_ALL_INFO));
                } else
                    rc = -ENOMEM;
        }
@@ -1643,6 +2153,7 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
        int rc = 0;
        int bytes_returned = 0;
        int name_len;
+       __u16 params, byte_count;
 
        cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
 UnixQPathInfoRetry:
@@ -1653,19 +2164,18 @@ UnixQPathInfoRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, 530);
+               name_len = strnlen(searchName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, searchName, name_len);
        }
 
-       pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
-           name_len /* includes null */ ;
+       params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
        pSMB->TotalDataCount = 0;
        pSMB->MaxParameterCount = cpu_to_le16(2);
        /* BB find exact max SMB PDU from sess structure BB */
@@ -1682,31 +2192,28 @@ UnixQPathInfoRetry:
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-       pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-       pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
        pSMB->ParameterCount = pSMB->TotalParameterCount;
        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
        pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
                cFYI(1, ("Send error in QPathInfo = %d", rc));
        } else {                /* decode response */
-               pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-               /* BB also check if enough total bytes returned */
-               if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) || 
-                       (pSMBr->DataOffset > 512) || 
-                       (pSMBr->DataOffset < sizeof(struct smb_hdr))) {
-                       cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
-                                       (int)pSMBr->DataOffset,bytes_returned));
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+               if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
                        rc = -EIO;      /* bad smb */
                } else {
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
                        memcpy((char *) pFindData,
                               (char *) &pSMBr->hdr.Protocol +
-                              pSMBr->DataOffset,
+                              data_offset,
                               sizeof (FILE_UNIX_BASIC_INFO));
                }
        }
@@ -1718,6 +2225,7 @@ UnixQPathInfoRetry:
        return rc;
 }
 
+#ifdef CONFIG_CIFS_EXPERIMENTAL  /* function unused at present */
 int
 CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
               const char *searchName, FILE_ALL_INFO * findData,
@@ -1729,6 +2237,7 @@ CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
        int rc = 0;
        int bytes_returned;
        int name_len;
+       __u16 params, byte_count;
 
        cFYI(1, ("In FindUnique"));
 findUniqueRetry:
@@ -1739,18 +2248,18 @@ findUniqueRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, 530);
+               name_len = strnlen(searchName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, searchName, name_len);
        }
 
-       pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
+       params = 12 + name_len /* includes null */ ;
        pSMB->TotalDataCount = 0;       /* no EAs */
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
@@ -1760,14 +2269,14 @@ findUniqueRetry:
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
        pSMB->ParameterOffset = cpu_to_le16(
-        offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
+         offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
        pSMB->DataCount = 0;
        pSMB->DataOffset = 0;
        pSMB->SetupCount = 1;   /* one byte, no need to le convert */
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
-       pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-       pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
        pSMB->ParameterCount = pSMB->TotalParameterCount;
        pSMB->SearchAttributes =
            cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
@@ -1776,8 +2285,8 @@ findUniqueRetry:
        pSMB->SearchFlags = cpu_to_le16(1);
        pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
        pSMB->SearchStorageType = 0;    /* BB what should we set this to? BB */
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -1795,6 +2304,7 @@ findUniqueRetry:
 
        return rc;
 }
+#endif /* CIFS_EXPERIMENTAL */
 
 int
 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
@@ -1810,6 +2320,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
        int rc = 0;
        int bytes_returned;
        int name_len;
+       __u16 params, byte_count;
 
        cFYI(1, ("In FindFirst"));
 findFirstRetry:
@@ -1820,18 +2331,18 @@ findFirstRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, 530);
+               name_len = strnlen(searchName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, searchName, name_len);
        }
 
-       pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
+       params = 12 + name_len /* includes null */ ;
        pSMB->TotalDataCount = 0;       /* no EAs */
        pSMB->MaxParameterCount = cpu_to_le16(10);
        pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
@@ -1841,11 +2352,11 @@ findFirstRetry:
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-       pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
        pSMB->ParameterCount = pSMB->TotalParameterCount;
-       pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
-        smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
+       pSMB->ParameterOffset = cpu_to_le16(
+               offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
        pSMB->DataCount = 0;
        pSMB->DataOffset = 0;
        pSMB->SetupCount = 1;   /* one byte no need to make endian neutral */
@@ -1854,7 +2365,7 @@ findFirstRetry:
        pSMB->SearchAttributes =
            cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
                        ATTR_DIRECTORY);
-       pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));       /* should this be shrunk even more ? */
+       pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
        pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
 
        /* test for Unix extensions */
@@ -1867,33 +2378,33 @@ findFirstRetry:
                *pUnixFlag = FALSE;
        }
        pSMB->SearchStorageType = 0;    /* BB what should we set this to? It is not clear if it matters BB */
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 
        if (rc) {               /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
                cFYI(1, ("Error in FindFirst = %d", rc));
-       } else {                /* decode response */
+       } else {
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+               if(!rc) {
+               /* decode response */
                /* BB add safety checks for these memcpys */
-               if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
-                       *pUnicodeFlag = TRUE;
-               else
-                       *pUnicodeFlag = FALSE;
-               memcpy(findParms,
-                      (char *) &pSMBr->hdr.Protocol +
-                      le16_to_cpu(pSMBr->ParameterOffset),
-                      sizeof (T2_FFIRST_RSP_PARMS));
-               /* search handle can stay LE and EAoffset not needed so not converted */
-               findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
-               findParms->LastNameOffset =
-                   le16_to_cpu(findParms->LastNameOffset);
-               findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
-               response_data =
-                   (char *) &pSMBr->hdr.Protocol +
-                   le16_to_cpu(pSMBr->DataOffset);
-               memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
+                       if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+                               *pUnicodeFlag = TRUE;
+                       else
+                               *pUnicodeFlag = FALSE;
+                       memcpy(findParms,
+                              (char *) &pSMBr->hdr.Protocol +
+                              le16_to_cpu(pSMBr->t2.ParameterOffset),
+                              sizeof (T2_FFIRST_RSP_PARMS));
+                       response_data =
+                           (char *) &pSMBr->hdr.Protocol +
+                           le16_to_cpu(pSMBr->t2.DataOffset);
+                       memcpy(findData, response_data, 
+                               le16_to_cpu(pSMBr->t2.DataCount));
+               }
        }
        if (pSMB)
                cifs_buf_release(pSMB);
@@ -1904,6 +2415,256 @@ findFirstRetry:
        return rc;
 }
 
+/* xid, tcon, searchName and codepage are input parms, rest are returned */
+int
+CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
+             const char *searchName, 
+             const struct nls_table *nls_codepage,
+             __u16 *   pnetfid,
+             struct cifs_search_info * psrch_inf)
+{
+/* level 257 SMB_ */
+       TRANSACTION2_FFIRST_REQ *pSMB = NULL;
+       TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
+       T2_FFIRST_RSP_PARMS * parms;
+       int rc = 0;
+       int bytes_returned = 0;
+       int name_len;
+       __u16 params, byte_count;
+
+       cFYI(1, ("In FindFirst2"));
+
+findFirst2Retry:
+       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+                     (void **) &pSMBr);
+       if (rc)
+               return rc;
+
+       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+               name_len =
+                   cifs_strtoUCS((wchar_t *) pSMB->FileName,searchName,
+                                PATH_MAX, nls_codepage);
+               name_len++;     /* trailing null */
+               name_len *= 2;
+               pSMB->FileName[name_len] = 0; /* null terminate just in case */
+               pSMB->FileName[name_len+1] = 0;
+       } else {        /* BB add check for overrun of SMB buf BB */
+               name_len = strnlen(searchName, PATH_MAX);
+               name_len++;     /* trailing null */
+/* BB fix here and in unicode clause above ie
+               if(name_len > buffersize-header)
+                       free buffer exit; BB */
+               strncpy(pSMB->FileName, searchName, name_len);
+               pSMB->FileName[name_len] = 0; /* just in case */
+       }
+
+       params = 12 + name_len /* includes null */ ;
+       pSMB->TotalDataCount = 0;       /* no EAs */
+       pSMB->MaxParameterCount = cpu_to_le16(10);
+       pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
+                                         MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+       pSMB->Flags = 0;
+       pSMB->Timeout = 0;
+       pSMB->Reserved2 = 0;
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
+       pSMB->ParameterCount = pSMB->TotalParameterCount;
+       pSMB->ParameterOffset = cpu_to_le16(
+         offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
+       pSMB->DataCount = 0;
+       pSMB->DataOffset = 0;
+       pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
+       pSMB->Reserved3 = 0;
+       pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
+       pSMB->SearchAttributes =
+           cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
+                       ATTR_DIRECTORY);
+       pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
+       pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | 
+               CIFS_SEARCH_RETURN_RESUME);
+       pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
+
+       /* BB what should we set StorageType to? Does it matter? BB */
+       pSMB->SearchStorageType = 0;
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+
+       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                        (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+
+       if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
+               /* BB Add code to handle unsupported level rc */
+               cFYI(1, ("Error in FindFirst = %d", rc));
+
+               if (pSMB)
+                       cifs_buf_release(pSMB);
+
+               /* BB eventually could optimize out free and realloc of buf */
+               /*    for this case */
+               if (rc == -EAGAIN)
+                       goto findFirst2Retry;
+       } else { /* decode response */
+               /* BB remember to free buffer if error BB */
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+               if(rc == 0) {
+                       if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+                               psrch_inf->unicode = TRUE;
+                       else
+                               psrch_inf->unicode = FALSE;
+
+                       psrch_inf->ntwrk_buf_start = (char *)pSMBr;
+                       psrch_inf->srch_entries_start = 
+                               (char *) &pSMBr->hdr.Protocol + 
+                                       le16_to_cpu(pSMBr->t2.DataOffset);
+
+                       parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
+                              le16_to_cpu(pSMBr->t2.ParameterOffset));
+
+                       if(parms->EndofSearch)
+                               psrch_inf->endOfSearch = TRUE;
+                       else
+                               psrch_inf->endOfSearch = FALSE;
+
+                       psrch_inf->entries_in_buffer  = le16_to_cpu(parms->SearchCount);
+                       psrch_inf->index_of_last_entry = 
+                               psrch_inf->entries_in_buffer;
+/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry));  */
+                       *pnetfid = parms->SearchHandle;
+               } else {
+                       if(pSMB)
+                               cifs_buf_release(pSMB);
+               }
+       }
+
+       return rc;
+}
+
+int CIFSFindNext2(const int xid, struct cifsTconInfo *tcon,
+            __u16 searchHandle, struct cifs_search_info * psrch_inf)
+{
+       TRANSACTION2_FNEXT_REQ *pSMB = NULL;
+       TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
+       T2_FNEXT_RSP_PARMS * parms;
+       char *response_data;
+       int rc = 0;
+       int bytes_returned, name_len;
+       __u16 params, byte_count;
+
+       cFYI(1, ("In FindNext2"));
+
+       if(psrch_inf->endOfSearch == TRUE)
+               return -ENOENT;
+
+       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+               (void **) &pSMBr);
+       if (rc)
+               return rc;
+
+       params = 14;    /* includes 2 bytes of null string, converted to LE below */
+       byte_count = 0;
+       pSMB->TotalDataCount = 0;       /* no EAs */
+       pSMB->MaxParameterCount = cpu_to_le16(8);
+       pSMB->MaxDataCount =
+            cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+       pSMB->Flags = 0;
+       pSMB->Timeout = 0;
+       pSMB->Reserved2 = 0;
+       pSMB->ParameterOffset =  cpu_to_le16(
+             offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
+       pSMB->DataCount = 0;
+       pSMB->DataOffset = 0;
+       pSMB->SetupCount = 1;
+       pSMB->Reserved3 = 0;
+       pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
+       pSMB->SearchHandle = searchHandle;      /* always kept as le */
+       pSMB->SearchCount =
+               cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
+       /* test for Unix extensions */
+/*     if (tcon->ses->capabilities & CAP_UNIX) {
+               pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
+               psrch_inf->info_level = SMB_FIND_FILE_UNIX;
+       } else {
+               pSMB->InformationLevel =
+                  cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
+               psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
+       } */
+       pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
+       pSMB->ResumeKey = psrch_inf->resume_key;
+       pSMB->SearchFlags =
+             cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
+
+       name_len = psrch_inf->resume_name_len;
+       params += name_len;
+       if(name_len < PATH_MAX) {
+               memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
+               byte_count += name_len;
+       } else {
+               rc = -EINVAL;
+               goto FNext2_err_exit;
+       }
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
+       pSMB->ParameterCount = pSMB->TotalParameterCount;
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+                                                                                              
+       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                       (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+                                                                                              
+       if (rc) {
+               if (rc == -EBADF) {
+                       psrch_inf->endOfSearch = TRUE;
+                       rc = 0; /* search probably was closed at end of search above */
+               } else
+                       cFYI(1, ("FindNext returned = %d", rc));
+       } else {                /* decode response */
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+               
+               if(rc == 0) {
+                       /* BB fixme add lock for file (srch_info) struct here */
+                       if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+                               psrch_inf->unicode = TRUE;
+                       else
+                               psrch_inf->unicode = FALSE;
+                       response_data = (char *) &pSMBr->hdr.Protocol +
+                              le16_to_cpu(pSMBr->t2.ParameterOffset);
+                       parms = (T2_FNEXT_RSP_PARMS *)response_data;
+                       response_data = (char *)&pSMBr->hdr.Protocol +
+                               le16_to_cpu(pSMBr->t2.DataOffset);
+                       cifs_buf_release(psrch_inf->ntwrk_buf_start);
+                       psrch_inf->srch_entries_start = response_data;
+                       psrch_inf->ntwrk_buf_start = (char *)pSMB;
+                       if(parms->EndofSearch)
+                               psrch_inf->endOfSearch = TRUE;
+                       else
+                               psrch_inf->endOfSearch = FALSE;
+                                                                                              
+                       psrch_inf->entries_in_buffer  = le16_to_cpu(parms->SearchCount);
+                       psrch_inf->index_of_last_entry +=
+                               psrch_inf->entries_in_buffer;
+/*  cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
+
+                       /* BB fixme add unlock here */
+               }
+
+       }
+
+       /* BB On error, should we leave previous search buf (and count and
+       last entry fields) intact or free the previous one? */
+
+       /* Note: On -EAGAIN error only caller can retry on handle based calls
+       since file handle passed in no longer valid */
+FNext2_err_exit:
+       if ((rc != 0) && pSMB)
+               cifs_buf_release(pSMB);
+                                                                                              
+       return rc;
+}
+
 int
 CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
                FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
@@ -1916,6 +2677,7 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
        char *response_data;
        int rc = 0;
        int bytes_returned;
+       __u16 params, byte_count;
 
        cFYI(1, ("In FindNext"));
 
@@ -1927,7 +2689,8 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
        if (rc)
                return rc;
 
-       pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
+       params = 14;    /* includes 2 bytes of null string, converted to LE below */
+       byte_count = 0;
        pSMB->TotalDataCount = 0;       /* no EAs */
        pSMB->MaxParameterCount = cpu_to_le16(8);
        pSMB->MaxDataCount =
@@ -1937,8 +2700,8 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ParameterOffset =  cpu_to_le16(offsetof(
-        struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
+       pSMB->ParameterOffset =  cpu_to_le16(
+           offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
        pSMB->DataCount = 0;
        pSMB->DataOffset = 0;
        pSMB->SetupCount = 1;
@@ -1947,7 +2710,7 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
        pSMB->SearchHandle = searchHandle;      /* always kept as le */
        findParms->SearchCount = 0;     /* set to zero in case of error */
        pSMB->SearchCount =
-           cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
+           cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
        /* test for Unix extensions */
        if (tcon->ses->capabilities & CAP_UNIX) {
                pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
@@ -1961,17 +2724,17 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
        pSMB->SearchFlags =
            cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
        /* BB add check to make sure we do not cross end of smb */
-       if(name_len < CIFS_MAX_MSGSIZE) {
+       if(name_len < PATH_MAX) {
                memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
-               pSMB->ByteCount += name_len;
+               byte_count += name_len;
        }
-       pSMB->TotalParameterCount += name_len;
-       pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-       pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+       params += name_len;
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
        pSMB->ParameterCount = pSMB->TotalParameterCount;
        /* BB improve error handling here */
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -1982,23 +2745,23 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
                else
                        cFYI(1, ("FindNext returned = %d", rc));
        } else {                /* decode response */
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
                /* BB add safety checks for these memcpys */
-               if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
-                       *pUnicodeFlag = TRUE;
-               else
-                       *pUnicodeFlag = FALSE;
-               memcpy(findParms,
-                      (char *) &pSMBr->hdr.Protocol +
-                      le16_to_cpu(pSMBr->ParameterOffset),
-                      sizeof (T2_FNEXT_RSP_PARMS));
-               findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
-               findParms->LastNameOffset =
-                   le16_to_cpu(findParms->LastNameOffset);
-               findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
-               response_data =
-                   (char *) &pSMBr->hdr.Protocol +
-                   le16_to_cpu(pSMBr->DataOffset);
-               memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
+               if(rc == 0) {
+                       if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+                               *pUnicodeFlag = TRUE;
+                       else
+                               *pUnicodeFlag = FALSE;
+                       memcpy(findParms,
+                              (char *) &pSMBr->hdr.Protocol +
+                              le16_to_cpu(pSMBr->t2.ParameterOffset),
+                              sizeof (T2_FNEXT_RSP_PARMS));
+                       response_data =
+                           (char *) &pSMBr->hdr.Protocol +
+                           le16_to_cpu(pSMBr->t2.DataOffset);
+                       memcpy(findData,response_data,le16_to_cpu(pSMBr->t2.DataCount));
+               }
        }
        if (pSMB)
                cifs_buf_release(pSMB);
@@ -2014,12 +2777,12 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle
 {
        int rc = 0;
        FINDCLOSE_REQ *pSMB = NULL;
-       CLOSE_RSP *pSMBr = NULL;
+       CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
        int bytes_returned;
 
        cFYI(1, ("In CIFSSMBFindClose"));
-       rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
+       rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
+       pSMBr = (CLOSE_RSP *)pSMB;  /* BB removeme BB */
        /* no sense returning error if session restarted
                file handle has been closed */
        if(rc == -EAGAIN)
@@ -2035,7 +2798,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle
                cERROR(1, ("Send error in FindClose = %d", rc));
        }
        if (pSMB)
-               cifs_buf_release(pSMB);
+               cifs_small_buf_release(pSMB);
 
        /* Since session is dead, search handle closed on server already */
        if (rc == -EAGAIN)
@@ -2044,6 +2807,39 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle
        return rc;
 }
 
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+int
+CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
+                const unsigned char *searchName,
+                __u64 * inode_number,
+                const struct nls_table *nls_codepage)
+{
+       int rc = 0;
+       TRANSACTION2_QPI_REQ *pSMB = NULL;
+       TRANSACTION2_QPI_RSP *pSMBr = NULL;
+
+       cFYI(1,("In GetSrvInodeNumber for %s",searchName));
+       if(tcon == NULL)
+               return -ENODEV; 
+
+        cFYI(1, ("In QPathInfo path %s", searchName));
+GetInodeNumberRetry:
+       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+                      (void **) &pSMBr);
+       if (rc)
+               return rc;
+
+/* BB add missing code here */
+
+       if (pSMB)
+               cifs_buf_release(pSMB);
+                                                                                                                         
+       if (rc == -EAGAIN)
+               goto GetInodeNumberRetry;
+       return rc;
+}
+#endif /* CIFS_EXPERIMENTAL */
+
 int
 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
                const unsigned char *searchName,
@@ -2060,6 +2856,7 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
        int name_len;
        unsigned int i;
        char * temp;
+       __u16 params, byte_count;
        *number_of_UNC_in_array = 0;
        *targetUNCs = NULL;
 
@@ -2085,18 +2882,18 @@ getDFSRetry:
                pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
                name_len =
                    cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
-                                 searchName, 530
+                                 searchName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, 530);
+               name_len = strnlen(searchName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->RequestFileName, searchName, name_len);
        }
 
-       pSMB->ParameterCount = 2 /* level */  + name_len /*includes null */ ;
+       params = 2 /* level */  + name_len /*includes null */ ;
        pSMB->TotalDataCount = 0;
        pSMB->DataCount = 0;
        pSMB->DataOffset = 0;
@@ -2112,12 +2909,12 @@ getDFSRetry:
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
-       pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
-       pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+       byte_count = params + 3 /* pad */ ;
+       pSMB->ParameterCount = cpu_to_le16(params);
        pSMB->TotalParameterCount = pSMB->ParameterCount;
        pSMB->MaxReferralLevel = cpu_to_le16(3);
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -2125,20 +2922,24 @@ getDFSRetry:
                cFYI(1, ("Send error in GetDFSRefer = %d", rc));
        } else {                /* decode response */
 /* BB Add logic to parse referrals here */
-               pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-               pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
-               cFYI(1,
-                    ("Decoding GetDFSRefer response.  BCC: %d  Offset %d",
-                     pSMBr->ByteCount, pSMBr->DataOffset));
-               if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512))       /* BB also check enough total bytes returned */
-                       rc = -EIO;      /* bad smb */
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+               if (rc || (pSMBr->ByteCount < 17))      /* BB also check enough total bytes returned */
+                       rc = -EIO;      /* bad smb */
                else {
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); 
+                       __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
+
+                       cFYI(1,
+                            ("Decoding GetDFSRefer response.  BCC: %d  Offset %d",
+                             pSMBr->ByteCount, data_offset));
                        referrals = 
                            (struct dfs_referral_level_3 *) 
                                        (8 /* sizeof start of data block */ +
-                                       pSMBr->DataOffset +
+                                       data_offset +
                                        (char *) &pSMBr->hdr.Protocol); 
-                       cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",pSMBr->NumberOfReferrals,pSMBr->DFSFlags, referrals->ReferralSize,referrals->ServerType,referrals->ReferralFlags,referrals->TimeToLive));
+                       cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",
+                               le16_to_cpu(pSMBr->NumberOfReferrals),le16_to_cpu(pSMBr->DFSFlags), le16_to_cpu(referrals->ReferralSize),le16_to_cpu(referrals->ServerType),le16_to_cpu(referrals->ReferralFlags),le16_to_cpu(referrals->TimeToLive)));
                        /* BB This field is actually two bytes in from start of
                           data block so we could do safety check that DataBlock
                           begins at address of pSMBr->NumberOfReferrals */
@@ -2152,19 +2953,19 @@ getDFSRetry:
                        name_len = 0;
                        for(i=0;i<*number_of_UNC_in_array;i++) {
                                /* make sure that DfsPathOffset not past end */
-                               referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
-                               if(referrals->DfsPathOffset > pSMBr->DataCount) {
+                               __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
+                               if (offset > data_count) {
                                        /* if invalid referral, stop here and do 
                                        not try to copy any more */
                                        *number_of_UNC_in_array = i;
                                        break;
                                } 
-                               temp = ((char *)referrals) + referrals->DfsPathOffset;
+                               temp = ((char *)referrals) + offset;
 
                                if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
-                                       name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
+                                       name_len += UniStrnlen((wchar_t *)temp,data_count);
                                } else {
-                                       name_len += strnlen(temp,pSMBr->DataCount);
+                                       name_len += strnlen(temp,data_count);
                                }
                                referrals++;
                                /* BB add check that referral pointer does not fall off end PDU */
@@ -2173,15 +2974,19 @@ getDFSRetry:
                        /* BB add check for name_len bigger than bcc */
                        *targetUNCs = 
                                kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
+                       if(*targetUNCs == NULL) {
+                               rc = -ENOMEM;
+                               goto GetDFSRefExit;
+                       }
                        /* copy the ref strings */
                        referrals =  
                            (struct dfs_referral_level_3 *) 
                                        (8 /* sizeof data hdr */ +
-                                       pSMBr->DataOffset + 
+                                       data_offset + 
                                        (char *) &pSMBr->hdr.Protocol);
 
                        for(i=0;i<*number_of_UNC_in_array;i++) {
-                               temp = ((char *)referrals) + referrals->DfsPathOffset;
+                               temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
                                if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
                                        cifs_strfromUCS_le(*targetUNCs,
                                                (wchar_t *) temp, name_len, nls_codepage);
@@ -2196,6 +3001,7 @@ getDFSRetry:
                }
 
        }
+GetDFSRefExit:
        if (pSMB)
                cifs_buf_release(pSMB);
 
@@ -2215,6 +3021,7 @@ CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
        FILE_SYSTEM_INFO *response_data;
        int rc = 0;
        int bytes_returned = 0;
+       __u16 params, byte_count;
 
        cFYI(1, ("In QFSInfo"));
 QFSInfoRetry:
@@ -2223,7 +3030,7 @@ QFSInfoRetry:
        if (rc)
                return rc;
 
-       pSMB->TotalParameterCount = 2;  /* level */
+       params = 2;     /* level */
        pSMB->TotalDataCount = 0;
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
@@ -2232,8 +3039,8 @@ QFSInfoRetry:
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-       pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
        pSMB->ParameterCount = pSMB->TotalParameterCount;
        pSMB->ParameterOffset = cpu_to_le16(offsetof(
         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
@@ -2243,25 +3050,28 @@ QFSInfoRetry:
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
                cERROR(1, ("Send error in QFSInfo = %d", rc));
        } else {                /* decode response */
-               pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-               cFYI(1,
-                    ("Decoding qfsinfo response.  BCC: %d  Offset %d",
-                     pSMBr->ByteCount, pSMBr->DataOffset));
-               if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512))       /* BB also check enough total bytes returned */
+                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+               if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
                        rc = -EIO;      /* bad smb */
                else {
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+                       cFYI(1,
+                               ("Decoding qfsinfo response.  BCC: %d  Offset %d",
+                               pSMBr->ByteCount, data_offset));
+
                        response_data =
                            (FILE_SYSTEM_INFO
                             *) (((char *) &pSMBr->hdr.Protocol) +
-                                pSMBr->DataOffset);
+                                data_offset);
                        FSData->f_bsize =
                            le32_to_cpu(response_data->BytesPerSector) *
                            le32_to_cpu(response_data->
@@ -2296,6 +3106,7 @@ CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon,
        FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
        int rc = 0;
        int bytes_returned = 0;
+       __u16 params, byte_count;
 
        cFYI(1, ("In QFSAttributeInfo"));
 QFSAttributeRetry:
@@ -2304,7 +3115,7 @@ QFSAttributeRetry:
        if (rc)
                return rc;
 
-       pSMB->TotalParameterCount = 2;  /* level */
+       params = 2;     /* level */
        pSMB->TotalDataCount = 0;
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
@@ -2313,8 +3124,8 @@ QFSAttributeRetry:
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-       pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
        pSMB->ParameterCount = pSMB->TotalParameterCount;
        pSMB->ParameterOffset = cpu_to_le16(offsetof(
         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
@@ -2324,27 +3135,24 @@ QFSAttributeRetry:
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
                cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
        } else {                /* decode response */
-               pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-               if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {     /* BB also check enough bytes returned */
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+               if (rc || (pSMBr->ByteCount < 13)) {    /* BB also check enough bytes returned */
                        rc = -EIO;      /* bad smb */
                } else {
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
                        response_data =
                            (FILE_SYSTEM_ATTRIBUTE_INFO
                             *) (((char *) &pSMBr->hdr.Protocol) +
-                                pSMBr->DataOffset);
-                       response_data->Attributes = le32_to_cpu(response_data->Attributes);
-                       response_data->MaxPathNameComponentLength = 
-                               le32_to_cpu(response_data->MaxPathNameComponentLength);
-                       response_data->FileSystemNameLen = 
-                               le32_to_cpu(response_data->FileSystemNameLen);
+                                data_offset);
                        memcpy(&tcon->fsAttrInfo, response_data,
                               sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
                }
@@ -2368,6 +3176,7 @@ CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
        FILE_SYSTEM_DEVICE_INFO *response_data;
        int rc = 0;
        int bytes_returned = 0;
+       __u16 params, byte_count;
 
        cFYI(1, ("In QFSDeviceInfo"));
 QFSDeviceRetry:
@@ -2376,7 +3185,7 @@ QFSDeviceRetry:
        if (rc)
                return rc;
 
-       pSMB->TotalParameterCount = 2;  /* level */
+       params = 2;     /* level */
        pSMB->TotalDataCount = 0;
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
@@ -2385,8 +3194,8 @@ QFSDeviceRetry:
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-       pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
        pSMB->ParameterCount = pSMB->TotalParameterCount;
        pSMB->ParameterOffset = cpu_to_le16(offsetof(
         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
@@ -2397,27 +3206,24 @@ QFSDeviceRetry:
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
                cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
        } else {                /* decode response */
-               pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-               if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
-                 || (pSMBr->DataOffset > 512))
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+               if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
                        rc = -EIO;      /* bad smb */
                else {
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
                        response_data =
                            (FILE_SYSTEM_DEVICE_INFO
                             *) (((char *) &pSMBr->hdr.Protocol) +
-                                pSMBr->DataOffset);
-                       response_data->DeviceType = 
-                               le32_to_cpu(response_data->DeviceType);
-                       response_data->DeviceCharacteristics = 
-                               le32_to_cpu(response_data->DeviceCharacteristics);
+                                data_offset);
                        memcpy(&tcon->fsDevInfo, response_data,
                               sizeof (FILE_SYSTEM_DEVICE_INFO));
                }
@@ -2441,6 +3247,7 @@ CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
        FILE_SYSTEM_UNIX_INFO *response_data;
        int rc = 0;
        int bytes_returned = 0;
+       __u16 params, byte_count;
 
        cFYI(1, ("In QFSUnixInfo"));
 QFSUnixRetry:
@@ -2449,7 +3256,7 @@ QFSUnixRetry:
        if (rc)
                return rc;
 
-       pSMB->ParameterCount = 2;       /* level */
+       params = 2;     /* level */
        pSMB->TotalDataCount = 0;
        pSMB->DataCount = 0;
        pSMB->DataOffset = 0;
@@ -2460,8 +3267,8 @@ QFSUnixRetry:
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
-       pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->ParameterCount = cpu_to_le16(params);
        pSMB->TotalParameterCount = pSMB->ParameterCount;
        pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
@@ -2469,28 +3276,24 @@ QFSUnixRetry:
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
                cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
        } else {                /* decode response */
-               pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
-               if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+               if (rc || (pSMBr->ByteCount < 13)) {
                        rc = -EIO;      /* bad smb */
                } else {
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
                        response_data =
                            (FILE_SYSTEM_UNIX_INFO
                             *) (((char *) &pSMBr->hdr.Protocol) +
-                                pSMBr->DataOffset);
-                       response_data->MajorVersionNumber =
-                               le16_to_cpu(response_data->MajorVersionNumber);
-                       response_data->MinorVersionNumber =
-                               le16_to_cpu(response_data->MinorVersionNumber);
-                       response_data->Capability =
-                               le64_to_cpu(response_data->Capability);
+                                data_offset);
                        memcpy(&tcon->fsUnixInfo, response_data,
                               sizeof (FILE_SYSTEM_UNIX_INFO));
                }
@@ -2521,6 +3324,7 @@ CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
        int name_len;
        int rc = 0;
        int bytes_returned = 0;
+       __u16 params, byte_count, data_count, param_offset, offset;
 
        cFYI(1, ("In SetEOF"));
 SetEOFRetry:
@@ -2531,18 +3335,18 @@ SetEOFRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fileName, 530);
+               name_len = strnlen(fileName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, fileName, name_len);
        }
-       pSMB->ParameterCount = 6 + name_len;
-       pSMB->DataCount = sizeof (struct file_end_of_file_info);
+       params = 6 + name_len;
+       data_count = sizeof (struct file_end_of_file_info);
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
        pSMB->MaxSetupCount = 0;
@@ -2550,9 +3354,9 @@ SetEOFRetry:
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+       param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-       pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+       offset = param_offset + params;
        if(SetAllocation) {
                if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
                    pSMB->InformationLevel =
@@ -2571,21 +3375,21 @@ SetEOFRetry:
 
        parm_data =
            (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
-                                      pSMB->DataOffset);
-       pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-       pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+                                      offset);
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-       pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-       pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+       byte_count = 3 /* pad */  + params + data_count;
+       pSMB->DataCount = cpu_to_le16(data_count);
        pSMB->TotalDataCount = pSMB->DataCount;
-       pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+       pSMB->ParameterCount = cpu_to_le16(params);
        pSMB->TotalParameterCount = pSMB->ParameterCount;
        pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+       pSMB->hdr.smb_buf_length += byte_count;
        parm_data->FileSize = cpu_to_le64(size);
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->ByteCount = cpu_to_le16(byte_count);
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
@@ -2611,7 +3415,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
        struct file_end_of_file_info *parm_data;
        int rc = 0;
        int bytes_returned = 0;
-       __u32 tmp;
+       __u16 params, param_offset, offset, byte_count, count;
 
        cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
                        (long long)size));
@@ -2620,40 +3424,36 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
        if (rc)
                return rc;
 
-       tmp = cpu_to_le32(pid_of_opener);  /* override pid of current process
-                                         so network fid will be valid */
-       pSMB->hdr.Pid = tmp & 0xFFFF;
-       tmp >>= 16;
-       pSMB->hdr.PidHigh = tmp & 0xFFFF;
+       pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+       pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
     
-       pSMB->ParameterCount = 6;
+       params = 6;
        pSMB->MaxSetupCount = 0;
        pSMB->Reserved = 0;
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
-                                     Fid) - 4;
-       pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+       param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+       offset = param_offset + params;
 
-       data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;        
+       data_offset = (char *) (&pSMB->hdr.Protocol) + offset;  
 
-       pSMB->DataCount = sizeof(struct file_end_of_file_info);
+       count = sizeof(struct file_end_of_file_info);
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
-       pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-       pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-       pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+       byte_count = 3 /* pad */  + params + count;
+       pSMB->DataCount = cpu_to_le16(count);
+       pSMB->ParameterCount = cpu_to_le16(params);
        pSMB->TotalDataCount = pSMB->DataCount;
        pSMB->TotalParameterCount = pSMB->ParameterCount;
-       pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
        parm_data =
                (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
-                       pSMB->DataOffset);
-       pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
+                       offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
        parm_data->FileSize = cpu_to_le64(size);
        pSMB->Fid = fid;
        if(SetAllocation) {
@@ -2672,8 +3472,8 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
                        cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
        }
        pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
@@ -2702,6 +3502,7 @@ CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
        int rc = 0;
        int bytes_returned = 0;
        char *data_offset;
+       __u16 params, param_offset, offset, byte_count, count;
 
        cFYI(1, ("In SetTimes"));
 
@@ -2713,19 +3514,19 @@ SetTimesRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fileName, 530);
+               name_len = strnlen(fileName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, fileName, name_len);
        }
 
-       pSMB->ParameterCount = 6 + name_len;
-       pSMB->DataCount = sizeof (FILE_BASIC_INFO);
+       params = 6 + name_len;
+       count = sizeof (FILE_BASIC_INFO);
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
        pSMB->MaxSetupCount = 0;
@@ -2733,19 +3534,19 @@ SetTimesRetry:
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+       param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-       pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
-       data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
-       pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-       pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+       offset = param_offset + params;
+       data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-       pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
+       byte_count = 3 /* pad */  + params + count;
 
-       pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-       pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+       pSMB->DataCount = cpu_to_le16(count);
+       pSMB->ParameterCount = cpu_to_le16(params);
        pSMB->TotalDataCount = pSMB->DataCount;
        pSMB->TotalParameterCount = pSMB->ParameterCount;
        if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
@@ -2753,9 +3554,9 @@ SetTimesRetry:
        else
                pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
        pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+       pSMB->hdr.smb_buf_length += byte_count;
        memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->ByteCount = cpu_to_le16(byte_count);
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
@@ -2771,7 +3572,6 @@ SetTimesRetry:
        return rc;
 }
 
-
 int
 CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
                FILE_INFO_STANDARD * data, const struct nls_table *nls_codepage)
@@ -2782,6 +3582,7 @@ CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
        int rc = 0;
        int bytes_returned = 0;
        char *data_offset;
+       __u16 params, param_offset, count, offset, byte_count;
 
        cFYI(1, ("In SetTimesLegacy"));
 
@@ -2793,20 +3594,20 @@ SetTimesRetryLegacy:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fileName, 530);
+               name_len = strnlen(fileName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, fileName, name_len);
        }
 /* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info
        in parent function, from the better and ususal FILE_BASIC_INFO */
-       pSMB->ParameterCount = 6 + name_len;
-       pSMB->DataCount = sizeof (FILE_INFO_STANDARD);
+       params = 6 + name_len;
+       count = sizeof (FILE_INFO_STANDARD);
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
        pSMB->MaxSetupCount = 0;
@@ -2814,31 +3615,26 @@ SetTimesRetryLegacy:
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+       param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-       pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
-       data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
-       pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-       pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+       offset = param_offset + params;
+       data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-       pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
+       byte_count = 3 /* pad */  + params + count;
 
-       pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-       pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+       pSMB->DataCount = cpu_to_le16(count);
+       pSMB->ParameterCount = cpu_to_le16(params);
        pSMB->TotalDataCount = pSMB->DataCount;
        pSMB->TotalParameterCount = pSMB->ParameterCount;
-       /* I doubt that passthrough levels apply to this old
-       preNT info level */
-/*     if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
-               pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
-       else*/
-               pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
+       pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
        pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+       pSMB->hdr.smb_buf_length += byte_count;
        memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD));
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->ByteCount = cpu_to_le16(byte_count);
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
@@ -2865,6 +3661,7 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
        int rc = 0;
        int bytes_returned = 0;
        FILE_UNIX_BASIC_INFO *data_offset;
+       __u16 params, param_offset, offset, count, byte_count;
 
        cFYI(1, ("In SetUID/GID/Mode"));
 setPermsRetry:
@@ -2875,19 +3672,19 @@ setPermsRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fileName, 530);
+               name_len = strnlen(fileName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, fileName, name_len);
        }
 
-       pSMB->ParameterCount = 6 + name_len;
-       pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
+       params = 6 + name_len;
+       count = sizeof (FILE_UNIX_BASIC_INFO);
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
        pSMB->MaxSetupCount = 0;
@@ -2895,25 +3692,26 @@ setPermsRetry:
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+       param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-       pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+       offset = param_offset + params;
        data_offset =
            (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
-                                     pSMB->DataOffset);
-       pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
-       pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+                                     offset);
+       memset(data_offset, 0, count);
+       pSMB->DataOffset = cpu_to_le16(offset);
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-       pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-       pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
-       pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+       byte_count = 3 /* pad */  + params + count;
+       pSMB->ParameterCount = cpu_to_le16(params);
+       pSMB->DataCount = cpu_to_le16(count);
        pSMB->TotalParameterCount = pSMB->ParameterCount;
        pSMB->TotalDataCount = pSMB->DataCount;
        pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
        pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+       pSMB->hdr.smb_buf_length += byte_count;
        data_offset->Uid = cpu_to_le64(uid);
        data_offset->Gid = cpu_to_le64(gid);
        /* better to leave device as zero when it is  */
@@ -2937,7 +3735,7 @@ setPermsRetry:
                data_offset->Type = cpu_to_le32(UNIX_SOCKET);
 
 
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->ByteCount = cpu_to_le16(byte_count);
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
@@ -2986,9 +3784,8 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
        pSMB->Fid = netfid; /* file handle always le */
        pSMB->ByteCount = 0;
 
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-                       (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+                       (struct smb_hdr *) pSMBr, &bytes_returned, -1);
        if (rc) {
                cFYI(1, ("Error in Notify = %d", rc));
        }
@@ -3013,6 +3810,7 @@ CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
        int name_len;
        struct fea * temp_fea;
        char * temp_ptr;
+       __u16 params, byte_count;
 
        cFYI(1, ("In Query All EAs path %s", searchName));
 QAllEAsRetry:
@@ -3023,19 +3821,18 @@ QAllEAsRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, 530);
+               name_len = strnlen(searchName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, searchName, name_len);
        }
 
-       pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
-           name_len /* includes null */ ;
+       params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
        pSMB->TotalDataCount = 0;
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
@@ -3051,46 +3848,46 @@ QAllEAsRetry:
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-       pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-       pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
        pSMB->ParameterCount = pSMB->TotalParameterCount;
        pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
        pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
                cFYI(1, ("Send error in QueryAllEAs = %d", rc));
        } else {                /* decode response */
-               pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
                /* BB also check enough total bytes returned */
                /* BB we need to improve the validity checking
                of these trans2 responses */
-               if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512)) 
+               if (rc || (pSMBr->ByteCount < 4)) 
                        rc = -EIO;      /* bad smb */
           /* else if (pFindData){
                        memcpy((char *) pFindData,
                               (char *) &pSMBr->hdr.Protocol +
-                              pSMBr->DataOffset, kl);
+                              data_offset, kl);
                }*/ else {
                        /* check that length of list is not more than bcc */
                        /* check that each entry does not go beyond length
                           of list */
                        /* check that each element of each entry does not
                           go beyond end of list */
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
                        struct fealist * ea_response_data;
                        rc = 0;
                        /* validate_trans2_offsets() */
-                       /* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
+                       /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
                        ea_response_data = (struct fealist *)
                                (((char *) &pSMBr->hdr.Protocol) +
-                               pSMBr->DataOffset);
-                       ea_response_data->list_len = 
-                               cpu_to_le32(ea_response_data->list_len);
-                       cFYI(1,("ea length %d",ea_response_data->list_len));
-                       name_len = ea_response_data->list_len;
+                               data_offset);
+                       name_len = le32_to_cpu(ea_response_data->list_len);
+                       cFYI(1,("ea length %d", name_len));
                        if(name_len <= 8) {
                        /* returned EA size zeroed at top of function */
                                cFYI(1,("empty EA list returned from server"));
@@ -3100,12 +3897,13 @@ QAllEAsRetry:
                                temp_fea = ea_response_data->list;
                                temp_ptr = (char *)temp_fea;
                                while(name_len > 0) {
+                                       __u16 value_len;
                                        name_len -= 4;
                                        temp_ptr += 4;
                                        rc += temp_fea->name_len;
                                /* account for prefix user. and trailing null */
                                        rc = rc + 5 + 1; 
-                                       if(rc<buf_size) {
+                                       if(rc<(int)buf_size) {
                                                memcpy(EAData,"user.",5);
                                                EAData+=5;
                                                memcpy(EAData,temp_ptr,temp_fea->name_len);
@@ -3125,9 +3923,9 @@ QAllEAsRetry:
                                        /* account for trailing null */
                                        name_len--;
                                        temp_ptr++;
-                                       temp_fea->value_len = cpu_to_le16(temp_fea->value_len);
-                                       name_len -= temp_fea->value_len;
-                                       temp_ptr += temp_fea->value_len;
+                                       value_len = le16_to_cpu(temp_fea->value_len);
+                                       name_len -= value_len;
+                                       temp_ptr += value_len;
                                        /* BB check that temp_ptr is still within smb BB*/
                                /* no trailing null to account for in value len */
                                        /* go on to next EA */
@@ -3141,7 +3939,7 @@ QAllEAsRetry:
        if (rc == -EAGAIN)
                goto QAllEAsRetry;
 
-       return rc;
+       return (ssize_t)rc;
 }
 
 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
@@ -3156,6 +3954,7 @@ ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
        int name_len;
        struct fea * temp_fea;
        char * temp_ptr;
+       __u16 params, byte_count;
 
        cFYI(1, ("In Query EA path %s", searchName));
 QEARetry:
@@ -3166,19 +3965,18 @@ QEARetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, 530);
+               name_len = strnlen(searchName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, searchName, name_len);
        }
 
-       pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
-           name_len /* includes null */ ;
+       params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
        pSMB->TotalDataCount = 0;
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
@@ -3194,46 +3992,46 @@ QEARetry:
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-       pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-       pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
        pSMB->ParameterCount = pSMB->TotalParameterCount;
        pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
        pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
                cFYI(1, ("Send error in Query EA = %d", rc));
        } else {                /* decode response */
-               pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
                /* BB also check enough total bytes returned */
                /* BB we need to improve the validity checking
                of these trans2 responses */
-               if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512)) 
+               if (rc || (pSMBr->ByteCount < 4)) 
                        rc = -EIO;      /* bad smb */
           /* else if (pFindData){
                        memcpy((char *) pFindData,
                               (char *) &pSMBr->hdr.Protocol +
-                              pSMBr->DataOffset, kl);
+                              data_offset, kl);
                }*/ else {
                        /* check that length of list is not more than bcc */
                        /* check that each entry does not go beyond length
                           of list */
                        /* check that each element of each entry does not
                           go beyond end of list */
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
                        struct fealist * ea_response_data;
-                       rc = -ENOENT;
+                       rc = -ENODATA;
                        /* validate_trans2_offsets() */
-                       /* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
+                       /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
                        ea_response_data = (struct fealist *)
                                (((char *) &pSMBr->hdr.Protocol) +
-                               pSMBr->DataOffset);
-                       ea_response_data->list_len = 
-                               cpu_to_le32(ea_response_data->list_len);
-                       cFYI(1,("ea length %d",ea_response_data->list_len));
-                       name_len = ea_response_data->list_len;
+                               data_offset);
+                       name_len = le32_to_cpu(ea_response_data->list_len);
+                       cFYI(1,("ea length %d", name_len));
                        if(name_len <= 8) {
                        /* returned EA size zeroed at top of function */
                                cFYI(1,("empty EA list returned from server"));
@@ -3245,17 +4043,18 @@ QEARetry:
                                /* loop through checking if we have a matching
                                name and then return the associated value */
                                while(name_len > 0) {
+                                       __u16 value_len;
                                        name_len -= 4;
                                        temp_ptr += 4;
-                                       temp_fea->value_len = cpu_to_le16(temp_fea->value_len);
+                                       value_len = le16_to_cpu(temp_fea->value_len);
                                /* BB validate that value_len falls within SMB, 
                                even though maximum for name_len is 255 */ 
                                        if(memcmp(temp_fea->name,ea_name,
                                                  temp_fea->name_len) == 0) {
                                                /* found a match */
-                                               rc = temp_fea->value_len;
+                                               rc = value_len;
                                /* account for prefix user. and trailing null */
-                                               if(rc<=buf_size) {
+                                               if(rc<=(int)buf_size) {
                                                        memcpy(ea_value,
                                                                temp_fea->name+temp_fea->name_len+1,
                                                                rc);
@@ -3274,8 +4073,8 @@ QEARetry:
                                        /* account for trailing null */
                                        name_len--;
                                        temp_ptr++;
-                                       name_len -= temp_fea->value_len;
-                                       temp_ptr += temp_fea->value_len;
+                                       name_len -= value_len;
+                                       temp_ptr += value_len;
                                /* no trailing null to account for in value len */
                                        /* go on to next EA */
                                        temp_fea = (struct fea *)temp_ptr;
@@ -3288,7 +4087,7 @@ QEARetry:
        if (rc == -EAGAIN)
                goto QEARetry;
 
-       return rc;
+       return (ssize_t)rc;
 }
 
 int
@@ -3302,6 +4101,7 @@ CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
        int name_len;
        int rc = 0;
        int bytes_returned = 0;
+       __u16 params, param_offset, byte_count, offset, count;
 
        cFYI(1, ("In SetEA"));
 SetEARetry:
@@ -3312,18 +4112,18 @@ SetEARetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fileName, 530);
+               name_len = strnlen(fileName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, fileName, name_len);
        }
 
-       pSMB->ParameterCount = 6 + name_len;
+       params = 6 + name_len;
 
        /* done calculating parms using name_len of file name,
        now use name_len to calculate length of ea name
@@ -3333,7 +4133,7 @@ SetEARetry:
        else
                name_len = strnlen(ea_name,255);
 
-       pSMB->DataCount = sizeof(*parm_data) + ea_value_len + name_len + 1;
+       count = sizeof(*parm_data) + ea_value_len + name_len + 1;
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
        pSMB->MaxSetupCount = 0;
@@ -3341,23 +4141,23 @@ SetEARetry:
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+       param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-       pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+       offset = param_offset + params;
        pSMB->InformationLevel =
                cpu_to_le16(SMB_SET_FILE_EA);
 
        parm_data =
                (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
-                                      pSMB->DataOffset);
-       pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-       pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+                                      offset);
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-       pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-       pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-       parm_data->list_len = (__u32)(pSMB->DataCount);
+       byte_count = 3 /* pad */  + params + count;
+       pSMB->DataCount = cpu_to_le16(count);
+       parm_data->list_len = cpu_to_le32(count);
        parm_data->list[0].EA_flags = 0;
        /* we checked above that name len is less than 255 */
        parm_data->list[0].name_len = (__u8)name_len;;
@@ -3374,11 +4174,11 @@ SetEARetry:
                memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
 
        pSMB->TotalDataCount = pSMB->DataCount;
-       pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+       pSMB->ParameterCount = cpu_to_le16(params);
        pSMB->TotalParameterCount = pSMB->ParameterCount;
        pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-       pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {