}
 
 static void
-fill_transform_hdr(struct TCP_Server_Info *server,
-                  struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq)
+fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
+                  struct smb_rqst *old_rq)
 {
        struct smb2_sync_hdr *shdr =
                        (struct smb2_sync_hdr *)old_rq->rq_iov[1].iov_base;
-       unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base);
 
        memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr));
        tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
        tr_hdr->Flags = cpu_to_le16(0x01);
        get_random_bytes(&tr_hdr->Nonce, SMB3_AES128CMM_NONCE);
        memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8);
-       inc_rfc1001_len(tr_hdr, sizeof(struct smb2_transform_hdr) - server->vals->header_preamble_size);
-       inc_rfc1001_len(tr_hdr, orig_len);
 }
 
 /* We can not use the normal sg_set_buf() as we will sometimes pass a
        sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
 }
 
+/* Assumes:
+ * rqst->rq_iov[0]  is rfc1002 length
+ * rqst->rq_iov[1]  is tranform header
+ * rqst->rq_iov[2+] data to be encrypted/decrypted
+ */
 static struct scatterlist *
 init_sg(struct smb_rqst *rqst, u8 *sign)
 {
-       unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages + 1;
-       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
+       unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages;
+       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
        struct scatterlist *sg;
        unsigned int i;
        unsigned int j;
                return NULL;
 
        sg_init_table(sg, sg_len);
-       smb2_sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 24, assoc_data_len);
-       for (i = 1; i < rqst->rq_nvec; i++)
-               smb2_sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base,
-                                               rqst->rq_iov[i].iov_len);
+       smb2_sg_set_buf(&sg[0], rqst->rq_iov[1].iov_base + 20, assoc_data_len);
+       for (i = 1; i < rqst->rq_nvec - 1; i++)
+               smb2_sg_set_buf(&sg[i], rqst->rq_iov[i+1].iov_base,
+                                               rqst->rq_iov[i+1].iov_len);
        for (j = 0; i < sg_len - 1; i++, j++) {
                unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz
                                                        : rqst->rq_tailsz;
 }
 /*
  * Encrypt or decrypt @rqst message. @rqst has the following format:
- * iov[0] - transform header (associate data),
- * iov[1-N] and pages - data to encrypt.
- * On success return encrypted data in iov[1-N] and pages, leave iov[0]
+ * iov[0] - rfc1002 length
+ * iov[1] - transform header (associate data),
+ * iov[2-N] and pages - data to encrypt.
+ * On success return encrypted data in iov[2-N] and pages, leave iov[0-1]
  * untouched.
  */
 static int
        return rc;
 }
 
+/*
+ * This is called from smb_send_rqst. At this point we have the rfc1002
+ * header as the first element in the vector.
+ */
 static int
 smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
                       struct smb_rqst *old_rq)
        struct page **pages;
        struct smb2_transform_hdr *tr_hdr;
        unsigned int npages = old_rq->rq_npages;
+       unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base);
        int i;
        int rc = -ENOMEM;
 
                        goto err_free_pages;
        }
 
-       iov = kmalloc_array(old_rq->rq_nvec, sizeof(struct kvec), GFP_KERNEL);
+       /* Make space for one extra iov to hold the transform header */
+       iov = kmalloc_array(old_rq->rq_nvec + 1, sizeof(struct kvec),
+                           GFP_KERNEL);
        if (!iov)
                goto err_free_pages;
 
        /* copy all iovs from the old except the 1st one (rfc1002 length) */
