s3: VFS: Change SMB_VFS_SYS_ACL_GET_FILE to use const struct smb_filename * instead...
[samba.git] / source3 / modules / vfs_default.c
index 2eb9a1794a08688243c768d8e3302c6188557ef0..c3de3d7572d2f05510bfc283f776d70c78c655ad 100644 (file)
 #include "source3/include/msdfs.h"
 #include "librpc/gen_ndr/ndr_dfsblobs.h"
 #include "lib/util/tevent_unix.h"
-#include "lib/asys/asys.h"
 #include "lib/util/tevent_ntstatus.h"
 #include "lib/util/sys_rw.h"
+#include "lib/pthreadpool/pthreadpool_tevent.h"
+#include "librpc/gen_ndr/ndr_ioctl.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_VFS
@@ -133,7 +134,7 @@ static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
         * use when setting a timestamp. */
 
        smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
-                                             NULL, NULL);
+                                             NULL, NULL, 0);
        if (smb_fname_cpath == NULL) {
                return caps;
        }
@@ -216,6 +217,8 @@ static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
 
        /* The following call can change cwd. */
        status = get_referred_path(r, pathnamep,
+                                  handle->conn->sconn->remote_address,
+                                  handle->conn->sconn->local_address,
                                   !handle->conn->sconn->using_smb2,
                                   junction, &consumedcnt, &self_referral);
        if (!NT_STATUS_IS_OK(status)) {
@@ -375,12 +378,15 @@ static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
 
 /* Directory operations */
 
-static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr)
+static DIR *vfswrap_opendir(vfs_handle_struct *handle,
+                               const struct smb_filename *smb_fname,
+                               const char *mask,
+                               uint32_t attr)
 {
        DIR *result;
 
        START_PROFILE(syscall_opendir);
-       result = opendir(fname);
+       result = opendir(smb_fname->base_name);
        END_PROFILE(syscall_opendir);
        return result;
 }
@@ -416,13 +422,20 @@ static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
                if (result != NULL) {
                        /* See if we can efficiently return this. */
                        struct stat st;
-                       int flags = (lp_posix_pathnames() ?
-                               AT_SYMLINK_NOFOLLOW : 0);
+                       int flags = AT_SYMLINK_NOFOLLOW;
                        int ret = fstatat(dirfd(dirp),
                                        result->d_name,
                                        &st,
                                        flags);
-                       if (ret == 0) {
+                       /*
+                        * As this is an optimization,
+                        * ignore it if we stat'ed a
+                        * symlink. Make the caller
+                        * do it again as we don't
+                        * know if they wanted the link
+                        * info, or its target info.
+                        */
+                       if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
                                init_stat_ex_from_stat(sbuf,
                                        &st,
                                        lp_fake_directory_create_times(
@@ -465,10 +478,13 @@ static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
        END_PROFILE(syscall_rewinddir);
 }
 
-static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
+static int vfswrap_mkdir(vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname,
+                       mode_t mode)
 {
        int result;
        bool has_dacl = False;
+       const char *path = smb_fname->base_name;
        char *parent = NULL;
 
        START_PROFILE(syscall_mkdir);
@@ -492,20 +508,23 @@ static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mod
                 * mess up any inherited ACL bits that were set. JRA.
                 */
                int saved_errno = errno; /* We may get ENOSYS */
-               if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
+               if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
+                               (errno == ENOSYS)) {
                        errno = saved_errno;
+               }
        }
 
        END_PROFILE(syscall_mkdir);
        return result;
 }
 
-static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
+static int vfswrap_rmdir(vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname)
 {
        int result;
 
        START_PROFILE(syscall_rmdir);
-       result = rmdir(path);
+       result = rmdir(smb_fname->base_name);
        END_PROFILE(syscall_rmdir);
        return result;
 }
@@ -567,22 +586,6 @@ static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
                                    const struct smb2_create_blobs *in_context_blobs,
                                    struct smb2_create_blobs *out_context_blobs)
 {
-       struct smb2_create_blob *svhdx = NULL;
-
-       /*
-        * It might be empty ... and smb2_create_blob_find does not handle that
-        */
-       if (in_context_blobs) {
-               svhdx = smb2_create_blob_find(in_context_blobs,
-                                             SVHDX_OPEN_DEVICE_CONTEXT);
-       }
-
-       if (svhdx != NULL) {
-               /* SharedVHD is not yet supported */
-               DEBUG(10, ("Shared VHD not yet supported, INVALID_DEVICE_REQUEST\n"));
-               return NT_STATUS_INVALID_DEVICE_REQUEST;
-       }
-
        return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
                                   access_mask, share_access,
                                   create_disposition, create_options,
@@ -705,65 +708,33 @@ static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, cons
        return result;
 }
 
