vfs: add snapshot create/delete hooks
authorDavid Disseldorp <ddiss@samba.org>
Tue, 10 Apr 2012 01:16:57 +0000 (03:16 +0200)
committerJeremy Allison <jra@samba.org>
Tue, 31 Mar 2015 16:40:24 +0000 (18:40 +0200)
This change adds three new VFS hooks covering snapshot manipulation:
- snap_check_path
  Check whether a path supports snapshots.
- snap_create
  Request the creation of a snapshot of the provided path.
- snap_delete
  Request the deletion of a snapshot.

These VFS call-outs will be used in future by Samba's File Server Remote
VSS Protocol (FSRVP) server.

MS-FSVRP states:
  At any given time, Windows servers allow only one shadow copy set to
  be going through the creation process.
Therefore, only provide synchronous hooks for now, which can be
converted to asynchronous _send/_recv functions when the corresponding
DCE/RPC server infrastructure is in place.

Signed-off-by: David Disseldorp <ddiss@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
docs-xml/manpages/vfs_full_audit.8.xml
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/vfs_default.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_time_audit.c
source3/smbd/vfs.c

index 7107fcb69ef8758e5809b75522b28af5a7ec1470..bc69618e24eb7acafa2db5ee4cf54afe1f3a3fa8 100644 (file)
@@ -96,6 +96,9 @@
         <member>set_nt_acl</member>
         <member>set_quota</member>
         <member>setxattr</member>
+        <member>snap_check_path</member>
+        <member>snap_create</member>
+        <member>snap_delete</member>
         <member>stat</member>
         <member>statvfs</member>
         <member>symlink</member>
index b6b1aefe5b002e9f1e8380be68480e2efb17bbd3..a9cbabf805733a5d1fee48256701e410d78c6bca 100644 (file)
@@ -102,6 +102,33 @@ static DIR *skel_opendir(vfs_handle_struct *handle, const char *fname,
        return NULL;
 }
 