-       memcpy(&iov[1], &old_rq->rq_iov[1],
+       memcpy(&iov[2], &old_rq->rq_iov[1],
                                sizeof(struct kvec) * (old_rq->rq_nvec - 1));
+       /* copy the rfc1002 iov */
+       iov[0].iov_base = old_rq->rq_iov[0].iov_base;
+       iov[0].iov_len  = old_rq->rq_iov[0].iov_len;
+
        new_rq->rq_iov = iov;
-       new_rq->rq_nvec = old_rq->rq_nvec;
+       new_rq->rq_nvec = old_rq->rq_nvec + 1;
 
        tr_hdr = kmalloc(sizeof(struct smb2_transform_hdr), GFP_KERNEL);
        if (!tr_hdr)
                goto err_free_iov;
 
-       /* fill the 1st iov with a transform header */
-       fill_transform_hdr(server, tr_hdr, old_rq);
-       new_rq->rq_iov[0].iov_base = tr_hdr;
-       new_rq->rq_iov[0].iov_len = sizeof(struct smb2_transform_hdr);
+       /* fill the 2nd iov with a transform header */
+       fill_transform_hdr(tr_hdr, orig_len, old_rq);
+       new_rq->rq_iov[1].iov_base = tr_hdr;
+       new_rq->rq_iov[1].iov_len = sizeof(struct smb2_transform_hdr);
+
+       /* Update rfc1002 header */
+       inc_rfc1001_len(new_rq->rq_iov[0].iov_base,
+                       sizeof(struct smb2_transform_hdr));
 
        /* copy pages form the old */
        for (i = 0; i < npages; i++) {
                put_page(rqst->rq_pages[i]);
        kfree(rqst->rq_pages);
        /* free transform header */
-       kfree(rqst->rq_iov[0].iov_base);
+       kfree(rqst->rq_iov[1].iov_base);
        kfree(rqst->rq_iov);
 }
 
                 unsigned int buf_data_size, struct page **pages,
                 unsigned int npages, unsigned int page_data_size)
 {
-       struct kvec iov[2];
+       struct kvec iov[3];
        struct smb_rqst rqst = {NULL};
-       struct smb2_hdr *hdr;
        int rc;
 
-       iov[0].iov_base = buf;
-       iov[0].iov_len = sizeof(struct smb2_transform_hdr);
-       iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr);
-       iov[1].iov_len = buf_data_size;
+       iov[0].iov_base = NULL;
+       iov[0].iov_len = 0;
+       iov[1].iov_base = buf;
+       iov[1].iov_len = sizeof(struct smb2_transform_hdr);
+       iov[2].iov_base = buf + sizeof(struct smb2_transform_hdr);
+       iov[2].iov_len = buf_data_size;
 
        rqst.rq_iov = iov;
-       rqst.rq_nvec = 2;
+       rqst.rq_nvec = 3;
        rqst.rq_pages = pages;
        rqst.rq_npages = npages;
        rqst.rq_pagesz = PAGE_SIZE;
        if (rc)
                return rc;
 
-       memmove(buf + server->vals->header_preamble_size, iov[1].iov_base, buf_data_size);
-       hdr = (struct smb2_hdr *)buf;
-       hdr->smb2_buf_length = cpu_to_be32(buf_data_size + page_data_size);
-       server->total_read = buf_data_size + page_data_size + server->vals->header_preamble_size;
+       memmove(buf + server->vals->header_preamble_size, iov[2].iov_base, buf_data_size);
+
+       server->total_read = buf_data_size + page_data_size;
 
        return rc;
 }
        .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
        .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
-       .header_size = sizeof(struct smb2_hdr),
-       .header_preamble_size = 4,
+       .header_size = sizeof(struct smb2_sync_hdr),
+       .header_preamble_size = 0,
        .max_header_size = MAX_SMB2_HDR_SIZE,
        .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
        .lock_cmd = SMB2_LOCK,
        .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
        .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
-       .header_size = sizeof(struct smb2_hdr),
-       .header_preamble_size = 4,
+       .header_size = sizeof(struct smb2_sync_hdr),
+       .header_preamble_size = 0,
        .max_header_size = MAX_SMB2_HDR_SIZE,
        .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
        .lock_cmd = SMB2_LOCK,
        .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
        .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
-       .header_size = sizeof(struct smb2_hdr),
-       .header_preamble_size = 4,
+       .header_size = sizeof(struct smb2_sync_hdr),
+       .header_preamble_size = 0,
        .max_header_size = MAX_SMB2_HDR_SIZE,
        .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
        .lock_cmd = SMB2_LOCK,
        .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
        .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
-       .header_size = sizeof(struct smb2_hdr),
-       .header_preamble_size = 4,
+       .header_size = sizeof(struct smb2_sync_hdr),
+       .header_preamble_size = 0,
        .max_header_size = MAX_SMB2_HDR_SIZE,
        .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
        .lock_cmd = SMB2_LOCK,
        .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
        .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
-       .header_size = sizeof(struct smb2_hdr),
-       .header_preamble_size = 4,
+       .header_size = sizeof(struct smb2_sync_hdr),
+       .header_preamble_size = 0,
        .max_header_size = MAX_SMB2_HDR_SIZE,
        .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
        .lock_cmd = SMB2_LOCK,
        .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
        .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
-       .header_size = sizeof(struct smb2_hdr),
-       .header_preamble_size = 4,
+       .header_size = sizeof(struct smb2_sync_hdr),
+       .header_preamble_size = 0,
        .max_header_size = MAX_SMB2_HDR_SIZE,
        .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
        .lock_cmd = SMB2_LOCK,
        .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
        .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
