vfs: add parameter to copy chunk VFS function to handle dup_extents
authorAurelien Aptel <aaptel@suse.com>
Mon, 24 Aug 2015 16:22:56 +0000 (18:22 +0200)
committerRalph Boehme <slow@samba.org>
Wed, 10 May 2017 06:22:18 +0000 (08:22 +0200)
FSCTL_DUPLICATE_EXTENTS_TO_FILE must be handled as a COW clone. Add a
copy-chunk flags parameter to the VFS to handle this.

Signed-off-by: Aurelien Aptel <aaptel@suse.com>
Signed-off-by: David Disseldorp <ddiss@samba.org>
Reviewed-by: Ralph Böhme <slow@samba.org>
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/vfs_btrfs.c
source3/modules/vfs_default.c
source3/modules/vfs_fruit.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_time_audit.c
source3/smbd/smb2_ioctl_network_fs.c
source3/smbd/vfs.c

index ffd951c..af119f3 100644 (file)
@@ -531,7 +531,8 @@ static struct tevent_req *skel_copy_chunk_send(struct vfs_handle_struct *handle,
                                               off_t src_off,
                                               struct files_struct *dest_fsp,
                                               off_t dest_off,
-                                              off_t num)
+                                              off_t num,
+                                              uint32_t flags)
 {
        struct tevent_req *req;
        struct skel_cc_state *cc_state;
index afadbc1..e974529 100644 (file)
@@ -619,7 +619,8 @@ static struct tevent_req *skel_copy_chunk_send(struct vfs_handle_struct *handle,
                                               off_t src_off,
                                               struct files_struct *dest_fsp,
                                               off_t dest_off,
-                                              off_t num)
+                                              off_t num,
+                                              uint32_t flags)
 {
        struct tevent_req *req;
        struct tevent_req *subreq;
@@ -633,7 +634,7 @@ static struct tevent_req *skel_copy_chunk_send(struct vfs_handle_struct *handle,
        cc_state->handle = handle;
        subreq = SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, cc_state, ev,
                                              src_fsp, src_off,
-                                             dest_fsp, dest_off, num);
+                                             dest_fsp, dest_off, num, flags);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
index f6df93a..fd493e4 100644 (file)
 /* Bump to version 36 - Samba 4.6 will ship with that */
 /* Version 36 - Remove is_offline and set_offline */
 /* Version 37 - Module init functions now take a TALLOC_CTX * parameter. */
+/* Version 37 - Add vfs_copy_chunk_flags for DUP_EXTENTS_TO_FILE */
 
 #define SMB_VFS_INTERFACE_VERSION 37
 
@@ -548,6 +549,17 @@ enum vfs_fallocate_flags {
        VFS_FALLOCATE_FL_PUNCH_HOLE             = 0x0002,
 };
 
+/*
+ * @VFS_COPY_CHUNK_FL_MUST_CLONE: indicates that copy_chunk_send_fn() copy must
+ *                               be handled as a COW clone, AKA reflink.
+ * @VFS_COPY_CHUNK_FL_MASK_ALL: all valid copychunk flags.
+ */
+enum vfs_copy_chunk_flags {
+       VFS_COPY_CHUNK_FL_MUST_CLONE            = 0x0001,
+
+       VFS_COPY_CHUNK_FL_MASK_ALL              = 0x0001,
+};
+
 struct vfs_aio_state {
        int error;
        uint64_t duration;
@@ -709,7 +721,8 @@ struct vfs_fn_pointers {
                                                 off_t src_off,
                                                 struct files_struct *dest_fsp,
                                                 off_t dest_off,
-                                                off_t num);
+                                                off_t to_copy,
+                                                uint32_t flags);
        NTSTATUS (*copy_chunk_recv_fn)(struct vfs_handle_struct *handle,
                                       struct tevent_req *req,
                                       off_t *copied);
@@ -1241,7 +1254,8 @@ struct tevent_req *smb_vfs_call_copy_chunk_send(struct vfs_handle_struct *handle
                                                off_t src_off,
                                                struct files_struct *dest_fsp,
                                                off_t dest_off,
-                                               off_t num);
+                                               off_t num,
+                                               uint32_t flags);
 NTSTATUS smb_vfs_call_copy_chunk_recv(struct vfs_handle_struct *handle,
                                      struct tevent_req *req,
                                      off_t *copied);
