vfs: Add SMB_VFS_GET_REAL_FILENAME_AT
[bbaumbach/samba-autobuild/.git] / source3 / modules / vfs_default.c
index 074de0960c05417d7bfe5242f3a2598a987dcd27..ca928ded260a002f95117eccd27b3c412c2167de 100644 (file)
@@ -386,8 +386,6 @@ static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
        int ret;
        char *msdfs_link = NULL;
 
-       SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
-
        /* Form the msdfs_link contents */
        msdfs_link = msdfs_link_string(frame,
                                        reflist,
@@ -397,7 +395,7 @@ static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
        }
 
        ret = symlinkat(msdfs_link,
-                       fsp_get_io_fd(dirfsp),
+                       fsp_get_pathref_fd(dirfsp),
                        smb_fname->base_name);
        if (ret == 0) {
                status = NT_STATUS_OK;
@@ -439,8 +437,6 @@ static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
 #endif
        int ret;
 
-       SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
-
        if (is_named_stream(smb_fname)) {
                status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
                goto err;
@@ -461,7 +457,7 @@ static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
                }
        }
 
-       referral_len = readlinkat(fsp_get_io_fd(dirfsp),
+       referral_len = readlinkat(fsp_get_pathref_fd(dirfsp),
                                smb_fname->base_name,
                                link_target,
                                bufsize - 1);
@@ -476,10 +472,17 @@ static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
                        status = NT_STATUS_OBJECT_TYPE_MISMATCH;
                } else {
                        status = map_nt_error_from_unix(errno);
-                       DBG_ERR("Error reading "
-                               "msdfs link %s: %s\n",
-                               smb_fname->base_name,
-                               strerror(errno));
+                       if (errno == ENOENT) {
+                               DBG_NOTICE("Error reading "
+                                        "msdfs link %s: %s\n",
+                                        smb_fname->base_name,
+                                        strerror(errno));
+                       } else {
+                               DBG_ERR("Error reading "
+                                       "msdfs link %s: %s\n",
+                                       smb_fname->base_name,
+                                       strerror(errno));
+                       }
                }
                 goto err;
         }
@@ -494,9 +497,11 @@ static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
                goto err;
        }
 