-static void vfswrap_asys_finished(struct tevent_context *ev,
-                                 struct tevent_fd *fde,
-                                 uint16_t flags, void *p);
-
-static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
+static int vfswrap_init_pool(struct smbd_server_connection *conn)
 {
-       struct asys_context *ctx;
-       struct tevent_fd *fde;
        int ret;
-       int fd;
-
-       if (conn->asys_ctx != NULL) {
-               return true;
-       }
-
-       ret = asys_context_init(&ctx, lp_aio_max_threads());
-       if (ret != 0) {
-               DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
-               return false;
-       }
 
-       fd = asys_signalfd(ctx);
-
-       ret = set_blocking(fd, false);
-       if (ret != 0) {
-               DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
-               goto fail;
-       }
-
-       fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
-                           vfswrap_asys_finished, ctx);
-       if (fde == NULL) {
-               DEBUG(1, ("tevent_add_fd failed\n"));
-               goto fail;
+       if (conn->pool != NULL) {
+               return 0;
        }
 
-       conn->asys_ctx = ctx;
-       conn->asys_fde = fde;
-       return true;
-
-fail:
-       asys_context_destroy(ctx);
-       return false;
+       ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
+                                     &conn->pool);
+       return ret;
 }
 
-struct vfswrap_asys_state {
-       struct asys_context *asys_ctx;
-       struct tevent_req *req;
+struct vfswrap_pread_state {
        ssize_t ret;
        int err;
-       SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
+       int fd;
+       void *buf;
+       size_t count;
+       off_t offset;
+
+       struct vfs_aio_state vfs_aio_state;
        SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
 };
 
-static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
-{
-       asys_cancel(s->asys_ctx, s->req);
-       return 0;
-}
+static void vfs_pread_do(void *private_data);
+static void vfs_pread_done(struct tevent_req *subreq);
 
 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
                                             TALLOC_CTX *mem_ctx,
@@ -772,33 +743,115 @@ static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
                                             void *data,
                                             size_t n, off_t offset)
 {
-       struct tevent_req *req;
-       struct vfswrap_asys_state *state;
+       struct tevent_req *req, *subreq;
+       struct vfswrap_pread_state *state;
        int ret;
 
-       req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
+       req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
        if (req == NULL) {
                return NULL;
        }
-       if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
-               tevent_req_oom(req);
+
+       ret = vfswrap_init_pool(handle->conn->sconn);
+       if (tevent_req_error(req, ret)) {
                return tevent_req_post(req, ev);
        }
-       state->asys_ctx = handle->conn->sconn->asys_ctx;
-       state->req = req;
+
+       state->ret = -1;
+       state->fd = fsp->fh->fd;
+       state->buf = data;
+       state->count = n;
+       state->offset = offset;
 
        SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
                                     state->profile_bytes, n);
-       ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
-       if (ret != 0) {
-               tevent_req_error(req, ret);
+       SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
+
+       subreq = pthreadpool_tevent_job_send(
+               state, ev, handle->conn->sconn->pool,
+               vfs_pread_do, state);
+       if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
-       talloc_set_destructor(state, vfswrap_asys_state_destructor);
+       tevent_req_set_callback(subreq, vfs_pread_done, req);
 
        return req;
 }
 
+static void vfs_pread_do(void *private_data)
+{
+       struct vfswrap_pread_state *state = talloc_get_type_abort(
+               private_data, struct vfswrap_pread_state);
+       struct timespec start_time;
+       struct timespec end_time;
+
+       SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
+
+       PROFILE_TIMESTAMP(&start_time);
+
+       do {
+               state->ret = pread(state->fd, state->buf, state->count,
+                                  state->offset);
+       } while ((state->ret == -1) && (errno == EINTR));
+
+       state->err = errno;
+
+       PROFILE_TIMESTAMP(&end_time);
+
+       state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
+
+       SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
+}
+
+static void vfs_pread_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+#ifdef WITH_PROFILE
+       struct vfswrap_pread_state *state = tevent_req_data(
+               req, struct vfswrap_pread_state);
+#endif
+       int ret;
+
+       ret = pthreadpool_tevent_job_recv(subreq);
+       TALLOC_FREE(subreq);
+       SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
+       if (tevent_req_error(req, ret)) {
+               return;
+       }
+
+       tevent_req_done(req);
+}
+
+static ssize_t vfswrap_pread_recv(struct tevent_req *req,
+                                 struct vfs_aio_state *vfs_aio_state)
+{
+       struct vfswrap_pread_state *state = tevent_req_data(
+               req, struct vfswrap_pread_state);
+
+       if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
+               return -1;
+       }
+
+       *vfs_aio_state = state->vfs_aio_state;
+       return state->ret;
+}
+
+struct vfswrap_pwrite_state {
+       ssize_t ret;
+       int err;
+       int fd;
+       const void *buf;
+       size_t count;
+       off_t offset;
+
+       struct vfs_aio_state vfs_aio_state;
+       SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
+};
+
+static void vfs_pwrite_do(void *private_data);
+static void vfs_pwrite_done(struct tevent_req *subreq);
+
 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
                                              TALLOC_CTX *mem_ctx,
                                              struct tevent_context *ev,
