cifs: fix possible memory corruption in CIFSFindNext, CVE-2011-3191
[linux-flexiantxendom0-natty.git] / fs / cifs / cifssmb.c
index 994de7c..e9abcf9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifssmb.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2008
+ *   Copyright (C) International Business Machines  Corp., 2002,2010
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   Contains the routines for constructing the SMB PDUs themselves
@@ -30,6 +30,7 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/vfs.h>
+#include <linux/slab.h>
 #include <linux/posix_acl_xattr.h>
 #include <asm/uaccess.h>
 #include "cifspdu.h"
@@ -81,41 +82,6 @@ static struct {
 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
 #endif /* CIFS_POSIX */
 
-/* Allocates buffer into dst and copies smb string from src to it.
- * caller is responsible for freeing dst if function returned 0.
- * returns:
- *     on success - 0
- *     on failure - errno
- */
-static int
-cifs_strncpy_to_host(char **dst, const char *src, const int maxlen,
-                const bool is_unicode, const struct nls_table *nls_codepage)
-{
-       int plen;
-
-       if (is_unicode) {
-               plen = UniStrnlen((wchar_t *)src, maxlen);
-               *dst = kmalloc(plen + 2, GFP_KERNEL);
-               if (!*dst)
-                       goto cifs_strncpy_to_host_ErrExit;
-               cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
-       } else {
-               plen = strnlen(src, maxlen);
-               *dst = kmalloc(plen + 2, GFP_KERNEL);
-               if (!*dst)
-                       goto cifs_strncpy_to_host_ErrExit;
-               strncpy(*dst, src, plen);
-       }
-       (*dst)[plen] = 0;
-       (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */
-       return 0;
-
-cifs_strncpy_to_host_ErrExit:
-       cERROR(1, ("Failed to allocate buffer for string\n"));
-       return -ENOMEM;
-}
-
-
 /* Mark as invalid, all open files on tree connections since they
    were closed when session to server was lost */
 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
@@ -125,120 +91,147 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
        struct list_head *tmp1;
 
 /* list all files open on tree connection and mark them invalid */
-       write_lock(&GlobalSMBSeslock);
+       spin_lock(&cifs_file_list_lock);
        list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
                open_file = list_entry(tmp, struct cifsFileInfo, tlist);
                open_file->invalidHandle = true;
+               open_file->oplock_break_cancelled = true;
        }
-       write_unlock(&GlobalSMBSeslock);
+       spin_unlock(&cifs_file_list_lock);
        /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
           to this tcon */
 }
 
-/* Allocate and return pointer to an SMB request buffer, and set basic
-   SMB information in the SMB header.  If the return code is zero, this
-   function must have filled in request_buf pointer */
+/* reconnect the socket, tcon, and smb session if needed */
 static int
-small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
-               void **request_buf)
+cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
 {
        int rc = 0;
+       struct cifsSesInfo *ses;
+       struct TCP_Server_Info *server;
+       struct nls_table *nls_codepage;
 
-       /* 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->tidStatus == CifsExiting) {
-                       /* only tree disconnect, open, and write,
-                       (and ulogoff which does not have tcon)
-                       are allowed as we start force umount */
-                       if ((smb_command != SMB_COM_WRITE_ANDX) &&
-                          (smb_command != SMB_COM_OPEN_ANDX) &&
-                          (smb_command != SMB_COM_TREE_DISCONNECT)) {
-                               cFYI(1, ("can not send cmd %d while umounting",
-                                       smb_command));
-                               return -ENODEV;
-                       }
+       /*
+        * 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)
+               return 0;
+
+       ses = tcon->ses;
+       server = ses->server;
+
+       /*
+        * only tree disconnect, open, and write, (and ulogoff which does not
+        * have tcon) are allowed as we start force umount
+        */
+       if (tcon->tidStatus == CifsExiting) {
+               if (smb_command != SMB_COM_WRITE_ANDX &&
+                   smb_command != SMB_COM_OPEN_ANDX &&
+                   smb_command != SMB_COM_TREE_DISCONNECT) {
+                       cFYI(1, "can not send cmd %d while umounting",
+                               smb_command);
+                       return -ENODEV;
                }
-               if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
-                                 (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 ||
-                                          (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 on-line */
-                               } 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);
-                               /* BB FIXME add code to check if wsize needs
-                                  update due to negotiated smb buffer size
-                                  shrinking */
-                               if (rc == 0) {
-                                       atomic_inc(&tconInfoReconnectCount);
-                                       /* tell server Unix caps we support */
-                                       if (tcon->ses->capabilities & CAP_UNIX)
-                                               reset_cifs_unix_caps(
-                                               0 /* no xid */,
-                                               tcon,
-                                               NULL /* we do not know sb */,
-                                               NULL /* no vol info */);
-                               }
+       /*
+        * Give demultiplex thread up to 10 seconds to reconnect, should be
+        * greater than cifs socket timeout which is 7 seconds
+        */
+       while (server->tcpStatus == CifsNeedReconnect) {
+               wait_event_interruptible_timeout(server->response_q,
+                       (server->tcpStatus == CifsGood), 10 * HZ);
 
-                               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);
+               /* is TCP session is reestablished now ?*/
+               if (server->tcpStatus != CifsNeedReconnect)
+                       break;
 
-               } else {
-                       return -EIO;
+               /*
+                * on "soft" mounts we wait once. Hard mounts keep
+                * retrying until process is killed or server comes
+                * back on-line
+                */
+               if (!tcon->retry) {
+                       cFYI(1, "gave up waiting on reconnect in smb_init");
+                       return -EHOSTDOWN;
                }
        }
+
+       if (!ses->need_reconnect && !tcon->need_reconnect)
+               return 0;
+
+       nls_codepage = load_nls_default();
+
+       /*
+        * need to prevent multiple threads trying to simultaneously
+        * reconnect the same SMB session
+        */
+       mutex_lock(&ses->session_mutex);
+       rc = cifs_negotiate_protocol(0, ses);
+       if (rc == 0 && ses->need_reconnect)
+               rc = cifs_setup_session(0, ses, nls_codepage);
+
+       /* do we need to reconnect tcon? */
+       if (rc || !tcon->need_reconnect) {
+               mutex_unlock(&ses->session_mutex);
+               goto out;
+       }
+
+       mark_open_files_invalid(tcon);
+       rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
+       mutex_unlock(&ses->session_mutex);
+       cFYI(1, "reconnect tcon rc = %d", rc);
+
+       if (rc)
+               goto out;
+
+       /*
+        * FIXME: check if wsize needs updated due to negotiated smb buffer
+        *        size shrinking
+        */
+       atomic_inc(&tconInfoReconnectCount);
+
+       /* tell server Unix caps we support */
+       if (ses->capabilities & CAP_UNIX)
+               reset_cifs_unix_caps(0, tcon, NULL, NULL);
+
+       /*
+        * 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.
+        *
+        * FIXME: what about file locks? don't we need to reclaim them ASAP?
+        */
+
+out:
+       /*
+        * 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:
+               rc = -EAGAIN;
+       }
+
+       unload_nls(nls_codepage);
+       return rc;
+}
+
+/* Allocate and return pointer to an SMB request buffer, and set basic
+   SMB information in the SMB header.  If the return code is zero, this
+   function must have filled in request_buf pointer */
+static int
+small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+               void **request_buf)
+{
+       int rc;
+
+       rc = cifs_reconnect_tcon(tcon, smb_command);
        if (rc)
                return rc;
 
@@ -254,7 +247,7 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
        if (tcon != NULL)
                cifs_stats_inc(&tcon->num_smbs_sent);
 
-       return rc;
+       return 0;
 }
 
 int
@@ -285,110 +278,9 @@ small_smb_init_no_tc(const int smb_command, const int wct,
 
 /* If the return code is zero, this function must fill in request_buf pointer */
 static int
-smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
-        void **request_buf /* returned */ ,
-        void **response_buf /* returned */ )
+__smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+                       void **request_buf, void **response_buf)
 {
-       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->tidStatus == CifsExiting) {
-                       /* only tree disconnect, open, and write,
-                         (and ulogoff which does not have tcon)
-                         are allowed as we start force umount */
-                       if ((smb_command != SMB_COM_WRITE_ANDX) &&
-                          (smb_command != SMB_COM_OPEN_ANDX) &&
-                          (smb_command != SMB_COM_TREE_DISCONNECT)) {
-                               cFYI(1, ("can not send cmd %d while umounting",
-                                       smb_command));
-                               return -ENODEV;
-                       }
-               }
-
-               if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
-                                 (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 ||
-                                          (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 on-line */
-                               } 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);
-                               /* BB FIXME add code to check if wsize needs
-                               update due to negotiated smb buffer size
-                               shrinking */
-                               if (rc == 0) {
-                                       atomic_inc(&tconInfoReconnectCount);
-                                       /* tell server Unix caps we support */
-                                       if (tcon->ses->capabilities & CAP_UNIX)
-                                               reset_cifs_unix_caps(
-                                               0 /* no xid */,
-                                               tcon,
-                                               NULL /* do not know sb */,
-                                               NULL /* no vol info */);
-                               }
-
-                               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_buf_get();
        if (*request_buf == NULL) {
                /* BB should we add a retry in here if not a writepage? */
@@ -407,42 +299,64 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
        if (tcon != NULL)
                cifs_stats_inc(&tcon->num_smbs_sent);
 
-       return rc;
+       return 0;
+}
+
+/* If the return code is zero, this function must fill in request_buf pointer */
+static int
+smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+        void **request_buf, void **response_buf)
+{
+       int rc;
+
+       rc = cifs_reconnect_tcon(tcon, smb_command);
+       if (rc)
+               return rc;
+
+       return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
+}
+
+static int
+smb_init_no_reconnect(int smb_command, int wct, struct cifsTconInfo *tcon,
+                       void **request_buf, void **response_buf)
+{
+       if (tcon->ses->need_reconnect || tcon->need_reconnect)
+               return -EHOSTDOWN;
+
+       return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
 }
 
 static int validate_t2(struct smb_t2_rsp *pSMB)
 {
-       int rc = -EINVAL;
-       int total_size;
-       char *pBCC;
+       unsigned int total_size;
+
+       /* check for plausible wct */
+       if (pSMB->hdr.WordCount < 10)
+               goto vt2_err;
 
-       /* 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;
-                               }
-                       }
-               }
-       }
+       if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
+           get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
+               goto vt2_err;
+
+       /* check that bcc is at least as big as parms + data */
+       /* check that bcc is less than negotiated smb buffer */
+       total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
+       if (total_size >= 512)
+               goto vt2_err;
+
+       total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
+       if (total_size > get_bcc(&pSMB->hdr) ||
+           total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
+               goto vt2_err;
+
+       return 0;
+vt2_err:
        cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
                sizeof(struct smb_t2_rsp) + 16);
-       return rc;
+       return -EINVAL;
 }
+
 int
 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 {
@@ -454,7 +368,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
        struct TCP_Server_Info *server;
        u16 count;
        unsigned int secFlags;
-       u16 dialect;
 
        if (ses->server)
                server = ses->server;
@@ -471,9 +384,9 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
        if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
                secFlags = ses->overrideSecFlg;  /* BB FIXME fix sign flags? */
        else /* if override flags set only sign/seal OR them with global auth */
-               secFlags = extended_security | ses->overrideSecFlg;
+               secFlags = global_secflags | ses->overrideSecFlg;
 
-       cFYI(1, ("secFlags 0x%x", secFlags));
+       cFYI(1, "secFlags 0x%x", secFlags);
 
        pSMB->hdr.Mid = GetNextMid(server);
        pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
@@ -481,7 +394,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
        if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
                pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
        else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
-               cFYI(1, ("Kerberos only mechanism, enable extended security"));
+               cFYI(1, "Kerberos only mechanism, enable extended security");
+               pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
+       } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
+               pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
+       else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
+               cFYI(1, "NTLMSSP only mechanism, enable extended security");
                pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
        }
 
@@ -499,10 +417,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
        if (rc != 0)
                goto neg_err_exit;
 
-       dialect = le16_to_cpu(pSMBr->DialectIndex);
-       cFYI(1, ("Dialect: %d", dialect));
+       server->dialect = le16_to_cpu(pSMBr->DialectIndex);
+       cFYI(1, "Dialect: %d", server->dialect);
        /* Check wct = 1 error case */
-       if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
+       if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
                /* core returns wct = 1, but we do not ask for core - otherwise
                small wct just comes when dialect index is -1 indicating we
                could not negotiate a common dialect */
@@ -510,8 +428,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                goto neg_err_exit;
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
        } else if ((pSMBr->hdr.WordCount == 13)
-                       && ((dialect == LANMAN_PROT)
-                               || (dialect == LANMAN2_PROT))) {
+                       && ((server->dialect == LANMAN_PROT)
+                               || (server->dialect == LANMAN2_PROT))) {
                __s16 tmp;
                struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
 
@@ -519,8 +437,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                        (secFlags & CIFSSEC_MAY_PLNTXT))
                        server->secType = LANMAN;
                else {
-                       cERROR(1, ("mount failed weak security disabled"
-                                  " in /proc/fs/cifs/SecurityFlags"));
+                       cERROR(1, "mount failed weak security disabled"
+                                  " in /proc/fs/cifs/SecurityFlags");
                        rc = -EOPNOTSUPP;
                        goto neg_err_exit;
                }
