diff options
-rw-r--r-- | fs/cifs/cifsproto.h | 3 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 89 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 5 | ||||
-rw-r--r-- | fs/cifs/transport.c | 2 |
4 files changed, 74 insertions, 25 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7b20993a5acc..711718cd73dd 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -79,6 +79,9 @@ extern int cifs_call_async(struct TCP_Server_Info *server, | |||
79 | struct smb_rqst *rqst, | 79 | struct smb_rqst *rqst, |
80 | mid_receive_t *receive, mid_callback_t *callback, | 80 | mid_receive_t *receive, mid_callback_t *callback, |
81 | void *cbdata, const int flags); | 81 | void *cbdata, const int flags); |
82 | extern int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, | ||
83 | struct smb_rqst *rqst, int *resp_buf_type, | ||
84 | const int flags, struct kvec *resp_iov); | ||
82 | extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *, | 85 | extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *, |
83 | struct smb_hdr * /* input */ , | 86 | struct smb_hdr * /* input */ , |
84 | struct smb_hdr * /* out */ , | 87 | struct smb_hdr * /* out */ , |
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 */ | ||
297 | static int | ||
298 | smb2_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 | */ |
301 | static int | 337 | static int |
302 | small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon, | 338 | small_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); |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 052342da4844..35ff9fae1c27 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
@@ -823,8 +823,9 @@ struct smb2_flush_rsp { | |||
823 | #define SMB2_CHANNEL_RDMA_V1 0x00000001 /* SMB3 or later */ | 823 | #define SMB2_CHANNEL_RDMA_V1 0x00000001 /* SMB3 or later */ |
824 | #define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000001 /* SMB3.02 or later */ | 824 | #define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000001 /* SMB3.02 or later */ |
825 | 825 | ||
826 | struct smb2_read_req { | 826 | /* SMB2 read request without RFC1001 length at the beginning */ |
827 | struct smb2_hdr hdr; | 827 | struct smb2_read_plain_req { |
828 | struct smb2_sync_hdr sync_hdr; | ||
828 | __le16 StructureSize; /* Must be 49 */ | 829 | __le16 StructureSize; /* Must be 49 */ |
829 | __u8 Padding; /* offset from start of SMB2 header to place read */ | 830 | __u8 Padding; /* offset from start of SMB2 header to place read */ |
830 | __u8 Flags; /* MBZ unless SMB3.02 or later */ | 831 | __u8 Flags; /* MBZ unless SMB3.02 or later */ |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index dacfdf080330..729e5b7b8044 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -666,7 +666,7 @@ cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst) | |||
666 | return mid; | 666 | return mid; |
667 | } | 667 | } |
668 | 668 | ||
669 | static int | 669 | int |
670 | cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, | 670 | cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, |
671 | struct smb_rqst *rqst, int *resp_buf_type, const int flags, | 671 | struct smb_rqst *rqst, int *resp_buf_type, const int flags, |
672 | struct kvec *resp_iov) | 672 | struct kvec *resp_iov) |