index 40c93f8..0cbcf89 100644 (file)
 #define SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES(handle, fsp, attributes) \
        smb_vfs_call_fset_dos_attributes((handle)->next, (fsp), (attributes))
 
-#define SMB_VFS_COPY_CHUNK_SEND(conn, mem_ctx, ev, src_fsp, src_off, dest_fsp, dest_off, num) \
-       smb_vfs_call_copy_chunk_send((conn)->vfs_handles, (mem_ctx), (ev), (src_fsp), (src_off), (dest_fsp), (dest_off), (num))
-#define SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, mem_ctx, ev, src_fsp, src_off, dest_fsp, dest_off, num) \
-       smb_vfs_call_copy_chunk_send((handle)->next, (mem_ctx), (ev), (src_fsp), (src_off), (dest_fsp), (dest_off), (num))
+#define SMB_VFS_COPY_CHUNK_SEND(conn, mem_ctx, ev, src_fsp, src_off, dest_fsp, dest_off, num, flags) \
+       smb_vfs_call_copy_chunk_send((conn)->vfs_handles, (mem_ctx), (ev), (src_fsp), (src_off), (dest_fsp), (dest_off), (num), (flags))
+#define SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, mem_ctx, ev, src_fsp, src_off, dest_fsp, dest_off, num, flags) \
+       smb_vfs_call_copy_chunk_send((handle)->next, (mem_ctx), (ev), (src_fsp), (src_off), (dest_fsp), (dest_off), (num), (flags))
 
 #define SMB_VFS_COPY_CHUNK_RECV(conn, req, copied) \
        smb_vfs_call_copy_chunk_recv((conn)->vfs_handles, (req), (copied))
index ab4fd99..bf0a080 100644 (file)
@@ -92,7 +92,8 @@ static struct tevent_req *btrfs_copy_chunk_send(struct vfs_handle_struct *handle
                                                off_t src_off,
                                                struct files_struct *dest_fsp,
                                                off_t dest_off,
-                                               off_t num)
+                                               off_t num,
+                                               uint32_t flags)
 {
        struct tevent_req *req;
        struct btrfs_cc_state *cc_state;
@@ -106,6 +107,12 @@ static struct tevent_req *btrfs_copy_chunk_send(struct vfs_handle_struct *handle
        if (req == NULL) {
                return NULL;
        }
+
+       if (flags & ~VFS_COPY_CHUNK_FL_MASK_ALL) {
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return tevent_req_post(req, ev);
+       }
+
        cc_state->handle = handle;
 
        if (num == 0) {
@@ -119,7 +126,8 @@ static struct tevent_req *btrfs_copy_chunk_send(struct vfs_handle_struct *handle
                                                                src_fsp,
                                                                src_off,
                                                                dest_fsp,
-                                                               dest_off, num);
+                                                               dest_off,
+                                                               num, flags);
                if (tevent_req_nomem(cc_state->subreq, req)) {
                        return tevent_req_post(req, ev);
                }
@@ -196,7 +204,8 @@ static struct tevent_req *btrfs_copy_chunk_send(struct vfs_handle_struct *handle
                                                                src_fsp,
                                                                src_off,
                                                                dest_fsp,
-                                                               dest_off, num);
+                                                               dest_off,
+                                                               num, flags);
                if (tevent_req_nomem(cc_state->subreq, req)) {
                        return tevent_req_post(req, ev);
                }
index d660120..ffdc40a 100644 (file)
@@ -1616,7 +1616,8 @@ static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *hand
                                                  off_t src_off,
                                                  struct files_struct *dest_fsp,
                                                  off_t dest_off,
-                                                 off_t to_copy)
+                                                 off_t to_copy,
+                                                 uint32_t flags)
 {
        struct tevent_req *req;
        struct vfs_cc_state *state = NULL;
@@ -1630,6 +1631,17 @@ static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *hand
                return NULL;
        }
 
