[PATCH 04/13] s3-vfs: add copy_chunk vfs hooks

David Disseldorp ddiss at samba.org
Tue Nov 13 08:16:28 MST 2012


From: David Disseldorp <ddiss at suse.de>

copy_chunk copies n bytes from a source file at a specific offset to a
destination file at a given offset. This interface will be used in
handling smb2 FSCTL_SRV_COPYCHUNK ioctl requests.

Provide send and receive hooks for copy chunk VFS interface, allowing
asynchronous behaviour.
---
 docs-xml/manpages/vfs_full_audit.8.xml |    2 +
 examples/VFS/skel_opaque.c             |   42 ++++++++++++++++
 examples/VFS/skel_transparent.c        |   75 ++++++++++++++++++++++++++++
 source3/include/vfs.h                  |   25 +++++++++-
 source3/include/vfs_macros.h           |   10 ++++
 source3/modules/vfs_default.c          |   71 ++++++++++++++++++++++++++
 source3/modules/vfs_full_audit.c       |   38 ++++++++++++++
 source3/modules/vfs_time_audit.c       |   85 ++++++++++++++++++++++++++++++++
 source3/smbd/vfs.c                     |   26 +++++++++-
 9 files changed, 371 insertions(+), 3 deletions(-)

diff --git a/docs-xml/manpages/vfs_full_audit.8.xml b/docs-xml/manpages/vfs_full_audit.8.xml
index a44924a..312bc25 100644
--- a/docs-xml/manpages/vfs_full_audit.8.xml
+++ b/docs-xml/manpages/vfs_full_audit.8.xml
@@ -46,6 +46,8 @@
         <member>close</member>
         <member>closedir</member>
         <member>connect</member>
+	<member>copy_chunk_send</member>
+	<member>copy_chunk_recv</member>
         <member>disconnect</member>
         <member>disk_free</member>
         <member>fchmod</member>
diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index 6948d64..53c64ca 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -22,6 +22,7 @@
  */
 
 #include "../source3/include/includes.h"