+static NTSTATUS skel_snap_check_path(struct vfs_handle_struct *handle,
+                                    TALLOC_CTX *mem_ctx,
+                                    const char *service_path,
+                                    char **base_volume)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS skel_snap_create(struct vfs_handle_struct *handle,
+                                TALLOC_CTX *mem_ctx,
+                                const char *base_volume,
+                                time_t *tstamp,
+                                bool rw,
+                                char **base_path,
+                                char **snap_path)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS skel_snap_delete(struct vfs_handle_struct *handle,
+                                TALLOC_CTX *mem_ctx,
+                                char *base_path,
+                                char *snap_path)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
 static DIR *skel_fdopendir(vfs_handle_struct *handle, files_struct *fsp,
                           const char *mask, uint32 attr)
 {
@@ -830,6 +857,9 @@ struct vfs_fn_pointers skel_opaque_fns = {
        .statvfs_fn = skel_statvfs,
        .fs_capabilities_fn = skel_fs_capabilities,
        .get_dfs_referrals_fn = skel_get_dfs_referrals,
+       .snap_check_path_fn = skel_snap_check_path,
+       .snap_create_fn = skel_snap_create,
+       .snap_delete_fn = skel_snap_delete,
 
        /* Directory operations */
 
index f7ed537025e9e763d6e39a82d54350b915701116..651eb2f840d749e3273aa77622d921e7c0a755c5 100644 (file)
@@ -100,6 +100,35 @@ static DIR *skel_opendir(vfs_handle_struct *handle, const char *fname,
        return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
 }
 
+static NTSTATUS skel_snap_check_path(struct vfs_handle_struct *handle,
+                                    TALLOC_CTX *mem_ctx,
+                                    const char *service_path,
+                                    char **base_volume)
+{
+       return SMB_VFS_NEXT_SNAP_CHECK_PATH(handle, mem_ctx, service_path,
+                                           base_volume);
+}
+
+static NTSTATUS skel_snap_create(struct vfs_handle_struct *handle,
+                                TALLOC_CTX *mem_ctx,
+                                const char *base_volume,
+                                time_t *tstamp,
+                                bool rw,
+                                char **base_path,
+                                char **snap_path)
+{
+       return SMB_VFS_NEXT_SNAP_CREATE(handle, mem_ctx, base_volume, tstamp,
+                                       rw, base_path, snap_path);
+}
+
+static NTSTATUS skel_snap_delete(struct vfs_handle_struct *handle,
+                                TALLOC_CTX *mem_ctx,
+                                char *base_path,
+                                char *snap_path)
+{
+       return SMB_VFS_NEXT_SNAP_DELETE(handle, mem_ctx, base_path, snap_path);
+}
+
 static DIR *skel_fdopendir(vfs_handle_struct *handle, files_struct *fsp,
                           const char *mask, uint32 attr)
 {
@@ -939,6 +968,9 @@ struct vfs_fn_pointers skel_transparent_fns = {
        .statvfs_fn = skel_statvfs,
        .fs_capabilities_fn = skel_fs_capabilities,
        .get_dfs_referrals_fn = skel_get_dfs_referrals,
+       .snap_check_path_fn = skel_snap_check_path,
+       .snap_create_fn = skel_snap_create,
+       .snap_delete_fn = skel_snap_delete,
 
        /* Directory operations */
 
index b2880b76253c4bfd4ef520f28b20b4c29dbd4e4c..5dcb894c0386b7c7573e9dc9f59f390ee8b6087f 100644 (file)
 /* Version 32 - Remove unnecessary SMB_VFS_DISK_FREE() small_query parameter */
 /* Bump to version 33 - Samba 4.3 will ship with that. */
 /* Version 33 - change fallocate mode flags param from enum->uint32_t */
+/* Version 33 - Add snapshot create/delete calls */
 
 #define SMB_VFS_INTERFACE_VERSION 33
 
@@ -656,6 +657,21 @@ struct vfs_fn_pointers {
                                       TALLOC_CTX *mem_ctx,
                                       struct files_struct *fsp,
                                       uint16_t compression_fmt);
+       NTSTATUS (*snap_check_path_fn)(struct vfs_handle_struct *handle,
+                                      TALLOC_CTX *mem_ctx,
+                                      const char *service_path,
+                                      char **base_volume);
+       NTSTATUS (*snap_create_fn)(struct vfs_handle_struct *handle,
+                                  TALLOC_CTX *mem_ctx,
+                                  const char *base_volume,
+                                  time_t *tstamp,
+                                  bool rw,
+                                  char **base_path,
+                                  char **snap_path);
+       NTSTATUS (*snap_delete_fn)(struct vfs_handle_struct *handle,
+                                  TALLOC_CTX *mem_ctx,
+                                  char *base_path,
+                                  char *snap_path);
 
        NTSTATUS (*streaminfo_fn)(struct vfs_handle_struct *handle,
                                  struct files_struct *fsp,
@@ -1151,6 +1167,21 @@ NTSTATUS smb_vfs_call_set_compression(struct vfs_handle_struct *handle,
                                      TALLOC_CTX *mem_ctx,
                                      struct files_struct *fsp,
                                      uint16_t compression_fmt);
+NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
+                                     TALLOC_CTX *mem_ctx,
+                                     const char *service_path,
+                                     char **base_volume);
+NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
+                                 TALLOC_CTX *mem_ctx,
+                                 const char *base_volume,
+                                 time_t *tstamp,
+                                 bool rw,
+                                 char **base_path,
+                                 char **snap_path);
+NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
+                                 TALLOC_CTX *mem_ctx,
+                                 char *base_path,
+                                 char *snap_path);
 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
                                  struct files_struct *fsp,
                                  uint32 security_info,
index 0cc442e010471558610b097edd6bf7d193eec1d7..9a686c9ad225ab113bd9bda433a17712ea19bc88 100644 (file)
 #define SMB_VFS_NEXT_SET_COMPRESSION(handle, mem_ctx, fsp, compression_fmt)            \
        smb_vfs_call_set_compression((handle)->next, (mem_ctx), (fsp), (compression_fmt))
 
+#define SMB_VFS_SNAP_CHECK_PATH(conn, mem_ctx, service_path, base_volume) \
+       smb_vfs_call_snap_check_path((conn)->vfs_handles, (mem_ctx), (service_path), (base_volume))
+#define SMB_VFS_NEXT_SNAP_CHECK_PATH(handle, mem_ctx, service_path, base_volume) \
+       smb_vfs_call_snap_check_path((handle)->next, (mem_ctx), (service_path), (base_volume))
+
+#define SMB_VFS_SNAP_CREATE(conn, mem_ctx, base_volume, tstamp, rw, base_path, snap_path) \
+       smb_vfs_call_snap_create((conn)->vfs_handles, (mem_ctx), (base_volume), (tstamp), (rw), (base_path), (snap_path))
+#define SMB_VFS_NEXT_SNAP_CREATE(handle, mem_ctx, base_volume, tstamp, rw, base_path, snap_path) \
+       smb_vfs_call_snap_create((handle)->next, (mem_ctx), (base_volume), (tstamp), (rw), (base_path), (snap_path))
+
+#define SMB_VFS_SNAP_DELETE(conn, mem_ctx, base_path, snap_path) \
+       smb_vfs_call_snap_delete((conn)->vfs_handles, (mem_ctx), (base_path), (snap_path))
+#define SMB_VFS_NEXT_SNAP_DELETE(handle, mem_ctx, base_path, snap_path) \
+       smb_vfs_call_snap_delete((handle)->next, (mem_ctx), (base_path), (snap_path))
+
 #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) \
index fdb90e410922654be62fb6fdb5b1d6bc23688fd2..dbcd6016af7fc32f8f7b20c6105672034af43b25 100644 (file)
@@ -342,6 +342,33 @@ static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
        return NT_STATUS_OK;
 }
 
+static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
+                                       TALLOC_CTX *mem_ctx,
+                                       const char *service_path,
+                                       char **base_volume)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
+                                   TALLOC_CTX *mem_ctx,
+                                   const char *base_volume,
+                                   time_t *tstamp,
+                                   bool rw,
+                                   char **base_path,
+                                   char **snap_path)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
+                                   TALLOC_CTX *mem_ctx,
+                                   char *base_path,
+                                   char *snap_path)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
 /* Directory operations */
 
 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