@@ -528,14 +446,14 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
                server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
                                (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
-               GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
+               server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
                /* even though we do not use raw we might as well set this
                accurately, in case we ever find a need for it */
                if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
-                       server->maxRw = 0xFF00;
+                       server->max_rw = 0xFF00;
                        server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
                } else {
-                       server->maxRw = 0;/* we do not need to use raw anyway */
+                       server->max_rw = 0;/* do not need to use raw anyway */
                        server->capabilities = CAP_MPX_MODE;
                }
                tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
@@ -550,11 +468,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                        int val, seconds, remain, result;
                        struct timespec ts, utc;
                        utc = CURRENT_TIME;
-                       ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
-                                               le16_to_cpu(rsp->SrvTime.Time));
-                       cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
+                       ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
+                                           rsp->SrvTime.Time, 0);
+                       cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
                                (int)ts.tv_sec, (int)utc.tv_sec,
-                               (int)(utc.tv_sec - ts.tv_sec)));
+                               (int)(utc.tv_sec - ts.tv_sec));
                        val = (int)(utc.tv_sec - ts.tv_sec);
                        seconds = abs(val);
                        result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
@@ -568,7 +486,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                        server->timeAdj = (int)tmp;
                        server->timeAdj *= 60; /* also in seconds */
                }
-               cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
+               cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
 
 
                /* BB get server time for time conversions and add
@@ -576,22 +494,22 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 
                if (rsp->EncryptionKeyLength ==
                                cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
-                       memcpy(server->cryptKey, rsp->EncryptionKey,
+                       memcpy(ses->server->cryptkey, rsp->EncryptionKey,
                                CIFS_CRYPTO_KEY_SIZE);
                } else if (server->secMode & SECMODE_PW_ENCRYPT) {
                        rc = -EIO; /* need cryptkey unless plain text */
                        goto neg_err_exit;
                }
 
-               cFYI(1, ("LANMAN negotiated"));
+               cFYI(1, "LANMAN negotiated");
                /* we will not end up setting signing flags - as no signing
                was in LANMAN and server did not return the flags on */
                goto signing_check;
 #else /* weak security disabled */
        } else if (pSMBr->hdr.WordCount == 13) {
-               cERROR(1, ("mount failed, cifs module not built "
-                         "with CIFS_WEAK_PW_HASH support"));
-                       rc = -EOPNOTSUPP;
+               cERROR(1, "mount failed, cifs module not built "
+                         "with CIFS_WEAK_PW_HASH support");
+               rc = -EOPNOTSUPP;
 #endif /* WEAK_PW_HASH */
                goto neg_err_exit;
        } else if (pSMBr->hdr.WordCount != 17) {
@@ -602,14 +520,14 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
        /* else wct == 17 NTLM */
        server->secMode = pSMBr->SecurityMode;
        if ((server->secMode & SECMODE_USER) == 0)
-               cFYI(1, ("share mode security"));
+               cFYI(1, "share mode security");
 
        if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
                if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
 #endif /* CIFS_WEAK_PW_HASH */
-                       cERROR(1, ("Server requests plain text password"
-                                 " but client support disabled"));
+                       cERROR(1, "Server requests plain text password"
+                                 " but client support disabled");
 
        if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
                server->secType = NTLMv2;
@@ -619,6 +537,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                server->secType = NTLMv2;
        else if (secFlags & CIFSSEC_MAY_KRB5)
                server->secType = Kerberos;
+       else if (secFlags & CIFSSEC_MAY_NTLMSSP)
+               server->secType = RawNTLMSSP;
        else if (secFlags & CIFSSEC_MAY_LANMAN)
                server->secType = LANMAN;
 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
@@ -627,7 +547,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 #endif */
        else {
                rc = -EOPNOTSUPP;
-               cERROR(1, ("Invalid security type"));
+               cERROR(1, "Invalid security type");
                goto neg_err_exit;
        }
        /* else ... any others ...? */
@@ -638,14 +558,13 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
        /* probably no need to store and check maxvcs */
        server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
                        (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
-       server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
-       cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
-       GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
+       server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
+       cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
        server->capabilities = le32_to_cpu(pSMBr->Capabilities);
        server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
        server->timeAdj *= 60;
        if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
-               memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
+               memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
                       CIFS_CRYPTO_KEY_SIZE);
        } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
                        && (pSMBr->EncryptionKeyLength == 0)) {
@@ -664,31 +583,42 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                        rc = -EIO;
                        goto neg_err_exit;
                }
-
-               if (server->socketUseCount.counter > 1) {
+               spin_lock(&cifs_tcp_ses_lock);
+               if (server->srv_count > 1) {
+                       spin_unlock(&cifs_tcp_ses_lock);
                        if (memcmp(server->server_GUID,
                                   pSMBr->u.extended_response.
                                   GUID, 16) != 0) {
-                               cFYI(1, ("server UID changed"));
+                               cFYI(1, "server UID changed");
                                memcpy(server->server_GUID,
                                        pSMBr->u.extended_response.GUID,
                                        16);
                        }
-               } else
+               } else {
+                       spin_unlock(&cifs_tcp_ses_lock);
                        memcpy(server->server_GUID,
                               pSMBr->u.extended_response.GUID, 16);
+               }
 
                if (count == 16) {
                        server->secType = RawNTLMSSP;
                } else {
                        rc = decode_negTokenInit(pSMBr->u.extended_response.
-                                                SecurityBlob,
-                                                count - 16,
-                                                &server->secType);
+                                                SecurityBlob, count - 16,
+                                                server);
                        if (rc == 1)
                                rc = 0;
                        else
                                rc = -EINVAL;
+                       if (server->secType == Kerberos) {
+                               if (!server->sec_kerberos &&
+                                               !server->sec_mskerberos)
+                                       rc = -EOPNOTSUPP;
+                       } else if (server->secType == RawNTLMSSP) {
+                               if (!server->sec_ntlmssp)
+                                       rc = -EOPNOTSUPP;
+                       } else
+                                       rc = -EOPNOTSUPP;
                }
        } else
                server->capabilities &= ~CAP_EXTENDED_SECURITY;
@@ -699,22 +629,21 @@ signing_check:
        if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
                /* MUST_SIGN already includes the MAY_SIGN FLAG
                   so if this is zero it means that signing is disabled */
-               cFYI(1, ("Signing disabled"));
+               cFYI(1, "Signing disabled");
                if (server->secMode & SECMODE_SIGN_REQUIRED) {
-                       cERROR(1, ("Server requires "
+                       cERROR(1, "Server requires "
                                   "packet signing to be enabled in "
-                                  "/proc/fs/cifs/SecurityFlags."));
+                                  "/proc/fs/cifs/SecurityFlags.");
                        rc = -EOPNOTSUPP;
                }
                server->secMode &=
                        ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
        } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
                /* signing required */
-               cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
+               cFYI(1, "Must sign - secFlags 0x%x", secFlags);
                if ((server->secMode &
                        (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
-                       cERROR(1,
-                               ("signing required but server lacks support"));
+                       cERROR(1, "signing required but server lacks support");
                        rc = -EOPNOTSUPP;
                } else
                        server->secMode |= SECMODE_SIGN_REQUIRED;
@@ -728,7 +657,7 @@ signing_check:
 neg_err_exit:
        cifs_buf_release(pSMB);
 
-       cFYI(1, ("negprot rc %d", rc));
+       cFYI(1, "negprot rc %d", rc);
        return rc;
 }
 
@@ -738,102 +667,123 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
        struct smb_hdr *smb_buffer;
        int rc = 0;
 
-       cFYI(1, ("In tree disconnect"));
-       /*
-        *  If last user of the connection and
-        *  connection alive - disconnect it
-        *  If this is the last connection on the server session disconnect it
-        *  (and inside session disconnect we should check if tcp socket needs
-        *  to be freed and kernel thread woken up).
-        */
-       if (tcon)
-               down(&tcon->tconSem);
-       else
-               return -EIO;
+       cFYI(1, "In tree disconnect");
 
-       atomic_dec(&tcon->useCount);
-       if (atomic_read(&tcon->useCount) > 0) {
-               up(&tcon->tconSem);
-               return -EBUSY;
-       }
+       /* BB: do we need to check this? These should never be NULL. */
+       if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
+               return -EIO;
 
-       /* No need to return error on this operation if tid invalidated and
-       closed on server already e.g. due to tcp session crashing */
-       if (tcon->tidStatus == CifsNeedReconnect) {
-               up(&tcon->tconSem);
+       /*
+        * No need to return error on this operation if tid invalidated and
+        * closed on server already e.g. due to tcp session crashing. Also,
+        * the tcon is no longer on the list, so no need to take lock before
+        * checking this.
+        */
+       if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
                return 0;
-       }
 
-       if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
-               up(&tcon->tconSem);
-               return -EIO;
-       }
        rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
                            (void **)&smb_buffer);
-       if (rc) {
-               up(&tcon->tconSem);
+       if (rc)
                return rc;
-       }
 
        rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
        if (rc)
-               cFYI(1, ("Tree disconnect failed %d", rc));
-
-       up(&tcon->tconSem);
+               cFYI(1, "Tree disconnect failed %d", rc);
 
        /* No need to return error on this operation if tid invalidated and
-       closed on server already e.g. due to tcp session crashing */
+          closed on server already e.g. due to tcp session crashing */
        if (rc == -EAGAIN)
                rc = 0;
 
        return rc;
 }
 
+/*
+ * This is a no-op for now. We're not really interested in the reply, but
+ * rather in the fact that the server sent one and that server->lstrp
+ * gets updated.
+ *
+ * FIXME: maybe we should consider checking that the reply matches request?
+ */
+static void
+cifs_echo_callback(struct mid_q_entry *mid)
+{
+       struct TCP_Server_Info *server = mid->callback_data;
+
+       DeleteMidQEntry(mid);
+       atomic_dec(&server->inFlight);
+       wake_up(&server->request_q);
+}
+
+int
+CIFSSMBEcho(struct TCP_Server_Info *server)
+{
+       ECHO_REQ *smb;
+       int rc = 0;
+
+       cFYI(1, "In echo request");
+
+       rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
+       if (rc)
+               return rc;
+
+       /* set up echo request */
+       smb->hdr.Tid = cpu_to_le16(0xffff);
+       smb->hdr.WordCount = 1;
+       put_unaligned_le16(1, &smb->EchoCount);
+       put_bcc_le(1, &smb->hdr);
+       smb->Data[0] = 'a';
+       smb->hdr.smb_buf_length += 3;
+
+       rc = cifs_call_async(server, (struct smb_hdr *)smb,
+                               cifs_echo_callback, server);
+       if (rc)
+               cFYI(1, "Echo request failed: %d", rc);
+
+       cifs_small_buf_release(smb);
+
+       return rc;
+}
+
 int
 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
 {
        LOGOFF_ANDX_REQ *pSMB;
        int rc = 0;
 
-       cFYI(1, ("In SMBLogoff for session disconnect"));
-       if (ses)
-               down(&ses->sesSem);
-       else
+       cFYI(1, "In SMBLogoff for session disconnect");
+
+       /*
+        * BB: do we need to check validity of ses and server? They should
+        * always be valid since we have an active reference. If not, that
+        * should probably be a BUG()
+        */
+       if (!ses || !ses->server)
                return -EIO;
 
-       atomic_dec(&ses->inUse);
-       if (atomic_read(&ses->inUse) > 0) {
-               up(&ses->sesSem);
-               return -EBUSY;
-       }
+       mutex_lock(&ses->session_mutex);
+       if (ses->need_reconnect)
+               goto session_already_dead; /* no need to send SMBlogoff if uid
+                                             already closed due to reconnect */
        rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
        if (rc) {
-               up(&ses->sesSem);
+               mutex_unlock(&ses->session_mutex);
                return rc;
        }
 
-       if (ses->server) {
-               pSMB->hdr.Mid = GetNextMid(ses->server);
+       pSMB->hdr.Mid = GetNextMid(ses->server);
 
-               if (ses->server->secMode &
+       if (ses->server->secMode &
                   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
                        pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-       }
 
        pSMB->hdr.Uid = ses->Suid;
 
        pSMB->AndXCommand = 0xFF;
        rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
-       if (ses->server) {
-               atomic_dec(&ses->server->socketUseCount);
-               if (atomic_read(&ses->server->socketUseCount) == 0) {
-                       spin_lock(&GlobalMid_Lock);
-                       ses->server->tcpStatus = CifsExiting;
-                       spin_unlock(&GlobalMid_Lock);
-                       rc = -ESHUTDOWN;
-               }
-       }
-       up(&ses->sesSem);
+session_already_dead:
+       mutex_unlock(&ses->session_mutex);
 
        /* if session dead then we do not need to do ulogoff,
                since server closed smb session, no sense reporting
@@ -855,7 +805,7 @@ CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
        int bytes_returned = 0;
        __u16 params, param_offset, offset, byte_count;
 
-       cFYI(1, ("In POSIX delete"));
+       cFYI(1, "In POSIX delete");
 PsxDelete:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -907,7 +857,7 @@ PsxDelete:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc)
-               cFYI(1, ("Posix delete returned %d", rc));
+               cFYI(1, "Posix delete returned %d", rc);
        cifs_buf_release(pSMB);
 
        cifs_stats_inc(&tcon->num_deletes);
@@ -954,7 +904,7 @@ DelFileRetry:
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        cifs_stats_inc(&tcon->num_deletes);
        if (rc)
-               cFYI(1, ("Error in RMFile = %d", rc));
+               cFYI(1, "Error in RMFile = %d", rc);
 
        cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
@@ -973,7 +923,7 @@ CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
        int bytes_returned;
        int name_len;
 
-       cFYI(1, ("In CIFSSMBRmDir"));
+       cFYI(1, "In CIFSSMBRmDir");
 RmDirRetry:
        rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -998,7 +948,7 @@ RmDirRetry:
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        cifs_stats_inc(&tcon->num_rmdirs);
        if (rc)
-               cFYI(1, ("Error in RMDir = %d", rc));
+               cFYI(1, "Error in RMDir = %d", rc);
 
        cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
@@ -1016,7 +966,7 @@ CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
        int bytes_returned;
        int name_len;
 
-       cFYI(1, ("In CIFSSMBMkDir"));
+       cFYI(1, "In CIFSSMBMkDir");
 MkDirRetry:
        rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -1041,7 +991,7 @@ MkDirRetry:
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        cifs_stats_inc(&tcon->num_mkdirs);
        if (rc)
-               cFYI(1, ("Error in Mkdir = %d", rc));
+               cFYI(1, "Error in Mkdir = %d", rc);
 
        cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
@@ -1064,7 +1014,7 @@ CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
        OPEN_PSX_REQ *pdata;
        OPEN_PSX_RSP *psx_rsp;
 
-       cFYI(1, ("In POSIX Create"));
+       cFYI(1, "In POSIX Create");
 PsxCreat:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -1118,11 +1068,11 @@ PsxCreat:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cFYI(1, ("Posix create returned %d", rc));
+               cFYI(1, "Posix create returned %d", rc);
                goto psx_create_err;
        }
 
-       cFYI(1, ("copying inode info"));
+       cFYI(1, "copying inode info");
        rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
        if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
@@ -1144,11 +1094,11 @@ PsxCreat:
        /* check to make sure response data is there */
        if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
                pRetData->Type = cpu_to_le32(-1); /* unknown */
-               cFYI(DBG2, ("unknown type"));
+               cFYI(DBG2, "unknown type");
        } else {
                if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
                                        + sizeof(FILE_UNIX_BASIC_INFO)) {
-                       cERROR(1, ("Open response data too small"));
+                       cERROR(1, "Open response data too small");
                        pRetData->Type = cpu_to_le32(-1);
                        goto psx_create_err;
                }
@@ -1160,7 +1110,10 @@ PsxCreat:
 psx_create_err:
        cifs_buf_release(pSMB);
 
-       cifs_stats_inc(&tcon->num_mkdirs);
+       if (posix_flags & SMB_O_DIRECTORY)
+               cifs_stats_inc(&tcon->num_posixmkdirs);
+       else
+               cifs_stats_inc(&tcon->num_posixopens);
 
        if (rc == -EAGAIN)
                goto PsxCreat;
@@ -1192,7 +1145,7 @@ static __u16 convert_disposition(int disposition)
                        ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
                        break;
                default:
-                       cFYI(1, ("unknown disposition %d", disposition));
+                       cFYI(1, "unknown disposition %d", disposition);
                        ofun =  SMBOPEN_OAPPEND; /* regular open */
        }
        return ofun;
@@ -1280,10 +1233,10 @@ OldOpenRetry:
        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, CIFS_LONG_OP);