+       if (flags & ~VFS_COPY_CHUNK_FL_MASK_ALL) {
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return tevent_req_post(req, ev);
+       }
+
+       if (flags & VFS_COPY_CHUNK_FL_MUST_CLONE) {
+               DEBUG(10, ("COW clones not supported by vfs_default\n"));
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return tevent_req_post(req, ev);
+       }
+
        *state = (struct vfs_cc_state) {
                .ev = ev,
                .src_fsp = src_fsp,
index 273540e..ee8cdb7 100644 (file)
@@ -5233,7 +5233,8 @@ static struct tevent_req *fruit_copy_chunk_send(struct vfs_handle_struct *handle
                                                off_t src_off,
                                                struct files_struct *dest_fsp,
                                                off_t dest_off,
-                                               off_t num)
+                                               off_t num,
+                                               uint32_t flags)
 {
        struct tevent_req *req, *subreq;
        struct fruit_copy_chunk_state *fruit_copy_chunk_state;
@@ -5283,7 +5284,8 @@ static struct tevent_req *fruit_copy_chunk_send(struct vfs_handle_struct *handle
                                              src_off,
                                              dest_fsp,
                                              dest_off,
-                                             to_copy);
+                                             to_copy,
+                                             flags);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
index 6614fbb..4c2eb87 100644 (file)
@@ -1889,12 +1889,14 @@ static struct tevent_req *smb_full_audit_copy_chunk_send(struct vfs_handle_struc
                                                         off_t src_off,
                                                         struct files_struct *dest_fsp,
                                                         off_t dest_off,
-                                                        off_t num)
+                                                        off_t num,
+                                                        uint32_t flags)
 {
        struct tevent_req *req;
 
        req = SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, mem_ctx, ev, src_fsp,
-                                          src_off, dest_fsp, dest_off, num);
+                                          src_off, dest_fsp, dest_off, num,
+                                          flags);
 
        do_log(SMB_VFS_OP_COPY_CHUNK_SEND, req, handle, "");
 
index 2ac3d97..52bd00e 100644 (file)
@@ -1886,7 +1886,8 @@ static struct tevent_req *smb_time_audit_copy_chunk_send(struct vfs_handle_struc
                                                         off_t src_off,
                                                         struct files_struct *dest_fsp,
                                                         off_t dest_off,
-                                                        off_t num)
+                                                        off_t num,
+                                                        uint32_t flags)
 {
        struct tevent_req *req;
        struct tevent_req *subreq;
@@ -1901,7 +1902,7 @@ static struct tevent_req *smb_time_audit_copy_chunk_send(struct vfs_handle_struc
        clock_gettime_mono(&cc_state->ts_send);
        subreq = SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, cc_state, ev,
                                              src_fsp, src_off,
-                                             dest_fsp, dest_off, num);
+                                             dest_fsp, dest_off, num, flags);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
index 5b869ec..7b496ef 100644 (file)
@@ -347,6 +347,7 @@ static NTSTATUS fsctl_srv_copychunk_loop(struct tevent_req *req)
                                                 0,
                                                 state->dst_fsp,
                                                 0,
+                                                0,
                                                 0);
                if (subreq == NULL) {
                        return NT_STATUS_NO_MEMORY;
@@ -366,7 +367,8 @@ static NTSTATUS fsctl_srv_copychunk_loop(struct tevent_req *req)
                                         chunk->source_off,
                                         state->dst_fsp,
                                         chunk->target_off,
-                                        length);
+                                        length,
+                                        0);
        if (tevent_req_nomem(subreq, req)) {
                return NT_STATUS_NO_MEMORY;
        }
index f75172a..560c4b2 100644 (file)
@@ -2305,11 +2305,13 @@ struct tevent_req *smb_vfs_call_copy_chunk_send(struct vfs_handle_struct *handle
                                                off_t src_off,
                                                struct files_struct *dest_fsp,
                                                off_t dest_off,
-                                               off_t num)
+                                               off_t num,
+                                               uint32_t flags)
 {
        VFS_FIND(copy_chunk_send);
        return handle->fns->copy_chunk_send_fn(handle, mem_ctx, ev, src_fsp,
-                                              src_off, dest_fsp, dest_off, num);
+                                              src_off, dest_fsp, dest_off, num,
+                                              flags);
 }
 
 NTSTATUS smb_vfs_call_copy_chunk_recv(struct vfs_handle_struct *handle,