@@ -806,128 +859,198 @@ static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
                                              const void *data,
                                              size_t n, off_t offset)
 {
-       struct tevent_req *req;
-       struct vfswrap_asys_state *state;
+       struct tevent_req *req, *subreq;
+       struct vfswrap_pwrite_state *state;
        int ret;
 
-       req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
+       req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
        if (req == NULL) {
                return NULL;
        }
-       if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
-               tevent_req_oom(req);
+
+       ret = vfswrap_init_pool(handle->conn->sconn);
+       if (tevent_req_error(req, ret)) {
                return tevent_req_post(req, ev);
        }
-       state->asys_ctx = handle->conn->sconn->asys_ctx;
-       state->req = req;
+
+       state->ret = -1;
+       state->fd = fsp->fh->fd;
+       state->buf = data;
+       state->count = n;
+       state->offset = offset;
 
        SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
                                     state->profile_bytes, n);
-       ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
-       if (ret != 0) {
-               tevent_req_error(req, ret);
+       SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
+
+       subreq = pthreadpool_tevent_job_send(
+               state, ev, handle->conn->sconn->pool,
+               vfs_pwrite_do, state);
+       if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
-       talloc_set_destructor(state, vfswrap_asys_state_destructor);
+       tevent_req_set_callback(subreq, vfs_pwrite_done, req);
 
        return req;
 }
 
+static void vfs_pwrite_do(void *private_data)
+{
+       struct vfswrap_pwrite_state *state = talloc_get_type_abort(
+               private_data, struct vfswrap_pwrite_state);
+       struct timespec start_time;
+       struct timespec end_time;
+
+       SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
+
+       PROFILE_TIMESTAMP(&start_time);
+
+       do {
+               state->ret = pwrite(state->fd, state->buf, state->count,
+                                  state->offset);
+       } while ((state->ret == -1) && (errno == EINTR));
+
+       state->err = errno;
+
+       PROFILE_TIMESTAMP(&end_time);
+
+       state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
+
+       SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
+}
+
+static void vfs_pwrite_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+#ifdef WITH_PROFILE
+       struct vfswrap_pwrite_state *state = tevent_req_data(
+               req, struct vfswrap_pwrite_state);
+#endif
+       int ret;
+
+       ret = pthreadpool_tevent_job_recv(subreq);
+       TALLOC_FREE(subreq);
+       SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
+       if (tevent_req_error(req, ret)) {
+               return;
+       }
+
+       tevent_req_done(req);
+}
+
+static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
+                                  struct vfs_aio_state *vfs_aio_state)
+{
+       struct vfswrap_pwrite_state *state = tevent_req_data(
+               req, struct vfswrap_pwrite_state);
+
+       if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
+               return -1;
+       }
+
+       *vfs_aio_state = state->vfs_aio_state;
+       return state->ret;
+}
+
+struct vfswrap_fsync_state {
+       ssize_t ret;
+       int err;
+       int fd;
+
+       struct vfs_aio_state vfs_aio_state;
+       SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
+};
+
+static void vfs_fsync_do(void *private_data);
+static void vfs_fsync_done(struct tevent_req *subreq);
+
 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
                                             TALLOC_CTX *mem_ctx,
                                             struct tevent_context *ev,
                                             struct files_struct *fsp)
 {
-       struct tevent_req *req;
-       struct vfswrap_asys_state *state;
+       struct tevent_req *req, *subreq;
+       struct vfswrap_fsync_state *state;
        int ret;
 
-       req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
+       req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
        if (req == NULL) {
                return NULL;
        }
-       if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
-               tevent_req_oom(req);
+
+       ret = vfswrap_init_pool(handle->conn->sconn);
+       if (tevent_req_error(req, ret)) {
                return tevent_req_post(req, ev);
        }
-       state->asys_ctx = handle->conn->sconn->asys_ctx;
-       state->req = req;
+
+       state->ret = -1;
+       state->fd = fsp->fh->fd;
 
        SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
                                     state->profile_basic);