+                       (struct smb_hdr *)pSMBr, &bytes_returned, 0);
        cifs_stats_inc(&tcon->num_opens);
        if (rc) {
-               cFYI(1, ("Error in Open = %d", rc));
+               cFYI(1, "Error in Open = %d", rc);
        } else {
        /* BB verify if wct == 15 */
 
@@ -1309,6 +1262,7 @@ OldOpenRetry:
                                cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
                        pfile_info->EndOfFile = pfile_info->AllocationSize;
                        pfile_info->NumberOfLinks = cpu_to_le32(1);
+                       pfile_info->DeletePending = 0;
                }
        }
 
@@ -1392,10 +1346,10 @@ openRetry:
        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, CIFS_LONG_OP);
+                       (struct smb_hdr *)pSMBr, &bytes_returned, 0);
        cifs_stats_inc(&tcon->num_opens);
        if (rc) {
-               cFYI(1, ("Error in Open = %d", rc));
+               cFYI(1, "Error in Open = %d", rc);
        } else {
                *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
                *netfid = pSMBr->Fid;   /* cifs fid stays in le */
@@ -1404,12 +1358,13 @@ openRetry:
                if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
                        *pOplock |= CIFS_CREATE_ACTION;
                if (pfile_info) {
-                   memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
-                       36 /* CreationTime to Attributes */);
-                   /* the file_info buf is endian converted by caller */
-                   pfile_info->AllocationSize = pSMBr->AllocationSize;
-                   pfile_info->EndOfFile = pSMBr->EndOfFile;
-                   pfile_info->NumberOfLinks = cpu_to_le32(1);
+                       memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
+                               36 /* CreationTime to Attributes */);
+                       /* the file_info buf is endian converted by caller */
+                       pfile_info->AllocationSize = pSMBr->AllocationSize;
+                       pfile_info->EndOfFile = pSMBr->EndOfFile;
+                       pfile_info->NumberOfLinks = cpu_to_le32(1);
+                       pfile_info->DeletePending = 0;
                }
        }
 
@@ -1432,11 +1387,16 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
        int resp_buf_type = 0;
        struct kvec iov[1];
 
-       cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
+       cFYI(1, "Reading %d bytes on fid %d", count, netfid);
        if (tcon->ses->capabilities & CAP_LARGE_FILES)
                wct = 12;
-       else
+       else {
                wct = 10; /* old style read */
+               if ((lseek >> 32) > 0)  {
+                       /* can not handle this big offset for old */
+                       return -EIO;
+               }
+       }
 
        *nbytes = 0;
        rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
@@ -1452,8 +1412,6 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
        pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
        if (wct == 12)
                pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
-       else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
-               return -EIO;
 
        pSMB->Remaining = 0;
        pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
@@ -1470,11 +1428,11 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
        iov[0].iov_base = (char *)pSMB;
        iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
        rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
-                        &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
+                        &resp_buf_type, CIFS_LOG_ERROR);
        cifs_stats_inc(&tcon->num_reads);
        pSMBr = (READ_RSP *)iov[0].iov_base;
        if (rc) {
-               cERROR(1, ("Send error in read = %d", rc));
+               cERROR(1, "Send error in read = %d", rc);
        } else {
                int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
                data_length = data_length << 16;
@@ -1484,15 +1442,15 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
                /*check that DataLength would not go beyond end of SMB */
                if ((data_length > CIFSMaxBufSize)
                                || (data_length > count)) {
-                       cFYI(1, ("bad length %d for count %d",
-                                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, data_length)) {
-                               cERROR(1,("Faulting on read rc = %d",rc));
+                               cERROR(1, "Faulting on read rc = %d",rc);
                                rc = -EFAULT;
                        }*/ /* can not use copy_to_user when using page cache*/
                        if (*buf)
@@ -1534,14 +1492,21 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
        __u32 bytes_sent;
        __u16 byte_count;
 
-       /* cFYI(1,("write at %lld %d bytes",offset,count));*/
+       *nbytes = 0;
+
+       /* cFYI(1, "write at %lld %d bytes", offset, count);*/
        if (tcon->ses == NULL)
                return -ECONNABORTED;
 
        if (tcon->ses->capabilities & CAP_LARGE_FILES)
                wct = 14;
-       else
+       else {
                wct = 12;
+               if ((offset >> 32) > 0) {
+                       /* can not handle big offset for old srv */
+                       return -EIO;
+               }
+       }
 
        rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -1556,8 +1521,6 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
        pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
        if (wct == 14)
                pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
-       else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
-               return -EIO;
 
        pSMB->Reserved = 0xFFFFFFFF;
        pSMB->WriteMode = 0;
@@ -1579,7 +1542,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
        pSMB->DataOffset =
                cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
        if (buf)
-           memcpy(pSMB->Data, buf, bytes_sent);
+               memcpy(pSMB->Data, buf, bytes_sent);
        else if (ubuf) {
                if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
                        cifs_buf_release(pSMB);
@@ -1612,12 +1575,19 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
                         (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
        cifs_stats_inc(&tcon->num_writes);
        if (rc) {
-               cFYI(1, ("Send error in write = %d", rc));
-               *nbytes = 0;
+               cFYI(1, "Send error in write = %d", rc);
        } else {
                *nbytes = le16_to_cpu(pSMBr->CountHigh);
                *nbytes = (*nbytes) << 16;
                *nbytes += le16_to_cpu(pSMBr->Count);
+
+               /*
+                * Mask off high 16 bits when bytes written as returned by the
+                * server is greater than bytes requested by the client. Some
+                * OS/2 servers are known to set incorrect CountHigh values.
+                */
+               if (*nbytes > count)
+                       *nbytes &= 0xFFFF;
        }
 
        cifs_buf_release(pSMB);
@@ -1640,12 +1610,19 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
        int smb_hdr_len;
        int resp_buf_type = 0;
 
-       cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
+       *nbytes = 0;
 
-       if (tcon->ses->capabilities & CAP_LARGE_FILES)
+       cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
+
+       if (tcon->ses->capabilities & CAP_LARGE_FILES) {
                wct = 14;
-       else
+       } else {
                wct = 12;
+               if ((offset >> 32) > 0) {
+                       /* can not handle big offset for old srv */
+                       return -EIO;
+               }
+       }
        rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
        if (rc)
                return rc;
@@ -1658,8 +1635,6 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
        pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
        if (wct == 14)
                pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
-       else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
-               return -EIO;
        pSMB->Reserved = 0xFFFFFFFF;
        pSMB->WriteMode = 0;
        pSMB->Remaining = 0;
@@ -1692,17 +1667,23 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
                          long_op);
        cifs_stats_inc(&tcon->num_writes);
        if (rc) {
-               cFYI(1, ("Send error Write2 = %d", rc));
-               *nbytes = 0;
+               cFYI(1, "Send error Write2 = %d", rc);
        } else if (resp_buf_type == 0) {
                /* presumably this can not happen, but best to be safe */
                rc = -EIO;
-               *nbytes = 0;
        } else {
                WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
                *nbytes = le16_to_cpu(pSMBr->CountHigh);
                *nbytes = (*nbytes) << 16;
                *nbytes += le16_to_cpu(pSMBr->Count);
+
+               /*
+                * Mask off high 16 bits when bytes written as returned by the
+                * server is greater than bytes requested by the client. OS/2
+                * servers are known to set incorrect CountHigh values.
+                */
+               if (*nbytes > count)
+                       *nbytes &= 0xFFFF;
        }
 
 /*     cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
@@ -1722,7 +1703,8 @@ int
 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
            const __u16 smb_file_id, const __u64 len,
            const __u64 offset, const __u32 numUnlock,
-           const __u32 numLock, const __u8 lockType, const bool waitFlag)
+           const __u32 numLock, const __u8 lockType,
+           const bool waitFlag, const __u8 oplock_level)
 {
        int rc = 0;
        LOCK_REQ *pSMB = NULL;
@@ -1731,7 +1713,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
        int timeout = 0;
        __u16 count;
 
-       cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
+       cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
        rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
 
        if (rc)
@@ -1750,6 +1732,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
        pSMB->NumberOfLocks = cpu_to_le16(numLock);
        pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
        pSMB->LockType = lockType;
+       pSMB->OplockLevel = oplock_level;
        pSMB->AndXCommand = 0xFF;       /* none */
        pSMB->Fid = smb_file_id; /* netfid stays le */
 
@@ -1779,7 +1762,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
        }
        cifs_stats_inc(&tcon->num_locks);
        if (rc)
-               cFYI(1, ("Send error in Lock = %d", rc));
+               cFYI(1, "Send error in Lock = %d", rc);
 
        /* Note: On -EAGAIN error only caller can retry on handle based calls
        since file handle passed in no longer valid */
@@ -1802,7 +1785,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
        __u16 params, param_offset, offset, byte_count, count;
        struct kvec iov[1];
 
-       cFYI(1, ("Posix Lock"));
+       cFYI(1, "Posix Lock");
 
        if (pLockData == NULL)
                return -EINVAL;
@@ -1872,7 +1855,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
        }
 
        if (rc) {
-               cFYI(1, ("Send error in Posix Lock = %d", rc));
+               cFYI(1, "Send error in Posix Lock = %d", rc);
        } else if (get_flag) {
                /* lock structure can be returned on get */
                __u16 data_offset;
@@ -1883,10 +1866,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
                        rc = -EIO;      /* bad smb */
                        goto plk_err_exit;
                }
-               if (pLockData == NULL) {
-                       rc = -EINVAL;
-                       goto plk_err_exit;
-               }
                data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
                data_count  = le16_to_cpu(pSMBr->t2.DataCount);
                if (data_count < sizeof(struct cifs_posix_lock)) {
@@ -1895,8 +1874,21 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
                }
                parm_data = (struct cifs_posix_lock *)
                        ((char *)&pSMBr->hdr.Protocol + data_offset);
-               if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
+               if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
                        pLockData->fl_type = F_UNLCK;
+               else {
+                       if (parm_data->lock_type ==
+                                       __constant_cpu_to_le16(CIFS_RDLCK))
+                               pLockData->fl_type = F_RDLCK;
+                       else if (parm_data->lock_type ==
+                                       __constant_cpu_to_le16(CIFS_WRLCK))
+                               pLockData->fl_type = F_WRLCK;
+
+                       pLockData->fl_start = parm_data->start;
+                       pLockData->fl_end = parm_data->start +
+                                               parm_data->length - 1;
+                       pLockData->fl_pid = parm_data->pid;
+               }
        }
 
 plk_err_exit:
