aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/smb2pdu.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/smb2pdu.c')
-rw-r--r--fs/cifs/smb2pdu.c89
1 files changed, 67 insertions, 22 deletions
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index f6ba2c03f7cc..d1a90371b649 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -293,10 +293,46 @@ fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, void *buf,
293 *total_len = parmsize + sizeof(struct smb2_sync_hdr); 293 *total_len = parmsize + sizeof(struct smb2_sync_hdr);
294} 294}
295 295
296/* init request without RFC1001 length at the beginning */
297static int
298smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon,
299 void **request_buf, unsigned int *total_len)
300{
301 int rc;
302 struct smb2_sync_hdr *shdr;
303
304 rc = smb2_reconnect(smb2_command, tcon);
305 if (rc)
306 return rc;
307
308 /* BB eventually switch this to SMB2 specific small buf size */
309 *request_buf = cifs_small_buf_get();
310 if (*request_buf == NULL) {
311 /* BB should we add a retry in here if not a writepage? */
312 return -ENOMEM;
313 }
314
315 shdr = (struct smb2_sync_hdr *)(*request_buf);
316
317 fill_small_buf(smb2_command, tcon, shdr, total_len);
318
319 if (tcon != NULL) {
320#ifdef CONFIG_CIFS_STATS2
321 uint16_t com_code = le16_to_cpu(smb2_command);
322
323 cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_sent[com_code]);
324#endif
325 cifs_stats_inc(&tcon->num_smbs_sent);
326 }
327
328 return rc;
329}
330
296/* 331/*
297 * Allocate and return pointer to an SMB request hdr, and set basic 332 * Allocate and return pointer to an SMB request hdr, and set basic
298 * SMB information in the SMB header. If the return code is zero, this 333 * SMB information in the SMB header. If the return code is zero, this
299 * function must have filled in request_buf pointer. 334 * function must have filled in request_buf pointer. The returned buffer
335 * has RFC1001 length at the beginning.
300 */ 336 */
301static int 337static int
302small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon, 338small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon,
@@ -2140,16 +2176,17 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
2140 int request_type) 2176 int request_type)
2141{ 2177{
2142 int rc = -EACCES; 2178 int rc = -EACCES;
2143 struct smb2_read_req *req = NULL; 2179 struct smb2_read_plain_req *req = NULL;
2144 struct smb2_sync_hdr *shdr; 2180 struct smb2_sync_hdr *shdr;
2145 2181
2146 rc = small_smb2_init(SMB2_READ, io_parms->tcon, (void **) &req); 2182 rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, (void **) &req,
2183 total_len);
2147 if (rc) 2184 if (rc)
2148 return rc; 2185 return rc;
2149 if (io_parms->tcon->ses->server == NULL) 2186 if (io_parms->tcon->ses->server == NULL)
2150 return -ECONNABORTED; 2187 return -ECONNABORTED;
2151 2188
2152 shdr = get_sync_hdr(req); 2189 shdr = &req->sync_hdr;
2153 shdr->ProcessId = cpu_to_le32(io_parms->pid); 2190 shdr->ProcessId = cpu_to_le32(io_parms->pid);
2154 2191
2155 req->PersistentFileId = io_parms->persistent_fid; 2192 req->PersistentFileId = io_parms->persistent_fid;
@@ -2163,9 +2200,9 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
2163 2200
2164 if (request_type & CHAINED_REQUEST) { 2201 if (request_type & CHAINED_REQUEST) {
2165 if (!(request_type & END_OF_CHAIN)) { 2202 if (!(request_type & END_OF_CHAIN)) {
2166 /* 4 for rfc1002 length field */ 2203 /* next 8-byte aligned request */
2167 shdr->NextCommand = 2204 *total_len = DIV_ROUND_UP(*total_len, 8) * 8;
2168 cpu_to_le32(get_rfc1002_length(req) + 4); 2205 shdr->NextCommand = cpu_to_le32(*total_len);
2169 } else /* END_OF_CHAIN */ 2206 } else /* END_OF_CHAIN */
2170 shdr->NextCommand = 0; 2207 shdr->NextCommand = 0;
2171 if (request_type & RELATED_REQUEST) { 2208 if (request_type & RELATED_REQUEST) {
@@ -2186,8 +2223,6 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
2186 req->RemainingBytes = 0; 2223 req->RemainingBytes = 0;
2187 2224
2188 *buf = req; 2225 *buf = req;
2189 /* 4 for rfc1002 length field */
2190 *total_len = get_rfc1002_length(req) + 4;
2191 return rc; 2226 return rc;
2192} 2227}
2193 2228
@@ -2264,6 +2299,7 @@ smb2_async_readv(struct cifs_readdata *rdata)
2264 .rq_nvec = 2 }; 2299 .rq_nvec = 2 };
2265 struct TCP_Server_Info *server; 2300 struct TCP_Server_Info *server;
2266 unsigned int total_len; 2301 unsigned int total_len;
2302 __be32 req_len;
2267 2303
2268 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n", 2304 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
2269 __func__, rdata->offset, rdata->bytes); 2305 __func__, rdata->offset, rdata->bytes);
@@ -2290,12 +2326,14 @@ smb2_async_readv(struct cifs_readdata *rdata)
2290 return rc; 2326 return rc;
2291 } 2327 }
2292 2328
2293 shdr = get_sync_hdr(buf); 2329 req_len = cpu_to_be32(total_len);
2294 /* 4 for rfc1002 length field */ 2330
2295 rdata->iov[0].iov_len = 4; 2331 rdata->iov[0].iov_base = &req_len;
2296 rdata->iov[0].iov_base = buf; 2332 rdata->iov[0].iov_len = sizeof(__be32);
2297 rdata->iov[1].iov_len = total_len - 4; 2333 rdata->iov[1].iov_base = buf;
2298 rdata->iov[1].iov_base = buf + 4; 2334 rdata->iov[1].iov_len = total_len;
2335
2336 shdr = (struct smb2_sync_hdr *)buf;
2299 2337
2300 if (rdata->credits) { 2338 if (rdata->credits) {
2301 shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes, 2339 shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes,
@@ -2327,24 +2365,31 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
2327 unsigned int *nbytes, char **buf, int *buf_type) 2365 unsigned int *nbytes, char **buf, int *buf_type)
2328{ 2366{
2329 int resp_buftype, rc = -EACCES; 2367 int resp_buftype, rc = -EACCES;
2368 struct smb2_read_plain_req *req = NULL;
2330 struct smb2_read_rsp *rsp = NULL; 2369 struct smb2_read_rsp *rsp = NULL;
2331 struct smb2_sync_hdr *shdr; 2370 struct smb2_sync_hdr *shdr;
2332 struct kvec iov[1]; 2371 struct kvec iov[2];
2333 struct kvec rsp_iov; 2372 struct kvec rsp_iov;
2334 unsigned int total_len; 2373 unsigned int total_len;
2335 char *req; 2374 __be32 req_len;
2375 struct smb_rqst rqst = { .rq_iov = iov,
2376 .rq_nvec = 2 };
2336 2377
2337 *nbytes = 0; 2378 *nbytes = 0;
2338 rc = smb2_new_read_req((void **)&req, &total_len, io_parms, 0, 0); 2379 rc = smb2_new_read_req((void **)&req, &total_len, io_parms, 0, 0);
2339 if (rc) 2380 if (rc)
2340 return rc; 2381 return rc;
2341 2382
2342 iov[0].iov_base = buf; 2383 req_len = cpu_to_be32(total_len);
2343 iov[0].iov_len = total_len;
2344 2384
2345 rc = SendReceive2(xid, io_parms->tcon->ses, iov, 1, 2385 iov[0].iov_base = &req_len;
2346 &resp_buftype, CIFS_LOG_ERROR, &rsp_iov); 2386 iov[0].iov_len = sizeof(__be32);
2347 cifs_small_buf_release(iov[0].iov_base); 2387 iov[1].iov_base = req;
2388 iov[1].iov_len = total_len;
2389
2390 rc = cifs_send_recv(xid, io_parms->tcon->ses, &rqst, &resp_buftype,
2391 CIFS_LOG_ERROR, &rsp_iov);
2392 cifs_small_buf_release(req);
2348 2393
2349 rsp = (struct smb2_read_rsp *)rsp_iov.iov_base; 2394 rsp = (struct smb2_read_rsp *)rsp_iov.iov_base;
2350 shdr = get_sync_hdr(rsp); 2395 shdr = get_sync_hdr(rsp);