-       ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
-       if (ret != 0) {
-               tevent_req_error(req, ret);
+
+       subreq = pthreadpool_tevent_job_send(
+               state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
+       if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
-       talloc_set_destructor(state, vfswrap_asys_state_destructor);
+       tevent_req_set_callback(subreq, vfs_fsync_done, req);
 
        return req;
 }
 
-static void vfswrap_asys_finished(struct tevent_context *ev,
-                                       struct tevent_fd *fde,
-                                       uint16_t flags, void *p)
+static void vfs_fsync_do(void *private_data)
 {
-       struct asys_context *asys_ctx = (struct asys_context *)p;
-       struct asys_result results[get_outstanding_aio_calls()];
-       int i, ret;
+       struct vfswrap_fsync_state *state = talloc_get_type_abort(
+               private_data, struct vfswrap_fsync_state);
+       struct timespec start_time;
+       struct timespec end_time;
 
-       if ((flags & TEVENT_FD_READ) == 0) {
-               return;
-       }
+       PROFILE_TIMESTAMP(&start_time);
 
-       ret = asys_results(asys_ctx, results, get_outstanding_aio_calls());
-       if (ret < 0) {
-               DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
-               return;
-       }
+       do {
+               state->ret = fsync(state->fd);
+       } while ((state->ret == -1) && (errno == EINTR));
 
-       for (i=0; i<ret; i++) {
-               struct asys_result *result = &results[i];
-               struct tevent_req *req;
-               struct vfswrap_asys_state *state;
+       state->err = errno;
 
-               if ((result->ret == -1) && (result->err == ECANCELED)) {
-                       continue;
-               }
-
-               req = talloc_get_type_abort(result->private_data,
-                                           struct tevent_req);
-               state = tevent_req_data(req, struct vfswrap_asys_state);
+       PROFILE_TIMESTAMP(&end_time);
 
-               talloc_set_destructor(state, NULL);
-
-               SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
-               SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
-               state->ret = result->ret;
-               state->err = result->err;
-               tevent_req_defer_callback(req, ev);
-               tevent_req_done(req);
-       }
+       state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
 }
 
-static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
+static void vfs_fsync_done(struct tevent_req *subreq)
 {
-       struct vfswrap_asys_state *state = tevent_req_data(
-               req, struct vfswrap_asys_state);
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+#ifdef WITH_PROFILE
+       struct vfswrap_fsync_state *state = tevent_req_data(
+               req, struct vfswrap_fsync_state);
+#endif
+       int ret;
 
-       if (tevent_req_is_unix_error(req, err)) {
-               return -1;
+       ret = pthreadpool_tevent_job_recv(subreq);
+       TALLOC_FREE(subreq);
+       SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
+       if (tevent_req_error(req, ret)) {
+               return;
        }
-       *err = state->err;
-       return state->ret;
+
+       tevent_req_done(req);
 }
 
-static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
+static int vfswrap_fsync_recv(struct tevent_req *req,
+                             struct vfs_aio_state *vfs_aio_state)
 {
-       struct vfswrap_asys_state *state = tevent_req_data(
-               req, struct vfswrap_asys_state);
+       struct vfswrap_fsync_state *state = tevent_req_data(
+               req, struct vfswrap_fsync_state);
 
-       if (tevent_req_is_unix_error(req, err)) {
+       if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
                return -1;
        }
-       *err = state->err;
+
+       *vfs_aio_state = state->vfs_aio_state;
        return state->ret;
 }
 
@@ -1424,11 +1547,71 @@ static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
        return NT_STATUS_NOT_SUPPORTED;
 }
 
+static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
+                              const struct smb_filename *fname,
+                              SMB_STRUCT_STAT *sbuf);
+
+static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
+                                          struct smb_filename *smb_fname,
+                                          uint32_t *dosmode)
+{
+       bool offline;
+
+       offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
+       if (offline) {
+               *dosmode |= FILE_ATTRIBUTE_OFFLINE;
+       }
+
+       return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
+}
+
+static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
+                                           struct files_struct *fsp,
+                                           uint32_t *dosmode)
+{
+       bool offline;
+
+       offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
+       if (offline) {
+               *dosmode |= FILE_ATTRIBUTE_OFFLINE;
+       }
+
+       return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
+}
+
+static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
+                                          const struct smb_filename *smb_fname,
+                                          uint32_t dosmode)
+{
+       return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
+}
+
+static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
+                                           struct files_struct *fsp,
+                                           uint32_t dosmode)
+{
+       return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
+}
+
 struct vfs_cc_state {
-       off_t copied;
+       struct tevent_context *ev;
        uint8_t *buf;
+       bool read_lck_locked;
+       struct lock_struct read_lck;
+       bool write_lck_locked;
+       struct lock_struct write_lck;
+       struct files_struct *src_fsp;
+       off_t src_off;
+       struct files_struct *dst_fsp;
+       off_t dst_off;
+       off_t to_copy;
+       off_t remaining;
+       size_t next_io_size;
+       uint32_t flags;
 };
 