@@ -1920,7 +1912,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
 {
        int rc = 0;
        CLOSE_REQ *pSMB = NULL;
-       cFYI(1, ("In CIFSSMBClose"));
+       cFYI(1, "In CIFSSMBClose");
 
 /* do not retry on dead session on close */
        rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
@@ -1937,7 +1929,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
        if (rc) {
                if (rc != -EINTR) {
                        /* EINTR is expected when user ctl-c to kill app */
-                       cERROR(1, ("Send error in Close = %d", rc));
+                       cERROR(1, "Send error in Close = %d", rc);
                }
        }
 
@@ -1949,6 +1941,27 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
 }
 
 int
+CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
+{
+       int rc = 0;
+       FLUSH_REQ *pSMB = NULL;
+       cFYI(1, "In CIFSSMBFlush");
+
+       rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
+       if (rc)
+               return rc;
+
+       pSMB->FileID = (__u16) smb_file_id;
+       pSMB->ByteCount = 0;
+       rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
+       cifs_stats_inc(&tcon->num_flushes);
+       if (rc)
+               cERROR(1, "Send error in Flush = %d", rc);
+
+       return rc;
+}
+
+int
 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
              const char *fromName, const char *toName,
              const struct nls_table *nls_codepage, int remap)
@@ -1960,7 +1973,7 @@ CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
        int name_len, name_len2;
        __u16 count;
 
-       cFYI(1, ("In CIFSSMBRename"));
+       cFYI(1, "In CIFSSMBRename");
 renameRetry:
        rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -2006,7 +2019,7 @@ renameRetry:
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        cifs_stats_inc(&tcon->num_renames);
        if (rc)
-               cFYI(1, ("Send error in rename = %d", rc));
+               cFYI(1, "Send error in rename = %d", rc);
 
        cifs_buf_release(pSMB);
 
@@ -2017,7 +2030,7 @@ renameRetry:
 }
 
 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
-               int netfid, char *target_name,
+               int netfid, const char *target_name,
                const struct nls_table *nls_codepage, int remap)
 {
        struct smb_com_transaction2_sfi_req *pSMB  = NULL;
@@ -2030,7 +2043,7 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
        int len_of_str;
        __u16 params, param_offset, offset, count, byte_count;
 
-       cFYI(1, ("Rename to File by handle"));
+       cFYI(1, "Rename to File by handle");
        rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
                        (void **) &pSMBr);
        if (rc)
@@ -2071,7 +2084,7 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
                                        remap);
        }
        rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
-       count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
+       count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
        byte_count += count;
        pSMB->DataCount = cpu_to_le16(count);
        pSMB->TotalDataCount = pSMB->DataCount;
@@ -2085,7 +2098,7 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        cifs_stats_inc(&pTcon->num_t2renames);
        if (rc)
-               cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
+               cFYI(1, "Send error in Rename (by file handle) = %d", rc);
 
        cifs_buf_release(pSMB);
 
@@ -2107,7 +2120,7 @@ CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
        int name_len, name_len2;
        __u16 count;
 
-       cFYI(1, ("In CIFSSMBCopy"));
+       cFYI(1, "In CIFSSMBCopy");
 copyRetry:
        rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
                        (void **) &pSMBr);
@@ -2152,8 +2165,8 @@ copyRetry:
        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, le16_to_cpu(pSMBr->CopyCount)));
+               cFYI(1, "Send error in copy = %d with %d files copied",
+                       rc, le16_to_cpu(pSMBr->CopyCount));
        }
        cifs_buf_release(pSMB);
 
@@ -2177,7 +2190,7 @@ CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
        int bytes_returned = 0;
        __u16 params, param_offset, offset, byte_count;
 
-       cFYI(1, ("In Symlink Unix style"));
+       cFYI(1, "In Symlink Unix style");
 createSymLinkRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -2242,7 +2255,7 @@ createSymLinkRetry:
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        cifs_stats_inc(&tcon->num_symlinks);
        if (rc)
-               cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
+               cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
 
        cifs_buf_release(pSMB);
 
@@ -2266,7 +2279,7 @@ CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
        int bytes_returned = 0;
        __u16 params, param_offset, offset, byte_count;
 
-       cFYI(1, ("In Create Hard link Unix style"));
+       cFYI(1, "In Create Hard link Unix style");
 createHardLinkRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -2328,7 +2341,7 @@ createHardLinkRetry:
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        cifs_stats_inc(&tcon->num_hardlinks);
        if (rc)
-               cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
+               cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
 
        cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
@@ -2349,7 +2362,7 @@ CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
        int name_len, name_len2;
        __u16 count;
 
-       cFYI(1, ("In CIFSCreateHardLink"));
+       cFYI(1, "In CIFSCreateHardLink");
 winCreateHardLinkRetry:
 
        rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
@@ -2371,8 +2384,10 @@ winCreateHardLinkRetry:
                                     PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-               pSMB->OldFileName[name_len] = 0;        /* pad */
-               pSMB->OldFileName[name_len + 1] = 0x04;
+
+               /* protocol specifies ASCII buffer format (0x04) for unicode */
+               pSMB->OldFileName[name_len] = 0x04;
+               pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
                name_len2 =
                    cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
                                     toName, PATH_MAX, nls_codepage, remap);
@@ -2398,7 +2413,7 @@ winCreateHardLinkRetry:
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        cifs_stats_inc(&tcon->num_hardlinks);
        if (rc)
-               cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
+               cFYI(1, "Send error in hard link (NT rename) = %d", rc);
 
        cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
@@ -2409,8 +2424,7 @@ winCreateHardLinkRetry:
 
 int
 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
-                       const unsigned char *searchName,
-                       char *symlinkinfo, const int buflen,
+                       const unsigned char *searchName, char **symlinkinfo,
                        const struct nls_table *nls_codepage)
 {
 /* SMB_QUERY_FILE_UNIX_LINK */
@@ -2420,8 +2434,9 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
        int bytes_returned;
        int name_len;
        __u16 params, byte_count;
+       char *data_start;
 
-       cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
+       cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
 
 querySymLinkRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -2444,8 +2459,7 @@ querySymLinkRetry:
        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->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
        pSMB->MaxSetupCount = 0;
        pSMB->Reserved = 0;
        pSMB->Flags = 0;
@@ -2469,35 +2483,31 @@ querySymLinkRetry:
        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));
+               cFYI(1, "Send error in QuerySymLinkInfo = %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 */
+               if (rc || (pSMBr->ByteCount < 2))
+                       rc = -EIO;
                else {
-                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
-                       __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+                       bool is_unicode;
+                       u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+
+                       data_start = ((char *) &pSMBr->hdr.Protocol) +
+                                          le16_to_cpu(pSMBr->t2.DataOffset);
+
+                       if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+                               is_unicode = true;
+                       else
+                               is_unicode = false;
 
-                       if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
-                               name_len = UniStrnlen((wchar_t *) ((char *)
-                                       &pSMBr->hdr.Protocol + data_offset),
-                                       min_t(const int, buflen, count) / 2);
                        /* BB FIXME investigate remapping reserved chars here */
-                               cifs_strfromUCS_le(symlinkinfo,
-                                       (__le16 *) ((char *)&pSMBr->hdr.Protocol
-                                                       + data_offset),
-                                       name_len, nls_codepage);
-                       } else {
-                               strncpy(symlinkinfo,
-                                       (char *) &pSMBr->hdr.Protocol +
-                                               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 */
+                       *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
+                                                   is_unicode, nls_codepage);
+                       if (!*symlinkinfo)
+                               rc = -ENOMEM;
                }
        }
        cifs_buf_release(pSMB);
@@ -2507,96 +2517,6 @@ querySymLinkRetry:
 }
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-/* Initialize NT TRANSACT SMB into small smb request buffer.
-   This assumes that all NT TRANSACTS that we init here have
-   total parm and data under about 400 bytes (to fit in small cifs
-   buffer size), which is the case so far, it easily fits. NB:
-       Setup words themselves and ByteCount
-       MaxSetupCount (size of returned setup area) and
-       MaxParameterCount (returned parms size) must be set by caller */
-static int
-smb_init_nttransact(const __u16 sub_command, const int setup_count,
-                  const int parm_len, struct cifsTconInfo *tcon,
-                  void **ret_buf)
-{
-       int rc;
-       __u32 temp_offset;
-       struct smb_com_ntransact_req *pSMB;
-
-       rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
-                               (void **)&pSMB);
-       if (rc)
-               return rc;
-       *ret_buf = (void *)pSMB;
-       pSMB->Reserved = 0;
-       pSMB->TotalParameterCount = cpu_to_le32(parm_len);
-       pSMB->TotalDataCount  = 0;
-       pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
-                                         MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
-       pSMB->ParameterCount = pSMB->TotalParameterCount;
-       pSMB->DataCount  = pSMB->TotalDataCount;
-       temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
-                       (setup_count * 2) - 4 /* for rfc1001 length itself */;
-       pSMB->ParameterOffset = cpu_to_le32(temp_offset);
-       pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
-       pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
-       pSMB->SubCommand = cpu_to_le16(sub_command);
-       return 0;
-}
-
-static int
-validate_ntransact(char *buf, char **ppparm, char **ppdata,
-                  __u32 *pparmlen, __u32 *pdatalen)
-{
-       char *end_of_smb;
-       __u32 data_count, data_offset, parm_count, parm_offset;
-       struct smb_com_ntransact_rsp *pSMBr;
-
-       *pdatalen = 0;
-       *pparmlen = 0;
-
-       if (buf == NULL)
-               return -EINVAL;
-
-       pSMBr = (struct smb_com_ntransact_rsp *)buf;
-
-       /* ByteCount was converted from little endian in SendReceive */
-       end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
-                       (char *)&pSMBr->ByteCount;
-
-       data_offset = le32_to_cpu(pSMBr->DataOffset);
-       data_count = le32_to_cpu(pSMBr->DataCount);
-       parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
-       parm_count = le32_to_cpu(pSMBr->ParameterCount);
-
-       *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
-       *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
-
-       /* should we also check that parm and data areas do not overlap? */
-       if (*ppparm > end_of_smb) {
-               cFYI(1, ("parms start after end of smb"));
-               return -EINVAL;
-       } else if (parm_count + *ppparm > end_of_smb) {
-               cFYI(1, ("parm end after end of smb"));
-               return -EINVAL;
-       } else if (*ppdata > end_of_smb) {
-               cFYI(1, ("data starts after end of smb"));
-               return -EINVAL;
-       } else if (data_count + *ppdata > end_of_smb) {
-               cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
-                       *ppdata, data_count, (data_count + *ppdata),
-                       end_of_smb, pSMBr));
-               return -EINVAL;
-       } else if (parm_count + data_count > pSMBr->ByteCount) {
-               cFYI(1, ("parm count and data count larger than SMB"));
-               return -EINVAL;
-       }
-       *pdatalen = data_count;
-       *pparmlen = parm_count;
-       return 0;
-}
-#endif /* CIFS_EXPERIMENTAL */
-
 int
 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
                        const unsigned char *searchName,
@@ -2605,11 +2525,10 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
 {
        int rc = 0;
        int bytes_returned;
-       int name_len;
        struct smb_com_transaction_ioctl_req *pSMB;
        struct smb_com_transaction_ioctl_rsp *pSMBr;
 
-       cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
+       cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
        rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
        if (rc)
@@ -2638,63 +2557,59 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
+               cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
        } else {                /* decode response */
                __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
                __u32 data_count = le32_to_cpu(pSMBr->DataCount);
-               if ((pSMBr->ByteCount < 2) || (data_offset > 512))
+               if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
                /* BB also check enough total bytes returned */
                        rc = -EIO;      /* bad smb */
-               else {
-                       if (data_count && (data_count < 2048)) {
-                               char *end_of_smb = 2 /* sizeof byte count */ +
-                                               pSMBr->ByteCount +
-                                               (char *)&pSMBr->ByteCount;
+                       goto qreparse_out;
+               }
+               if (data_count && (data_count < 2048)) {
+                       char *end_of_smb = 2 /* sizeof byte count */ +
+                               pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
 
-                               struct reparse_data *reparse_buf =
+                       struct reparse_data *reparse_buf =
                                                (struct reparse_data *)
                                                ((char *)&pSMBr->hdr.Protocol
                                                                 + data_offset);
-                               if ((char *)reparse_buf >= end_of_smb) {
-                                       rc = -EIO;
-                                       goto qreparse_out;
-                               }
-                               if ((reparse_buf->LinkNamesBuf +
-                                       reparse_buf->TargetNameOffset +
-                                       reparse_buf->TargetNameLen) >
-                                               end_of_smb) {
-                                       cFYI(1, ("reparse buf beyond SMB"));
-                                       rc = -EIO;
-                                       goto qreparse_out;
-                               }
+                       if ((char *)reparse_buf >= end_of_smb) {
+                               rc = -EIO;
+                               goto qreparse_out;
+                       }
+                       if ((reparse_buf->LinkNamesBuf +
+                               reparse_buf->TargetNameOffset +
+                               reparse_buf->TargetNameLen) > end_of_smb) {
+                               cFYI(1, "reparse buf beyond SMB");
+                               rc = -EIO;
+                               goto qreparse_out;
+                       }
 
-                               if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
-                                       name_len = UniStrnlen((wchar_t *)
+                       if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
+                               cifs_from_ucs2(symlinkinfo, (__le16 *)
                                                (reparse_buf->LinkNamesBuf +
                                                reparse_buf->TargetNameOffset),
-                                               min(buflen/2,
-                                               reparse_buf->TargetNameLen / 2));
-                                       cifs_strfromUCS_le(symlinkinfo,
-                                               (__le16 *) (reparse_buf->LinkNamesBuf +
-                                               reparse_buf->TargetNameOffset),
-                                               name_len, nls_codepage);
-                               } else { /* ASCII names */
-                                       strncpy(symlinkinfo,
-                                               reparse_buf->LinkNamesBuf +
-                                               reparse_buf->TargetNameOffset,
-                                               min_t(const int, buflen,
-                                                  reparse_buf->TargetNameLen));
-                               }
-                       } else {
-                               rc = -EIO;
-                               cFYI(1, ("Invalid return data count on "
-                                        "get reparse info ioctl"));
+                                               buflen,
+                                               reparse_buf->TargetNameLen,
+                                               nls_codepage, 0);
+                       } else { /* ASCII names */
+                               strncpy(symlinkinfo,
+                                       reparse_buf->LinkNamesBuf +
+                                       reparse_buf->TargetNameOffset,
+                                       min_t(const int, buflen,
+                                          reparse_buf->TargetNameLen));
                        }
-                       symlinkinfo[buflen] = 0; /* just in case so the caller
-                                       does not go off the end of the buffer */
-                       cFYI(1, ("readlink result - %s", symlinkinfo));
+               } else {
+                       rc = -EIO;
+                       cFYI(1, "Invalid return data count on "
+                                "get reparse info ioctl");
                }