-       ret = sys_lstat(smb_fname->base_name,
-                       &smb_fname->st,
-                       lp_fake_directory_create_times(SNUM(handle->conn)));
+       ret = sys_fstatat(fsp_get_pathref_fd(dirfsp),
+                        smb_fname->base_name,
+                        &smb_fname->st,
+                        AT_SYMLINK_NOFOLLOW,
+                        lp_fake_directory_create_times(SNUM(handle->conn)));
        if (ret < 0) {
                status = map_nt_error_from_unix(errno);
                goto err;
@@ -571,51 +576,63 @@ static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
 
 
 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
-                                         DIR *dirp,
-                                         SMB_STRUCT_STAT *sbuf)
+                                     struct files_struct *dirfsp,
+                                     DIR *dirp,
+                                     SMB_STRUCT_STAT *sbuf)
 {
        struct dirent *result;
+       bool fake_ctime = lp_fake_directory_create_times(SNUM(handle->conn));
+       int flags = AT_SYMLINK_NOFOLLOW;
+       SMB_STRUCT_STAT st;
+       int ret;
 
        START_PROFILE(syscall_readdir);
+
        result = readdir(dirp);
        END_PROFILE(syscall_readdir);
-       if (sbuf) {
-               /* Default Posix readdir() does not give us stat info.
-                * Set to invalid to indicate we didn't return this info. */
-               SET_STAT_INVALID(*sbuf);
-#if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
-               if (result != NULL) {
-                       /* See if we can efficiently return this. */
-                       struct stat st;
-                       int flags = AT_SYMLINK_NOFOLLOW;
-                       int ret = fstatat(dirfd(dirp),
-                                       result->d_name,
-                                       &st,
-                                       flags);
-                       /*
-                        * 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(
-                                               SNUM(handle->conn)));
-                       }
-               }
-#endif
+
+       if (sbuf == NULL) {
+               return result;
+       }
+       if (result == NULL) {
+               return NULL;
+       }
+
+       /*
+        * Default Posix readdir() does not give us stat info.
+        * Set to invalid to indicate we didn't return this info.
+        */
+       SET_STAT_INVALID(*sbuf);
+
+       ret = sys_fstatat(dirfd(dirp),
+                     result->d_name,
+                     &st,
+                     flags,
+                     fake_ctime);
+       if (ret != 0) {
+               return result;
+       }
+
+       /*
+        * As this is an optimization, ignore it if we stat'ed a
+        * symlink for non-POSIX context. Make the caller do it again
+        * as we don't know if they wanted the link info, or its
+        * target info.
+        */
+       if (S_ISLNK(st.st_ex_mode) &&
+           !(dirfsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH))
+       {
+               return result;
        }
+       *sbuf = st;
+
        return result;
 }
 
-static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
-                                    const struct smb_filename *fname,
-                                    TALLOC_CTX *mem_ctx,
-                                    struct readdir_attr_data **attr_data)
+static NTSTATUS vfswrap_freaddir_attr(struct vfs_handle_struct *handle,
+                                     struct files_struct *fsp,
+                                     TALLOC_CTX *mem_ctx,
+                                     struct readdir_attr_data **attr_data)
 {
        return NT_STATUS_NOT_SUPPORTED;
 }
@@ -649,25 +666,9 @@ static int vfswrap_mkdirat(vfs_handle_struct *handle,
                        mode_t mode)
 {
        int result;
-       struct smb_filename *parent = NULL;
-       bool ok;
 
        START_PROFILE(syscall_mkdirat);
 
-       SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
-
-       if (lp_inherit_acls(SNUM(handle->conn))) {
-               ok = parent_smb_fname(talloc_tos(), smb_fname, &parent, NULL);
-               if (ok && directory_has_default_acl(handle->conn,
-                               dirfsp,
-                               parent))
-               {
-                       mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
-               }
-       }
-
-       TALLOC_FREE(parent);
-
        result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
 
        END_PROFILE(syscall_mkdirat);
@@ -1313,6 +1314,33 @@ static int vfswrap_lstat(vfs_handle_struct *handle,
        return result;
 }
 
+static int vfswrap_fstatat(
+       struct vfs_handle_struct *handle,
+       const struct files_struct *dirfsp,
+       const struct smb_filename *smb_fname,
+       SMB_STRUCT_STAT *sbuf,
+       int flags)
+{
+       int result = -1;
+
+       START_PROFILE(syscall_fstatat);
+
+       if (is_named_stream(smb_fname)) {
+               errno = ENOENT;
+               goto out;
+       }
+
+       result = sys_fstatat(
+               fsp_get_pathref_fd(dirfsp),
+               smb_fname->base_name,
+               sbuf,
+               flags,
+               lp_fake_directory_create_times(SNUM(handle->conn)));
+ out:
+       END_PROFILE(syscall_fstatat);
+       return result;
+}
+
 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
                                       const char *name,
                                       enum vfs_translate_direction direction,
@@ -1322,6 +1350,69 @@ static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
        return NT_STATUS_NONE_MAPPED;
 }
 
+/**
+ * Return allocated parent directory and basename of path
+ *
+ * Note: if requesting atname, it is returned as talloc child of the
+ * parent. Freeing the parent is thus sufficient to free both.
+ */
+static NTSTATUS vfswrap_parent_pathname(struct vfs_handle_struct *handle,
+                                       TALLOC_CTX *mem_ctx,
+                                       const struct smb_filename *smb_fname_in,
+                                       struct smb_filename **parent_dir_out,
+                                       struct smb_filename **atname_out)
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct smb_filename *parent = NULL;
+       struct smb_filename *name = NULL;
+       char *p = NULL;
+
+       parent = cp_smb_filename_nostream(frame, smb_fname_in);
+       if (parent == NULL) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
+       }
+       SET_STAT_INVALID(parent->st);
+
+       p = strrchr_m(parent->base_name, '/'); /* Find final '/', if any */
+       if (p == NULL) {
+               TALLOC_FREE(parent->base_name);
+               parent->base_name = talloc_strdup(parent, ".");
+               if (parent->base_name == NULL) {
+                       TALLOC_FREE(frame);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               p = smb_fname_in->base_name;
+       } else {
+               *p = '\0';
+               p++;
+       }
+
+       if (atname_out == NULL) {
+               *parent_dir_out = talloc_move(mem_ctx, &parent);
+               TALLOC_FREE(frame);
+               return NT_STATUS_OK;
+       }
+
+       name = cp_smb_filename(frame, smb_fname_in);
+       if (name == NULL) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
+       }
+       TALLOC_FREE(name->base_name);
+
+       name->base_name = talloc_strdup(name, p);
+       if (name->base_name == NULL) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       *parent_dir_out = talloc_move(mem_ctx, &parent);
+       *atname_out = talloc_move(*parent_dir_out, &name);
+       TALLOC_FREE(frame);
+       return NT_STATUS_OK;
+}
+
 /*
  * Implement the default fsctl operation.
  */
@@ -1682,20 +1773,6 @@ static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
 static bool vfswrap_is_offline(struct connection_struct *conn,
                               const struct smb_filename *fname);
 
-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->conn, smb_fname);
-       if (offline) {
-               *dosmode |= FILE_ATTRIBUTE_OFFLINE;
-       }
-
-       return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
-}
-
 struct vfswrap_get_dos_attributes_state {
        struct vfs_aio_state aio_state;
        connection_struct *conn;
@@ -1734,6 +1811,14 @@ static struct tevent_req *vfswrap_get_dos_attributes_send(
                .smb_fname = smb_fname,
        };
 
+       if (!lp_store_dos_attributes(SNUM(dir_fsp->conn))) {
+               DBG_ERR("%s: \"smbd async dosmode\" enabled, but "
+                       "\"store dos attributes\" is disabled\n",
+                       dir_fsp->conn->connectpath);
+               tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
+               return tevent_req_post(req, ev);
+       }
+
        subreq = SMB_VFS_GETXATTRAT_SEND(state,
                                         ev,
                                         dir_fsp,
@@ -1873,14 +1958,7 @@ static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
                *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);
+       return fget_ea_dos_attribute(fsp, dosmode);
 }
 
 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