+static NTSTATUS copy_chunk_loop(struct tevent_req *req);
+
 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
                                                  TALLOC_CTX *mem_ctx,
                                                  struct tevent_context *ev,
@@ -1436,23 +1619,44 @@ 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 num)
+                                                 off_t to_copy,
+                                                 uint32_t flags)
 {
        struct tevent_req *req;
-       struct vfs_cc_state *vfs_cc_state;
+       struct vfs_cc_state *state = NULL;
+       size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
        NTSTATUS status;
 
-       DEBUG(10, ("performing server side copy chunk of length %lu\n",
-                  (unsigned long)num));
+       DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
 
-       req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
+       req = tevent_req_create(mem_ctx, &state, struct vfs_cc_state);
        if (req == NULL) {
                return NULL;
        }
 
-       vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
-                                        MIN(num, 8*1024*1024));
-       if (tevent_req_nomem(vfs_cc_state->buf, req)) {
+       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,
+               .src_off = src_off,
+               .dst_fsp = dest_fsp,
+               .dst_off = dest_off,
+               .to_copy = to_copy,
+               .remaining = to_copy,
+               .flags = flags,
+       };
+       state->buf = talloc_array(state, uint8_t, num);
+       if (tevent_req_nomem(state->buf, req)) {
                return tevent_req_post(req, ev);
        }
 
@@ -1475,115 +1679,196 @@ static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *hand
                return tevent_req_post(req, ev);
        }
 
-       /* could use 2.6.33+ sendfile here to do this in kernel */
-       while (vfs_cc_state->copied < num) {
-               ssize_t ret;
-               struct lock_struct lck;
-               int saved_errno;
+       if (src_fsp->op == NULL) {
+               tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+               return tevent_req_post(req, ev);
+       }
+
+       if (dest_fsp->op == NULL) {
+               tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+               return tevent_req_post(req, ev);
+       }
+
+       status = copy_chunk_loop(req);
+       if (!NT_STATUS_IS_OK(status)) {
+               tevent_req_nterror(req, status);
+               return tevent_req_post(req, ev);
+       }
 
-               off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
-                                    num - vfs_cc_state->copied);
+       return req;
+}
 
-               if (src_fsp->op == NULL) {
-                       tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
-                       return tevent_req_post(req, ev);
-               }
-               init_strict_lock_struct(src_fsp,
-                                       src_fsp->op->global->open_persistent_id,
-                                       src_off,
-                                       this_num,
+static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq);
+
+static NTSTATUS copy_chunk_loop(struct tevent_req *req)
+{
+       struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
+       struct tevent_req *subreq = NULL;
+       bool ok;
+
+       state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
+
+       if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
+               init_strict_lock_struct(state->src_fsp,
+                               state->src_fsp->op->global->open_persistent_id,
+                                       state->src_off,
+                                       state->next_io_size,
                                        READ_LOCK,
-                                       &lck);
+                                       &state->read_lck);
 
-               if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
-                       tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
-                       return tevent_req_post(req, ev);
+               ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
+                                        state->src_fsp,
+                                        &state->read_lck);
+               if (!ok) {
+                       return NT_STATUS_FILE_LOCK_CONFLICT;
                }
+       }
 
-               ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
-                                   this_num, src_off);
-               if (ret == -1) {
-                       saved_errno = errno;
-               }
+       subreq = SMB_VFS_PREAD_SEND(state,
+                                   state->src_fsp->conn->sconn->ev_ctx,
+                                   state->src_fsp,
+                                   state->buf,
+                                   state->next_io_size,
+                                   state->src_off);
+       if (subreq == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       tevent_req_set_callback(subreq, vfswrap_copy_chunk_read_done, req);
 
-               SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
+       return NT_STATUS_OK;
+}
 
-               if (ret == -1) {
-                       errno = saved_errno;
-                       tevent_req_nterror(req, map_nt_error_from_unix(errno));
-                       return tevent_req_post(req, ev);
-               }
-               if (ret != this_num) {
-                       /* zero tolerance for short reads */
-                       tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
-                       return tevent_req_post(req, ev);
-               }
+static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq);
 
