aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/smb2ops.c12
-rw-r--r--fs/cifs/smb2pdu.c51
-rw-r--r--fs/cifs/smb2proto.h2
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
397static int
398smb2_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
396struct smb_version_operations smb21_operations = { 407struct 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
440struct smb_version_values smb21_values = { 452struct 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
1332int
1333SMB2_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);
100extern int smb2_async_readv(struct cifs_readdata *rdata); 100extern int smb2_async_readv(struct cifs_readdata *rdata);
101extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
102 unsigned int *nbytes, char **buf, int *buf_type);
101extern int smb2_async_writev(struct cifs_writedata *wdata); 103extern int smb2_async_writev(struct cifs_writedata *wdata);
102extern int SMB2_echo(struct TCP_Server_Info *server); 104extern int SMB2_echo(struct TCP_Server_Info *server);
103 105