@@ -1946,6 +2024,8 @@ static struct tevent_req *vfswrap_offload_read_send(
 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
                                          struct vfs_handle_struct *handle,
                                          TALLOC_CTX *mem_ctx,
+                                         uint32_t *flags,
+                                         uint64_t *xferlen,
                                          DATA_BLOB *token)
 {
        struct vfswrap_offload_read_state *state = tevent_req_data(
@@ -1957,6 +2037,8 @@ static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
                return status;
        }
 
+       *flags = 0;
+       *xferlen = 0;
        token->length = state->token.length;
        token->data = talloc_move(mem_ctx, &state->token.data);
 
@@ -1977,6 +2059,7 @@ struct vfswrap_offload_write_state {
        off_t dst_off;
        off_t to_copy;
        off_t remaining;
+       off_t copied;
        size_t next_io_size;
 };
 
@@ -1996,6 +2079,7 @@ static void vfswrap_offload_write_cleanup(struct tevent_req *req,
        state->dst_fsp = NULL;
 }
 
+static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req);
 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
 
 static struct tevent_req *vfswrap_offload_write_send(
@@ -2135,6 +2219,16 @@ static struct tevent_req *vfswrap_offload_write_send(
                return tevent_req_post(req, ev);
        }
 
+       status = vfswrap_offload_copy_file_range(req);
+       if (NT_STATUS_IS_OK(status)) {
+               tevent_req_done(req);
+               return tevent_req_post(req, ev);
+       }
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+               tevent_req_nterror(req, status);
+               return tevent_req_post(req, ev);
+       }
+
        state->buf = talloc_array(state, uint8_t, num);
        if (tevent_req_nomem(state->buf, req)) {
                return tevent_req_post(req, ev);
@@ -2149,6 +2243,137 @@ static struct tevent_req *vfswrap_offload_write_send(
        return req;
 }
 
+static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
+{
+       struct vfswrap_offload_write_state *state = tevent_req_data(
+               req, struct vfswrap_offload_write_state);
+       struct lock_struct lck;
+       ssize_t nwritten;
+       NTSTATUS status;
+       bool same_file;
+       bool ok;
+       static bool try_copy_file_range = true;
+
+       if (!try_copy_file_range) {
+               return NT_STATUS_MORE_PROCESSING_REQUIRED;
+       }
+
+       same_file = file_id_equal(&state->src_fsp->file_id,
+                                 &state->dst_fsp->file_id);
+       if (same_file &&
+           sys_io_ranges_overlap(state->remaining,
+                                 state->src_off,
+                                 state->remaining,
+                                 state->dst_off))
+       {
+               return NT_STATUS_MORE_PROCESSING_REQUIRED;
+       }
+
+       if (fsp_is_alternate_stream(state->src_fsp) ||
+           fsp_is_alternate_stream(state->dst_fsp))
+       {
+               return NT_STATUS_MORE_PROCESSING_REQUIRED;
+       }
+
+       init_strict_lock_struct(state->src_fsp,
+                               state->src_fsp->op->global->open_persistent_id,
+                               state->src_off,
+                               state->remaining,
+                               READ_LOCK,
+                               lp_posix_cifsu_locktype(state->src_fsp),
+                               &lck);
+
+       ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
+                                state->src_fsp,
+                                &lck);
+       if (!ok) {
+               return NT_STATUS_FILE_LOCK_CONFLICT;
+       }
+
+       ok = change_to_user_and_service_by_fsp(state->dst_fsp);
+       if (!ok) {
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
+       init_strict_lock_struct(state->dst_fsp,
+                               state->dst_fsp->op->global->open_persistent_id,
+                               state->dst_off,
+                               state->remaining,
+                               WRITE_LOCK,
+                               lp_posix_cifsu_locktype(state->dst_fsp),
+                               &lck);
+
+       ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
+                                      state->dst_fsp,
+                                      &lck);
+       if (!ok) {
+               return NT_STATUS_FILE_LOCK_CONFLICT;
+       }
+
+       while (state->remaining > 0) {
+               nwritten = copy_file_range(fsp_get_io_fd(state->src_fsp),
+                                          &state->src_off,
+                                          fsp_get_io_fd(state->dst_fsp),
+                                          &state->dst_off,
+                                          state->remaining,
+                                          0);
+               if (nwritten == -1) {
+                       DBG_DEBUG("copy_file_range src [%s]:[%jd] dst [%s]:[%jd] "
+                                 "n [%jd] failed: %s\n",
+                                 fsp_str_dbg(state->src_fsp),
+                                 (intmax_t)state->src_off,
+                                 fsp_str_dbg(state->dst_fsp),
+                                 (intmax_t)state->dst_off,
+                                 (intmax_t)state->remaining,
+                                 strerror(errno));
+                       switch (errno) {
+                       case EOPNOTSUPP:
+                       case ENOSYS:
+                               try_copy_file_range = false;
+                               status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+                               break;
+                       case EXDEV:
+                               status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+                               break;
+                       default:
+                               status = map_nt_error_from_unix(errno);
+                               if (NT_STATUS_EQUAL(
+                                           status,
+                                           NT_STATUS_MORE_PROCESSING_REQUIRED))
+                               {
+                                       /* Avoid triggering the fallback */
+                                       status = NT_STATUS_INTERNAL_ERROR;
+                               }
+                               break;
+                       }
+                       return status;
+               }
+
+               if (state->remaining < nwritten) {
+                       DBG_DEBUG("copy_file_range src [%s] dst [%s] "
+                                 "n [%jd] remaining [%jd]\n",
+                                 fsp_str_dbg(state->src_fsp),
+                                 fsp_str_dbg(state->dst_fsp),
+                                 (intmax_t)nwritten,
+                                 (intmax_t)state->remaining);
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
+
+               if (nwritten == 0) {
+                       break;
+               }
+               state->copied += nwritten;
+               state->remaining -= nwritten;
+       }
+
+       /*
+        * Tell the req cleanup function there's no need to call
+        * change_to_user_and_service_by_fsp() on the dst handle.
+        */
+       state->dst_fsp = NULL;
+       return NT_STATUS_OK;
+}
+
 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
 
 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
@@ -2170,6 +2395,7 @@ static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
                                state->src_off,
                                state->next_io_size,
                                READ_LOCK,
+                               lp_posix_cifsu_locktype(state->src_fsp),
                                &read_lck);
 
        ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
