diff options
author | Ralph Boehme <slow@samba.org> | 2017-06-06 12:23:27 +0200 |
---|---|---|
committer | Ralph Boehme <slow@samba.org> | 2017-07-03 19:59:08 +0200 |
commit | 67ed1edba75e967d7d8d4157f918b50d23c47b0b (patch) | |
tree | 1cc62c41ed2a9664217a2c4ed079508914f34897 | |
parent | af6cbc7a441e05f71ae4e97c7d82c27868633e53 (diff) | |
download | samba-67ed1edba75e967d7d8d4157f918b50d23c47b0b.tar.gz |
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>
-rw-r--r-- | source3/smbd/smb2_ioctl_filesys.c | 47 | ||||
-rw-r--r-- | source3/smbd/smb2_ioctl_network_fs.c | 93 |
2 files changed, 91 insertions, 49 deletions
diff --git a/source3/smbd/smb2_ioctl_filesys.c b/source3/smbd/smb2_ioctl_filesys.c index 392372ffecd..7008a473f4c 100644 --- a/source3/smbd/smb2_ioctl_filesys.c +++ b/source3/smbd/smb2_ioctl_filesys.c @@ -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) diff --git a/source3/smbd/smb2_ioctl_network_fs.c b/source3/smbd/smb2_ioctl_network_fs.c index 016a0e4ee5e..acb17c3b0c7 100644 --- a/source3/smbd/smb2_ioctl_network_fs.c +++ b/source3/smbd/smb2_ioctl_network_fs.c @@ -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; +} |