+               symlinkinfo[buflen] = 0; /* just in case so the caller
+                                       does not go off the end of the buffer */
+               cFYI(1, "readlink result - %s", symlinkinfo);
        }
+
 qreparse_out:
        cifs_buf_release(pSMB);
 
@@ -2703,6 +2618,7 @@ qreparse_out:
 
        return rc;
 }
+#endif /* CIFS_EXPERIMENTAL */
 
 #ifdef CONFIG_CIFS_POSIX
 
@@ -2714,7 +2630,7 @@ static void cifs_convert_ace(posix_acl_xattr_entry *ace,
        ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
        ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
        ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
-       /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
+       /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
 
        return;
 }
@@ -2740,8 +2656,8 @@ static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
                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));
+                       cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
+                               size_of_data_area, size);
                        return -EINVAL;
                }
        } else if (acl_type & ACL_TYPE_DEFAULT) {
@@ -2788,7 +2704,7 @@ static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
                cifs_ace->cifs_uid = cpu_to_le64(-1);
        } else
                cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
-       /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
+       /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
        return rc;
 }
 
@@ -2806,12 +2722,12 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
                return 0;
 
        count = posix_acl_xattr_count((size_t)buflen);
-       cFYI(1, ("setting acl with %d entries from buf of length %d and "
+       cFYI(1, "setting acl with %d entries from buf of length %d and "
                "version of %d",
-               count, buflen, le32_to_cpu(local_acl->a_version)));
+               count, buflen, le32_to_cpu(local_acl->a_version));
        if (le32_to_cpu(local_acl->a_version) != 2) {
-               cFYI(1, ("unknown POSIX ACL version %d",
-                    le32_to_cpu(local_acl->a_version)));
+               cFYI(1, "unknown POSIX ACL version %d",
+                    le32_to_cpu(local_acl->a_version));
                return 0;
        }
        cifs_acl->version = cpu_to_le16(1);
@@ -2820,7 +2736,7 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
        else if (acl_type == ACL_TYPE_DEFAULT)
                cifs_acl->default_entry_count = cpu_to_le16(count);
        else {
-               cFYI(1, ("unknown ACL type %d", acl_type));
+               cFYI(1, "unknown ACL type %d", acl_type);
                return 0;
        }
        for (i = 0; i < count; i++) {
@@ -2853,7 +2769,7 @@ CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
        int name_len;
        __u16 params, byte_count;
 
-       cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
+       cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
 
 queryAclRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -2905,7 +2821,7 @@ queryAclRetry:
                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        cifs_stats_inc(&tcon->num_acl_get);
        if (rc) {
-               cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
+               cFYI(1, "Send error in Query POSIX ACL = %d", rc);
        } else {
                /* decode response */
 
@@ -2942,7 +2858,7 @@ CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
        int bytes_returned = 0;
        __u16 params, byte_count, data_count, param_offset, offset;
 
-       cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
+       cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
 setAclRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -2997,7 +2913,7 @@ setAclRetry:
        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));
+               cFYI(1, "Set POSIX ACL returned %d", rc);
 
 setACLerrorExit:
        cifs_buf_release(pSMB);
@@ -3017,7 +2933,7 @@ CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
        int bytes_returned;
        __u16 params, byte_count;
 
-       cFYI(1, ("In GetExtAttr"));
+       cFYI(1, "In GetExtAttr");
        if (tcon == NULL)
                return -ENODEV;
 
@@ -3056,7 +2972,7 @@ GetExtAttrRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cFYI(1, ("error %d in GetExtAttr", rc));
+               cFYI(1, "error %d in GetExtAttr", rc);
        } else {
                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -3071,7 +2987,7 @@ GetExtAttrRetry:
                        struct file_chattr_info *pfinfo;
                        /* BB Do we need a cast or hash here ? */
                        if (count != 16) {
-                               cFYI(1, ("Illegal size ret in GetExtAttr"));
+                               cFYI(1, "Illegal size ret in GetExtAttr");
                                rc = -EIO;
                                goto GetExtAttrOut;
                        }
@@ -3090,7 +3006,97 @@ GetExtAttrOut:
 
 #endif /* CONFIG_POSIX */
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
+#ifdef CONFIG_CIFS_ACL
+/*
+ * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
+ * all NT TRANSACTS that we init here have total parm and data under about 400
+ * bytes (to fit in small cifs buffer size), which is the case so far, it
+ * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
+ * returned setup area) and MaxParameterCount (returned parms size) must be set
+ * by caller
+ */
+static int
+smb_init_nttransact(const __u16 sub_command, const int setup_count,
+                  const int parm_len, struct cifsTconInfo *tcon,
+                  void **ret_buf)
+{
+       int rc;
+       __u32 temp_offset;
+       struct smb_com_ntransact_req *pSMB;
+
+       rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
+                               (void **)&pSMB);
+       if (rc)
+               return rc;
+       *ret_buf = (void *)pSMB;
+       pSMB->Reserved = 0;
+       pSMB->TotalParameterCount = cpu_to_le32(parm_len);
+       pSMB->TotalDataCount  = 0;
+       pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
+                                         MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+       pSMB->ParameterCount = pSMB->TotalParameterCount;
+       pSMB->DataCount  = pSMB->TotalDataCount;
+       temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
+                       (setup_count * 2) - 4 /* for rfc1001 length itself */;
+       pSMB->ParameterOffset = cpu_to_le32(temp_offset);
+       pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
+       pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
+       pSMB->SubCommand = cpu_to_le16(sub_command);
+       return 0;
+}
+
+static int
+validate_ntransact(char *buf, char **ppparm, char **ppdata,
+                  __u32 *pparmlen, __u32 *pdatalen)
+{
+       char *end_of_smb;
+       __u32 data_count, data_offset, parm_count, parm_offset;
+       struct smb_com_ntransact_rsp *pSMBr;
+
+       *pdatalen = 0;
+       *pparmlen = 0;
+
+       if (buf == NULL)
+               return -EINVAL;
+
+       pSMBr = (struct smb_com_ntransact_rsp *)buf;
+
+       /* ByteCount was converted from little endian in SendReceive */
+       end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
+                       (char *)&pSMBr->ByteCount;
+
+       data_offset = le32_to_cpu(pSMBr->DataOffset);
+       data_count = le32_to_cpu(pSMBr->DataCount);
+       parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
+       parm_count = le32_to_cpu(pSMBr->ParameterCount);
+
+       *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
+       *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
+
+       /* should we also check that parm and data areas do not overlap? */
+       if (*ppparm > end_of_smb) {
+               cFYI(1, "parms start after end of smb");
+               return -EINVAL;
+       } else if (parm_count + *ppparm > end_of_smb) {
+               cFYI(1, "parm end after end of smb");
+               return -EINVAL;
+       } else if (*ppdata > end_of_smb) {
+               cFYI(1, "data starts after end of smb");
+               return -EINVAL;
+       } else if (data_count + *ppdata > end_of_smb) {
+               cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
+                       *ppdata, data_count, (data_count + *ppdata),
+                       end_of_smb, pSMBr);
+               return -EINVAL;
+       } else if (parm_count + data_count > pSMBr->ByteCount) {
+               cFYI(1, "parm count and data count larger than SMB");
+               return -EINVAL;
+       }
+       *pdatalen = data_count;
+       *pparmlen = parm_count;
+       return 0;
+}
+
 /* Get Security Descriptor (by handle) from remote server for a file or dir */
 int
 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
@@ -3101,7 +3107,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
        QUERY_SEC_DESC_REQ *pSMB;
        struct kvec iov[1];
 
-       cFYI(1, ("GetCifsACL"));
+       cFYI(1, "GetCifsACL");
 
        *pbuflen = 0;
        *acl_inf = NULL;
@@ -3123,10 +3129,10 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
        iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
 
        rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
-                        CIFS_STD_OP);
+                        0);
        cifs_stats_inc(&tcon->num_acl_get);
        if (rc) {
-               cFYI(1, ("Send error in QuerySecDesc = %d", rc));
+               cFYI(1, "Send error in QuerySecDesc = %d", rc);
        } else {                /* decode response */
                __le32 *parm;
                __u32 parm_len;
@@ -3141,7 +3147,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
                        goto qsec_out;
                pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
 
-               cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
+               cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
 
                if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
                        rc = -EIO;      /* bad smb */
@@ -3153,8 +3159,8 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
 
                acl_len = le32_to_cpu(*parm);
                if (acl_len != *pbuflen) {
-                       cERROR(1, ("acl length %d does not match %d",
-                                  acl_len, *pbuflen));
+                       cERROR(1, "acl length %d does not match %d",
+                                  acl_len, *pbuflen);
                        if (*pbuflen > acl_len)
                                *pbuflen = acl_len;
                }
@@ -3163,7 +3169,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
                   header followed by the smallest SID */
                if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
                    (*pbuflen >= 64 * 1024)) {
-                       cERROR(1, ("bad acl length %d", *pbuflen));
+                       cERROR(1, "bad acl length %d", *pbuflen);
                        rc = -EINVAL;
                        *pbuflen = 0;
                } else {
@@ -3237,9 +3243,9 @@ setCifsAclRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 
-       cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
+       cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
        if (rc)
-               cFYI(1, ("Set CIFS ACL returned %d", rc));
+               cFYI(1, "Set CIFS ACL returned %d", rc);
        cifs_buf_release(pSMB);
 
        if (rc == -EAGAIN)
@@ -3248,7 +3254,7 @@ setCifsAclRetry:
        return (rc);
 }
 
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
+#endif /* CONFIG_CIFS_ACL */
 
 /* Legacy Query Path Information call for lookup to old servers such
    as Win9x/WinME */
@@ -3263,7 +3269,7 @@ int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
        int bytes_returned;
        int name_len;
 
-       cFYI(1, ("In SMBQPath path %s", searchName));
+       cFYI(1, "In SMBQPath path %s", searchName);
 QInfRetry:
        rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -3289,7 +3295,7 @@ QInfRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cFYI(1, ("Send error in QueryInfo = %d", rc));
+               cFYI(1, "Send error in QueryInfo = %d", rc);
        } else if (pFinfo) {
                struct timespec ts;
                __u32 time = le32_to_cpu(pSMBr->last_write_time);
@@ -3319,8 +3325,72 @@ QInfRetry:
        return rc;
 }
 
+int
+CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
+                u16 netfid, FILE_ALL_INFO *pFindData)
+{
+       struct smb_t2_qfi_req *pSMB = NULL;
+       struct smb_t2_qfi_rsp *pSMBr = NULL;
+       int rc = 0;
+       int bytes_returned;
+       __u16 params, byte_count;
+
+QFileInfoRetry:
+       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+                     (void **) &pSMBr);
+       if (rc)
+               return rc;
+
+       params = 2 /* level */ + 2 /* fid */;
+       pSMB->t2.TotalDataCount = 0;
+       pSMB->t2.MaxParameterCount = cpu_to_le16(4);
+       /* BB find exact max data count below from sess structure BB */
+       pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
+       pSMB->t2.MaxSetupCount = 0;
+       pSMB->t2.Reserved = 0;
+       pSMB->t2.Flags = 0;
+       pSMB->t2.Timeout = 0;
+       pSMB->t2.Reserved2 = 0;
+       pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
+                                              Fid) - 4);
+       pSMB->t2.DataCount = 0;
+       pSMB->t2.DataOffset = 0;
+       pSMB->t2.SetupCount = 1;
+       pSMB->t2.Reserved3 = 0;
+       pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->t2.TotalParameterCount = cpu_to_le16(params);
+       pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
+       pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
+       pSMB->Pad = 0;
+       pSMB->Fid = netfid;
+       pSMB->hdr.smb_buf_length += 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 */
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
+               if (rc) /* BB add auto retry on EOPNOTSUPP? */
+                       rc = -EIO;
+               else if (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 +
+                              data_offset, sizeof(FILE_ALL_INFO));
+               } else
+                   rc = -ENOMEM;
+       }
+       cifs_buf_release(pSMB);
+       if (rc == -EAGAIN)
+               goto QFileInfoRetry;
 
+       return rc;
+}
 
 int
 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
@@ -3337,7 +3407,7 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
        int name_len;
        __u16 params, byte_count;
 
-/* cFYI(1, ("In QPathInfo path %s", searchName)); */
+/* cFYI(1, "In QPathInfo path %s", searchName); */
 QPathInfoRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -3387,7 +3457,7 @@ QPathInfoRetry:
        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));
