s3/smbd: use SMB_VFS_OFFLOAD_READ_SEND/RECV
authorRalph Boehme <slow@samba.org>
Tue, 6 Jun 2017 10:23:27 +0000 (12:23 +0200)
committerRalph Boehme <slow@samba.org>
Mon, 3 Jul 2017 17:59:08 +0000 (19:59 +0200)
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>
source3/smbd/smb2_ioctl_filesys.c
source3/smbd/smb2_ioctl_network_fs.c

index 392372ffecdfd2ac9507fa576c2a0697e03e5029..7008a473f4c3b998b504307de6e1c5727d5c7a15 100644 (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)
index 016a0e4ee5eda72a20a5bfed8daba128d2316090..acb17c3b0c75e84f6860131e8bb395c79f26c360 100644 (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;
+}