CIFS: Add readpage support for SMB2
Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org> Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:
parent
f9c6e234c3
commit
d8e050398d
3 changed files with 65 additions and 0 deletions
|
@ -393,6 +393,17 @@ smb2_read_data_length(char *buf)
|
|||
return le32_to_cpu(rsp->DataLength);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
smb2_sync_read(const unsigned int xid, struct cifsFileInfo *cfile,
|
||||
struct cifs_io_parms *parms, unsigned int *bytes_read,
|
||||
char **buf, int *buf_type)
|
||||
{
|
||||
parms->persistent_fid = cfile->fid.persistent_fid;
|
||||
parms->volatile_fid = cfile->fid.volatile_fid;
|
||||
return SMB2_read(xid, parms, bytes_read, buf, buf_type);
|
||||
}
|
||||
|
||||
struct smb_version_operations smb21_operations = {
|
||||
.setup_request = smb2_setup_request,
|
||||
.setup_async_request = smb2_setup_async_request,
|
||||
|
@ -435,6 +446,7 @@ struct smb_version_operations smb21_operations = {
|
|||
.flush = smb2_flush_file,
|
||||
.async_readv = smb2_async_readv,
|
||||
.async_writev = smb2_async_writev,
|
||||
.sync_read = smb2_sync_read,
|
||||
};
|
||||
|
||||
struct smb_version_values smb21_values = {
|
||||
|
|
|
@ -1329,6 +1329,57 @@ smb2_async_readv(struct cifs_readdata *rdata)
|
|||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
|
||||
unsigned int *nbytes, char **buf, int *buf_type)
|
||||
{
|
||||
int resp_buftype, rc = -EACCES;
|
||||
struct smb2_read_rsp *rsp = NULL;
|
||||
struct kvec iov[1];
|
||||
|
||||
*nbytes = 0;
|
||||
rc = smb2_new_read_req(iov, io_parms, 0, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = SendReceive2(xid, io_parms->tcon->ses, iov, 1,
|
||||
&resp_buftype, CIFS_LOG_ERROR);
|
||||
|
||||
rsp = (struct smb2_read_rsp *)iov[0].iov_base;
|
||||
|
||||
if (rsp->hdr.Status == STATUS_END_OF_FILE) {
|
||||
free_rsp_buf(resp_buftype, iov[0].iov_base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
|
||||
cERROR(1, "Send error in read = %d", rc);
|
||||
} else {
|
||||
*nbytes = le32_to_cpu(rsp->DataLength);
|
||||
if ((*nbytes > CIFS_MAX_MSGSIZE) ||
|
||||
(*nbytes > io_parms->length)) {
|
||||
cFYI(1, "bad length %d for count %d", *nbytes,
|
||||
io_parms->length);
|
||||
rc = -EIO;
|
||||
*nbytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (*buf) {
|
||||
memcpy(*buf, (char *)rsp->hdr.ProtocolId + rsp->DataOffset,
|
||||
*nbytes);
|
||||
free_rsp_buf(resp_buftype, iov[0].iov_base);
|
||||
} else if (resp_buftype != CIFS_NO_BUFFER) {
|
||||
*buf = iov[0].iov_base;
|
||||
if (resp_buftype == CIFS_SMALL_BUFFER)
|
||||
*buf_type = CIFS_SMALL_BUFFER;
|
||||
else if (resp_buftype == CIFS_LARGE_BUFFER)
|
||||
*buf_type = CIFS_LARGE_BUFFER;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the mid_state and signature on received buffer (if any), and queue the
|
||||
* workqueue completion task.
|
||||
|
|
|
@ -98,6 +98,8 @@ extern int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
u64 persistent_fid, u64 volatile_fid,
|
||||
__le64 *uniqueid);
|
||||
extern int smb2_async_readv(struct cifs_readdata *rdata);
|
||||
extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
|
||||
unsigned int *nbytes, char **buf, int *buf_type);
|
||||
extern int smb2_async_writev(struct cifs_writedata *wdata);
|
||||
extern int SMB2_echo(struct TCP_Server_Info *server);
|
||||
|
||||
|
|
Loading…
Reference in a new issue