+               cFYI(1, "Send error in QPathInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -3424,42 +3494,111 @@ QPathInfoRetry:
 }
 
 int
-CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
-                    const unsigned char *searchName,
-                    FILE_UNIX_BASIC_INFO *pFindData,
-                    const struct nls_table *nls_codepage, int remap)
+CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
+                u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
 {
-/* SMB_QUERY_FILE_UNIX_BASIC */
-       TRANSACTION2_QPI_REQ *pSMB = NULL;
-       TRANSACTION2_QPI_RSP *pSMBr = NULL;
+       struct smb_t2_qfi_req *pSMB = NULL;
+       struct smb_t2_qfi_rsp *pSMBr = NULL;
        int rc = 0;
-       int bytes_returned = 0;
-       int name_len;
+       int bytes_returned;
        __u16 params, byte_count;
 
-       cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
-UnixQPathInfoRetry:
+UnixQFileInfoRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
        if (rc)
                return rc;
 
-       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-                                 PATH_MAX, nls_codepage, remap);
-               name_len++;     /* trailing null */
-               name_len *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, searchName, name_len);
-       }
-
-       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 */
+       params = 2 /* level */ + 2 /* fid */;
+       pSMB->t2.TotalDataCount = 0;
+       pSMB->t2.MaxParameterCount = cpu_to_le16(4);
+       /* BB find exact max data count below from sess structure BB */
+       pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
+       pSMB->t2.MaxSetupCount = 0;
+       pSMB->t2.Reserved = 0;
+       pSMB->t2.Flags = 0;
+       pSMB->t2.Timeout = 0;
+       pSMB->t2.Reserved2 = 0;
+       pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
+                                              Fid) - 4);
+       pSMB->t2.DataCount = 0;
+       pSMB->t2.DataOffset = 0;
+       pSMB->t2.SetupCount = 1;
+       pSMB->t2.Reserved3 = 0;
+       pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->t2.TotalParameterCount = cpu_to_le16(params);
+       pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
+       pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
+       pSMB->Pad = 0;
+       pSMB->Fid = netfid;
+       pSMB->hdr.smb_buf_length += 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 */
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+               if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
+                       cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
+                                  "Unix Extensions can be disabled on mount "
+                                  "by specifying the nosfu mount option.");
+                       rc = -EIO;      /* bad smb */
+               } else {
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+                       memcpy((char *) pFindData,
+                              (char *) &pSMBr->hdr.Protocol +
+                              data_offset,
+                              sizeof(FILE_UNIX_BASIC_INFO));
+               }
+       }
+
+       cifs_buf_release(pSMB);
+       if (rc == -EAGAIN)
+               goto UnixQFileInfoRetry;
+
+       return rc;
+}
+
+int
+CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
+                    const unsigned char *searchName,
+                    FILE_UNIX_BASIC_INFO *pFindData,
+                    const struct nls_table *nls_codepage, int remap)
+{
+/* SMB_QUERY_FILE_UNIX_BASIC */
+       TRANSACTION2_QPI_REQ *pSMB = NULL;
+       TRANSACTION2_QPI_RSP *pSMBr = NULL;
+       int rc = 0;
+       int bytes_returned = 0;
+       int name_len;
+       __u16 params, byte_count;
+
+       cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
+UnixQPathInfoRetry:
+       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+                     (void **) &pSMBr);
+       if (rc)
+               return rc;
+
+       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+               name_len =
+                   cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
+                                 PATH_MAX, nls_codepage, remap);
+               name_len++;     /* trailing null */
+               name_len *= 2;
+       } else {        /* BB improve the check for buffer overruns BB */
+               name_len = strnlen(searchName, PATH_MAX);
+               name_len++;     /* trailing null */
+               strncpy(pSMB->FileName, searchName, name_len);
+       }
+
+       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 */
        pSMB->MaxDataCount = cpu_to_le16(4000);
        pSMB->MaxSetupCount = 0;
        pSMB->Reserved = 0;
@@ -3484,14 +3623,14 @@ UnixQPathInfoRetry:
        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));
+               cFYI(1, "Send error in QPathInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
                if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
-                       cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
+                       cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
                                   "Unix Extensions can be disabled on mount "
-                                  "by specifying the nosfu mount option."));
+                                  "by specifying the nosfu mount option.");
                        rc = -EIO;      /* bad smb */
                } else {
                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
@@ -3525,7 +3664,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
        int name_len;
        __u16 params, byte_count;
 
-       cFYI(1, ("In FindFirst for %s", searchName));
+       cFYI(1, "In FindFirst for %s", searchName);
 
 findFirstRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -3602,7 +3741,7 @@ findFirstRetry:
        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));
+               cFYI(1, "Error in FindFirst = %d", rc);
 
                cifs_buf_release(pSMB);
 
@@ -3614,6 +3753,8 @@ findFirstRetry:
                /* BB remember to free buffer if error BB */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
                if (rc == 0) {
+                       unsigned int lnoff;
+
                        if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
                                psrch_inf->unicode = true;
                        else
@@ -3636,6 +3777,17 @@ findFirstRetry:
                                        le16_to_cpu(parms->SearchCount);
                        psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
                                psrch_inf->entries_in_buffer;
+                       lnoff = le16_to_cpu(parms->LastNameOffset);
+                       if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
+                             lnoff) {
+                               cERROR(1, "ignoring corrupt resume name");
+                               psrch_inf->last_entry = NULL;
+                               return rc;
+                       }
+
+                       psrch_inf->last_entry = psrch_inf->srch_entries_start +
+                                                       lnoff;
+
                        *pnetfid = parms->SearchHandle;
                } else {
                        cifs_buf_release(pSMB);
@@ -3653,10 +3805,11 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
        T2_FNEXT_RSP_PARMS *parms;
        char *response_data;
        int rc = 0;
-       int bytes_returned, name_len;
+       int bytes_returned;
+       unsigned int name_len;
        __u16 params, byte_count;
 
-       cFYI(1, ("In FindNext"));
+       cFYI(1, "In FindNext");
 
        if (psrch_inf->endOfSearch)
                return -ENOENT;
@@ -3720,11 +3873,13 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
                        cifs_buf_release(pSMB);
                        rc = 0; /* search probably was closed at end of search*/
                } else
-                       cFYI(1, ("FindNext returned = %d", rc));
+                       cFYI(1, "FindNext returned = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
                if (rc == 0) {
+                       unsigned int lnoff;
+
                        /* BB fixme add lock for file (srch_info) struct here */
                        if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
                                psrch_inf->unicode = true;
@@ -3751,8 +3906,18 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
                                                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)); */
+                       lnoff = le16_to_cpu(parms->LastNameOffset);
+                       if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
+                             lnoff) {
+                               cERROR(1, "ignoring corrupt resume name");
+                               psrch_inf->last_entry = NULL;
+                               return rc;
+                       } else
+                               psrch_inf->last_entry =
+                                       psrch_inf->srch_entries_start + lnoff;
+
+/*  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 */
                }
@@ -3777,7 +3942,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
        int rc = 0;
        FINDCLOSE_REQ *pSMB = NULL;
 
-       cFYI(1, ("In CIFSSMBFindClose"));
+       cFYI(1, "In CIFSSMBFindClose");
        rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
 
        /* no sense returning error if session restarted
@@ -3791,7 +3956,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
        pSMB->ByteCount = 0;
        rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
        if (rc)
-               cERROR(1, ("Send error in FindClose = %d", rc));
+               cERROR(1, "Send error in FindClose = %d", rc);
 
        cifs_stats_inc(&tcon->num_fclose);
 
@@ -3814,7 +3979,7 @@ CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
        int name_len, bytes_returned;
        __u16 params, byte_count;
 
-       cFYI(1, ("In GetSrvInodeNum for %s", searchName));
+       cFYI(1, "In GetSrvInodeNum for %s", searchName);
        if (tcon == NULL)
                return -ENODEV;
 
@@ -3864,7 +4029,7 @@ GetInodeNumberRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cFYI(1, ("error %d in QueryInternalInfo", rc));
+               cFYI(1, "error %d in QueryInternalInfo", rc);
        } else {
                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -3879,13 +4044,13 @@ GetInodeNumberRetry:
                        struct file_internal_info *pfinfo;
                        /* BB Do we need a cast or hash here ? */
                        if (count < 8) {
-                               cFYI(1, ("Illegal size ret in QryIntrnlInf"));
+                               cFYI(1, "Illegal size ret in QryIntrnlInf");
                                rc = -EIO;
                                goto GetInodeNumOut;
                        }
                        pfinfo = (struct file_internal_info *)
                                (data_offset + (char *) &pSMBr->hdr.Protocol);
-                       *inode_number = pfinfo->UniqueId;
+                       *inode_number = le64_to_cpu(pfinfo->UniqueId);
                }
        }
 GetInodeNumOut:
@@ -3905,7 +4070,8 @@ static int
 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
                unsigned int *num_of_nodes,
                struct dfs_info3_param **target_nodes,
-               const struct nls_table *nls_codepage)
+               const struct nls_table *nls_codepage, int remap,
+               const char *searchName)
 {
        int i, rc = 0;
        char *data_end;
@@ -3919,16 +4085,16 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
        *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
 
        if (*num_of_nodes < 1) {
-               cERROR(1, ("num_referrals: must be at least > 0,"
-                       "but we get num_referrals = %d\n", *num_of_nodes));
+               cERROR(1, "num_referrals: must be at least > 0,"
+                       "but we get num_referrals = %d\n", *num_of_nodes);
                rc = -EINVAL;
                goto parse_DFS_referrals_exit;
        }
 
        ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
        if (ref->VersionNumber != cpu_to_le16(3)) {
-               cERROR(1, ("Referrals of V%d version are not supported,"
-                       "should be V3", le16_to_cpu(ref->VersionNumber)));
+               cERROR(1, "Referrals of V%d version are not supported,"
+                       "should be V3", le16_to_cpu(ref->VersionNumber));
                rc = -EINVAL;
                goto parse_DFS_referrals_exit;
        }
@@ -3937,46 +4103,61 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
        data_end = (char *)(&(pSMBr->PathConsumed)) +
                                le16_to_cpu(pSMBr->t2.DataCount);
 
-       cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
+       cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
                        *num_of_nodes,
-                       le16_to_cpu(pSMBr->DFSFlags)));
+                       le32_to_cpu(pSMBr->DFSFlags));
 
        *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
                        *num_of_nodes, GFP_KERNEL);
        if (*target_nodes == NULL) {
-               cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
+               cERROR(1, "Failed to allocate buffer for target_nodes\n");
                rc = -ENOMEM;
                goto parse_DFS_referrals_exit;
        }
 
-       /* collect neccessary data from referrals */
+       /* collect necessary data from referrals */
        for (i = 0; i < *num_of_nodes; i++) {
                char *temp;
                int max_len;
                struct dfs_info3_param *node = (*target_nodes)+i;
 
-               node->flags = le16_to_cpu(pSMBr->DFSFlags);
-               node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
+               node->flags = le32_to_cpu(pSMBr->DFSFlags);
+               if (is_unicode) {
+                       __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
+                                               GFP_KERNEL);
+                       if (tmp == NULL) {
+                               rc = -ENOMEM;
+                               goto parse_DFS_referrals_exit;
+                       }
+                       cifsConvertToUCS((__le16 *) tmp, searchName,
+                                       PATH_MAX, nls_codepage, remap);
+                       node->path_consumed = cifs_ucs2_bytes(tmp,
+                                       le16_to_cpu(pSMBr->PathConsumed),
+                                       nls_codepage);
+                       kfree(tmp);
+               } else
+                       node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
+
                node->server_type = le16_to_cpu(ref->ServerType);
                node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
 
                /* copy DfsPath */
                temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
                max_len = data_end - temp;
-               rc = cifs_strncpy_to_host(&(node->path_name), temp,
-                                       max_len, is_unicode, nls_codepage);
-               if (rc)
+               node->path_name = cifs_strndup_from_ucs(temp, max_len,
+                                                     is_unicode, nls_codepage);
+               if (!node->path_name) {
+                       rc = -ENOMEM;
                        goto parse_DFS_referrals_exit;
+               }
 
                /* copy link target UNC */
                temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
                max_len = data_end - temp;
-               rc = cifs_strncpy_to_host(&(node->node_name), temp,
-                                       max_len, is_unicode, nls_codepage);
-               if (rc)
-                       goto parse_DFS_referrals_exit;
-
-               ref += le16_to_cpu(ref->Size);
+               node->node_name = cifs_strndup_from_ucs(temp, max_len,
+                                                     is_unicode, nls_codepage);
+               if (!node->node_name)
+                       rc = -ENOMEM;
        }
 
 parse_DFS_referrals_exit:
@@ -4005,7 +4186,7 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
        *num_of_nodes = 0;
        *target_nodes = NULL;
 
-       cFYI(1, ("In GetDFSRefer the path %s", searchName));
+       cFYI(1, "In GetDFSRefer the path %s", searchName);
        if (ses == NULL)
                return -ENODEV;
 getDFSRetry:
@@ -4072,7 +4253,7 @@ getDFSRetry:
        rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cFYI(1, ("Send error in GetDFSRefer = %d", rc));
+               cFYI(1, "Send error in GetDFSRefer = %d", rc);
                goto GetDFSRefExit;
        }
        rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -4083,13 +4264,14 @@ getDFSRetry:
                goto GetDFSRefExit;
        }
 