+#include "lib/util/tevent_ntstatus.h"
 
 /* PLEASE,PLEASE READ THE VFS MODULES CHAPTER OF THE 
    SAMBA DEVELOPERS GUIDE!!!!!!
@@ -488,6 +489,45 @@ static struct file_id skel_file_id_create(vfs_handle_struct *handle,
 	return id;
 }
 
+struct skel_cc_state {
+	uint64_t unused;
+};
+static struct tevent_req *skel_copy_chunk_send(struct vfs_handle_struct *handle,
+					       TALLOC_CTX *mem_ctx,
+					       struct tevent_context *ev,
+					       struct files_struct *src_fsp,
+					       off_t src_off,
+					       struct files_struct *dest_fsp,
+					       off_t dest_off,
+					       off_t num)
+{
+	struct tevent_req *req;
+	struct skel_cc_state *cc_state;
+
+	req = tevent_req_create(mem_ctx, &cc_state, struct skel_cc_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
+	return tevent_req_post(req, ev);
+}
+
+static NTSTATUS skel_copy_chunk_recv(struct vfs_handle_struct *handle,
+				     struct tevent_req *req,
+				     off_t *copied)
+{
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		tevent_req_received(req);
+		return status;
+	}
+	tevent_req_received(req);
+
+	return NT_STATUS_OK;
+}
+
 static NTSTATUS skel_streaminfo(struct vfs_handle_struct *handle,
 				struct files_struct *fsp,
 				const char *fname,
@@ -825,6 +865,8 @@ struct vfs_fn_pointers skel_opaque_fns = {
 	.notify_watch_fn = skel_notify_watch,
 	.chflags_fn = skel_chflags,
 	.file_id_create_fn = skel_file_id_create,
+	.copy_chunk_send_fn = skel_copy_chunk_send,
+	.copy_chunk_recv_fn = skel_copy_chunk_recv,
 
 	.streaminfo_fn = skel_streaminfo,
 	.get_real_filename_fn = skel_get_real_filename,
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index 02e8184..99feade 100644
--- a/examples/VFS/skel_transparent.c
+++ b/examples/VFS/skel_transparent.c
@@ -23,6 +23,7 @@
 
 #include "../source3/include/includes.h"
 #include "lib/util/tevent_unix.h"
+#include "lib/util/tevent_ntstatus.h"
 
 /* PLEASE,PLEASE READ THE VFS MODULES CHAPTER OF THE 
    SAMBA DEVELOPERS GUIDE!!!!!!
@@ -572,6 +573,78 @@ static struct file_id skel_file_id_create(vfs_handle_struct *handle,
 	return SMB_VFS_NEXT_FILE_ID_CREATE(handle, sbuf);
 }
 
+struct skel_cc_state {
+	struct vfs_handle_struct *handle;
+	off_t copied;
+};
+static void skel_copy_chunk_done(struct tevent_req *subreq);
+
+static struct tevent_req *skel_copy_chunk_send(struct vfs_handle_struct *handle,
+					       TALLOC_CTX *mem_ctx,
+					       struct tevent_context *ev,
+					       struct files_struct *src_fsp,
+					       off_t src_off,
+					       struct files_struct *dest_fsp,
+					       off_t dest_off,
+					       off_t num)
+{
+	struct tevent_req *req;
+	struct tevent_req *subreq;
+	struct skel_cc_state *cc_state;
+
+	req = tevent_req_create(mem_ctx, &cc_state, struct skel_cc_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	cc_state->handle = handle;
+	subreq = SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, cc_state, ev,
+					      src_fsp, src_off,
+					      dest_fsp, dest_off, num);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	tevent_req_set_callback(subreq, skel_copy_chunk_done, req);
+	return req;
+}
+
+static void skel_copy_chunk_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct skel_cc_state *cc_state
+			= tevent_req_data(req, struct skel_cc_state);
+	NTSTATUS status;
+
+	status = SMB_VFS_NEXT_COPY_CHUNK_RECV(cc_state->handle,
+					      subreq,
+					      &cc_state->copied);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+	tevent_req_done(req);
+}
+
+static NTSTATUS skel_copy_chunk_recv(struct vfs_handle_struct *handle,
+				     struct tevent_req *req,
+				     off_t *copied)
+{
+	struct skel_cc_state *cc_state
+			= tevent_req_data(req, struct skel_cc_state);
+	NTSTATUS status;
+
+	*copied = cc_state->copied;
+	if (tevent_req_is_nterror(req, &status)) {
+		tevent_req_received(req);
+		return status;
+	}
+
+	tevent_req_received(req);
+	return NT_STATUS_OK;
+}
+
 static NTSTATUS skel_streaminfo(struct vfs_handle_struct *handle,
 				struct files_struct *fsp,
 				const char *fname,
@@ -898,6 +971,8 @@ struct vfs_fn_pointers skel_transparent_fns = {
 	.notify_watch_fn = skel_notify_watch,
 	.chflags_fn = skel_chflags,
 	.file_id_create_fn = skel_file_id_create,
+	.copy_chunk_send_fn = skel_copy_chunk_send,
+	.copy_chunk_recv_fn = skel_copy_chunk_recv,
 
 	.streaminfo_fn = skel_streaminfo,
 	.get_real_filename_fn = skel_get_real_filename,
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 2992c1d..2805c1e 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -147,6 +147,7 @@
 /* Bump to version 30 - Samba 4.0.0 will ship with interface version 30 */
 /* Leave at 30 - not yet released. Added conn->cwd to save vfs_GetWd() calls. */
 /* Leave at 30 - not yet released. Changed sys_acl_blob_get_file interface to remove type */