-               src_off += ret;
+static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
+       struct vfs_aio_state aio_state;
+       ssize_t nread;
+       bool ok;
 
-               if (dest_fsp->op == NULL) {
-                       tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
-                       return tevent_req_post(req, ev);
-               }
+       if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
+               SMB_VFS_STRICT_UNLOCK(state->src_fsp->conn,
+                                     state->src_fsp,
+                                     &state->read_lck);
+               ZERO_STRUCT(state->read_lck);
+       }
+
+       nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
+       TALLOC_FREE(subreq);
+       if (nread == -1) {
+               DBG_ERR("read failed: %s\n", strerror(errno));
+               tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
+               return;
+       }
+       if (nread != state->next_io_size) {
+               DBG_ERR("Short read, only %zd of %zu\n",
+                       nread, state->next_io_size);
+               tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
+               return;
+       }
 
-               init_strict_lock_struct(dest_fsp,
-                                       dest_fsp->op->global->open_persistent_id,
-                                       dest_off,
-                                       this_num,
+       state->src_off += nread;
+
+       if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
+               init_strict_lock_struct(state->dst_fsp,
+                               state->dst_fsp->op->global->open_persistent_id,
+                                       state->dst_off,
+                                       state->next_io_size,
                                        WRITE_LOCK,
-                                       &lck);
+                                       &state->write_lck);
 
-               if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
+               ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
+                                        state->dst_fsp,
+                                        &state->write_lck);
+               if (!ok) {
                        tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
-                       return tevent_req_post(req, ev);
+                       return;
                }
+       }
 
-               ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
-                                    this_num, dest_off);
-               if (ret == -1) {
-                       saved_errno = errno;
-               }
+       subreq = SMB_VFS_PWRITE_SEND(state,
+                                    state->ev,
+                                    state->dst_fsp,
+                                    state->buf,
+                                    state->next_io_size,
+                                    state->dst_off);
+       if (subreq == NULL) {
+               tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
+       }
+       tevent_req_set_callback(subreq, vfswrap_copy_chunk_write_done, req);
+}
 
-               SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
+static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
+       struct vfs_aio_state aio_state;
+       ssize_t nwritten;
+       NTSTATUS status;
 
-               if (ret == -1) {
-                       errno = saved_errno;
-                       tevent_req_nterror(req, map_nt_error_from_unix(errno));
-                       return tevent_req_post(req, ev);
-               }
-               if (ret != this_num) {
-                       /* zero tolerance for short writes */
-                       tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
-                       return tevent_req_post(req, ev);
-               }
-               dest_off += ret;
+       if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
+               SMB_VFS_STRICT_UNLOCK(state->dst_fsp->conn,
+                                     state->dst_fsp,
+                                     &state->write_lck);
+               ZERO_STRUCT(state->write_lck);
+       }
+
+       nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
+       TALLOC_FREE(subreq);
+       if (nwritten == -1) {
+               DBG_ERR("write failed: %s\n", strerror(errno));
+               tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
+               return;
+       }
+       if (nwritten != state->next_io_size) {
+               DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
+               tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
+               return;
+       }
 
-               vfs_cc_state->copied += this_num;
+       state->dst_off += nwritten;
+
+       if (state->remaining < nwritten) {
+               /* Paranoia check */
+               tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+               return;
+       }
+       state->remaining -= nwritten;
+       if (state->remaining == 0) {
+               tevent_req_done(req);
+               return;
        }
 
-       tevent_req_done(req);
-       return tevent_req_post(req, ev);
+       status = copy_chunk_loop(req);
+       if (!NT_STATUS_IS_OK(status)) {
+               tevent_req_nterror(req, status);
+               return;
+       }
+
+       return;
 }
 
 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);
+       struct vfs_cc_state *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)));
+               DBG_DEBUG("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));
+       *copied = state->to_copy;
+       DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
        tevent_req_received(req);
 
        return NT_STATUS_OK;
@@ -1682,7 +1967,9 @@ static int vfswrap_unlink(vfs_handle_struct *handle,
        return result;
 }
 
-static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
+static int vfswrap_chmod(vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname,
+                       mode_t mode)
 {
        int result;
 
@@ -1697,7 +1984,10 @@ static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mod
 
        {
                int saved_errno = errno; /* We might get ENOSYS */
-               if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
+               result = SMB_VFS_CHMOD_ACL(handle->conn,
+                               smb_fname,
+                               mode);
+               if (result == 0) {
                        END_PROFILE(syscall_chmod);
                        return result;
                }
@@ -1705,7 +1995,7 @@ static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mod
                errno = saved_errno;
        }
 
-       result = chmod(path, mode);
+       result = chmod(smb_fname->base_name, mode);
        END_PROFILE(syscall_chmod);
        return result;
 }
@@ -1743,12 +2033,15 @@ static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t m
        return result;
 }
 