@@ -2233,6 +2459,7 @@ static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
                                state->dst_off,
                                state->next_io_size,
                                WRITE_LOCK,
+                               lp_posix_cifsu_locktype(state->dst_fsp),
                                &write_lck);
 
        ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
@@ -2287,6 +2514,7 @@ static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
                tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
                return;
        }
+       state->copied += nwritten;
        state->remaining -= nwritten;
        if (state->remaining == 0) {
                tevent_req_done(req);
@@ -2323,17 +2551,16 @@ static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
                return status;
        }
 
-       *copied = state->to_copy;
+       *copied = state->copied;
        DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
        tevent_req_received(req);
 
        return NT_STATUS_OK;
 }
 
-static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
+static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
                                        TALLOC_CTX *mem_ctx,
                                        struct files_struct *fsp,
-                                       struct smb_filename *smb_fname,
                                        uint16_t *_compression_fmt)
 {
        return NT_STATUS_INVALID_DEVICE_REQUEST;
@@ -2414,8 +2641,6 @@ static int vfswrap_unlinkat(vfs_handle_struct *handle,
 
        START_PROFILE(syscall_unlinkat);
 
-       SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
-
        if (is_named_stream(smb_fname)) {
                errno = ENOENT;
                goto out;
@@ -2429,29 +2654,37 @@ static int vfswrap_unlinkat(vfs_handle_struct *handle,
        return result;
 }
 
-static int vfswrap_chmod(vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname,
-                       mode_t mode)
-{
-       int result;
-
-       START_PROFILE(syscall_chmod);
-       result = chmod(smb_fname->base_name, mode);
-       END_PROFILE(syscall_chmod);
-       return result;
-}
-
 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
 {
        int result;
 
        START_PROFILE(syscall_fchmod);
-#if defined(HAVE_FCHMOD)
-       result = fchmod(fsp_get_io_fd(fsp), mode);
-#else
-       result = -1;
-       errno = ENOSYS;
-#endif
+
+       if (!fsp->fsp_flags.is_pathref) {
+               result = fchmod(fsp_get_io_fd(fsp), mode);
+               END_PROFILE(syscall_fchmod);
+               return result;
+       }
+
+       if (fsp->fsp_flags.have_proc_fds) {
+               int fd = fsp_get_pathref_fd(fsp);
+               const char *p = NULL;
+               char buf[PATH_MAX];
+
+               p = sys_proc_fd_path(fd, buf, sizeof(buf));
+               if (p != NULL) {
+                       result = chmod(p, mode);
+               } else {
+                       result = -1;
+               }
+               END_PROFILE(syscall_fchmod);
+               return result;
+       }
+
+       /*
+        * This is no longer a handle based call.
+        */
+       result = chmod(fsp->fsp_name->base_name, mode);
 
        END_PROFILE(syscall_fchmod);
        return result;
@@ -2463,7 +2696,31 @@ static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t ui
        int result;
 
        START_PROFILE(syscall_fchown);
-       result = fchown(fsp_get_io_fd(fsp), uid, gid);
+       if (!fsp->fsp_flags.is_pathref) {
+               result = fchown(fsp_get_io_fd(fsp), uid, gid);
+               END_PROFILE(syscall_fchown);
+               return result;
+       }
+
+       if (fsp->fsp_flags.have_proc_fds) {
+               int fd = fsp_get_pathref_fd(fsp);
+               const char *p = NULL;
+               char buf[PATH_MAX];
+
+               p = sys_proc_fd_path(fd, buf, sizeof(buf));
+               if (p != NULL) {
+                       result = chown(p, uid, gid);
+               } else {
+                       result = -1;
+               }
+               END_PROFILE(syscall_fchown);
+               return result;
+       }
+
+       /*
+        * This is no longer a handle based call.
+        */
+       result = chown(fsp->fsp_name->base_name, uid, gid);
        END_PROFILE(syscall_fchown);
        return result;
 #else
@@ -2529,89 +2786,87 @@ static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
  system will support.
 **********************************************************************/
 
-static int vfswrap_ntimes(vfs_handle_struct *handle,
-                         const struct smb_filename *smb_fname,
-                         struct smb_file_time *ft)
+static int vfswrap_fntimes(vfs_handle_struct *handle,
+                          files_struct *fsp,
+                          struct smb_file_time *ft)
 {
        int result = -1;
+       struct timespec ts[2];
+       struct timespec *times = NULL;
 
-       START_PROFILE(syscall_ntimes);
+       START_PROFILE(syscall_fntimes);
 
-       if (is_named_stream(smb_fname)) {
+       if (fsp_is_alternate_stream(fsp)) {
                errno = ENOENT;
                goto out;
        }
 
        if (ft != NULL) {
                if (is_omit_timespec(&ft->atime)) {
-                       ft->atime= smb_fname->st.st_ex_atime;
+                       ft->atime = fsp->fsp_name->st.st_ex_atime;
                }
 
                if (is_omit_timespec(&ft->mtime)) {
-                       ft->mtime = smb_fname->st.st_ex_mtime;
+                       ft->mtime = fsp->fsp_name->st.st_ex_mtime;
                }
 
                if (!is_omit_timespec(&ft->create_time)) {
-                       set_create_timespec_ea(handle->conn,
-                                              smb_fname,
+                       set_create_timespec_ea(fsp,
                                               ft->create_time);
                }
 
                if ((timespec_compare(&ft->atime,
-                                     &smb_fname->st.st_ex_atime) == 0) &&
+                                     &fsp->fsp_name->st.st_ex_atime) == 0) &&
                    (timespec_compare(&ft->mtime,
-                                     &smb_fname->st.st_ex_mtime) == 0)) {
-                       return 0;
+                                     &fsp->fsp_name->st.st_ex_mtime) == 0)) {
+                       result = 0;
+                       goto out;
                }
-       }
 
-#if defined(HAVE_UTIMENSAT)
-       if (ft != NULL) {
-               struct timespec ts[2];
                ts[0] = ft->atime;
                ts[1] = ft->mtime;
-               result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
-       } else {
-               result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
-       }
-       if (!((result == -1) && (errno == ENOSYS))) {
-               goto out;
-       }
-#endif
-#if defined(HAVE_UTIMES)
-       if (ft != NULL) {
-               struct timeval tv[2];
-               tv[0] = convert_timespec_to_timeval(ft->atime);
-               tv[1] = convert_timespec_to_timeval(ft->mtime);
-               result = utimes(smb_fname->base_name, tv);
+               times = ts;
        } else {
-               result = utimes(smb_fname->base_name, NULL);
+               times = NULL;
        }
-       if (!((result == -1) && (errno == ENOSYS))) {
+
+       if (!fsp->fsp_flags.is_pathref) {
+               result = futimens(fsp_get_io_fd(fsp), times);
                goto out;
        }
-#endif
-#if defined(HAVE_UTIME)
-       if (ft != NULL) {
-               struct utimbuf times;
-               times.actime = convert_timespec_to_time_t(ft->atime);
-               times.modtime = convert_timespec_to_time_t(ft->mtime);
-               result = utime(smb_fname->base_name, &times);
-       } else {
-               result = utime(smb_fname->base_name, NULL);
-       }
-       if (!((result == -1) && (errno == ENOSYS))) {
+
+       if (fsp->fsp_flags.have_proc_fds) {
+               int fd = fsp_get_pathref_fd(fsp);
+               const char *p = NULL;
+               char buf[PATH_MAX];
+
+               p = sys_proc_fd_path(fd, buf, sizeof(buf));
+               if (p != NULL) {
+                       /*
+                        * The dirfd argument of utimensat is ignored when
+                        * pathname is an absolute path
+                        */
+                       result = utimensat(AT_FDCWD, p, times, 0);
+               } else {
+                       result = -1;
+               }
+
                goto out;
        }
-#endif
-       errno = ENOSYS;
-       result = -1;
 
- out:
-       END_PROFILE(syscall_ntimes);
+       /*
+        * The fd is a pathref (opened with O_PATH) and there isn't fd to
+        * path translation mechanism. Fallback to path based call.
+        */
+       result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
+
+out:
+       END_PROFILE(syscall_fntimes);
+
        return result;
 }
 
+
 /*********************************************************************
  A version of ftruncate that will write the space on disk if strict
  allocate is set.
@@ -2802,13 +3057,13 @@ static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, o
        return result;
 }
 
-static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
-                               uint32_t share_access, uint32_t access_mask)
+static int vfswrap_filesystem_sharemode(vfs_handle_struct *handle,
+                                       files_struct *fsp,
+                                       uint32_t share_access,
+                                       uint32_t access_mask)
 {
-       START_PROFILE(syscall_kernel_flock);
-       kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
-       END_PROFILE(syscall_kernel_flock);
-       return 0;
+       errno = ENOTSUP;
+       return -1;
 }
 
 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
@@ -2985,12 +3240,33 @@ static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
        return result_fname;
 }
 
-static int vfswrap_chflags(vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname,
+static int vfswrap_fchflags(vfs_handle_struct *handle,
+                       struct files_struct *fsp,
                        unsigned int flags)
 {
-#ifdef HAVE_CHFLAGS
-       return chflags(smb_fname->base_name, flags);
+#ifdef HAVE_FCHFLAGS
+       int fd = fsp_get_pathref_fd(fsp);
+
+       if (!fsp->fsp_flags.is_pathref) {
+               return fchflags(fd, flags);
+       }
+
+       if (fsp->fsp_flags.have_proc_fds) {
+               const char *p = NULL;
+               char buf[PATH_MAX];
+
+               p = sys_proc_fd_path(fd, buf, sizeof(buf));
+               if (p == NULL) {
+                       return -1;
+               }
+
+               return chflags(p, flags);
+       }
+
+       /*
+        * This is no longer a handle based call.
+        */
+       return chflags(fsp->fsp_name->base_name, flags);
 #else
        errno = ENOSYS;
        return -1;
@@ -3018,10 +3294,6 @@ static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
 {
        uint64_t file_id;
 
-       if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
-               return psbuf->st_ex_file_id;
-       }
-
        if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
                return (uint64_t)psbuf->st_ex_ino;
        }
@@ -3035,82 +3307,82 @@ static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
        return file_id;
 }
 
-static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
+static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
                                   struct files_struct *fsp,
-                                  const struct smb_filename *smb_fname,
                                   TALLOC_CTX *mem_ctx,
                                   unsigned int *pnum_streams,
                                   struct stream_struct **pstreams)
 {
-       SMB_STRUCT_STAT sbuf;
        struct stream_struct *tmp_streams = NULL;
-       int ret;
+       unsigned int num_streams = *pnum_streams;
+       struct stream_struct *streams = *pstreams;
+       NTSTATUS status;
 
-       if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
+       if (fsp->fsp_flags.is_directory) {
                /*
                 * No default streams on directories
                 */
                goto done;
        }
-
-       if ((fsp != NULL) && (fsp_get_pathref_fd(fsp) != -1)) {
-               ret = SMB_VFS_FSTAT(fsp, &sbuf);
-       }
-       else {
-               struct smb_filename *smb_fname_cp = NULL;
-
-               smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
-               if (smb_fname_cp == NULL) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-
-               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_cp);
-               }
-               sbuf = smb_fname_cp->st;
-               TALLOC_FREE(smb_fname_cp);
-       }
-
-       if (ret == -1) {
-               return map_nt_error_from_unix(errno);
+       status = vfs_stat_fsp(fsp);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
-       if (S_ISDIR(sbuf.st_ex_mode)) {
-               goto done;
+       if (num_streams + 1 < 1) {
+               /* Integer wrap. */
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
-                                       (*pnum_streams) + 1);
+       tmp_streams = talloc_realloc(mem_ctx,
+                                       streams,
+                                       struct stream_struct,
+                                       num_streams + 1);
        if (tmp_streams == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
-       tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
-       if (tmp_streams[*pnum_streams].name == NULL) {
+       tmp_streams[num_streams].name = talloc_strdup(tmp_streams, "::$DATA");
+       if (tmp_streams[num_streams].name == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
-       tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
-       tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
+       tmp_streams[num_streams].size = fsp->fsp_name->st.st_ex_size;
+       tmp_streams[num_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(
+                                               handle->conn,
+                                               fsp,
+                                               &fsp->fsp_name->st);
+       num_streams += 1;
 
-       *pnum_streams += 1;
+       *pnum_streams = num_streams;
        *pstreams = tmp_streams;
  done:
        return NT_STATUS_OK;
 }
 
-static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
-                                    const struct smb_filename *path,
-                                    const char *name,
-                                    TALLOC_CTX *mem_ctx,
-                                    char **found_name)
+static NTSTATUS vfswrap_get_real_filename(struct vfs_handle_struct *handle,
+                                         const struct smb_filename *path,
+                                         const char *name,
+                                         TALLOC_CTX *mem_ctx,
+                                         char **found_name)
 {
        /*
         * Don't fall back to get_real_filename so callers can differentiate
         * between a full directory scan and an actual case-insensitive stat.
         */
-       errno = EOPNOTSUPP;
-       return -1;
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS vfswrap_get_real_filename_at(
+       struct vfs_handle_struct *handle,
+       struct files_struct *dirfsp,
+       const char *name,
+       TALLOC_CTX *mem_ctx,
+       char **found_name)
+{
+       /*
+        * Don't fall back to get_real_filename so callers can differentiate
+        * between a full directory scan and an actual case-insensitive stat.
+        */
+       return NT_STATUS_NOT_SUPPORTED;
 }
 
 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
@@ -3165,28 +3437,6 @@ static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
        return result;
 }
 
-static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
-                       struct files_struct *dirfsp,
-                       const struct smb_filename *smb_fname,
-                       uint32_t security_info,
-                       TALLOC_CTX *mem_ctx,
-                       struct security_descriptor **ppdesc)
-{
-       NTSTATUS result;
-
-       START_PROFILE(get_nt_acl_at);
-
-       SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
-
-       result = posix_get_nt_acl(handle->conn,
-                               smb_fname,
-                               security_info,
-                               mem_ctx,
-                               ppdesc);
-       END_PROFILE(get_nt_acl_at);
-       return result;
-}
-
 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
 {
        NTSTATUS result;
@@ -3206,55 +3456,65 @@ static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
        return NT_STATUS_OK; /* Nothing to do here ... */
 }
 
-static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
-                                         const struct smb_filename *smb_fname,
-                                         SMB_ACL_TYPE_T type,
-                                         TALLOC_CTX *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,
                                        files_struct *fsp,
+                                       SMB_ACL_TYPE_T type,
                                        TALLOC_CTX *mem_ctx)
 {
-       return sys_acl_get_fd(handle, fsp, mem_ctx);
+       return sys_acl_get_fd(handle, fsp, type, mem_ctx);
 }
 
-static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
-                               const struct smb_filename *smb_fname,
-                               SMB_ACL_TYPE_T acltype,
-                               SMB_ACL_T theacl)
-{
-       return sys_acl_set_file(handle, smb_fname, acltype, theacl);
-}
-
-static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
+static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
+                                 files_struct *fsp,
+                                 SMB_ACL_TYPE_T type,
+                                 SMB_ACL_T theacl)
 {
-       return sys_acl_set_fd(handle, fsp, theacl);
+       return sys_acl_set_fd(handle, fsp, type, theacl);
 }
 