+/* Leave at 30 - not yet released. add SMB_VFS_COPY_CHUNK() */
 #define SMB_VFS_INTERFACE_VERSION 30
 
 /*
@@ -609,6 +610,17 @@ struct vfs_fn_pointers {
 	int (*chflags_fn)(struct vfs_handle_struct *handle, const char *path, unsigned int flags);
 	struct file_id (*file_id_create_fn)(struct vfs_handle_struct *handle,
 					    const SMB_STRUCT_STAT *sbuf);
+	struct tevent_req *(*copy_chunk_send_fn)(struct vfs_handle_struct *handle,
+						 TALLOC_CTX *mem_ctx,
+						 struct tevent_context *ev,
+						 struct files_struct *src_fsp,
+						 off_t src_off,
+						 struct files_struct *dest_fsp,
+						 off_t dest_off,
+						 off_t num);
+	NTSTATUS (*copy_chunk_recv_fn)(struct vfs_handle_struct *handle,
+				       struct tevent_req *req,
+				       off_t *copied);
 
 	NTSTATUS (*streaminfo_fn)(struct vfs_handle_struct *handle,
 				  struct files_struct *fsp,
@@ -1080,7 +1092,18 @@ NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
 			    uint32_t in_len,
 			    uint8_t **_out_data,
 			    uint32_t max_out_len,
-			    uint32_t *out_len); 
+			    uint32_t *out_len);
+struct tevent_req *smb_vfs_call_copy_chunk_send(struct vfs_handle_struct *handle,
+						TALLOC_CTX *mem_ctx,
+						struct tevent_context *ev,
+						struct files_struct *src_fsp,
+						off_t src_off,
+						struct files_struct *dest_fsp,
+						off_t dest_off,
+						off_t num);
+NTSTATUS smb_vfs_call_copy_chunk_recv(struct vfs_handle_struct *handle,
+				      struct tevent_req *req,
+				      off_t *copied);
 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
 				  struct files_struct *fsp,
 				  uint32 security_info,
diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
index 331fe00..364a4ca 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -399,6 +399,16 @@
 #define SMB_VFS_NEXT_FSCTL(handle, fsp, ctx, function, req_flags, in_data, in_len, out_data, max_out_len, out_len) \
 	smb_vfs_call_fsctl((handle)->next, (fsp), (ctx), (function), (req_flags), (in_data), (in_len), (out_data), (max_out_len), (out_len))
 
+#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_RECV(conn, req, copied) \
+	smb_vfs_call_copy_chunk_recv((conn)->vfs_handles, (req), (copied))
+#define SMB_VFS_NEXT_COPY_CHUNK_RECV(handle, req, copied) \
+	smb_vfs_call_copy_chunk_recv((handle)->next, (req), (copied))
+
 #define SMB_VFS_FGET_NT_ACL(fsp, security_info, mem_ctx, ppdesc)		\
 		smb_vfs_call_fget_nt_acl((fsp)->conn->vfs_handles, (fsp), (security_info), (mem_ctx), (ppdesc))
 #define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, mem_ctx, ppdesc) \
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 0f651dc..2bac8f2 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -31,6 +31,7 @@
 #include "librpc/gen_ndr/ndr_dfsblobs.h"
 #include "lib/util/tevent_unix.h"
 #include "lib/asys/asys.h"
+#include "lib/util/tevent_ntstatus.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_VFS
@@ -1323,6 +1324,74 @@ static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
 	return NT_STATUS_NOT_SUPPORTED;
 }
 
+struct vfs_cc_state {
+	off_t copied;
+};
+
+static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
+						  TALLOC_CTX *mem_ctx,
+						  struct tevent_context *ev,
+						  struct files_struct *src_fsp,
+						  off_t src_off,
+						  struct files_struct *dest_fsp,
+						  off_t dest_off,
+						  off_t num)
+{
+	struct tevent_req *req;
+	struct vfs_cc_state *vfs_cc_state;
+
+	DEBUG(10, ("performing server side copy chunk of length %lu\n",
+		   (unsigned long)num));
+
+	req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	/* everything is done synchronously for now */
+	if (SMB_VFS_LSEEK(src_fsp, src_off, SEEK_SET) != src_off) {
+		tevent_req_nterror(req, map_nt_error_from_unix(errno));
+		return tevent_req_post(req, ev);
+	}
+	if (SMB_VFS_LSEEK(dest_fsp, dest_off, SEEK_SET) != dest_off) {
+		tevent_req_nterror(req, map_nt_error_from_unix(errno));
+		return tevent_req_post(req, ev);
+	}
+
+	vfs_cc_state->copied = vfs_transfer_file(src_fsp, dest_fsp, num);
+	if (vfs_cc_state->copied == -1) {
+		tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
+		return tevent_req_post(req, ev);
+	}
+
+	tevent_req_done(req);
+	return tevent_req_post(req, ev);
+}
+
+static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
+					struct tevent_req *req,
+					off_t *copied)
+{
+	struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
+							struct vfs_cc_state);
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		DEBUG(2, ("server side copy chunk failed: %s\n",
+			  nt_errstr(status)));
+		*copied = 0;
+		tevent_req_received(req);
+		return status;
+	}
+
+	*copied = vfs_cc_state->copied;
+	DEBUG(10, ("server side copy chunk copied %lu\n",
+		   (unsigned long)*copied));
+	tevent_req_received(req);
+
+	return NT_STATUS_OK;
+}
+
 /********************************************************************
  Given a stat buffer return the allocated size on disk, taking into
  account sparse files.
@@ -2367,6 +2436,8 @@ static struct vfs_fn_pointers vfs_default_fns = {
 	.strict_unlock_fn = vfswrap_strict_unlock,
 	.translate_name_fn = vfswrap_translate_name,
 	.fsctl_fn = vfswrap_fsctl,
+	.copy_chunk_send_fn = vfswrap_copy_chunk_send,
+	.copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
 
 	/* NT ACL operations. */
 
diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c
index b1fb090..549f55e 100644
--- a/source3/modules/vfs_full_audit.c
+++ b/source3/modules/vfs_full_audit.c
@@ -161,6 +161,8 @@ typedef enum _vfs_op_type {
 	SMB_VFS_OP_STRICT_LOCK,
 	SMB_VFS_OP_STRICT_UNLOCK,
 	SMB_VFS_OP_TRANSLATE_NAME,
+	SMB_VFS_OP_COPY_CHUNK_SEND,
+	SMB_VFS_OP_COPY_CHUNK_RECV,
 
 	/* NT ACL operations. */
 
@@ -281,6 +283,8 @@ static struct {
 	{ SMB_VFS_OP_STRICT_LOCK, "strict_lock" },
 	{ SMB_VFS_OP_STRICT_UNLOCK, "strict_unlock" },
 	{ SMB_VFS_OP_TRANSLATE_NAME,	"translate_name" },
+	{ SMB_VFS_OP_COPY_CHUNK_SEND,	"copy_chunk_send" },
+	{ SMB_VFS_OP_COPY_CHUNK_RECV,	"copy_chunk_recv" },
 	{ SMB_VFS_OP_FGET_NT_ACL,	"fget_nt_acl" },
 	{ SMB_VFS_OP_GET_NT_ACL,	"get_nt_acl" },
 	{ SMB_VFS_OP_FSET_NT_ACL,	"fset_nt_acl" },
@@ -1732,6 +1736,38 @@ static NTSTATUS smb_full_audit_translate_name(struct vfs_handle_struct *handle,
 	return result;
 }
 
+static struct tevent_req *smb_full_audit_copy_chunk_send(struct vfs_handle_struct *handle,
+							 TALLOC_CTX *mem_ctx,
+							 struct tevent_context *ev,
+							 struct files_struct *src_fsp,
+							 off_t src_off,
+							 struct files_struct *dest_fsp,
+							 off_t dest_off,
+							 off_t num)
+{
+	struct tevent_req *req;
+
+	req = SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, mem_ctx, ev, src_fsp,
+					   src_off, dest_fsp, dest_off, num);
+
+	do_log(SMB_VFS_OP_COPY_CHUNK_SEND, req, handle, "");
+
+	return req;
+}
+
+static NTSTATUS smb_full_audit_copy_chunk_recv(struct vfs_handle_struct *handle,
+					       struct tevent_req *req,
+					       off_t *copied)
+{
+	NTSTATUS result;
+
+	result = SMB_VFS_NEXT_COPY_CHUNK_RECV(handle, req, copied);
+
+	do_log(SMB_VFS_OP_COPY_CHUNK_RECV, NT_STATUS_IS_OK(result), handle, "");
+
+	return result;
+}
+
 static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
 					   uint32 security_info,
 					   TALLOC_CTX *mem_ctx,
@@ -2131,6 +2167,8 @@ static struct vfs_fn_pointers vfs_full_audit_fns = {
 	.strict_lock_fn = smb_full_audit_strict_lock,
 	.strict_unlock_fn = smb_full_audit_strict_unlock,
 	.translate_name_fn = smb_full_audit_translate_name,
+	.copy_chunk_send_fn = smb_full_audit_copy_chunk_send,
+	.copy_chunk_recv_fn = smb_full_audit_copy_chunk_recv,
 	.fget_nt_acl_fn = smb_full_audit_fget_nt_acl,
 	.get_nt_acl_fn = smb_full_audit_get_nt_acl,
 	.fset_nt_acl_fn = smb_full_audit_fset_nt_acl,
diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c
index 95b4148..1b14d65 100644
--- a/source3/modules/vfs_time_audit.c
+++ b/source3/modules/vfs_time_audit.c
@@ -29,6 +29,7 @@
 #include "smbd/smbd.h"
 #include "ntioctl.h"
 #include "lib/util/tevent_unix.h"
+#include "lib/util/tevent_ntstatus.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_VFS
@@ -1668,6 +1669,88 @@ static NTSTATUS smb_time_audit_translate_name(struct vfs_handle_struct *handle,
 	return result;
 }
 
+struct time_audit_cc_state {
+	struct timespec ts_send;
+	struct vfs_handle_struct *handle;
+	off_t copied;
+};
+static void smb_time_audit_copy_chunk_done(struct tevent_req *subreq);
+
+static struct tevent_req *smb_time_audit_copy_chunk_send(struct vfs_handle_struct *handle,
+							 TALLOC_CTX *mem_ctx,
+							 struct tevent_context *ev,
+							 struct files_struct *src_fsp,
+							 off_t src_off,
+							 struct files_struct *dest_fsp,
+							 off_t dest_off,
+							 off_t num)
+{
+	struct tevent_req *req;
+	struct tevent_req *subreq;
+	struct time_audit_cc_state *cc_state;
+
+	req = tevent_req_create(mem_ctx, &cc_state, struct time_audit_cc_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	cc_state->handle = handle;
+	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);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	tevent_req_set_callback(subreq, smb_time_audit_copy_chunk_done, req);
+	return req;
+}
+
+static void smb_time_audit_copy_chunk_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct time_audit_cc_state *cc_state
+			= tevent_req_data(req, struct time_audit_cc_state);
+	NTSTATUS status;
+
+	status = SMB_VFS_NEXT_COPY_CHUNK_RECV(cc_state->handle,
+					      subreq,
+					      &cc_state->copied);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+	tevent_req_done(req);
+}
+
+static NTSTATUS smb_time_audit_copy_chunk_recv(struct vfs_handle_struct *handle,
+					       struct tevent_req *req,
+					       off_t *copied)
+{
+	struct time_audit_cc_state *cc_state
+			= tevent_req_data(req, struct time_audit_cc_state);
+	struct timespec ts_recv;
+	double timediff;
+	NTSTATUS status;
+
+	clock_gettime_mono(&ts_recv);
+	timediff = nsec_time_diff(&ts_recv, &cc_state->ts_send)*1.0e-9;
+	if (timediff > audit_timeout) {
+		smb_time_audit_log("copy_chunk", timediff);
+	}
+
+	*copied = cc_state->copied;
+	if (tevent_req_is_nterror(req, &status)) {
+		tevent_req_received(req);
+		return status;
+	}
+
+	tevent_req_received(req);
+	return NT_STATUS_OK;
+}
+
 static NTSTATUS smb_time_audit_fget_nt_acl(vfs_handle_struct *handle,
 					   files_struct *fsp,
 					   uint32 security_info,
@@ -2179,6 +2262,8 @@ static struct vfs_fn_pointers vfs_time_audit_fns = {
 	.strict_lock_fn = smb_time_audit_strict_lock,
 	.strict_unlock_fn = smb_time_audit_strict_unlock,
 	.translate_name_fn = smb_time_audit_translate_name,
+	.copy_chunk_send_fn = smb_time_audit_copy_chunk_send,
+	.copy_chunk_recv_fn = smb_time_audit_copy_chunk_recv,
 	.fget_nt_acl_fn = smb_time_audit_fget_nt_acl,
 	.get_nt_acl_fn = smb_time_audit_get_nt_acl,
 	.fset_nt_acl_fn = smb_time_audit_fset_nt_acl,
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 581a025..b81e8de 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -2157,11 +2157,33 @@ NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
 			    uint32_t *out_len)
 {
 	VFS_FIND(fsctl);
-	return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags, 
-				     in_data, in_len, out_data, max_out_len, 
+	return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
+				     in_data, in_len, out_data, max_out_len,
 				     out_len);
 }
 
+struct tevent_req *smb_vfs_call_copy_chunk_send(struct vfs_handle_struct *handle,
+						TALLOC_CTX *mem_ctx,
+						struct tevent_context *ev,
+						struct files_struct *src_fsp,
+						off_t src_off,
+						struct files_struct *dest_fsp,
+						off_t dest_off,
+						off_t num)
+{
+	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);
+}
+
+NTSTATUS smb_vfs_call_copy_chunk_recv(struct vfs_handle_struct *handle,
+				      struct tevent_req *req,
+				      off_t *copied)
+{
+	VFS_FIND(copy_chunk_recv);
+	return handle->fns->copy_chunk_recv_fn(handle, req, copied);
+}
+
 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
 				  struct files_struct *fsp,
 				  uint32 security_info,
-- 
1.7.10.4



More information about the samba-technical mailing list