summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2017-06-06 12:23:27 +0200
committerRalph Boehme <slow@samba.org>2017-07-03 19:59:08 +0200
commit67ed1edba75e967d7d8d4157f918b50d23c47b0b (patch)
tree1cc62c41ed2a9664217a2c4ed079508914f34897
parentaf6cbc7a441e05f71ae4e97c7d82c27868633e53 (diff)
downloadsamba-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.c47
-rw-r--r--source3/smbd/smb2_ioctl_network_fs.c93
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;
+}