diff options
-rw-r--r-- | fs/cifs/smb2ops.c | 12 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 61 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 2 |
3 files changed, 75 insertions, 0 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index fb289d2abae7..f9c3dbee9010 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -404,6 +404,17 @@ smb2_sync_read(const unsigned int xid, struct cifsFileInfo *cfile, | |||
404 | return SMB2_read(xid, parms, bytes_read, buf, buf_type); | 404 | return SMB2_read(xid, parms, bytes_read, buf, buf_type); |
405 | } | 405 | } |
406 | 406 | ||
407 | static int | ||
408 | smb2_sync_write(const unsigned int xid, struct cifsFileInfo *cfile, | ||
409 | struct cifs_io_parms *parms, unsigned int *written, | ||
410 | struct kvec *iov, unsigned long nr_segs) | ||
411 | { | ||
412 | |||
413 | parms->persistent_fid = cfile->fid.persistent_fid; | ||
414 | parms->volatile_fid = cfile->fid.volatile_fid; | ||
415 | return SMB2_write(xid, parms, written, iov, nr_segs); | ||
416 | } | ||
417 | |||
407 | struct smb_version_operations smb21_operations = { | 418 | struct smb_version_operations smb21_operations = { |
408 | .setup_request = smb2_setup_request, | 419 | .setup_request = smb2_setup_request, |
409 | .setup_async_request = smb2_setup_async_request, | 420 | .setup_async_request = smb2_setup_async_request, |
@@ -447,6 +458,7 @@ struct smb_version_operations smb21_operations = { | |||
447 | .async_readv = smb2_async_readv, | 458 | .async_readv = smb2_async_readv, |
448 | .async_writev = smb2_async_writev, | 459 | .async_writev = smb2_async_writev, |
449 | .sync_read = smb2_sync_read, | 460 | .sync_read = smb2_sync_read, |
461 | .sync_write = smb2_sync_write, | ||
450 | }; | 462 | }; |
451 | 463 | ||
452 | struct smb_version_values smb21_values = { | 464 | struct smb_version_values smb21_values = { |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 23c569386f32..00dc45a7881c 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -1501,3 +1501,64 @@ async_writev_out: | |||
1501 | kfree(iov); | 1501 | kfree(iov); |
1502 | return rc; | 1502 | return rc; |
1503 | } | 1503 | } |
1504 | |||
1505 | /* | ||
1506 | * SMB2_write function gets iov pointer to kvec array with n_vec as a length. | ||
1507 | * The length field from io_parms must be at least 1 and indicates a number of | ||
1508 | * elements with data to write that begins with position 1 in iov array. All | ||
1509 | * data length is specified by count. | ||
1510 | */ | ||
1511 | int | ||
1512 | SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, | ||
1513 | unsigned int *nbytes, struct kvec *iov, int n_vec) | ||
1514 | { | ||
1515 | int rc = 0; | ||
1516 | struct smb2_write_req *req = NULL; | ||
1517 | struct smb2_write_rsp *rsp = NULL; | ||
1518 | int resp_buftype; | ||
1519 | *nbytes = 0; | ||
1520 | |||
1521 | if (n_vec < 1) | ||
1522 | return rc; | ||
1523 | |||
1524 | rc = small_smb2_init(SMB2_WRITE, io_parms->tcon, (void **) &req); | ||
1525 | if (rc) | ||
1526 | return rc; | ||
1527 | |||
1528 | if (io_parms->tcon->ses->server == NULL) | ||
1529 | return -ECONNABORTED; | ||
1530 | |||
1531 | req->hdr.ProcessId = cpu_to_le32(io_parms->pid); | ||
1532 | |||
1533 | req->PersistentFileId = io_parms->persistent_fid; | ||
1534 | req->VolatileFileId = io_parms->volatile_fid; | ||
1535 | req->WriteChannelInfoOffset = 0; | ||
1536 | req->WriteChannelInfoLength = 0; | ||
1537 | req->Channel = 0; | ||
1538 | req->Length = cpu_to_le32(io_parms->length); | ||
1539 | req->Offset = cpu_to_le64(io_parms->offset); | ||
1540 | /* 4 for rfc1002 length field */ | ||
1541 | req->DataOffset = cpu_to_le16( | ||
1542 | offsetof(struct smb2_write_req, Buffer) - 4); | ||
1543 | req->RemainingBytes = 0; | ||
1544 | |||
1545 | iov[0].iov_base = (char *)req; | ||
1546 | /* 4 for rfc1002 length field and 1 for Buffer */ | ||
1547 | iov[0].iov_len = get_rfc1002_length(req) + 4 - 1; | ||
1548 | |||
1549 | /* length of entire message including data to be written */ | ||
1550 | inc_rfc1001_len(req, io_parms->length - 1 /* Buffer */); | ||
1551 | |||
1552 | rc = SendReceive2(xid, io_parms->tcon->ses, iov, n_vec + 1, | ||
1553 | &resp_buftype, 0); | ||
1554 | |||
1555 | if (rc) { | ||
1556 | cifs_stats_fail_inc(io_parms->tcon, SMB2_WRITE_HE); | ||
1557 | cERROR(1, "Send error in write = %d", rc); | ||
1558 | } else { | ||
1559 | rsp = (struct smb2_write_rsp *)iov[0].iov_base; | ||
1560 | *nbytes = le32_to_cpu(rsp->DataLength); | ||
1561 | free_rsp_buf(resp_buftype, rsp); | ||
1562 | } | ||
1563 | return rc; | ||
1564 | } | ||
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 97e62f3df410..192d0c7d91eb 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
@@ -101,6 +101,8 @@ extern int smb2_async_readv(struct cifs_readdata *rdata); | |||
101 | extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | 101 | extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, |
102 | unsigned int *nbytes, char **buf, int *buf_type); | 102 | unsigned int *nbytes, char **buf, int *buf_type); |
103 | extern int smb2_async_writev(struct cifs_writedata *wdata); | 103 | extern int smb2_async_writev(struct cifs_writedata *wdata); |
104 | extern int SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, | ||
105 | unsigned int *nbytes, struct kvec *iov, int n_vec); | ||
104 | extern int SMB2_echo(struct TCP_Server_Info *server); | 106 | extern int SMB2_echo(struct TCP_Server_Info *server); |
105 | 107 | ||
106 | #endif /* _SMB2PROTO_H */ | 108 | #endif /* _SMB2PROTO_H */ |