diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/smb2ops.c | 12 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 51 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 2 |
3 files changed, 65 insertions, 0 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index da31235023fb..fb289d2abae7 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -393,6 +393,17 @@ smb2_read_data_length(char *buf) | |||
393 | return le32_to_cpu(rsp->DataLength); | 393 | return le32_to_cpu(rsp->DataLength); |
394 | } | 394 | } |
395 | 395 | ||
396 | |||
397 | static int | ||
398 | smb2_sync_read(const unsigned int xid, struct cifsFileInfo *cfile, | ||
399 | struct cifs_io_parms *parms, unsigned int *bytes_read, | ||
400 | char **buf, int *buf_type) | ||
401 | { | ||
402 | parms->persistent_fid = cfile->fid.persistent_fid; | ||
403 | parms->volatile_fid = cfile->fid.volatile_fid; | ||
404 | return SMB2_read(xid, parms, bytes_read, buf, buf_type); | ||
405 | } | ||
406 | |||
396 | struct smb_version_operations smb21_operations = { | 407 | struct smb_version_operations smb21_operations = { |
397 | .setup_request = smb2_setup_request, | 408 | .setup_request = smb2_setup_request, |
398 | .setup_async_request = smb2_setup_async_request, | 409 | .setup_async_request = smb2_setup_async_request, |
@@ -435,6 +446,7 @@ struct smb_version_operations smb21_operations = { | |||
435 | .flush = smb2_flush_file, | 446 | .flush = smb2_flush_file, |
436 | .async_readv = smb2_async_readv, | 447 | .async_readv = smb2_async_readv, |
437 | .async_writev = smb2_async_writev, | 448 | .async_writev = smb2_async_writev, |
449 | .sync_read = smb2_sync_read, | ||
438 | }; | 450 | }; |
439 | 451 | ||
440 | struct smb_version_values smb21_values = { | 452 | struct smb_version_values smb21_values = { |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index cb6acc7b1ca8..23c569386f32 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -1329,6 +1329,57 @@ smb2_async_readv(struct cifs_readdata *rdata) | |||
1329 | return rc; | 1329 | return rc; |
1330 | } | 1330 | } |
1331 | 1331 | ||
1332 | int | ||
1333 | SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | ||
1334 | unsigned int *nbytes, char **buf, int *buf_type) | ||
1335 | { | ||
1336 | int resp_buftype, rc = -EACCES; | ||
1337 | struct smb2_read_rsp *rsp = NULL; | ||
1338 | struct kvec iov[1]; | ||
1339 | |||
1340 | *nbytes = 0; | ||
1341 | rc = smb2_new_read_req(iov, io_parms, 0, 0); | ||
1342 | if (rc) | ||
1343 | return rc; | ||
1344 | |||
1345 | rc = SendReceive2(xid, io_parms->tcon->ses, iov, 1, | ||
1346 | &resp_buftype, CIFS_LOG_ERROR); | ||
1347 | |||
1348 | rsp = (struct smb2_read_rsp *)iov[0].iov_base; | ||
1349 | |||
1350 | if (rsp->hdr.Status == STATUS_END_OF_FILE) { | ||
1351 | free_rsp_buf(resp_buftype, iov[0].iov_base); | ||
1352 | return 0; | ||
1353 | } | ||
1354 | |||
1355 | if (rc) { | ||
1356 | cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE); | ||
1357 | cERROR(1, "Send error in read = %d", rc); | ||
1358 | } else { | ||
1359 | *nbytes = le32_to_cpu(rsp->DataLength); | ||
1360 | if ((*nbytes > CIFS_MAX_MSGSIZE) || | ||
1361 | (*nbytes > io_parms->length)) { | ||
1362 | cFYI(1, "bad length %d for count %d", *nbytes, | ||
1363 | io_parms->length); | ||
1364 | rc = -EIO; | ||
1365 | *nbytes = 0; | ||
1366 | } | ||
1367 | } | ||
1368 | |||
1369 | if (*buf) { | ||
1370 | memcpy(*buf, (char *)rsp->hdr.ProtocolId + rsp->DataOffset, | ||
1371 | *nbytes); | ||
1372 | free_rsp_buf(resp_buftype, iov[0].iov_base); | ||
1373 | } else if (resp_buftype != CIFS_NO_BUFFER) { | ||
1374 | *buf = iov[0].iov_base; | ||
1375 | if (resp_buftype == CIFS_SMALL_BUFFER) | ||
1376 | *buf_type = CIFS_SMALL_BUFFER; | ||
1377 | else if (resp_buftype == CIFS_LARGE_BUFFER) | ||
1378 | *buf_type = CIFS_LARGE_BUFFER; | ||
1379 | } | ||
1380 | return rc; | ||
1381 | } | ||
1382 | |||
1332 | /* | 1383 | /* |
1333 | * Check the mid_state and signature on received buffer (if any), and queue the | 1384 | * Check the mid_state and signature on received buffer (if any), and queue the |
1334 | * workqueue completion task. | 1385 | * workqueue completion task. |
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index ec983be0ba31..97e62f3df410 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
@@ -98,6 +98,8 @@ extern int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon, | |||
98 | u64 persistent_fid, u64 volatile_fid, | 98 | u64 persistent_fid, u64 volatile_fid, |
99 | __le64 *uniqueid); | 99 | __le64 *uniqueid); |
100 | extern int smb2_async_readv(struct cifs_readdata *rdata); | 100 | extern int smb2_async_readv(struct cifs_readdata *rdata); |
101 | extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | ||
102 | unsigned int *nbytes, char **buf, int *buf_type); | ||
101 | extern int smb2_async_writev(struct cifs_writedata *wdata); | 103 | extern int smb2_async_writev(struct cifs_writedata *wdata); |
102 | extern int SMB2_echo(struct TCP_Server_Info *server); | 104 | extern int SMB2_echo(struct TCP_Server_Info *server); |
103 | 105 | ||