[PATCH 04/12] s3-vfs: add copy_chunk vfs hooks
Stefan (metze) Metzmacher
metze at samba.org
Thu Nov 8 07:21:50 MST 2012
Hi David,
> +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)
> +{
> + return NULL;
> +}
> +
> +static NTSTATUS skel_copy_chunk_recv(struct vfs_handle_struct *handle,
> + struct tevent_req *req,
> + off_t *copied)
> +{
> + return NT_STATUS_NOT_IMPLEMENTED;
> +}
> +
Can you implement this as complete tevent_req function please?
The _send() function should only return NULL if tevent_req_create() fails.
> static NTSTATUS skel_streaminfo(struct vfs_handle_struct *handle,
> struct files_struct *fsp,
> const char *fname,
> @@ -825,6 +844,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..4bd659f 100644
> --- a/examples/VFS/skel_transparent.c
> +++ b/examples/VFS/skel_transparent.c
> @@ -572,6 +572,26 @@ static struct file_id skel_file_id_create(vfs_handle_struct *handle,
> return SMB_VFS_NEXT_FILE_ID_CREATE(handle, sbuf);
> }
>
> +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)
> +{
> + return SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, mem_ctx, ev, src_fsp, src_off,
> + dest_fsp, dest_off, num);
> +}
> +
> +static NTSTATUS skel_copy_chunk_recv(struct vfs_handle_struct *handle,
> + struct tevent_req *req,
> + off_t *copied)
> +{
> + return SMB_VFS_NEXT_COPY_CHUNK_RECV(handle, req, copied);
> +}
We should also implement a correct tevent_req layering with a subreq here.
> static NTSTATUS skel_streaminfo(struct vfs_handle_struct *handle,
> struct files_struct *fsp,
> const char *fname,
> @@ -898,6 +918,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..73ee59c 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,90 @@ 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;
> + struct tevent_req *subreq;
> +};
We don't need to remember subreq here.
> +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 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);
> + cc_state->subreq = SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, cc_state, ev,
> + src_fsp, src_off,
> + dest_fsp, dest_off,
> + num);
> + if (tevent_req_nomem(cc_state->subreq, req)) {
> + return tevent_req_post(req, ev);
> + }
> +
> + tevent_req_set_callback(cc_state->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,
> + cc_state->subreq,
> + &cc_state->copied);
Here we can use 'subreq' as it's the same as cc_state->subreq.
Also TALLOC_FREE(subreq); should be typically called after
the _recv() function.
metze
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 259 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20121108/0b687b24/attachment.pgp>
More information about the samba-technical
mailing list