-static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname)
+static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct *handle,
+                                        files_struct *fsp)
 {
-       return sys_acl_delete_def_file(handle, smb_fname);
+       return sys_acl_delete_def_fd(handle, fsp);
 }
 
 /****************************************************************
  Extended attribute operations.
 *****************************************************************/
 
-static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname,
-                       const char *name,
-                       void *value,
-                       size_t size)
+static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
+                                struct files_struct *fsp,
+                                const char *name,
+                                void *value,
+                                size_t size)
 {
-       return getxattr(smb_fname->base_name, name, value, size);
+       int fd = fsp_get_pathref_fd(fsp);
+
+       if (!fsp->fsp_flags.is_pathref) {
+               return fgetxattr(fd, name, value, size);
+       }
+
+       if (fsp->fsp_flags.have_proc_fds) {
+               const char *p = NULL;
+               char buf[PATH_MAX];
+
+               p = sys_proc_fd_path(fd, buf, sizeof(buf));
+               if (p == NULL) {
+                       return -1;
+               }
+
+               return getxattr(p, name, value, size);
+       }
+
+       /*
+        * This is no longer a handle based call.
+        */
+       return getxattr(fsp->fsp_name->base_name, name, value, size);
 }
 
 struct vfswrap_getxattrat_state {
        struct tevent_context *ev;
+       struct vfs_handle_struct *handle;
        files_struct *dir_fsp;
        const struct smb_filename *smb_fname;
 
@@ -3307,6 +3567,7 @@ static struct tevent_req *vfswrap_getxattrat_send(
        }
        *state = (struct vfswrap_getxattrat_state) {
                .ev = ev,
+               .handle = handle,
                .dir_fsp = dir_fsp,
                .smb_fname = smb_fname,
        };
@@ -3405,31 +3666,15 @@ static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
 {
        struct vfswrap_getxattrat_state *state = tevent_req_data(
                req, struct vfswrap_getxattrat_state);
-       char *path = NULL;
-       char *tofree = NULL;
-       char pathbuf[PATH_MAX+1];
-       ssize_t pathlen;
-       int err;
+       struct files_struct *fsp = metadata_fsp(state->smb_fname->fsp);
 
-       pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
-                               state->smb_fname->base_name,
-                               pathbuf,
-                               sizeof(pathbuf),
-                               &path,
-                               &tofree);
-       if (pathlen == -1) {
-               tevent_req_error(req, ENOMEM);
-               return;
-       }
-
-       state->xattr_size = getxattr(path,
-                                    state->xattr_name,
-                                    state->xattr_value,
-                                    talloc_array_length(state->xattr_value));
-       err = errno;
-       TALLOC_FREE(tofree);
+       state->xattr_size = vfswrap_fgetxattr(state->handle,
+                                             fsp,
+                                             state->xattr_name,
+                                             state->xattr_value,
+                                             talloc_array_length(state->xattr_value));
        if (state->xattr_size == -1) {
-               tevent_req_error(req, err);
+               tevent_req_error(req, errno);
                return;
        }
 
@@ -3444,6 +3689,7 @@ static void vfswrap_getxattrat_do_async(void *private_data)
        struct timespec start_time;
        struct timespec end_time;
        int ret;
+       struct files_struct *fsp = metadata_fsp(state->smb_fname->fsp);
 
        PROFILE_TIMESTAMP(&start_time);
        SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
@@ -3466,17 +3712,11 @@ static void vfswrap_getxattrat_do_async(void *private_data)
                goto end_profile;
        }
 