@@ -2544,6 +2571,9 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .statvfs_fn = vfswrap_statvfs,
        .fs_capabilities_fn = vfswrap_fs_capabilities,
        .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
+       .snap_check_path_fn = vfswrap_snap_check_path,
+       .snap_create_fn = vfswrap_snap_create,
+       .snap_delete_fn = vfswrap_snap_delete,
 
        /* Directory operations */
 
index 87a2f9c3bc4d173eebd4fbffb03f2d949efa2e6a..c8cef605b31a237ff1e337ca96054b9899fc315a 100644 (file)
@@ -97,6 +97,9 @@ typedef enum _vfs_op_type {
        SMB_VFS_OP_GET_SHADOW_COPY_DATA,
        SMB_VFS_OP_STATVFS,
        SMB_VFS_OP_FS_CAPABILITIES,
+       SMB_VFS_OP_SNAP_CHECK_PATH,
+       SMB_VFS_OP_SNAP_CREATE,
+       SMB_VFS_OP_SNAP_DELETE,
 
        /* Directory operations */
 
@@ -228,6 +231,9 @@ static struct {
        { SMB_VFS_OP_GET_SHADOW_COPY_DATA,      "get_shadow_copy_data" },
        { SMB_VFS_OP_STATVFS,   "statvfs" },
        { SMB_VFS_OP_FS_CAPABILITIES,   "fs_capabilities" },
+       { SMB_VFS_OP_SNAP_CHECK_PATH, "snap_check_path" },
+       { SMB_VFS_OP_SNAP_CREATE, "snap_create" },
+       { SMB_VFS_OP_SNAP_DELETE, "snap_delete" },
        { SMB_VFS_OP_OPENDIR,   "opendir" },
        { SMB_VFS_OP_FDOPENDIR, "fdopendir" },
        { SMB_VFS_OP_READDIR,   "readdir" },
@@ -674,7 +680,6 @@ static int smb_full_audit_get_quota(struct vfs_handle_struct *handle,
        return result;
 }
 
-       
 static int smb_full_audit_set_quota(struct vfs_handle_struct *handle,
                           enum SMB_QUOTA_TYPE qtype, unid_t id,
                           SMB_DISK_QUOTA *qt)
@@ -726,6 +731,52 @@ static uint32_t smb_full_audit_fs_capabilities(struct vfs_handle_struct *handle,
        return result;
 }
 
+static NTSTATUS smb_full_audit_snap_check_path(struct vfs_handle_struct *handle,
+                                              TALLOC_CTX *mem_ctx,
+                                              const char *service_path,
+                                              char **base_volume)
+{
+       NTSTATUS status;
+
+       status = SMB_VFS_NEXT_SNAP_CHECK_PATH(handle, mem_ctx, service_path,
+                                             base_volume);
+       do_log(SMB_VFS_OP_SNAP_CHECK_PATH, NT_STATUS_IS_OK(status),
+              handle, "");
+
+       return status;
+}
+
+static NTSTATUS smb_full_audit_snap_create(struct vfs_handle_struct *handle,
+                                          TALLOC_CTX *mem_ctx,
+                                          const char *base_volume,
+                                          time_t *tstamp,
+                                          bool rw,
+                                          char **base_path,
+                                          char **snap_path)
+{
+       NTSTATUS status;
+
+       status = SMB_VFS_NEXT_SNAP_CREATE(handle, mem_ctx, base_volume, tstamp,
+                                         rw, base_path, snap_path);
+       do_log(SMB_VFS_OP_SNAP_CREATE, NT_STATUS_IS_OK(status), handle, "");
+
+       return status;
+}
+
+static NTSTATUS smb_full_audit_snap_delete(struct vfs_handle_struct *handle,
+                                          TALLOC_CTX *mem_ctx,
+                                          char *base_path,
+                                          char *snap_path)
+{
+       NTSTATUS status;
+
+       status = SMB_VFS_NEXT_SNAP_DELETE(handle, mem_ctx, base_path,
+                                         snap_path);
+       do_log(SMB_VFS_OP_SNAP_DELETE, NT_STATUS_IS_OK(status), handle, "");
+
+       return status;
+}
+
 static DIR *smb_full_audit_opendir(vfs_handle_struct *handle,
                          const char *fname, const char *mask, uint32 attr)
 {
@@ -2199,6 +2250,9 @@ static struct vfs_fn_pointers vfs_full_audit_fns = {
        .get_shadow_copy_data_fn = smb_full_audit_get_shadow_copy_data,
        .statvfs_fn = smb_full_audit_statvfs,
        .fs_capabilities_fn = smb_full_audit_fs_capabilities,
+       .snap_check_path_fn =  smb_full_audit_snap_check_path,
+       .snap_create_fn = smb_full_audit_snap_create,
+       .snap_delete_fn = smb_full_audit_snap_delete,
        .opendir_fn = smb_full_audit_opendir,
        .fdopendir_fn = smb_full_audit_fdopendir,
        .readdir_fn = smb_full_audit_readdir,
index 45e30acfd17b398ebeb67058e1b5ceb2bb3a5698..eebd8cec033526f452ee9ab6f0f7e76194f356a6 100644 (file)
@@ -277,9 +277,78 @@ static uint32_t smb_time_audit_fs_capabilities(struct vfs_handle_struct *handle,
        return result;
 }
 
+static NTSTATUS smb_time_audit_snap_check_path(struct vfs_handle_struct *handle,
+                                              TALLOC_CTX *mem_ctx,
+                                              const char *service_path,
+                                              char **base_volume)
+{
+       NTSTATUS status;
+       struct timespec ts1,ts2;
+       double timediff;
+
+       clock_gettime_mono(&ts1);
+       status = SMB_VFS_NEXT_SNAP_CHECK_PATH(handle, mem_ctx, service_path,
+                                             base_volume);
+       clock_gettime_mono(&ts2);
+       timediff = nsec_time_diff(&ts2, &ts1) * 1.0e-9;
+
+       if (timediff > audit_timeout) {
+               smb_time_audit_log("snap_check_path", timediff);
+       }
+
+       return status;
+}
+
+static NTSTATUS smb_time_audit_snap_create(struct vfs_handle_struct *handle,
+                                          TALLOC_CTX *mem_ctx,
+                                          const char *base_volume,
+                                          time_t *tstamp,
+                                          bool rw,
+                                          char **base_path,
+                                          char **snap_path)
+{
+       NTSTATUS status;
+       struct timespec ts1,ts2;
+       double timediff;
+
+       clock_gettime_mono(&ts1);
+       status = SMB_VFS_NEXT_SNAP_CREATE(handle, mem_ctx, base_volume, tstamp,
+                                         rw, base_path, snap_path);
+       clock_gettime_mono(&ts2);
+       timediff = nsec_time_diff(&ts2 ,&ts1) * 1.0e-9;
+
+       if (timediff > audit_timeout) {
+               smb_time_audit_log("snap_create", timediff);
+       }
+
+       return status;
+}
+
+static NTSTATUS smb_time_audit_snap_delete(struct vfs_handle_struct *handle,
+                                          TALLOC_CTX *mem_ctx,
+                                          char *base_path,
+                                          char *snap_path)
+{
+       NTSTATUS status;
+       struct timespec ts1,ts2;
+       double timediff;
+
+       clock_gettime_mono(&ts1);
+       status = SMB_VFS_NEXT_SNAP_DELETE(handle, mem_ctx, base_path,
+                                         snap_path);
+       clock_gettime_mono(&ts2);
+       timediff = nsec_time_diff(&ts2, &ts1) * 1.0e-9;
+
+       if (timediff > audit_timeout) {
+               smb_time_audit_log("snap_delete", timediff);
+       }
+
+       return status;
+}
+
 static DIR *smb_time_audit_opendir(vfs_handle_struct *handle,
-                                             const char *fname,
-                                             const char *mask, uint32 attr)
+                                  const char *fname,
+                                  const char *mask, uint32 attr)
 {
        DIR *result;
        struct timespec ts1,ts2;
@@ -2383,6 +2452,9 @@ static struct vfs_fn_pointers vfs_time_audit_fns = {
        .get_shadow_copy_data_fn = smb_time_audit_get_shadow_copy_data,
        .statvfs_fn = smb_time_audit_statvfs,
        .fs_capabilities_fn = smb_time_audit_fs_capabilities,
+       .snap_check_path_fn = smb_time_audit_snap_check_path,
+       .snap_create_fn = smb_time_audit_snap_create,
+       .snap_delete_fn = smb_time_audit_snap_delete,
        .opendir_fn = smb_time_audit_opendir,
        .fdopendir_fn = smb_time_audit_fdopendir,
        .readdir_fn = smb_time_audit_readdir,
index 1e20963da1a2bbe12c1721bd71a56a406e05c549..ebd3440e73f62bade8339691ad6e28e1a6528994 100644 (file)
@@ -2227,6 +2227,39 @@ NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
                                               compression_fmt);
 }
 
+NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
+                                     TALLOC_CTX *mem_ctx,
+                                     const char *service_path,
+                                     char **base_volume)
+{
+       VFS_FIND(snap_check_path);
+       return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
+                                              base_volume);
+}
+
+NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
+                                 TALLOC_CTX *mem_ctx,
+                                 const char *base_volume,
+                                 time_t *tstamp,
+                                 bool rw,
+                                 char **base_path,
+                                 char **snap_path)
+{
+       VFS_FIND(snap_create);
+       return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
+                                          rw, base_path, snap_path);
+}
+
+NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
+                                 TALLOC_CTX *mem_ctx,
+                                 char *base_path,
+                                 char *snap_path)
+{
+       VFS_FIND(snap_delete);
+       return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
+                                          snap_path);
+}
+
 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
                                  struct files_struct *fsp,
                                  uint32 security_info,