diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index badcfb2f3c2281e442d0b7939c294cf268b51a88..0356b5559c711ffa20d2710425b823106b0a0dc5 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -2485,7 +2485,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
 	struct page **pages;
 	struct smb2_transform_hdr *tr_hdr;
 	unsigned int npages = old_rq->rq_npages;
-	unsigned int orig_len = 0;
+	unsigned int orig_len;
 	int i;
 	int rc = -ENOMEM;
 
@@ -2499,9 +2499,6 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
 	new_rq->rq_pagesz = old_rq->rq_pagesz;
 	new_rq->rq_tailsz = old_rq->rq_tailsz;
 
-	for (i = 0; i < old_rq->rq_nvec; i++)
-		orig_len += old_rq->rq_iov[i].iov_len;
-
 	for (i = 0; i < npages; i++) {
 		pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
 		if (!pages[i])
@@ -2524,6 +2521,8 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
 	if (!tr_hdr)
 		goto err_free_iov;
 
+	orig_len = smb2_rqst_len(old_rq, false);
+
 	/* fill the 2nd iov with a transform header */
 	fill_transform_hdr(tr_hdr, orig_len, old_rq);
 	new_rq->rq_iov[0].iov_base = tr_hdr;
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 78371c1a650338adb6eb5766ba5607fed729c6b3..3ae208ac2a770d2177036d60e86d0104a4de022a 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -113,6 +113,8 @@ extern int smb2_unlock_range(struct cifsFileInfo *cfile,
 extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile);
 extern void smb2_reconnect_server(struct work_struct *work);
 extern int smb3_crypto_aead_allocate(struct TCP_Server_Info *server);
+extern unsigned long
+smb2_rqst_len(struct smb_rqst *rqst, bool skip_rfc1002_marker);
 
 /*
  * SMB2 Worker functions - most of protocol specific implementation details
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
index e459c97151b34e684dc3f3cbbc36772fee5aaee5..6fd94d9ffac21ad6d8c4fbc436d2b8afa063aede 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -18,6 +18,7 @@
 #include "smbdirect.h"
 #include "cifs_debug.h"
 #include "cifsproto.h"
+#include "smb2proto.h"
 
 static struct smbd_response *get_empty_queue_buffer(
 		struct smbd_connection *info);
@@ -2087,7 +2088,7 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
 	struct kvec vec;
 	int nvecs;
 	int size;
-	unsigned int buflen = 0, remaining_data_length;
+	unsigned int buflen, remaining_data_length;
 	int start, i, j;
 	int max_iov_size =
 		info->max_send_size - sizeof(struct smbd_data_transfer);
@@ -2111,25 +2112,13 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
 		log_write(ERR, "expected the pdu length in 1st iov, but got %zu\n", rqst->rq_iov[0].iov_len);
 		return -EINVAL;
 	}
-	iov = &rqst->rq_iov[1];
-
-	/* total up iov array first */
-	for (i = 0; i < rqst->rq_nvec-1; i++) {
-		buflen += iov[i].iov_len;
-	}
 
 	/*
 	 * Add in the page array if there is one. The caller needs to set
 	 * rq_tailsz to PAGE_SIZE when the buffer has multiple pages and
 	 * ends at page boundary
 	 */
-	if (rqst->rq_npages) {
-		if (rqst->rq_npages == 1)
-			buflen += rqst->rq_tailsz;
-		else
-			buflen += rqst->rq_pagesz * (rqst->rq_npages - 1) -
-					rqst->rq_offset + rqst->rq_tailsz;
-	}
+	buflen = smb2_rqst_len(rqst, true);
 
 	if (buflen + sizeof(struct smbd_data_transfer) >
 		info->max_fragmented_send_size) {
@@ -2139,6 +2128,8 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
 		goto done;
 	}
 
+	iov = &rqst->rq_iov[1];
+
 	cifs_dbg(FYI, "Sending smb (RDMA): smb_len=%u\n", buflen);
 	for (i = 0; i < rqst->rq_nvec-1; i++)
 		dump_smb(iov[i].iov_base, iov[i].iov_len);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index a3ea42a4cb98d1cd1a2f91f033e9b53980cb0b9d..fb57dfbfb749973c1c72423a93d76442c0a07fad 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -201,15 +201,24 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
 	return 0;
 }
 
-static unsigned long
-smb2_rqst_len(struct smb_rqst *rqst)
+unsigned long
+smb2_rqst_len(struct smb_rqst *rqst, bool skip_rfc1002_marker)
 {
 	unsigned int i;
-	struct kvec *iov = rqst->rq_iov;
+	struct kvec *iov;
+	int nvec;
 	unsigned long buflen = 0;
 
+	if (skip_rfc1002_marker && rqst->rq_iov[0].iov_len == 4) {
+		iov = &rqst->rq_iov[1];
+		nvec = rqst->rq_nvec - 1;
+	} else {
+		iov = rqst->rq_iov;
+		nvec = rqst->rq_nvec;
+	}
+
 	/* total up iov array first */
-	for (i = 0; i < rqst->rq_nvec; i++)
+	for (i = 0; i < nvec; i++)
 		buflen += iov[i].iov_len;
 
 	/*
@@ -262,7 +271,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
 				(char *)&val, sizeof(val));
 
 	for (j = 0; j < num_rqst; j++)
-		send_length += smb2_rqst_len(&rqst[j]);
+		send_length += smb2_rqst_len(&rqst[j], true);
 	rfc1002_marker = cpu_to_be32(send_length);
 
 	/* Generate a rfc1002 marker for SMB2+ */