-       ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
-       if (ret == -1) {
-               state->xattr_size = -1;
-               state->vfs_aio_state.error = errno;
-               goto end_profile;
-       }
-
-       state->xattr_size = getxattr(state->name,
-                                    state->xattr_name,
-                                    state->xattr_value,
-                                    talloc_array_length(state->xattr_value));
+       state->xattr_size = vfswrap_fgetxattr(state->handle,
+                                             fsp,
+                                             state->xattr_name,
+                                             state->xattr_value,
+                                             talloc_array_length(state->xattr_value));
        if (state->xattr_size == -1) {
                state->vfs_aio_state.error = errno;
        }
@@ -3570,44 +3810,6 @@ static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
        return xattr_size;
 }
 
-static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
-                                struct files_struct *fsp,
-                                const char *name,
-                                void *value,
-                                size_t size)
-{
-       int fd = fsp_get_pathref_fd(fsp);
-
-       if (!fsp->fsp_flags.is_pathref) {
-               return fgetxattr(fd, name, value, size);
-       }
-
-       if (fsp->fsp_flags.have_proc_fds) {
-               const char *p = NULL;
-               char buf[PATH_MAX];
-
-               p = sys_proc_fd_path(fd, buf, sizeof(buf));
-               if (p == NULL) {
-                       return -1;
-               }
-
-               return getxattr(p, name, value, size);
-       }
-
-       /*
-        * This is no longer a handle based call.
-        */
-       return getxattr(fsp->fsp_name->base_name, name, value, size);
-}
-
-static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname,
-                       char *list,
-                       size_t size)
-{
-       return listxattr(smb_fname->base_name, list, size);
-}
-
 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
 {
        int fd = fsp_get_pathref_fd(fsp);
@@ -3634,13 +3836,6 @@ static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files
        return listxattr(fsp->fsp_name->base_name, list, size);
 }
 