-       cFYI(1, ("Decoding GetDFSRefer response BCC: %d  Offset %d",
+       cFYI(1, "Decoding GetDFSRefer response BCC: %d  Offset %d",
                                pSMBr->ByteCount,
-                               le16_to_cpu(pSMBr->t2.DataOffset)));
+                               le16_to_cpu(pSMBr->t2.DataOffset));
 
        /* parse returned result into more usable form */
        rc = parse_DFS_referrals(pSMBr, num_of_nodes,
-                                target_nodes, nls_codepage);
+                                target_nodes, nls_codepage, remap,
+                                searchName);
 
 GetDFSRefExit:
        cifs_buf_release(pSMB);
@@ -4112,7 +4294,7 @@ SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
        int bytes_returned = 0;
        __u16 params, byte_count;
 
-       cFYI(1, ("OldQFSInfo"));
+       cFYI(1, "OldQFSInfo");
 oldQFSInfoRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                (void **) &pSMBr);
@@ -4145,7 +4327,7 @@ oldQFSInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cFYI(1, ("Send error in QFSInfo = %d", rc));
+               cFYI(1, "Send error in QFSInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4153,8 +4335,8 @@ oldQFSInfoRetry:
                        rc = -EIO;      /* bad smb */
                else {
                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
-                       cFYI(1, ("qfsinf resp BCC: %d  Offset %d",
-                                pSMBr->ByteCount, data_offset));
+                       cFYI(1, "qfsinf resp BCC: %d  Offset %d",
+                                pSMBr->ByteCount, data_offset);
 
                        response_data = (FILE_SYSTEM_ALLOC_INFO *)
                                (((char *) &pSMBr->hdr.Protocol) + data_offset);
@@ -4166,11 +4348,10 @@ oldQFSInfoRetry:
                               le32_to_cpu(response_data->TotalAllocationUnits);
                        FSData->f_bfree = FSData->f_bavail =
                                le32_to_cpu(response_data->FreeAllocationUnits);
-                       cFYI(1,
-                            ("Blocks: %lld  Free: %lld Block size %ld",
-                             (unsigned long long)FSData->f_blocks,
-                             (unsigned long long)FSData->f_bfree,
-                             FSData->f_bsize));
+                       cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
+                            (unsigned long long)FSData->f_blocks,
+                            (unsigned long long)FSData->f_bfree,
+                            FSData->f_bsize);
                }
        }
        cifs_buf_release(pSMB);
@@ -4192,7 +4373,7 @@ CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
        int bytes_returned = 0;
        __u16 params, byte_count;
 
-       cFYI(1, ("In QFSInfo"));
+       cFYI(1, "In QFSInfo");
 QFSInfoRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -4225,7 +4406,7 @@ QFSInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cFYI(1, ("Send error in QFSInfo = %d", rc));
+               cFYI(1, "Send error in QFSInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4246,11 +4427,10 @@ QFSInfoRetry:
                            le64_to_cpu(response_data->TotalAllocationUnits);
                        FSData->f_bfree = FSData->f_bavail =
                            le64_to_cpu(response_data->FreeAllocationUnits);
-                       cFYI(1,
-                            ("Blocks: %lld  Free: %lld Block size %ld",
-                             (unsigned long long)FSData->f_blocks,
-                             (unsigned long long)FSData->f_bfree,
-                             FSData->f_bsize));
+                       cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
+                            (unsigned long long)FSData->f_blocks,
+                            (unsigned long long)FSData->f_bfree,
+                            FSData->f_bsize);
                }
        }
        cifs_buf_release(pSMB);
@@ -4272,7 +4452,7 @@ CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
        int bytes_returned = 0;
        __u16 params, byte_count;
 
-       cFYI(1, ("In QFSAttributeInfo"));
+       cFYI(1, "In QFSAttributeInfo");
 QFSAttributeRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -4306,7 +4486,7 @@ QFSAttributeRetry:
        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));
+               cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4342,7 +4522,7 @@ CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
        int bytes_returned = 0;
        __u16 params, byte_count;
 
-       cFYI(1, ("In QFSDeviceInfo"));
+       cFYI(1, "In QFSDeviceInfo");
 QFSDeviceRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -4377,7 +4557,7 @@ QFSDeviceRetry:
        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));
+               cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4412,10 +4592,10 @@ CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
        int bytes_returned = 0;
        __u16 params, byte_count;
 
-       cFYI(1, ("In QFSUnixInfo"));
+       cFYI(1, "In QFSUnixInfo");
 QFSUnixRetry:
-       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
+       rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
+                                  (void **) &pSMB, (void **) &pSMBr);
        if (rc)
                return rc;
 
@@ -4446,7 +4626,7 @@ QFSUnixRetry:
        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));
+               cERROR(1, "Send error in QFSUnixInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4481,11 +4661,11 @@ CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
        int bytes_returned = 0;
        __u16 params, param_offset, offset, byte_count;
 
-       cFYI(1, ("In SETFSUnixInfo"));
+       cFYI(1, "In SETFSUnixInfo");
 SETFSUnixRetry:
        /* BB switch to small buf init to save memory */
-       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
+       rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
+                                       (void **) &pSMB, (void **) &pSMBr);
        if (rc)
                return rc;
 
@@ -4529,7 +4709,7 @@ SETFSUnixRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
+               cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
                if (rc)
@@ -4557,7 +4737,7 @@ CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
        int bytes_returned = 0;
        __u16 params, byte_count;
 
-       cFYI(1, ("In QFSPosixInfo"));
+       cFYI(1, "In QFSPosixInfo");
 QFSPosixRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -4591,7 +4771,7 @@ QFSPosixRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
+               cFYI(1, "Send error in QFSUnixInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4651,7 +4831,7 @@ CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
        int bytes_returned = 0;
        __u16 params, byte_count, data_count, param_offset, offset;
 
-       cFYI(1, ("In SetEOF"));
+       cFYI(1, "In SetEOF");
 SetEOFRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -4717,7 +4897,7 @@ SetEOFRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc)
-               cFYI(1, ("SetPathInfo (file size) returned %d", rc));
+               cFYI(1, "SetPathInfo (file size) returned %d", rc);
 
        cifs_buf_release(pSMB);
 
@@ -4732,13 +4912,12 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
                   __u16 fid, __u32 pid_of_opener, bool SetAllocation)
 {
        struct smb_com_transaction2_sfi_req *pSMB  = NULL;
-       char *data_offset;
        struct file_end_of_file_info *parm_data;
        int rc = 0;
        __u16 params, param_offset, offset, byte_count, count;
 
-       cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
-                       (long long)size));
+       cFYI(1, "SetFileSize (via SetFileInfo) %lld",
+                       (long long)size);
        rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
 
        if (rc)
@@ -4756,8 +4935,6 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
        param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
        offset = param_offset + params;
 
-       data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
-
        count = sizeof(struct file_end_of_file_info);
        pSMB->MaxParameterCount = cpu_to_le16(2);
        /* BB find exact max SMB PDU from sess structure BB */
@@ -4797,9 +4974,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
        pSMB->ByteCount = cpu_to_le16(byte_count);
        rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
        if (rc) {
-               cFYI(1,
-                    ("Send error in SetFileInfo (SetFileSize) = %d",
-                     rc));
+               cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
        }
 
        /* Note: On -EAGAIN error only caller can retry on handle based calls
@@ -4823,7 +4998,7 @@ CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
        int rc = 0;
        __u16 params, param_offset, offset, byte_count, count;
 
-       cFYI(1, ("Set Times (via SetFileInfo)"));
+       cFYI(1, "Set Times (via SetFileInfo)");
        rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
 
        if (rc)
@@ -4868,7 +5043,7 @@ CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
        memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
        rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
        if (rc)
-               cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
+               cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
 
        /* Note: On -EAGAIN error only caller can retry on handle based calls
                since file handle passed in no longer valid */
@@ -4876,6 +5051,61 @@ CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
        return rc;
 }
 
+int
+CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
+                         bool delete_file, __u16 fid, __u32 pid_of_opener)
+{
+       struct smb_com_transaction2_sfi_req *pSMB  = NULL;
+       char *data_offset;
+       int rc = 0;
+       __u16 params, param_offset, offset, byte_count, count;
+
+       cFYI(1, "Set File Disposition (via SetFileInfo)");
+       rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
+
+       if (rc)
+               return rc;
+
+       pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+       pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
+
+       params = 6;
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+       pSMB->Flags = 0;
+       pSMB->Timeout = 0;
+       pSMB->Reserved2 = 0;
+       param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+       offset = param_offset + params;
+
+       data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+
+       count = 1;
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+       /* BB find max SMB PDU from sess */
+       pSMB->MaxDataCount = cpu_to_le16(1000);
+       pSMB->SetupCount = 1;
+       pSMB->Reserved3 = 0;
+       pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+       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(param_offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
+       pSMB->Fid = fid;
+       pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
+       pSMB->Reserved4 = 0;
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+       *data_offset = delete_file ? 1 : 0;
+       rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
+       if (rc)
+               cFYI(1, "Send error in SetFileDisposition = %d", rc);
+
+       return rc;
+}
 
 int
 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
@@ -4890,7 +5120,7 @@ CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
        char *data_offset;
        __u16 params, param_offset, offset, byte_count, count;
 
-       cFYI(1, ("In SetTimes"));
+       cFYI(1, "In SetTimes");
 
 SetTimesRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -4946,7 +5176,7 @@ SetTimesRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc)
-               cFYI(1, ("SetPathInfo (times) returned %d", rc));
+               cFYI(1, "SetPathInfo (times) returned %d", rc);
 
        cifs_buf_release(pSMB);
 
@@ -4971,7 +5201,7 @@ CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
        int bytes_returned;
        int name_len;
 
-       cFYI(1, ("In SetAttrLegacy"));
+       cFYI(1, "In SetAttrLegacy");
 
 SetAttrLgcyRetry:
        rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
@@ -4997,7 +5227,7 @@ SetAttrLgcyRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc)
-               cFYI(1, ("Error in LegacySetAttr = %d", rc));
+               cFYI(1, "Error in LegacySetAttr = %d", rc);
 
        cifs_buf_release(pSMB);
 
@@ -5008,10 +5238,114 @@ SetAttrLgcyRetry:
 }
 #endif /* temporarily unneeded SetAttr legacy function */
 
+static void
+cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
+                       const struct cifs_unix_set_info_args *args)
+{
+       u64 mode = args->mode;
+
+       /*
+        * Samba server ignores set of file size to zero due to bugs in some
+        * older clients, but we should be precise - we use SetFileSize to
+        * set file size and do not want to truncate file size to zero
+        * accidently as happened on one Samba server beta by putting
+        * zero instead of -1 here
+        */
+       data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
+       data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
+       data_offset->LastStatusChange = cpu_to_le64(args->ctime);
+       data_offset->LastAccessTime = cpu_to_le64(args->atime);
+       data_offset->LastModificationTime = cpu_to_le64(args->mtime);
+       data_offset->Uid = cpu_to_le64(args->uid);
+       data_offset->Gid = cpu_to_le64(args->gid);
+       /* better to leave device as zero when it is  */
+       data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
+       data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
+       data_offset->Permissions = cpu_to_le64(mode);
+
+       if (S_ISREG(mode))
+               data_offset->Type = cpu_to_le32(UNIX_FILE);
+       else if (S_ISDIR(mode))
+               data_offset->Type = cpu_to_le32(UNIX_DIR);
+       else if (S_ISLNK(mode))
+               data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
+       else if (S_ISCHR(mode))
+               data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
+       else if (S_ISBLK(mode))
+               data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
+       else if (S_ISFIFO(mode))
+               data_offset->Type = cpu_to_le32(UNIX_FIFO);
+       else if (S_ISSOCK(mode))
+               data_offset->Type = cpu_to_le32(UNIX_SOCKET);
+}
+
 int
-CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
-                  const struct cifs_unix_set_info_args *args,
-                  const struct nls_table *nls_codepage, int remap)
+CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
+                      const struct cifs_unix_set_info_args *args,
+                      u16 fid, u32 pid_of_opener)
+{
+       struct smb_com_transaction2_sfi_req *pSMB  = NULL;
+       FILE_UNIX_BASIC_INFO *data_offset;
+       int rc = 0;
+       u16 params, param_offset, offset, byte_count, count;
+
+       cFYI(1, "Set Unix Info (via SetFileInfo)");
+       rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
+
+       if (rc)
+               return rc;
+
+       pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+       pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
+
+       params = 6;
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+       pSMB->Flags = 0;
+       pSMB->Timeout = 0;
+       pSMB->Reserved2 = 0;
+       param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+       offset = param_offset + params;
+
+       data_offset = (FILE_UNIX_BASIC_INFO *)
+                               ((char *)(&pSMB->hdr.Protocol) + offset);
+       count = sizeof(FILE_UNIX_BASIC_INFO);
+
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+       /* BB find max SMB PDU from sess */
+       pSMB->MaxDataCount = cpu_to_le16(1000);
+       pSMB->SetupCount = 1;
+       pSMB->Reserved3 = 0;
+       pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+       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(param_offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
+       pSMB->Fid = fid;
+       pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
+       pSMB->Reserved4 = 0;
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+
+       cifs_fill_unix_set_info(data_offset, args);
+
+       rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
+       if (rc)
+               cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
+
+       /* Note: On -EAGAIN error only caller can retry on handle based calls
+               since file handle passed in no longer valid */
+
+       return rc;
+}
+
+int
+CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
+                      const struct cifs_unix_set_info_args *args,
+                      const struct nls_table *nls_codepage, int remap)
 {
        TRANSACTION2_SPI_REQ *pSMB = NULL;
        TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -5020,9 +5354,8 @@ CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
        int bytes_returned = 0;
        FILE_UNIX_BASIC_INFO *data_offset;
        __u16 params, param_offset, offset, count, byte_count;
-       __u64 mode = args->mode;
 
-       cFYI(1, ("In SetUID/GID/Mode"));
+       cFYI(1, "In SetUID/GID/Mode");
 setPermsRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -5071,44 +5404,14 @@ setPermsRetry:
        pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
        pSMB->Reserved4 = 0;
        pSMB->hdr.smb_buf_length += byte_count;
-       /* Samba server ignores set of file size to zero due to bugs in some
-       older clients, but we should be precise - we use SetFileSize to
-       set file size and do not want to truncate file size to zero
-       accidently as happened on one Samba server beta by putting
-       zero instead of -1 here */
-       data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
-       data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
-       data_offset->LastStatusChange = cpu_to_le64(args->ctime);
-       data_offset->LastAccessTime = cpu_to_le64(args->atime);
-       data_offset->LastModificationTime = cpu_to_le64(args->mtime);
-       data_offset->Uid = cpu_to_le64(args->uid);
-       data_offset->Gid = cpu_to_le64(args->gid);
-       /* better to leave device as zero when it is  */
-       data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
-       data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
-       data_offset->Permissions = cpu_to_le64(mode);
-
-       if (S_ISREG(mode))
-               data_offset->Type = cpu_to_le32(UNIX_FILE);
-       else if (S_ISDIR(mode))
-               data_offset->Type = cpu_to_le32(UNIX_DIR);
-       else if (S_ISLNK(mode))
-               data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
-       else if (S_ISCHR(mode))
-               data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
-       else if (S_ISBLK(mode))
-               data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
-       else if (S_ISFIFO(mode))
-               data_offset->Type = cpu_to_le32(UNIX_FIFO);
-       else if (S_ISSOCK(mode))
-               data_offset->Type = cpu_to_le32(UNIX_SOCKET);
 
+       cifs_fill_unix_set_info(data_offset, args);
 
        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, ("SetPathInfo (perms) returned %d", rc));
+               cFYI(1, "SetPathInfo (perms) returned %d", rc);
 
        cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
@@ -5127,7 +5430,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
        struct dir_notify_req *dnotify_req;
        int bytes_returned;
 
-       cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
+       cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
        rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
        if (rc)
@@ -5161,7 +5464,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
                         (struct smb_hdr *)pSMBr, &bytes_returned,
                         CIFS_ASYNC_OP);
        if (rc) {
-               cFYI(1, ("Error in Notify = %d", rc));
+               cFYI(1, "Error in Notify = %d", rc);
        } else {
                /* Add file to outstanding requests */
                /* BB change to kmem cache alloc */
@@ -5188,24 +5491,36 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
        cifs_buf_release(pSMB);
        return rc;
 }
+
 #ifdef CONFIG_CIFS_XATTR
+/*
+ * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
+ * function used by listxattr and getxattr type calls. When ea_name is set,
+ * it looks for that attribute name and stuffs that value into the EAData
+ * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
+ * buffer. In both cases, the return value is either the length of the
+ * resulting data or a negative error code. If EAData is a NULL pointer then
+ * the data isn't copied to it, but the length is returned.
+ */
 ssize_t
 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
-                const unsigned char *searchName,
-                char *EAData, size_t buf_size,
-                const struct nls_table *nls_codepage, int remap)
+               const unsigned char *searchName, const unsigned char *ea_name,
+               char *EAData, size_t buf_size,
+               const struct nls_table *nls_codepage, int remap)
 {
                /* BB assumes one setup word */
        TRANSACTION2_QPI_REQ *pSMB = NULL;
        TRANSACTION2_QPI_RSP *pSMBr = NULL;
        int rc = 0;
        int bytes_returned;
-       int name_len;
+       int list_len;
+       struct fealist *ea_response_data;
        struct fea *temp_fea;
        char *temp_ptr;
-       __u16 params, byte_count;
+       char *end_of_smb;
+       __u16 params, byte_count, data_offset;
 
-       cFYI(1, ("In Query All EAs path %s", searchName));
+       cFYI(1, "In Query All EAs path %s", searchName);
 QAllEAsRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -5213,22 +5528,22 @@ QAllEAsRetry:
                return rc;
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len =
+               list_len =
                    cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
                                     PATH_MAX, nls_codepage, remap);
-               name_len++;     /* trailing null */
-               name_len *= 2;
+               list_len++;     /* trailing null */
+               list_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, searchName, name_len);
+               list_len = strnlen(searchName, PATH_MAX);
+               list_len++;     /* trailing null */
+               strncpy(pSMB->FileName, searchName, list_len);
        }
 
-       params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
+       params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
        pSMB->TotalDataCount = 0;
        pSMB->MaxParameterCount = cpu_to_le16(2);
        /* BB find exact max SMB PDU from sess structure BB */
-       pSMB->MaxDataCount = cpu_to_le16(4000);
+       pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
        pSMB->MaxSetupCount = 0;
        pSMB->Reserved = 0;
        pSMB->Flags = 0;
@@ -5252,238 +5567,118 @@ QAllEAsRetry:
        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 */
-               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+               cFYI(1, "Send error in QueryAllEAs = %d", rc);
+               goto QAllEAsOut;
+       }
 
-               /* BB also check enough total bytes returned */
-               /* BB we need to improve the validity checking
-               of these trans2 responses */
-               if (rc || (pSMBr->ByteCount < 4))
-                       rc = -EIO;      /* bad smb */
-          /* else if (pFindData){
-                       memcpy((char *) pFindData,
-                              (char *) &pSMBr->hdr.Protocol +
-                              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 check if start of smb + data_offset > &bcc+ bcc */
-                       ea_response_data = (struct fealist *)
-                               (((char *) &pSMBr->hdr.Protocol) +
-                               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"));
-                       } else {
-                               /* account for ea list len */
-                               name_len -= 4;
-                               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 < (int)buf_size) {
-                                               memcpy(EAData, "user.", 5);
-                                               EAData += 5;
-                                               memcpy(EAData, temp_ptr,
-                                                      temp_fea->name_len);
-                                               EAData += temp_fea->name_len;
-                                               /* null terminate name */
-                                               *EAData = 0;
-                                               EAData = EAData + 1;
-                                       } else if (buf_size == 0) {
-                                               /* skip copy - calc size only */
-                                       } else {
-                                               /* stop before overrun buffer */
-                                               rc = -ERANGE;
-                                               break;
-                                       }
-                                       name_len -= temp_fea->name_len;
-                                       temp_ptr += temp_fea->name_len;
-                                       /* account for trailing null */
-                                       name_len--;
-                                       temp_ptr++;
-                                       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 the SMB BB*/
-
-                                       /* no trailing null to account for
-                                          in value len */
-                                       /* go on to next EA */
-                                       temp_fea = (struct fea *)temp_ptr;
-                               }
-                       }
-               }
+
+       /* BB also check enough total bytes returned */
+       /* BB we need to improve the validity checking
+       of these trans2 responses */
+
+       rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+       if (rc || (pSMBr->ByteCount < 4)) {
+               rc = -EIO;      /* bad smb */
+               goto QAllEAsOut;
        }
-       cifs_buf_release(pSMB);
-       if (rc == -EAGAIN)
-               goto QAllEAsRetry;
 
-       return (ssize_t)rc;
-}
+       /* 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 */
+       /* validate_trans2_offsets() */
+       /* BB check if start of smb + data_offset > &bcc+ bcc */
 
-ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
-               const unsigned char *searchName, const unsigned char *ea_name,
-               unsigned char *ea_value, size_t buf_size,
-               const struct nls_table *nls_codepage, int remap)
-{
-       TRANSACTION2_QPI_REQ *pSMB = NULL;
-       TRANSACTION2_QPI_RSP *pSMBr = NULL;
-       int rc = 0;
-       int bytes_returned;
-       int name_len;
-       struct fea *temp_fea;
-       char *temp_ptr;
-       __u16 params, byte_count;
+       data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+       ea_response_data = (struct fealist *)
+                               (((char *) &pSMBr->hdr.Protocol) + data_offset);
 
-       cFYI(1, ("In Query EA path %s", searchName));
-QEARetry:
-       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
-       if (rc)
-               return rc;
+       list_len = le32_to_cpu(ea_response_data->list_len);
+       cFYI(1, "ea length %d", list_len);
+       if (list_len <= 8) {
+               cFYI(1, "empty EA list returned from server");
+               goto QAllEAsOut;
+       }
 
-       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-                                    PATH_MAX, nls_codepage, remap);
-               name_len++;     /* trailing null */
-               name_len *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, searchName, name_len);
+       /* make sure list_len doesn't go past end of SMB */
+       end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
+       if ((char *)ea_response_data + list_len > end_of_smb) {
+               cFYI(1, "EA list appears to go beyond SMB");
+               rc = -EIO;
+               goto QAllEAsOut;
        }
 
-       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 */
-       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_INFO_QUERY_ALL_EAS);
-       pSMB->Reserved4 = 0;
-       pSMB->hdr.smb_buf_length += byte_count;
-       pSMB->ByteCount = cpu_to_le16(byte_count);
+       /* account for ea list len */
+       list_len -= 4;
+       temp_fea = ea_response_data->list;
+       temp_ptr = (char *)temp_fea;
+       while (list_len > 0) {
+               unsigned int name_len;
+               __u16 value_len;
+
+               list_len -= 4;
+               temp_ptr += 4;
+               /* make sure we can read name_len and value_len */
+               if (list_len < 0) {
+                       cFYI(1, "EA entry goes beyond length of list");
+                       rc = -EIO;
+                       goto QAllEAsOut;
+               }
 
-       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 */
-               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+               name_len = temp_fea->name_len;
+               value_len = le16_to_cpu(temp_fea->value_len);
+               list_len -= name_len + 1 + value_len;
+               if (list_len < 0) {
+                       cFYI(1, "EA entry goes beyond length of list");
+                       rc = -EIO;
+                       goto QAllEAsOut;
+               }
 
-               /* BB also check enough total bytes returned */
-               /* BB we need to improve the validity checking
-               of these trans2 responses */
-               if (rc || (pSMBr->ByteCount < 4))
-                       rc = -EIO;      /* bad smb */
-          /* else if (pFindData){
-                       memcpy((char *) pFindData,
-                              (char *) &pSMBr->hdr.Protocol +
-                              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 = -ENODATA;
-                       /* validate_trans2_offsets() */
-                       /* BB check if start of smb + data_offset > &bcc+ bcc*/
-                       ea_response_data = (struct fealist *)
-                               (((char *) &pSMBr->hdr.Protocol) +
-                               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"));
-                       } else {
-                               /* account for ea list len */
-                               name_len -= 4;
-                               temp_fea = ea_response_data->list;
-                               temp_ptr = (char *)temp_fea;
-                               /* 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;
-                                       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 = value_len;
-                               /* account for prefix user. and trailing null */
-                                               if (rc <= (int)buf_size) {
-                                                       memcpy(ea_value,
-                                                               temp_fea->name+temp_fea->name_len+1,
-                                                               rc);
-                                                       /* ea values, unlike ea
-                                                          names, are not null
-                                                          terminated */
-                                               } else if (buf_size == 0) {
-                                               /* skip copy - calc size only */
-                                               } else {
-                                               /* stop before overrun buffer */
-                                                       rc = -ERANGE;
-                                               }
-                                               break;
-                                       }
-                                       name_len -= temp_fea->name_len;
-                                       temp_ptr += temp_fea->name_len;
-                                       /* account for trailing null */
-                                       name_len--;
-                                       temp_ptr++;
-                                       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;
+               if (ea_name) {
+                       if (strncmp(ea_name, temp_ptr, name_len) == 0) {
+                               temp_ptr += name_len + 1;
+                               rc = value_len;
+                               if (buf_size == 0)
+                                       goto QAllEAsOut;
+                               if ((size_t)value_len > buf_size) {
+                                       rc = -ERANGE;
+                                       goto QAllEAsOut;
                                }
+                               memcpy(EAData, temp_ptr, value_len);
+                               goto QAllEAsOut;
+                       }
+               } else {
+                       /* account for prefix user. and trailing null */
+                       rc += (5 + 1 + name_len);
+                       if (rc < (int) buf_size) {
+                               memcpy(EAData, "user.", 5);
+                               EAData += 5;
+                               memcpy(EAData, temp_ptr, name_len);
+                               EAData += name_len;
+                               /* null terminate name */
+                               *EAData = 0;
+                               ++EAData;
+                       } else if (buf_size == 0) {
+                               /* skip copy - calc size only */
+                       } else {
+                               /* stop before overrun buffer */
+                               rc = -ERANGE;
+                               break;
                        }
                }
+               temp_ptr += name_len + 1 + value_len;
+               temp_fea = (struct fea *)temp_ptr;
        }
+
+       /* didn't find the named attribute */
+       if (ea_name)
+               rc = -ENODATA;
+
+QAllEAsOut:
        cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
-               goto QEARetry;
+               goto QAllEAsRetry;
 
        return (ssize_t)rc;
 }
@@ -5502,7 +5697,7 @@ CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
        int bytes_returned = 0;
        __u16 params, param_offset, byte_count, offset, count;
 
-       cFYI(1, ("In SetEA"));
+       cFYI(1, "In SetEA");
 SetEARetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -5584,7 +5779,7 @@ SetEARetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc)
-               cFYI(1, ("SetPathInfo (EA) returned %d", rc));
+               cFYI(1, "SetPathInfo (EA) returned %d", rc);
 
        cifs_buf_release(pSMB);