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,
*state = (struct fsctl_dup_extents_state) {
.conn = dst_fsp->conn,
.ev = ev,
+ .dst_fsp = dst_fsp,
};
if ((dst_fsp->conn->fs_capabilities
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);
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)
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,
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;
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;
+}