1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-28 01:58:17 +03:00

s3/smbd: use SMB_VFS_OFFLOAD_READ_SEND/RECV

No change in behaviour, this just uses the new SMB_VFS_OFFLOAD_READ_SEND
in the duplicate extents and the resume key ioctls.

In the copy-chunk/resume-key case this means using
SMB_VFS_OFFLOAD_READ_SEND to create the resume-key token that is
returned to the client.

In the duplicate-extents case this ensures we can later call
offload-write, which requires a previous call to offload-read that
associates a token with a file-handle.

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
This commit is contained in:
Ralph Boehme 2017-06-06 12:23:27 +02:00
parent af6cbc7a44
commit 67ed1edba7
2 changed files with 91 additions and 49 deletions

View File

@ -161,9 +161,12 @@ static NTSTATUS fsctl_dup_extents_check_sparse(struct files_struct *src_fsp,
struct fsctl_dup_extents_state {
struct tevent_context *ev;
struct connection_struct *conn;
struct files_struct *src_fsp;
struct files_struct *dst_fsp;
struct fsctl_dup_extents_to_file dup_extents;
};
static void fsctl_dup_extents_offload_read_done(struct tevent_req *subreq);
static void fsctl_dup_extents_vfs_done(struct tevent_req *subreq);
static struct tevent_req *fsctl_dup_extents_send(TALLOC_CTX *mem_ctx,
@ -195,6 +198,7 @@ static struct tevent_req *fsctl_dup_extents_send(TALLOC_CTX *mem_ctx,
*state = (struct fsctl_dup_extents_state) {
.conn = dst_fsp->conn,
.ev = ev,
.dst_fsp = dst_fsp,
};
if ((dst_fsp->conn->fs_capabilities
@ -230,6 +234,7 @@ static struct tevent_req *fsctl_dup_extents_send(TALLOC_CTX *mem_ctx,
tevent_req_nterror(req, NT_STATUS_INVALID_HANDLE);
return tevent_req_post(req, ev);
}
state->src_fsp = src_fsp;
status = fsctl_dup_extents_check_lengths(src_fsp, dst_fsp,
&state->dup_extents);
@ -257,20 +262,48 @@ static struct tevent_req *fsctl_dup_extents_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
subreq = SMB_VFS_OFFLOAD_READ_SEND(state, ev, src_fsp,
FSCTL_DUP_EXTENTS_TO_FILE,
0, 0, 0);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
tevent_req_set_callback(subreq, fsctl_dup_extents_offload_read_done,
req);
return req;
}
static void fsctl_dup_extents_offload_read_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req);
struct fsctl_dup_extents_state *state = tevent_req_data(
req, struct fsctl_dup_extents_state);
DATA_BLOB token_blob;
NTSTATUS status;
status = SMB_VFS_OFFLOAD_READ_RECV(subreq, state->dst_fsp->conn,
state, &token_blob);
if (tevent_req_nterror(req, status)) {
return;
}
/* tell the VFS to ignore locks across the clone, matching ReFS */
subreq = SMB_VFS_COPY_CHUNK_SEND(dst_fsp->conn, state, ev,
src_fsp, state->dup_extents.source_off,
dst_fsp, state->dup_extents.target_off,
subreq = SMB_VFS_COPY_CHUNK_SEND(state->dst_fsp->conn,
state,
state->ev,
state->src_fsp,
state->dup_extents.source_off,
state->dst_fsp,
state->dup_extents.target_off,
state->dup_extents.byte_count,
VFS_COPY_CHUNK_FL_MUST_CLONE
| VFS_COPY_CHUNK_FL_IGNORE_LOCKS);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
return;
}
tevent_req_set_callback(subreq, fsctl_dup_extents_vfs_done, req);
return subreq;
return;
}
static void fsctl_dup_extents_vfs_done(struct tevent_req *subreq)

View File

@ -672,42 +672,8 @@ static NTSTATUS fsctl_validate_neg_info(TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
static NTSTATUS fsctl_srv_req_resume_key(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct files_struct *fsp,
uint32_t in_max_output,
DATA_BLOB *out_output)
{
struct req_resume_key_rsp rkey_rsp;
enum ndr_err_code ndr_ret;
DATA_BLOB output;
if (fsp == NULL) {
return NT_STATUS_FILE_CLOSED;
}
ZERO_STRUCT(rkey_rsp);
/* combine persistent and volatile handles for the resume key */
SBVAL(rkey_rsp.resume_key, 0, fsp->op->global->open_persistent_id);
SBVAL(rkey_rsp.resume_key, 8, fsp->op->global->open_volatile_id);
ndr_ret = ndr_push_struct_blob(&output, mem_ctx, &rkey_rsp,
(ndr_push_flags_fn_t)ndr_push_req_resume_key_rsp);
if (ndr_ret != NDR_ERR_SUCCESS) {
return NT_STATUS_INTERNAL_ERROR;
}
if (in_max_output < output.length) {
DEBUG(1, ("max output %u too small for resume key rsp %ld\n",
(unsigned int)in_max_output, (long int)output.length));
return NT_STATUS_INVALID_PARAMETER;
}
*out_output = output;
return NT_STATUS_OK;
}
static void smb2_ioctl_network_fs_copychunk_done(struct tevent_req *subreq);
static void smb2_ioctl_network_fs_offload_read_done(struct tevent_req *subreq);
struct tevent_req *smb2_ioctl_network_fs(uint32_t ctl_code,
struct tevent_context *ev,
@ -777,14 +743,18 @@ struct tevent_req *smb2_ioctl_network_fs(uint32_t ctl_code,
return tevent_req_post(req, ev);
break;
case FSCTL_SRV_REQUEST_RESUME_KEY:
status = fsctl_srv_req_resume_key(state, ev, state->fsp,
state->in_max_output,
&state->out_output);
if (!tevent_req_nterror(req, status)) {
tevent_req_done(req);
subreq = SMB_VFS_OFFLOAD_READ_SEND(state,
ev,
state->fsp,
FSCTL_SRV_REQUEST_RESUME_KEY,
0, 0, 0);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
return tevent_req_post(req, ev);
break;
tevent_req_set_callback(
subreq, smb2_ioctl_network_fs_offload_read_done, req);
return req;
default: {
uint8_t *out_data = NULL;
uint32_t out_data_len = 0;
@ -854,3 +824,42 @@ static void smb2_ioctl_network_fs_copychunk_done(struct tevent_req *subreq)
tevent_req_done(req);
}
}
static void smb2_ioctl_network_fs_offload_read_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req);
struct smbd_smb2_ioctl_state *state = tevent_req_data(
req, struct smbd_smb2_ioctl_state);
struct req_resume_key_rsp rkey_rsp;
enum ndr_err_code ndr_ret;
DATA_BLOB token;
NTSTATUS status;
status = SMB_VFS_OFFLOAD_READ_RECV(subreq,
state->fsp->conn,
state,
&token);
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
return;
}
if (token.length != sizeof(rkey_rsp.resume_key)) {
tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
return;
}
ZERO_STRUCT(rkey_rsp);
memcpy(rkey_rsp.resume_key, token.data, token.length);
ndr_ret = ndr_push_struct_blob(&state->out_output, state, &rkey_rsp,
(ndr_push_flags_fn_t)ndr_push_req_resume_key_rsp);
if (ndr_ret != NDR_ERR_SUCCESS) {
tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
return;
}
tevent_req_done(req);
return;
}