-static int vfswrap_removexattr(struct vfs_handle_struct *handle,
-                               const struct smb_filename *smb_fname,
-                               const char *name)
-{
-       return removexattr(smb_fname->base_name, name);
-}
-
 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
 {
        int fd = fsp_get_pathref_fd(fsp);
@@ -3667,16 +3862,6 @@ static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_s
        return removexattr(fsp->fsp_name->base_name, name);
 }
 
-static int vfswrap_setxattr(struct vfs_handle_struct *handle,
-                               const struct smb_filename *smb_fname,
-                               const char *name,
-                               const void *value,
-                               size_t size,
-                               int flags)
-{
-       return setxattr(smb_fname->base_name, name, value, size, flags);
-}
-
 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
 {
        int fd = fsp_get_pathref_fd(fsp);
@@ -3792,7 +3977,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
 
        .fdopendir_fn = vfswrap_fdopendir,
        .readdir_fn = vfswrap_readdir,
-       .readdir_attr_fn = vfswrap_readdir_attr,
+       .freaddir_attr_fn = vfswrap_freaddir_attr,
        .seekdir_fn = vfswrap_seekdir,
        .telldir_fn = vfswrap_telldir,
        .rewind_dir_fn = vfswrap_rewinddir,
@@ -3819,19 +4004,19 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .stat_fn = vfswrap_stat,
        .fstat_fn = vfswrap_fstat,
        .lstat_fn = vfswrap_lstat,
+       .fstatat_fn = vfswrap_fstatat,
        .get_alloc_size_fn = vfswrap_get_alloc_size,
        .unlinkat_fn = vfswrap_unlinkat,
-       .chmod_fn = vfswrap_chmod,
        .fchmod_fn = vfswrap_fchmod,
        .fchown_fn = vfswrap_fchown,
        .lchown_fn = vfswrap_lchown,
        .chdir_fn = vfswrap_chdir,
        .getwd_fn = vfswrap_getwd,
-       .ntimes_fn = vfswrap_ntimes,
+       .fntimes_fn = vfswrap_fntimes,
        .ftruncate_fn = vfswrap_ftruncate,
        .fallocate_fn = vfswrap_fallocate,
        .lock_fn = vfswrap_lock,
-       .kernel_flock_fn = vfswrap_kernel_flock,
+       .filesystem_sharemode_fn = vfswrap_filesystem_sharemode,
        .fcntl_fn = vfswrap_fcntl,
        .linux_setlease_fn = vfswrap_linux_setlease,
        .getlock_fn = vfswrap_getlock,
@@ -3840,20 +4025,20 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .linkat_fn = vfswrap_linkat,
        .mknodat_fn = vfswrap_mknodat,
        .realpath_fn = vfswrap_realpath,
-       .chflags_fn = vfswrap_chflags,
+       .fchflags_fn = vfswrap_fchflags,
        .file_id_create_fn = vfswrap_file_id_create,
        .fs_file_id_fn = vfswrap_fs_file_id,
-       .streaminfo_fn = vfswrap_streaminfo,
+       .fstreaminfo_fn = vfswrap_fstreaminfo,
        .get_real_filename_fn = vfswrap_get_real_filename,
+       .get_real_filename_at_fn = vfswrap_get_real_filename_at,
        .connectpath_fn = vfswrap_connectpath,
        .brl_lock_windows_fn = vfswrap_brl_lock_windows,
        .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
        .strict_lock_check_fn = vfswrap_strict_lock_check,
        .translate_name_fn = vfswrap_translate_name,
+       .parent_pathname_fn = vfswrap_parent_pathname,
        .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,
        .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
        .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
        .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
@@ -3861,36 +4046,28 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .offload_read_recv_fn = vfswrap_offload_read_recv,
        .offload_write_send_fn = vfswrap_offload_write_send,
        .offload_write_recv_fn = vfswrap_offload_write_recv,
-       .get_compression_fn = vfswrap_get_compression,
+       .fget_compression_fn = vfswrap_fget_compression,
        .set_compression_fn = vfswrap_set_compression,
 
        /* NT ACL operations. */
 
        .fget_nt_acl_fn = vfswrap_fget_nt_acl,
-       .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
        .fset_nt_acl_fn = vfswrap_fset_nt_acl,
        .audit_file_fn = vfswrap_audit_file,
 
        /* POSIX ACL operations. */
 
-       .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
        .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
-       .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
        .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
-       .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
        .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
-       .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
+       .sys_acl_delete_def_fd_fn = vfswrap_sys_acl_delete_def_fd,
 
        /* EA operations. */
-       .getxattr_fn = vfswrap_getxattr,
        .getxattrat_send_fn = vfswrap_getxattrat_send,
        .getxattrat_recv_fn = vfswrap_getxattrat_recv,
        .fgetxattr_fn = vfswrap_fgetxattr,
-       .listxattr_fn = vfswrap_listxattr,
        .flistxattr_fn = vfswrap_flistxattr,
-       .removexattr_fn = vfswrap_removexattr,
        .fremovexattr_fn = vfswrap_fremovexattr,
-       .setxattr_fn = vfswrap_setxattr,
        .fsetxattr_fn = vfswrap_fsetxattr,
 
        /* aio operations */