-static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
+static int vfswrap_chown(vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname,
+                       uid_t uid,
+                       gid_t gid)
 {
        int result;
 
        START_PROFILE(syscall_chown);
-       result = chown(path, uid, gid);
+       result = chown(smb_fname->base_name, uid, gid);
        END_PROFILE(syscall_chown);
        return result;
 }
@@ -1768,12 +2061,15 @@ static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t ui
 #endif
 }
 
-static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
+static int vfswrap_lchown(vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname,
+                       uid_t uid,
+                       gid_t gid)
 {
        int result;
 
        START_PROFILE(syscall_lchown);
-       result = lchown(path, uid, gid);
+       result = lchown(smb_fname->base_name, uid, gid);
        END_PROFILE(syscall_lchown);
        return result;
 }
@@ -1936,9 +2232,8 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs
                "error %d. Falling back to slow manual allocation\n", errno));
 
        /* available disk space is enough or not? */
-       space_avail = get_dfree_info(fsp->conn,
-                                    fsp->fsp_name->base_name,
-                                    &bsize, &dfree, &dsize);
+       space_avail =
+           get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
        /* space_avail is 1k blocks */
        if (space_avail == (uint64_t)-1 ||
                        ((uint64_t)space_to_write/1024 > space_avail) ) {
@@ -2060,6 +2355,14 @@ static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, o
        bool result;
 
        START_PROFILE(syscall_fcntl_lock);
+
+       if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
+                                               "smbd",
+                                               "force process locks",
+                                               false)) {
+               op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
+       }
+
        result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
        END_PROFILE(syscall_fcntl_lock);
        return result;
@@ -2077,9 +2380,18 @@ static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
 {
        bool result;
+       int op = F_GETLK;
 
        START_PROFILE(syscall_fcntl_getlock);
-       result =  fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
+
+       if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
+                                               "smbd",
+                                               "force process locks",
+                                               false)) {
+               op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
+       }
+
+       result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
        END_PROFILE(syscall_fcntl_getlock);
        return result;
 }
@@ -2145,20 +2457,7 @@ static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
        char *result;
 
        START_PROFILE(syscall_realpath);
-#ifdef REALPATH_TAKES_NULL
-       result = realpath(path, NULL);
-#else
-       result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
-       if (result) {
-               char *resolved_path = realpath(path, result);
-               if (!resolved_path) {
-                       SAFE_FREE(result);
-               } else {
-                       /* SMB_ASSERT(result == resolved_path) ? */
-                       result = resolved_path;
-               }
-       }
-#endif
+       result = sys_realpath(path);
        END_PROFILE(syscall_realpath);
        return result;
 }
@@ -2192,7 +2491,7 @@ static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
 
 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
                                   struct files_struct *fsp,
-                                  const char *fname,
+                                  const struct smb_filename *smb_fname,
                                   TALLOC_CTX *mem_ctx,
                                   unsigned int *pnum_streams,
                                   struct stream_struct **pstreams)
@@ -2212,17 +2511,19 @@ static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
                ret = SMB_VFS_FSTAT(fsp, &sbuf);
        }
        else {
-               struct smb_filename smb_fname;
+               struct smb_filename smb_fname_cp;
 
-               ZERO_STRUCT(smb_fname);
-               smb_fname.base_name = discard_const_p(char, fname);
+               ZERO_STRUCT(smb_fname_cp);
+               smb_fname_cp.base_name = discard_const_p(char,
+                                       smb_fname->base_name);
+               smb_fname_cp.flags = smb_fname->flags;
 
-               if (lp_posix_pathnames()) {
-                       ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
+               if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
+                       ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
                } else {
-                       ret = SMB_VFS_STAT(handle->conn, &smb_fname);
+                       ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
                }
-               sbuf = smb_fname.st;
+               sbuf = smb_fname_cp.st;
        }
 
        if (ret == -1) {
@@ -2340,7 +2641,7 @@ static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
 }
 
 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
-                                  const char *name,
+                                  const struct smb_filename *smb_fname,
                                   uint32_t security_info,
                                   TALLOC_CTX *mem_ctx,
                                   struct security_descriptor **ppdesc)
@@ -2348,8 +2649,11 @@ static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
        NTSTATUS result;
 
        START_PROFILE(get_nt_acl);
