aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/smb2ops.c7
-rw-r--r--fs/cifs/smb2proto.h2
-rw-r--r--fs/cifs/smbdirect.c19
-rw-r--r--fs/cifs/transport.c19
4 files changed, 24 insertions, 23 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index badcfb2f3c22..0356b5559c71 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,
2485 struct page **pages; 2485 struct page **pages;
2486 struct smb2_transform_hdr *tr_hdr; 2486 struct smb2_transform_hdr *tr_hdr;
2487 unsigned int npages = old_rq->rq_npages; 2487 unsigned int npages = old_rq->rq_npages;
2488 unsigned int orig_len = 0; 2488 unsigned int orig_len;
2489 int i; 2489 int i;
2490 int rc = -ENOMEM; 2490 int rc = -ENOMEM;
2491 2491
@@ -2499,9 +2499,6 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
2499 new_rq->rq_pagesz = old_rq->rq_pagesz; 2499 new_rq->rq_pagesz = old_rq->rq_pagesz;
2500 new_rq->rq_tailsz = old_rq->rq_tailsz; 2500 new_rq->rq_tailsz = old_rq->rq_tailsz;
2501 2501
2502 for (i = 0; i < old_rq->rq_nvec; i++)
2503 orig_len += old_rq->rq_iov[i].iov_len;
2504
2505 for (i = 0; i < npages; i++) { 2502 for (i = 0; i < npages; i++) {
2506 pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM); 2503 pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
2507 if (!pages[i]) 2504 if (!pages[i])
@@ -2524,6 +2521,8 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
2524 if (!tr_hdr) 2521 if (!tr_hdr)
2525 goto err_free_iov; 2522 goto err_free_iov;
2526 2523
2524 orig_len = smb2_rqst_len(old_rq, false);
2525
2527 /* fill the 2nd iov with a transform header */ 2526 /* fill the 2nd iov with a transform header */
2528 fill_transform_hdr(tr_hdr, orig_len, old_rq); 2527 fill_transform_hdr(tr_hdr, orig_len, old_rq);
2529 new_rq->rq_iov[0].iov_base = tr_hdr; 2528 new_rq->rq_iov[0].iov_base = tr_hdr;
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 78371c1a6503..3ae208ac2a77 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -113,6 +113,8 @@ extern int smb2_unlock_range(struct cifsFileInfo *cfile,
113extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile); 113extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile);
114extern void smb2_reconnect_server(struct work_struct *work); 114extern void smb2_reconnect_server(struct work_struct *work);
115extern int smb3_crypto_aead_allocate(struct TCP_Server_Info *server); 115extern int smb3_crypto_aead_allocate(struct TCP_Server_Info *server);
116extern unsigned long
117smb2_rqst_len(struct smb_rqst *rqst, bool skip_rfc1002_marker);
116 118
117/* 119/*
118 * SMB2 Worker functions - most of protocol specific implementation details 120 * SMB2 Worker functions - most of protocol specific implementation details
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
index e459c97151b3..6fd94d9ffac2 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -18,6 +18,7 @@
18#include "smbdirect.h" 18#include "smbdirect.h"
19#include "cifs_debug.h" 19#include "cifs_debug.h"
20#include "cifsproto.h" 20#include "cifsproto.h"
21#include "smb2proto.h"
21 22
22static struct smbd_response *get_empty_queue_buffer( 23static struct smbd_response *get_empty_queue_buffer(
23 struct smbd_connection *info); 24 struct smbd_connection *info);
@@ -2087,7 +2088,7 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
2087 struct kvec vec; 2088 struct kvec vec;
2088 int nvecs; 2089 int nvecs;
2089 int size; 2090 int size;
2090 unsigned int buflen = 0, remaining_data_length; 2091 unsigned int buflen, remaining_data_length;
2091 int start, i, j; 2092 int start, i, j;
2092 int max_iov_size = 2093 int max_iov_size =
2093 info->max_send_size - sizeof(struct smbd_data_transfer); 2094 info->max_send_size - sizeof(struct smbd_data_transfer);
@@ -2111,25 +2112,13 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
2111 log_write(ERR, "expected the pdu length in 1st iov, but got %zu\n", rqst->rq_iov[0].iov_len); 2112 log_write(ERR, "expected the pdu length in 1st iov, but got %zu\n", rqst->rq_iov[0].iov_len);
2112 return -EINVAL; 2113 return -EINVAL;
2113 } 2114 }
2114 iov = &rqst->rq_iov[1];
2115
2116 /* total up iov array first */
2117 for (i = 0; i < rqst->rq_nvec-1; i++) {
2118 buflen += iov[i].iov_len;
2119 }
2120 2115
2121 /* 2116 /*
2122 * Add in the page array if there is one. The caller needs to set 2117 * Add in the page array if there is one. The caller needs to set
2123 * rq_tailsz to PAGE_SIZE when the buffer has multiple pages and 2118 * rq_tailsz to PAGE_SIZE when the buffer has multiple pages and
2124 * ends at page boundary 2119 * ends at page boundary
2125 */ 2120 */
2126 if (rqst->rq_npages) { 2121 buflen = smb2_rqst_len(rqst, true);
2127 if (rqst->rq_npages == 1)
2128 buflen += rqst->rq_tailsz;
2129 else
2130 buflen += rqst->rq_pagesz * (rqst->rq_npages - 1) -
2131 rqst->rq_offset + rqst->rq_tailsz;
2132 }
2133 2122
2134 if (buflen + sizeof(struct smbd_data_transfer) > 2123 if (buflen + sizeof(struct smbd_data_transfer) >
2135 info->max_fragmented_send_size) { 2124 info->max_fragmented_send_size) {
@@ -2139,6 +2128,8 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
2139 goto done; 2128 goto done;
2140 } 2129 }
2141 2130
2131 iov = &rqst->rq_iov[1];
2132
2142 cifs_dbg(FYI, "Sending smb (RDMA): smb_len=%u\n", buflen); 2133 cifs_dbg(FYI, "Sending smb (RDMA): smb_len=%u\n", buflen);
2143 for (i = 0; i < rqst->rq_nvec-1; i++) 2134 for (i = 0; i < rqst->rq_nvec-1; i++)
2144 dump_smb(iov[i].iov_base, iov[i].iov_len); 2135 dump_smb(iov[i].iov_base, iov[i].iov_len);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index a3ea42a4cb98..fb57dfbfb749 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,
201 return 0; 201 return 0;
202} 202}
203 203
204static unsigned long 204unsigned long
205smb2_rqst_len(struct smb_rqst *rqst) 205smb2_rqst_len(struct smb_rqst *rqst, bool skip_rfc1002_marker)
206{ 206{
207 unsigned int i; 207 unsigned int i;
208 struct kvec *iov = rqst->rq_iov; 208 struct kvec *iov;
209 int nvec;
209 unsigned long buflen = 0; 210 unsigned long buflen = 0;
210 211
212 if (skip_rfc1002_marker && rqst->rq_iov[0].iov_len == 4) {
213 iov = &rqst->rq_iov[1];
214 nvec = rqst->rq_nvec - 1;
215 } else {
216 iov = rqst->rq_iov;
217 nvec = rqst->rq_nvec;
218 }
219
211 /* total up iov array first */ 220 /* total up iov array first */
212 for (i = 0; i < rqst->rq_nvec; i++) 221 for (i = 0; i < nvec; i++)
213 buflen += iov[i].iov_len; 222 buflen += iov[i].iov_len;
214 223
215 /* 224 /*
@@ -262,7 +271,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
262 (char *)&val, sizeof(val)); 271 (char *)&val, sizeof(val));
263 272
264 for (j = 0; j < num_rqst; j++) 273 for (j = 0; j < num_rqst; j++)
265 send_length += smb2_rqst_len(&rqst[j]); 274 send_length += smb2_rqst_len(&rqst[j], true);
266 rfc1002_marker = cpu_to_be32(send_length); 275 rfc1002_marker = cpu_to_be32(send_length);
267 276
268 /* Generate a rfc1002 marker for SMB2+ */ 277 /* Generate a rfc1002 marker for SMB2+ */