-       .header_size = sizeof(struct smb2_hdr),
-       .header_preamble_size = 4,
+       .header_size = sizeof(struct smb2_sync_hdr),
+       .header_preamble_size = 0,
        .max_header_size = MAX_SMB2_HDR_SIZE,
        .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
        .lock_cmd = SMB2_LOCK,
 
 }
 
 static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
-                                    struct TCP_Server_Info *server)
+                                    struct TCP_Server_Info *server,
+                                    unsigned int len_of_smb)
 {
        struct smb2_neg_context *pctx;
        unsigned int offset = le32_to_cpu(rsp->NegotiateContextOffset);
        unsigned int ctxt_cnt = le16_to_cpu(rsp->NegotiateContextCount);
-       unsigned int len_of_smb = be32_to_cpu(rsp->hdr.smb2_buf_length);
        unsigned int len_of_ctxts, i;
        int rc = 0;
 
 #ifdef CONFIG_CIFS_SMB311
        if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
                if (rsp->NegotiateContextCount)
-                       rc = smb311_decode_neg_context(rsp, server);
+                       rc = smb311_decode_neg_context(rsp, server,
+                                                      rsp_iov.iov_len);
                else
                        cifs_dbg(VFS, "Missing expected negotiate contexts\n");
        }
 {
        struct smb2_ioctl_req *req;
        struct smb2_ioctl_rsp *rsp;
-       struct smb2_sync_hdr *shdr;
        struct cifs_ses *ses;
        struct kvec iov[2];
        struct kvec rsp_iov;
                goto ioctl_exit;
        }
 
-       if (get_rfc1002_length(rsp) < le32_to_cpu(rsp->OutputOffset) + *plen) {
+       if (rsp_iov.iov_len < le32_to_cpu(rsp->OutputOffset) + *plen) {
                cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen,
                        le32_to_cpu(rsp->OutputOffset));
                *plen = 0;
                goto ioctl_exit;
        }
 
-       shdr = get_sync_hdr(rsp);
-       memcpy(*out_data, (char *)shdr + le32_to_cpu(rsp->OutputOffset), *plen);
+       memcpy(*out_data, (char *)rsp + le32_to_cpu(rsp->OutputOffset), *plen);
 ioctl_exit:
        free_rsp_buf(resp_buftype, rsp);
        return rc;
        struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
        struct TCP_Server_Info *server = tcon->ses->server;
        struct smb2_sync_hdr *shdr =
-                               (struct smb2_sync_hdr *)rdata->iov[1].iov_base;
+                               (struct smb2_sync_hdr *)rdata->iov[0].iov_base;
        unsigned int credits_received = 1;
        struct smb_rqst rqst = { .rq_iov = rdata->iov,
                                 .rq_nvec = 2,
        int resp_buftype, rc = -EACCES;
        struct smb2_read_plain_req *req = NULL;
        struct smb2_read_rsp *rsp = NULL;
-       struct smb2_sync_hdr *shdr;
        struct kvec iov[1];
        struct kvec rsp_iov;
        unsigned int total_len;
                *nbytes = 0;
        }
 
-       shdr = get_sync_hdr(rsp);
-
        if (*buf) {
-               memcpy(*buf, (char *)shdr + rsp->DataOffset, *nbytes);
+               memcpy(*buf, (char *)rsp + rsp->DataOffset, *nbytes);
                free_rsp_buf(resp_buftype, rsp_iov.iov_base);
        } else if (resp_buftype != CIFS_NO_BUFFER) {
                *buf = rsp_iov.iov_base;
                        cifs_buf_release(srch_inf->ntwrk_buf_start);
        }
        srch_inf->ntwrk_buf_start = (char *)rsp;
-       srch_inf->srch_entries_start = srch_inf->last_entry = 4 /* rfclen */ +
-               (char *)&rsp->hdr + le16_to_cpu(rsp->OutputBufferOffset);
-       /* 4 for rfc1002 length field */
-       end_of_smb = get_rfc1002_length(rsp) + 4 + (char *)&rsp->hdr;
+       srch_inf->srch_entries_start = srch_inf->last_entry =
+               (char *)rsp + le16_to_cpu(rsp->OutputBufferOffset);
+       end_of_smb = rsp_iov.iov_len + (char *)rsp;
        srch_inf->entries_in_buffer =
                        num_entries(srch_inf->srch_entries_start, end_of_smb,
                                    &srch_inf->last_entry, info_buf_size);