s4:dns_server: no-op dns updates with ACCESS_DENIED should be ignored
[samba.git] / source3 / modules / vfs_glusterfs.c
index 56a403b5547b3e94df3fed69e6473311085ca2d8..00b4cdd4698da6f06f4f751fbd1fd1a1c2016795 100644 (file)
@@ -41,6 +41,7 @@
 #include <glusterfs/api/glfs.h>
 #include "lib/util/dlinklist.h"
 #include "lib/util/tevent_unix.h"
+#include "lib/util/util_file.h"
 #include "smbd/globals.h"
 #include "lib/util/sys_rw.h"
 #include "smbprofile.h"
@@ -151,6 +152,7 @@ static void glfs_clear_preopened(glfs_t *fs)
 
                        glfs_fini(entry->fs);
                        talloc_free(entry);
+                       break;
                }
        }
 }
@@ -313,7 +315,7 @@ static int check_for_write_behind_translator(TALLOC_CTX *mem_ctx,
 
        /*
         * file_lines_parse() plays horrible tricks with
-        * the passed-in talloc pointers and the hierarcy
+        * the passed-in talloc pointers and the hierarchy
         * which makes freeing hard to get right.
         *
         * As we know mem_ctx is freed by the caller, after
@@ -606,7 +608,7 @@ static uint32_t vfs_gluster_fs_capabilities(struct vfs_handle_struct *handle,
 }
 
 static glfs_fd_t *vfs_gluster_fetch_glfd(struct vfs_handle_struct *handle,
-                                        files_struct *fsp)
+                                        const files_struct *fsp)
 {
        glfs_fd_t **glfd = (glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp);
        if (glfd == NULL) {
@@ -625,9 +627,10 @@ static DIR *vfs_gluster_fdopendir(struct vfs_handle_struct *handle,
                                  files_struct *fsp, const char *mask,
                                  uint32_t attributes)
 {
-       glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp);
+       glfs_fd_t *glfd = NULL;
+
+       glfd = glfs_opendir(handle->data, fsp->fsp_name->base_name);
        if (glfd == NULL) {
-               DBG_ERR("Failed to fetch gluster fd\n");
                return NULL;
        }
 
@@ -647,57 +650,25 @@ static int vfs_gluster_closedir(struct vfs_handle_struct *handle, DIR *dirp)
 
 static struct dirent *vfs_gluster_readdir(struct vfs_handle_struct *handle,
                                          struct files_struct *dirfsp,
-                                         DIR *dirp,
-                                         SMB_STRUCT_STAT *sbuf)
+                                         DIR *dirp)
 {
        static char direntbuf[512];
        int ret;
-       struct stat stat;
        struct dirent *dirent = 0;
 
        START_PROFILE(syscall_readdir);
-       if (sbuf != NULL) {
-               ret = glfs_readdirplus_r((void *)dirp, &stat, (void *)direntbuf,
-                                        &dirent);
-       } else {
-               ret = glfs_readdir_r((void *)dirp, (void *)direntbuf, &dirent);
-       }
+
+       ret = glfs_readdir_r((void *)dirp, (void *)direntbuf, &dirent);
 
        if ((ret < 0) || (dirent == NULL)) {
                END_PROFILE(syscall_readdir);
                return NULL;
        }
 
-       if (sbuf != NULL) {
-               SET_STAT_INVALID(*sbuf);
-               if (!S_ISLNK(stat.st_mode)) {
-                       smb_stat_ex_from_stat(sbuf, &stat);
-               }
-       }
-
        END_PROFILE(syscall_readdir);
        return dirent;
 }
 
-static long vfs_gluster_telldir(struct vfs_handle_struct *handle, DIR *dirp)
-{
-       long ret;
-
-       START_PROFILE(syscall_telldir);
-       ret = glfs_telldir((void *)dirp);
-       END_PROFILE(syscall_telldir);
-
-       return ret;
-}
-
-static void vfs_gluster_seekdir(struct vfs_handle_struct *handle, DIR *dirp,
-                               long offset)
-{
-       START_PROFILE(syscall_seekdir);
-       glfs_seekdir((void *)dirp, offset);
-       END_PROFILE(syscall_seekdir);
-}
-
 static void vfs_gluster_rewinddir(struct vfs_handle_struct *handle, DIR *dirp)
 {
        START_PROFILE(syscall_rewinddir);
@@ -710,9 +681,24 @@ static int vfs_gluster_mkdirat(struct vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
                        mode_t mode)
 {
-       struct smb_filename *full_fname = NULL;
        int ret;
 
+#ifdef HAVE_GFAPI_VER_7_11
+       glfs_fd_t *pglfd = NULL;
+
+       START_PROFILE(syscall_mkdirat);
+
+       pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
+       if (pglfd == NULL) {
+               END_PROFILE(syscall_mkdirat);
+               DBG_ERR("Failed to fetch gluster fd\n");
+               return -1;
+       }
+
+       ret = glfs_mkdirat(pglfd, smb_fname->base_name, mode);
+#else
+       struct smb_filename *full_fname = NULL;
+
        START_PROFILE(syscall_mkdirat);
 
        full_fname = full_path_from_dirfsp_atname(talloc_tos(),
@@ -726,6 +712,7 @@ static int vfs_gluster_mkdirat(struct vfs_handle_struct *handle,
        ret = glfs_mkdir(handle->data, full_fname->base_name, mode);
 
        TALLOC_FREE(full_fname);
+#endif
 
        END_PROFILE(syscall_mkdirat);
 
@@ -736,63 +723,103 @@ static int vfs_gluster_openat(struct vfs_handle_struct *handle,
                              const struct files_struct *dirfsp,
                              const struct smb_filename *smb_fname,
                              files_struct *fsp,
-                             int flags,
-                             mode_t mode)
+                             const struct vfs_open_how *how)
 {
-       struct smb_filename *name = NULL;
+       int flags = how->flags;
+       struct smb_filename *full_fname = NULL;
+       bool have_opath = false;
        bool became_root = false;
-       glfs_fd_t *glfd;
+       glfs_fd_t *glfd = NULL;
+       glfs_fd_t *pglfd = NULL;
        glfs_fd_t **p_tmp;
 
        START_PROFILE(syscall_openat);
 
-       /*
-        * Looks like glfs API doesn't have openat().
-        */
-       if (fsp_get_pathref_fd(dirfsp) != AT_FDCWD) {
-               name = full_path_from_dirfsp_atname(talloc_tos(),
-                                                   dirfsp,
-                                                   smb_fname);
-               if (name == NULL) {
-                       return -1;
-               }
-               smb_fname = name;
+       if (how->resolve != 0) {
+               END_PROFILE(syscall_openat);
+               errno = ENOSYS;
+               return -1;
        }
 
        p_tmp = VFS_ADD_FSP_EXTENSION(handle, fsp, glfs_fd_t *, NULL);
        if (p_tmp == NULL) {
-               TALLOC_FREE(name);
                END_PROFILE(syscall_openat);
                errno = ENOMEM;
                return -1;
        }
 
+#ifdef O_PATH
+       have_opath = true;
        if (fsp->fsp_flags.is_pathref) {
-               /*
-                * ceph doesn't support O_PATH so we have to fallback to
-                * become_root().
-                */
+               flags |= O_PATH;
+       }
+#endif
+
+       full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+                                                 dirfsp,
+                                                 smb_fname);
+       if (full_fname == NULL) {
+               END_PROFILE(syscall_openat);
+               return -1;
+       }
+
+       if (fsp->fsp_flags.is_pathref && !have_opath) {
                become_root();
                became_root = true;
        }
 
-       if (flags & O_DIRECTORY) {
-               glfd = glfs_opendir(handle->data, smb_fname->base_name);
-       } else if (flags & O_CREAT) {
-               glfd = glfs_creat(handle->data, smb_fname->base_name, flags,
-                                 mode);
-       } else {
-               glfd = glfs_open(handle->data, smb_fname->base_name, flags);
+       if (fsp_get_pathref_fd(dirfsp) != AT_FDCWD) {
+#ifdef HAVE_GFAPI_VER_7_11
+               /*
+                * Fetch Gluster fd for parent directory using dirfsp
+                * before calling glfs_openat();
+                */
+               pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
+               if (pglfd == NULL) {
+                       END_PROFILE(syscall_openat);
+                       DBG_ERR("Failed to fetch gluster fd\n");
+                       return -1;
+               }
+
+               glfd = glfs_openat(pglfd,
+                                  smb_fname->base_name,
+                                  flags,
+                                  how->mode);
+#else
+               /*
+                * Replace smb_fname with full_path constructed above.
+                */
+               smb_fname = full_fname;
+#endif
+       }
+
+       if (pglfd == NULL) {
+               /*
+                * smb_fname can either be a full_path or the same one
+                * as received from the caller. In the latter case we
+                * are operating at current working directory.
+                */
+               if (flags & O_CREAT) {
+                       glfd = glfs_creat(handle->data,
+                                         smb_fname->base_name,
+                                         flags,
+                                         how->mode);
+               } else {
+                       glfd = glfs_open(handle->data,
+                                        smb_fname->base_name,
+                                        flags);
+               }
        }
 
        if (became_root) {
                unbecome_root();
        }
 
+       TALLOC_FREE(full_fname);
+
        fsp->fsp_flags.have_proc_fds = false;
 
        if (glfd == NULL) {
-               TALLOC_FREE(name);
                END_PROFILE(syscall_openat);
                /* no extension destroy_fn, so no need to save errno */
                VFS_REMOVE_FSP_EXTENSION(handle, fsp);
@@ -801,7 +828,6 @@ static int vfs_gluster_openat(struct vfs_handle_struct *handle,
 
        *p_tmp = glfd;
 
-       TALLOC_FREE(name);
        END_PROFILE(syscall_openat);
        /* An arbitrary value for error reporting, so you know its us. */
        return 13371337;
@@ -1205,9 +1231,33 @@ static int vfs_gluster_renameat(struct vfs_handle_struct *handle,
                        files_struct *dstfsp,
                        const struct smb_filename *smb_fname_dst)
 {
+       int ret;
+
+#ifdef HAVE_GFAPI_VER_7_11
+       glfs_fd_t *src_pglfd = NULL;
+       glfs_fd_t *dst_pglfd = NULL;
+
+       START_PROFILE(syscall_renameat);
+
+       src_pglfd = vfs_gluster_fetch_glfd(handle, srcfsp);
+       if (src_pglfd == NULL) {
+               END_PROFILE(syscall_renameat);
+               DBG_ERR("Failed to fetch gluster fd\n");
+               return -1;
+       }
+
+       dst_pglfd = vfs_gluster_fetch_glfd(handle, dstfsp);
+       if (dst_pglfd == NULL) {
+               END_PROFILE(syscall_renameat);
+               DBG_ERR("Failed to fetch gluster fd\n");
+               return -1;
+       }
+
+       ret = glfs_renameat(src_pglfd, smb_fname_src->base_name,
+                           dst_pglfd, smb_fname_dst->base_name);
+#else
        struct smb_filename *full_fname_src = NULL;
        struct smb_filename *full_fname_dst = NULL;
-       int ret;
 
        START_PROFILE(syscall_renameat);
 
@@ -1215,24 +1265,28 @@ static int vfs_gluster_renameat(struct vfs_handle_struct *handle,
                                                      srcfsp,
                                                      smb_fname_src);
        if (full_fname_src == NULL) {
-               errno = ENOMEM;
                END_PROFILE(syscall_renameat);
+               errno = ENOMEM;
                return -1;
        }
+
        full_fname_dst = full_path_from_dirfsp_atname(talloc_tos(),
                                                      dstfsp,
                                                      smb_fname_dst);
        if (full_fname_dst == NULL) {
+               END_PROFILE(syscall_renameat);
                TALLOC_FREE(full_fname_src);
                errno = ENOMEM;
-               END_PROFILE(syscall_renameat);
                return -1;
        }
        ret = glfs_rename(handle->data,
                          full_fname_src->base_name,
                          full_fname_dst->base_name);
+
        TALLOC_FREE(full_fname_src);
        TALLOC_FREE(full_fname_dst);
+#endif
+
        END_PROFILE(syscall_renameat);
 
        return ret;
@@ -1415,6 +1469,55 @@ static int vfs_gluster_fstat(struct vfs_handle_struct *handle,
        return ret;
 }
 
+static int vfs_gluster_fstatat(struct vfs_handle_struct *handle,
+                              const struct files_struct *dirfsp,
+                              const struct smb_filename *smb_fname,
+                              SMB_STRUCT_STAT *sbuf,
+                              int flags)
+{
+       struct stat st;
+       int ret;
+
+#ifdef HAVE_GFAPI_VER_7_11
+       glfs_fd_t *pglfd = NULL;
+
+       START_PROFILE(syscall_fstatat);
+
+       pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
+       if (pglfd == NULL) {
+               END_PROFILE(syscall_fstatat);
+               DBG_ERR("Failed to fetch gluster fd\n");
+               return -1;
+       }
+
+       ret = glfs_fstatat(pglfd, smb_fname->base_name, &st, flags);
+#else
+       struct smb_filename *full_fname = NULL;
+
+       START_PROFILE(syscall_fstatat);
+
+       full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+                                                 dirfsp,
+                                                 smb_fname);
+       if (full_fname == NULL) {
+               END_PROFILE(syscall_fstatat);
+               return -1;
+       }
+
+       ret = glfs_stat(handle->data, full_fname->base_name, &st);
+
+       TALLOC_FREE(full_fname->base_name);
+#endif
+
+       if (ret == 0) {
+               smb_stat_ex_from_stat(sbuf, &st);
+       }
+
+       END_PROFILE(syscall_fstatat);
+
+       return ret;
+}
+
 static int vfs_gluster_lstat(struct vfs_handle_struct *handle,
                             struct smb_filename *smb_fname)
 {
@@ -1453,9 +1556,24 @@ static int vfs_gluster_unlinkat(struct vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
                        int flags)
 {
-       struct smb_filename *full_fname = NULL;
        int ret;
 
+#ifdef HAVE_GFAPI_VER_7_11
+       glfs_fd_t *pglfd = NULL;
+
+       START_PROFILE(syscall_unlinkat);
+
+       pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
+       if (pglfd == NULL) {
+               END_PROFILE(syscall_unlinkat);
+               DBG_ERR("Failed to fetch gluster fd\n");
+               return -1;
+       }
+
+       ret = glfs_unlinkat(pglfd, smb_fname->base_name, flags);
+#else
+       struct smb_filename *full_fname = NULL;
+
        START_PROFILE(syscall_unlinkat);
 
        full_fname = full_path_from_dirfsp_atname(talloc_tos(),
@@ -1471,7 +1589,10 @@ static int vfs_gluster_unlinkat(struct vfs_handle_struct *handle,
        } else {
                ret = glfs_unlink(handle->data, full_fname->base_name);
        }
+
        TALLOC_FREE(full_fname);
+#endif
+
        END_PROFILE(syscall_unlinkat);
 
        return ret;
@@ -1620,7 +1741,13 @@ static int vfs_gluster_fntimes(struct vfs_handle_struct *handle,
                return -1;
        }
 
-       ret = glfs_futimens(glfd, times);
+       if (!fsp->fsp_flags.is_pathref) {
+               ret = glfs_futimens(glfd, times);
+       } else {
+               ret = glfs_utimens(handle->data,
+                                  fsp->fsp_name->base_name,
+                                  times);
+       }
        END_PROFILE(syscall_fntimes);
 
        return ret;
@@ -1871,24 +1998,42 @@ static int vfs_gluster_symlinkat(struct vfs_handle_struct *handle,
                                struct files_struct *dirfsp,
                                const struct smb_filename *new_smb_fname)
 {
-       struct smb_filename *full_fname = NULL;
        int ret;
 
+#ifdef HAVE_GFAPI_VER_7_11
+       glfs_fd_t *pglfd = NULL;
+
+       START_PROFILE(syscall_symlinkat);
+
+       pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
+       if (pglfd == NULL) {
+               END_PROFILE(syscall_symlinkat);
+               DBG_ERR("Failed to fetch gluster fd\n");
+               return -1;
+       }
+
+       ret = glfs_symlinkat(link_target->base_name,
+                            pglfd,
+                            new_smb_fname->base_name);
+#else
+       struct smb_filename *full_fname = NULL;
+
        START_PROFILE(syscall_symlinkat);
 
        full_fname = full_path_from_dirfsp_atname(talloc_tos(),
-                                               dirfsp,
-                                               new_smb_fname);
+                                                 dirfsp,
+                                                 new_smb_fname);
        if (full_fname == NULL) {
                END_PROFILE(syscall_symlinkat);
                return -1;
        }
 
        ret = glfs_symlink(handle->data,
-                       link_target->base_name,
-                       full_fname->base_name);
+                          link_target->base_name,
+                          full_fname->base_name);
 
        TALLOC_FREE(full_fname);
+#endif
 
        END_PROFILE(syscall_symlinkat);
 
@@ -1901,14 +2046,29 @@ static int vfs_gluster_readlinkat(struct vfs_handle_struct *handle,
                                char *buf,
                                size_t bufsiz)
 {
-       struct smb_filename *full_fname = NULL;
        int ret;
 
+#ifdef HAVE_GFAPI_VER_7_11
+       glfs_fd_t *pglfd = NULL;
+
+       START_PROFILE(syscall_readlinkat);
+
+       pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
+       if (pglfd == NULL) {
+               END_PROFILE(syscall_readlinkat);
+               DBG_ERR("Failed to fetch gluster fd\n");
+               return -1;
+       }
+
+       ret = glfs_readlinkat(pglfd, smb_fname->base_name, buf, bufsiz);
+#else
+       struct smb_filename *full_fname = NULL;
+
        START_PROFILE(syscall_readlinkat);
 
        full_fname = full_path_from_dirfsp_atname(talloc_tos(),
-                                               dirfsp,
-                                               smb_fname);
+                                                 dirfsp,
+                                                 smb_fname);
        if (full_fname == NULL) {
                END_PROFILE(syscall_readlinkat);
                return -1;
@@ -1917,6 +2077,7 @@ static int vfs_gluster_readlinkat(struct vfs_handle_struct *handle,
        ret = glfs_readlink(handle->data, full_fname->base_name, buf, bufsiz);
 
        TALLOC_FREE(full_fname);
+#endif
 
        END_PROFILE(syscall_readlinkat);
 
@@ -1931,24 +2092,52 @@ static int vfs_gluster_linkat(struct vfs_handle_struct *handle,
                                int flags)
 {
        int ret;
+
+#ifdef HAVE_GFAPI_VER_7_11
+       glfs_fd_t *src_pglfd = NULL;
+       glfs_fd_t *dst_pglfd = NULL;
+
+       START_PROFILE(syscall_linkat);
+
+       src_pglfd = vfs_gluster_fetch_glfd(handle, srcfsp);
+       if (src_pglfd == NULL) {
+               END_PROFILE(syscall_linkat);
+               DBG_ERR("Failed to fetch gluster fd\n");
+               return -1;
+       }
+
+       dst_pglfd = vfs_gluster_fetch_glfd(handle, dstfsp);
+       if (dst_pglfd == NULL) {
+               END_PROFILE(syscall_linkat);
+               DBG_ERR("Failed to fetch gluster fd\n");
+               return -1;
+       }
+
+       ret = glfs_linkat(src_pglfd,
+                         old_smb_fname->base_name,
+                         dst_pglfd,
+                         new_smb_fname->base_name,
+                         flags);
+#else
        struct smb_filename *full_fname_old = NULL;
        struct smb_filename *full_fname_new = NULL;
 
        START_PROFILE(syscall_linkat);
 
        full_fname_old = full_path_from_dirfsp_atname(talloc_tos(),
-                                               srcfsp,
-                                               old_smb_fname);
+                                                     srcfsp,
+                                                     old_smb_fname);
        if (full_fname_old == NULL) {
                END_PROFILE(syscall_linkat);
                return -1;
        }
+
        full_fname_new = full_path_from_dirfsp_atname(talloc_tos(),
-                                               dstfsp,
-                                               new_smb_fname);
+                                                     dstfsp,
+                                                     new_smb_fname);
        if (full_fname_new == NULL) {
-               TALLOC_FREE(full_fname_old);
                END_PROFILE(syscall_linkat);
+               TALLOC_FREE(full_fname_old);
                return -1;
        }
 
@@ -1958,6 +2147,8 @@ static int vfs_gluster_linkat(struct vfs_handle_struct *handle,
 
        TALLOC_FREE(full_fname_old);
        TALLOC_FREE(full_fname_new);
+#endif
+
        END_PROFILE(syscall_linkat);
 
        return ret;
@@ -1969,14 +2160,29 @@ static int vfs_gluster_mknodat(struct vfs_handle_struct *handle,
                                mode_t mode,
                                SMB_DEV_T dev)
 {
-       struct smb_filename *full_fname = NULL;
        int ret;
 
+#ifdef HAVE_GFAPI_VER_7_11
+       glfs_fd_t *pglfd = NULL;
+
+       START_PROFILE(syscall_mknodat);
+
+       pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
+       if (pglfd == NULL) {
+               END_PROFILE(syscall_mknodat);
+               DBG_ERR("Failed to fetch gluster fd\n");
+               return -1;
+       }
+
+       ret = glfs_mknodat(pglfd, smb_fname->base_name, mode, dev);
+#else
+       struct smb_filename *full_fname = NULL;
+
        START_PROFILE(syscall_mknodat);
 
        full_fname = full_path_from_dirfsp_atname(talloc_tos(),
-                                               dirfsp,
-                                               smb_fname);
+                                                 dirfsp,
+                                                 smb_fname);
        if (full_fname == NULL) {
                END_PROFILE(syscall_mknodat);
                return -1;
@@ -1985,6 +2191,7 @@ static int vfs_gluster_mknodat(struct vfs_handle_struct *handle,
        ret = glfs_mknod(handle->data, full_fname->base_name, mode, dev);
 
        TALLOC_FREE(full_fname);
+#endif
 
        END_PROFILE(syscall_mknodat);
 
@@ -1999,9 +2206,9 @@ static int vfs_gluster_fchflags(struct vfs_handle_struct *handle,
        return -1;
 }
 
-static NTSTATUS vfs_gluster_get_real_filename(
+static NTSTATUS vfs_gluster_get_real_filename_at(
        struct vfs_handle_struct *handle,
-       const struct smb_filename *path,
+       struct files_struct *dirfsp,
        const char *name,
        TALLOC_CTX *mem_ctx,
        char **found_name)
@@ -2017,7 +2224,10 @@ static NTSTATUS vfs_gluster_get_real_filename(
        snprintf(key_buf, GLUSTER_NAME_MAX + 64,
                 "glusterfs.get_real_filename:%s", name);
 
-       ret = glfs_getxattr(handle->data, path->base_name, key_buf, val_buf,
+       ret = glfs_getxattr(handle->data,
+                           dirfsp->fsp_name->base_name,
+                           key_buf,
+                           val_buf,
                            GLUSTER_NAME_MAX + 1);
        if (ret == -1) {
                if (errno == ENOATTR) {
@@ -2030,11 +2240,14 @@ static NTSTATUS vfs_gluster_get_real_filename(
        if (found_name[0] == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
+
        return NT_STATUS_OK;
 }
 
-static const char *vfs_gluster_connectpath(struct vfs_handle_struct *handle,
-                               const struct smb_filename *smb_fname)
+static const char *vfs_gluster_connectpath(
+       struct vfs_handle_struct *handle,
+       const struct files_struct *dirfsp,
+       const struct smb_filename *smb_fname)
 {
        return handle->conn->connectpath;
 }
@@ -2051,7 +2264,21 @@ static ssize_t vfs_gluster_fgetxattr(struct vfs_handle_struct *handle,
                return -1;
        }
 
-       return glfs_fgetxattr(glfd, name, value, size);
+       if (!fsp->fsp_flags.is_pathref) {
+               /*
+                * We can use an io_fd to retrieve xattr value.
+                */
+               return glfs_fgetxattr(glfd, name, value, size);
+       }
+
+       /*
+        * This is no longer a handle based call.
+        */
+       return glfs_getxattr(handle->data,
+                            fsp->fsp_name->base_name,
+                            name,
+                            value,
+                            size);
 }
 
 static ssize_t vfs_gluster_flistxattr(struct vfs_handle_struct *handle,
@@ -2148,14 +2375,11 @@ static NTSTATUS vfs_gluster_create_dfs_pathat(struct vfs_handle_struct *handle,
        NTSTATUS status = NT_STATUS_NO_MEMORY;
        int ret;
        char *msdfs_link = NULL;
+#ifdef HAVE_GFAPI_VER_7_11
+       glfs_fd_t *pglfd = NULL;
+#else
        struct smb_filename *full_fname = NULL;
-
-       full_fname = full_path_from_dirfsp_atname(talloc_tos(),
-                                                 dirfsp,
-                                                 smb_fname);
-       if (full_fname == NULL) {
-               goto out;
-       }
+#endif
 
        /* Form the msdfs_link contents */
        msdfs_link = msdfs_link_string(frame,
@@ -2165,9 +2389,27 @@ static NTSTATUS vfs_gluster_create_dfs_pathat(struct vfs_handle_struct *handle,
                goto out;
        }
 
-       ret = glfs_symlink(handle->data,
-                       msdfs_link,
-                       full_fname->base_name);
+#ifdef HAVE_GFAPI_VER_7_11
+       pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
+       if (pglfd == NULL) {
+               DBG_ERR("Failed to fetch gluster fd\n");
+               status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+               goto out;
+       }
+
+       ret = glfs_symlinkat(msdfs_link, pglfd, smb_fname->base_name);
+#else
+       full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+                                                 dirfsp,
+                                                 smb_fname);
+       if (full_fname == NULL) {
+               goto out;
+       }
+
+       ret = glfs_symlink(handle->data, msdfs_link, full_fname->base_name);
+
+       TALLOC_FREE(full_fname);
+#endif
        if (ret == 0) {
                status = NT_STATUS_OK;
        } else {
@@ -2209,6 +2451,9 @@ static NTSTATUS vfs_gluster_read_dfs_pathat(struct vfs_handle_struct *handle,
        struct stat st;
        struct smb_filename *full_fname = NULL;
        int ret;
+#ifdef HAVE_GFAPI_VER_7_11
+       glfs_fd_t *pglfd = NULL;
+#endif
 
        if (is_named_stream(smb_fname)) {
                status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
@@ -2244,10 +2489,23 @@ static NTSTATUS vfs_gluster_read_dfs_pathat(struct vfs_handle_struct *handle,
                goto err;
        }
 
+#ifdef HAVE_GFAPI_VER_7_11
+       pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
+       if (pglfd == NULL) {
+               DBG_ERR("Failed to fetch gluster fd\n");
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       referral_len = glfs_readlinkat(pglfd,
+                                      smb_fname->base_name,
+                                      link_target,
+                                      bufsize - 1);
+#else
        referral_len = glfs_readlink(handle->data,
                                full_fname->base_name,
                                link_target,
                                bufsize - 1);
+#endif
        if (referral_len < 0) {
                if (errno == EINVAL) {
                        DBG_INFO("%s is not a link.\n", full_fname->base_name);
@@ -2319,8 +2577,6 @@ static struct vfs_fn_pointers glusterfs_fns = {
 
        .fdopendir_fn = vfs_gluster_fdopendir,
        .readdir_fn = vfs_gluster_readdir,
-       .seekdir_fn = vfs_gluster_seekdir,
-       .telldir_fn = vfs_gluster_telldir,
        .rewind_dir_fn = vfs_gluster_rewinddir,
        .mkdirat_fn = vfs_gluster_mkdirat,
        .closedir_fn = vfs_gluster_closedir,
@@ -2345,6 +2601,7 @@ static struct vfs_fn_pointers glusterfs_fns = {
 
        .stat_fn = vfs_gluster_stat,
        .fstat_fn = vfs_gluster_fstat,
+       .fstatat_fn = vfs_gluster_fstatat,
        .lstat_fn = vfs_gluster_lstat,
        .get_alloc_size_fn = vfs_gluster_get_alloc_size,
        .unlinkat_fn = vfs_gluster_unlinkat,
@@ -2370,7 +2627,7 @@ static struct vfs_fn_pointers glusterfs_fns = {
        .fchflags_fn = vfs_gluster_fchflags,
        .file_id_create_fn = NULL,
        .fstreaminfo_fn = NULL,
-       .get_real_filename_fn = vfs_gluster_get_real_filename,
+       .get_real_filename_at_fn = vfs_gluster_get_real_filename_at,
        .connectpath_fn = vfs_gluster_connectpath,
        .create_dfs_pathat_fn = vfs_gluster_create_dfs_pathat,
        .read_dfs_pathat_fn = vfs_gluster_read_dfs_pathat,