-       result = posix_get_nt_acl(handle->conn, name, security_info,
-                                 mem_ctx, ppdesc);
+       result = posix_get_nt_acl(handle->conn,
+                               smb_fname,
+                               security_info,
+                               mem_ctx,
+                               ppdesc);
        END_PROFILE(get_nt_acl);
        return result;
 }
@@ -2373,7 +2677,9 @@ static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
        return NT_STATUS_OK; /* Nothing to do here ... */
 }
 
-static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
+static int vfswrap_chmod_acl(vfs_handle_struct *handle,
+                               const struct smb_filename *smb_fname,
+                               mode_t mode)
 {
 #ifdef HAVE_NO_ACL
        errno = ENOSYS;
@@ -2382,7 +2688,7 @@ static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t
        int result;
 
        START_PROFILE(chmod_acl);
-       result = chmod_acl(handle->conn, name, mode);
+       result = chmod_acl(handle->conn, smb_fname, mode);
        END_PROFILE(chmod_acl);
        return result;
 #endif
@@ -2404,11 +2710,11 @@ static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode
 }
 
 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
-                                         const char *path_p,
+                                         const struct smb_filename *smb_fname,
                                          SMB_ACL_TYPE_T type,
                                          TALLOC_CTX *mem_ctx)
 {
-       return sys_acl_get_file(handle, path_p, type, mem_ctx);
+       return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
 }
 
 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
@@ -2428,9 +2734,10 @@ static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
        return sys_acl_set_fd(handle, fsp, theacl);
 }
 
-static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
+static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname)
 {
-       return sys_acl_delete_def_file(handle, path);
+       return sys_acl_delete_def_file(handle, smb_fname);
 }
 
 /****************************************************************
@@ -2514,16 +2821,6 @@ static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
        return offline;
 }
 
-static int vfswrap_set_offline(struct vfs_handle_struct *handle,
-                              const struct smb_filename *fname)
-{
-       /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
-#if defined(ENOTSUP)
-       errno = ENOTSUP;
-#endif
-       return -1;
-}
-
 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
                                       struct files_struct *fsp,
                                       TALLOC_CTX *mem_ctx,
@@ -2593,18 +2890,18 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .read_fn = vfswrap_read,
        .pread_fn = vfswrap_pread,
        .pread_send_fn = vfswrap_pread_send,
-       .pread_recv_fn = vfswrap_asys_ssize_t_recv,
+       .pread_recv_fn = vfswrap_pread_recv,
        .write_fn = vfswrap_write,
        .pwrite_fn = vfswrap_pwrite,
        .pwrite_send_fn = vfswrap_pwrite_send,
-       .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
+       .pwrite_recv_fn = vfswrap_pwrite_recv,
        .lseek_fn = vfswrap_lseek,
        .sendfile_fn = vfswrap_sendfile,
        .recvfile_fn = vfswrap_recvfile,
        .rename_fn = vfswrap_rename,
        .fsync_fn = vfswrap_fsync,
        .fsync_send_fn = vfswrap_fsync_send,
-       .fsync_recv_fn = vfswrap_asys_int_recv,
+       .fsync_recv_fn = vfswrap_fsync_recv,
        .stat_fn = vfswrap_stat,
        .fstat_fn = vfswrap_fstat,
        .lstat_fn = vfswrap_lstat,
@@ -2641,6 +2938,10 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .strict_unlock_fn = vfswrap_strict_unlock,
        .translate_name_fn = vfswrap_translate_name,
        .fsctl_fn = vfswrap_fsctl,
+       .set_dos_attributes_fn = vfswrap_set_dos_attributes,
+       .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
+       .get_dos_attributes_fn = vfswrap_get_dos_attributes,
+       .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
        .copy_chunk_send_fn = vfswrap_copy_chunk_send,
        .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
        .get_compression_fn = vfswrap_get_compression,
@@ -2679,18 +2980,14 @@ static struct vfs_fn_pointers vfs_default_fns = {
        /* aio operations */
        .aio_force_fn = vfswrap_aio_force,
 
-       /* offline operations */
-       .is_offline_fn = vfswrap_is_offline,
-       .set_offline_fn = vfswrap_set_offline,
-
        /* durable handle operations */
        .durable_cookie_fn = vfswrap_durable_cookie,
        .durable_disconnect_fn = vfswrap_durable_disconnect,
        .durable_reconnect_fn = vfswrap_durable_reconnect,
 };
 
-NTSTATUS vfs_default_init(void);
-NTSTATUS vfs_default_init(void)
+NTSTATUS vfs_default_init(TALLOC_CTX *);
+NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
 {
        return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
                                DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);