]> git.ipfire.org Git - ipfire-2.x.git/blobdiff - src/patches/samba/samba-3.6.23-glusterfs.patch
samba: add current RHEL6 patches
[ipfire-2.x.git] / src / patches / samba / samba-3.6.23-glusterfs.patch
diff --git a/src/patches/samba/samba-3.6.23-glusterfs.patch b/src/patches/samba/samba-3.6.23-glusterfs.patch
new file mode 100644 (file)
index 0000000..2b82064
--- /dev/null
@@ -0,0 +1,2318 @@
+From f2f684d4eadadeebf725b513bf4945ccf0aa7371 Mon Sep 17 00:00:00 2001
+From: Anand Avati <avati@redhat.com>
+Date: Wed, 29 May 2013 07:21:46 -0400
+Subject: [PATCH 1/9] PATCHSET13: vfs_glusterfs: Samba VFS module for glusterfs
+
+Implement a Samba VFS plugin for glusterfs based on gluster's gfapi.
+This is a "bottom" vfs plugin (not something to be stacked on top of
+another module), and translates (most) calls into closest actions
+on gfapi.
+
+Reviewed-by: Andrew Bartlett <abartlet@samba.org>
+Reviewed-by: Simo Sorce <idra@samba.org>
+Signed-off-by: Anand Avati <avati@redhat.com>
+---
+ source3/Makefile.in             |    5 +
+ source3/configure.in            |   23 +
+ source3/modules/vfs_glusterfs.c | 1461 +++++++++++++++++++++++++++++++++++++++
+ source3/modules/wscript_build   |    9 +
+ source3/wscript                 |   22 +
+ 5 files changed, 1520 insertions(+)
+ create mode 100644 source3/modules/vfs_glusterfs.c
+
+diff --git a/source3/Makefile.in b/source3/Makefile.in
+index 9e8e03d..27bc43e 100644
+--- a/source3/Makefile.in
++++ b/source3/Makefile.in
+@@ -848,6 +848,7 @@ VFS_SCANNEDONLY_OBJ = modules/vfs_scannedonly.o
+ VFS_CROSSRENAME_OBJ = modules/vfs_crossrename.o
+ VFS_LINUX_XFS_SGID_OBJ = modules/vfs_linux_xfs_sgid.o
+ VFS_TIME_AUDIT_OBJ = modules/vfs_time_audit.o
++VFS_GLUSTERFS_OBJ = modules/vfs_glusterfs.o
+ PAM_ERRORS_OBJ = ../libcli/auth/pam_errors.o
+ PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o $(PAM_ERRORS_OBJ)
+@@ -3191,6 +3192,10 @@ bin/time_audit.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_TIME_AUDIT_OBJ)
+       @echo "Building plugin $@"
+       @$(SHLD_MODULE) $(VFS_TIME_AUDIT_OBJ)
++bin/glusterfs.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_GLUSTERFS_OBJ)
++      @echo "Building plugin $@"
++      $(SHLD_MODULE) $(VFS_GLUSTERFS_OBJ) @GLUSTERFS_LIBS@
++
+ #########################################################
+ ## IdMap NSS plugins
+diff --git a/source3/configure.in b/source3/configure.in
+index 42c23e3..3cc78e9 100644
+--- a/source3/configure.in
++++ b/source3/configure.in
+@@ -6688,6 +6688,29 @@
+ fi
++#############
++AC_ARG_ENABLE([glusterfs],
++       AC_HELP_STRING([--disable-glusterfs],[Do not build vfs_glusterfs module]))
++
++GLUTERFS_LIBS=""
++
++if test "x$enable_glusterfs" != "xno"; then
++   PKG_CHECK_MODULES([GLFS], [glusterfs-api >= 4], glfs_found=yes, glfs_found=no)
++fi
++
++if test "x$enable_glusterfs" = "xyes" -a "x$glfs_found" != "xyes"; then
++   echo "GFAPI not found in build system"
++   exit 1
++fi
++
++if test "x$glfs_found" = "xyes"; then
++    CFLAGS="$CFLAGS $GLFS_CFLAGS"
++    GLUSTERFS_LIBS="$GLFS_LIBS"
++    default_shared_modules="$default_shared_modules vfs_glusterfs"
++fi
++AC_SUBST(GLUSTERFS_LIBS)
++
++
+ #################################################
+ # Set pthread stuff
+@@ -7007,6 +7030,7 @@
+ SMB_MODULE(vfs_crossrename, \$(VFS_CROSSRENAME_OBJ), "bin/crossrename.$SHLIBEXT", VFS)
+ SMB_MODULE(vfs_linux_xfs_sgid, \$(VFS_LINUX_XFS_SGID_OBJ), "bin/linux_xfs_sgid.$SHLIBEXT", VFS)
+ SMB_MODULE(vfs_time_audit, \$(VFS_TIME_AUDIT_OBJ), "bin/time_audit.$SHLIBEXT", VFS)
++SMB_MODULE(vfs_glusterfs, \$(VFS_GLUSTERFS_OBJ), "bin/glusterfs.$SHLIBEXT", VFS)
+ SMB_SUBSYSTEM(VFS,smbd/vfs.o)
+diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
+new file mode 100644
+index 0000000..4beac1d
+--- /dev/null
++++ b/source3/modules/vfs_glusterfs.c
+@@ -0,0 +1,1461 @@
++/*
++   Unix SMB/CIFS implementation.
++
++   Wrap GlusterFS GFAPI calls in vfs functions.
++
++   Copyright (c) 2013 Anand Avati <avati@redhat.com>
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include "includes.h"
++#include "smbd/smbd.h"
++#include <stdio.h>
++#include "api/glfs.h"
++
++#define DEFAULT_VOLFILE_SERVER "localhost"
++
++/*
++  TODO
++  ----
++  Short term:
++  - AIO support
++  - sendfile/recvfile support
++*/
++
++/* Helpers to provide 'integer' fds */
++
++/* This is global. gfapi's FD operations do not
++   require filesystem context.
++*/
++static glfs_fd_t **glfd_fd;
++static int glfd_fd_size;
++static int glfd_fd_used;
++static int glfd_fd_store(glfs_fd_t *glfd)
++{
++      int i;
++      void *tmp;
++
++      if (glfd_fd_size == glfd_fd_used) {
++              if (glfd_fd_size >= INT_MAX - 1) {
++                      errno = ENOMEM;
++                      return -1;
++              }
++
++              tmp = talloc_realloc(glfd_fd, glfd_fd, glfs_fd_t *,
++                                   glfd_fd_size + 1);
++              if (tmp == NULL) {
++                      errno = ENOMEM;
++                      return -1;
++              }
++
++              glfd_fd = tmp;
++              glfd_fd[glfd_fd_size] = 0;
++              glfd_fd_size++;
++      }
++
++      for (i = 0; i < glfd_fd_size; i++) {
++              if (!glfd_fd[i]) {
++                      break;
++              }
++      }
++      glfd_fd_used++;
++      glfd_fd[i] = glfd;
++      return i;
++}
++
++static glfs_fd_t *glfd_fd_get(int i)
++{
++      if (i < 0 || i >= glfd_fd_size) {
++              return NULL;
++      }
++      return glfd_fd[i];
++}
++
++static glfs_fd_t *glfd_fd_clear(int i)
++{
++      glfs_fd_t *glfd = NULL;
++
++      if (i < 0 || i >= glfd_fd_size) {
++              return NULL;
++      }
++
++      glfd = glfd_fd[i];
++      glfd_fd[i] = 0;
++      glfd_fd_used--;
++      return glfd;
++}
++
++/* Helper to convert stat to stat_ex */
++
++static void smb_stat_ex_from_stat(struct stat_ex *dst, const struct stat *src)
++{
++      ZERO_STRUCTP(dst);
++
++      dst->st_ex_dev = src->st_dev;
++      dst->st_ex_ino = src->st_ino;
++      dst->st_ex_mode = src->st_mode;
++      dst->st_ex_nlink = src->st_nlink;
++      dst->st_ex_uid = src->st_uid;
++      dst->st_ex_gid = src->st_gid;
++      dst->st_ex_rdev = src->st_rdev;
++      dst->st_ex_size = src->st_size;
++      dst->st_ex_atime.tv_sec = src->st_atime;
++#ifdef STAT_HAVE_NSEC
++      dst->st_ex_atime.tv_nsec = src->st_atime_nsec;
++#endif
++      dst->st_ex_mtime.tv_sec = src->st_mtime;
++#ifdef STAT_HAVE_NSEC
++      dst->st_ex_mtime.tv_nsec = src->st_mtime_nsec;
++#endif
++      dst->st_ex_ctime.tv_sec = src->st_ctime;
++#ifdef STAT_HAVE_NSEC
++      dst->st_ex_ctime.tv_nsec = src->st_ctime_nsec;
++#endif
++      dst->st_ex_btime.tv_sec = src->st_mtime;
++#ifdef STAT_HAVE_NSEC
++      dst->st_ex_btime.tv_nsec = src->st_mtime_nsec;
++#endif
++      dst->st_ex_blksize = src->st_blksize;
++      dst->st_ex_blocks = src->st_blocks;
++}
++
++/* pre-opened glfs_t */
++
++static struct glfs_preopened {
++      char *volume;
++      glfs_t *fs;
++      int ref;
++      struct glfs_preopened *next, *prev;
++} *glfs_preopened;
++
++
++int glfs_set_preopened(const char *volume, glfs_t *fs)
++{
++      struct glfs_preopened *entry = NULL;
++
++      entry = talloc_zero(NULL, struct glfs_preopened);
++      if (!entry) {
++              errno = ENOMEM;
++              return -1;
++      }
++
++      entry->volume = talloc_strdup(entry, volume);
++      if (!entry->volume) {
++              talloc_free(entry);
++              errno = ENOMEM;
++              return -1;
++      }
++
++      entry->fs = fs;
++      entry->ref = 1;
++
++      DLIST_ADD(glfs_preopened, entry);
++
++      return 0;
++}
++
++static glfs_t *glfs_find_preopened(const char *volume)
++{
++      struct glfs_preopened *entry = NULL;
++
++      for (entry = glfs_preopened; entry; entry = entry->next) {
++              if (strcmp(entry->volume, volume) == 0) {
++                      entry->ref++;
++                      return entry->fs;
++              }
++      }
++
++      return NULL;
++}
++
++static void glfs_clear_preopened(glfs_t *fs)
++{
++      int i;
++      struct glfs_preopened *entry = NULL;
++
++      for (entry = glfs_preopened; entry; entry = entry->next) {
++              if (entry->fs == fs) {
++                      if (--entry->ref)
++                              return;
++
++                      DLIST_REMOVE(glfs_preopened, entry);
++
++                      glfs_fini(entry->fs);
++                      talloc_free(entry);
++              }
++      }
++}
++
++/* Disk Operations */
++
++static int vfs_gluster_connect(struct vfs_handle_struct *handle,
++                             const char *service, const char *user)
++{
++      const char *volfile_server;
++      const char *volume;
++      const char *logfile;
++      int loglevel;
++      glfs_t *fs;
++      int ret;
++
++      logfile = lp_parm_const_string(SNUM(handle->conn), "glusterfs",
++                                     "logfile", NULL);
++
++      loglevel = lp_parm_int(SNUM(handle->conn), "glusterfs", "loglevel", -1);
++
++      volfile_server = lp_parm_const_string(SNUM(handle->conn), "glusterfs",
++                                            "volfile_server", NULL);
++      if (volfile_server == NULL) {
++              volfile_server = DEFAULT_VOLFILE_SERVER;
++      }
++
++      volume = lp_parm_const_string(SNUM(handle->conn), "glusterfs", "volume",
++                                    NULL);
++      if (volume == NULL) {
++              volume = service;
++      }
++
++      fs = glfs_find_preopened(volume);
++      if (fs) {
++              goto found;
++      }
++
++      fs = glfs_new(volume);
++      if (fs == NULL) {
++              return -1;
++      }
++
++      ret = glfs_set_volfile_server(fs, "tcp", volfile_server, 0);
++      if (ret < 0) {
++              DEBUG(0, ("Failed to set volfile_server %s\n", volfile_server));
++              glfs_fini(fs);
++              return -1;
++      }
++
++      ret = glfs_set_xlator_option(fs, "*-md-cache", "cache-posix-acl",
++                                   "true");
++      if (ret < 0) {
++              DEBUG(0, ("%s: Failed to set xlator options\n", volume));
++              glfs_fini(fs);
++              return -1;
++      }
++
++      ret = glfs_set_logging(fs, logfile, loglevel);
++      if (ret < 0) {
++              DEBUG(0, ("%s: Failed to set logfile %s loglevel %d\n",
++                        volume, logfile, loglevel));
++              glfs_fini(fs);
++              return -1;
++      }
++
++      ret = glfs_init(fs);
++      if (ret < 0) {
++              DEBUG(0, ("%s: Failed to initialize volume (%s)\n",
++                        volume, strerror(errno)));
++              glfs_fini(fs);
++              return -1;
++      }
++
++      ret = glfs_set_preopened(volume, fs);
++      if (ret < 0) {
++              DEBUG(0, ("%s: Failed to register volume (%s)\n",
++                        volume, strerror(errno)));
++              glfs_fini(fs);
++              return -1;
++      }
++found:
++      DEBUG(0, ("%s: Initialized volume from server %s\n",
++                volume, volfile_server));
++      handle->data = fs;
++      return 0;
++}
++
++static void vfs_gluster_disconnect(struct vfs_handle_struct *handle)
++{
++      glfs_t *fs = NULL;
++
++      fs = handle->data;
++
++      glfs_clear_preopened(fs);
++}
++
++static uint64_t
++vfs_gluster_disk_free(struct vfs_handle_struct *handle, const char *path,
++                    bool small_query, uint64_t *bsize_p, uint64_t *dfree_p,
++                    uint64_t *dsize_p)
++{
++      struct statvfs statvfs = { 0, };
++      uint64_t dfree = 0;
++      int ret;
++
++      ret = glfs_statvfs(handle->data, path, &statvfs);
++      if (ret < 0) {
++              DEBUG(0, ("glfs_statvfs(%s) failed: %s\n",
++                        path, strerror(errno)));
++              return -1;
++      }
++
++      dfree = statvfs.f_bsize * statvfs.f_bavail;
++
++      if (bsize_p) {
++              *bsize_p = statvfs.f_bsize;
++      }
++      if (dfree_p) {
++              *dfree_p = dfree;
++      }
++      if (dsize_p) {
++              *dsize_p = statvfs.f_bsize * statvfs.f_blocks;
++      }
++
++      return dfree;
++}
++
++static int
++vfs_gluster_get_quota(struct vfs_handle_struct *handle,
++                    enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
++{
++      errno = ENOSYS;
++      return -1;
++}
++
++static int
++vfs_gluster_set_quota(struct vfs_handle_struct *handle,
++                    enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
++{
++      errno = ENOSYS;
++      return -1;
++}
++
++static int vfs_gluster_statvfs(struct vfs_handle_struct *handle,
++                             const char *path,
++                             struct vfs_statvfs_struct *vfs_statvfs)
++{
++      struct statvfs statvfs = { 0, };
++      int ret;
++
++      ret = glfs_statvfs(handle->data, path, &statvfs);
++      if (ret < 0) {
++              DEBUG(0, ("glfs_statvfs(%s) failed: %s\n",
++                        path, strerror(errno)));
++              return -1;
++      }
++
++      ZERO_STRUCTP(vfs_statvfs);
++
++      vfs_statvfs->OptimalTransferSize = statvfs.f_frsize;
++      vfs_statvfs->BlockSize = statvfs.f_bsize;
++      vfs_statvfs->TotalBlocks = statvfs.f_blocks;
++      vfs_statvfs->BlocksAvail = statvfs.f_bfree;
++      vfs_statvfs->UserBlocksAvail = statvfs.f_bavail;
++      vfs_statvfs->TotalFileNodes = statvfs.f_files;
++      vfs_statvfs->FreeFileNodes = statvfs.f_ffree;
++      vfs_statvfs->FsIdentifier = statvfs.f_fsid;
++      vfs_statvfs->FsCapabilities =
++          FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
++
++      return ret;
++}
++
++static uint32_t vfs_gluster_fs_capabilities(struct vfs_handle_struct *handle,
++                                          enum timestamp_set_resolution *p_ts_res)
++{
++      uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
++
++#ifdef STAT_HAVE_NSEC
++      *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
++#endif
++
++      return caps;
++}
++
++static DIR *vfs_gluster_opendir(struct vfs_handle_struct *handle,
++                              const char *path, const char *mask,
++                              uint32 attributes)
++{
++      glfs_fd_t *fd;
++
++      fd = glfs_opendir(handle->data, path);
++      if (fd == NULL) {
++              DEBUG(0, ("glfs_opendir(%s) failed: %s\n",
++                        path, strerror(errno)));
++      }
++
++      return (DIR *) fd;
++}
++
++static DIR *vfs_gluster_fdopendir(struct vfs_handle_struct *handle,
++                                files_struct *fsp, const char *mask,
++                                uint32 attributes)
++{
++      return (DIR *) glfd_fd_get(fsp->fh->fd);
++}
++
++static int vfs_gluster_closedir(struct vfs_handle_struct *handle, DIR *dirp)
++{
++      return glfs_closedir((void *)dirp);
++}
++
++static SMB_STRUCT_DIRENT *vfs_gluster_readdir(struct vfs_handle_struct *handle,
++                                            SMB_STRUCT_DIR *dirp,
++                                            SMB_STRUCT_STAT *sbuf)
++{
++      char direntbuf[512];
++      int ret;
++      struct stat stat;
++      struct dirent *dirent = 0;
++      static SMB_STRUCT_DIRENT result;
++
++      if (sbuf != NULL) {
++              ret = glfs_readdirplus_r((void *)dirp, &stat, (void *)direntbuf,
++                                       &dirent);
++      } else {
++              ret = glfs_readdir_r((void *)dirp, (void *)direntbuf, &dirent);
++      }
++
++      if (ret < 0 || (dirent == NULL)) {
++              return NULL;
++      }
++
++      if (sbuf != NULL) {
++              smb_stat_ex_from_stat(sbuf, &stat);
++      }
++
++      result.d_ino = dirent->d_ino;
++      result.d_off = dirent->d_off;
++      result.d_reclen = dirent->d_reclen;
++      result.d_type = dirent->d_type;
++      strncpy(result.d_name, dirent->d_name, 256);
++
++      return &result;
++}
++
++static long vfs_gluster_telldir(struct vfs_handle_struct *handle, DIR *dirp)
++{
++      return glfs_telldir((void *)dirp);
++}
++
++static void vfs_gluster_seekdir(struct vfs_handle_struct *handle, DIR *dirp,
++                              long offset)
++{
++      glfs_seekdir((void *)dirp, offset);
++}
++
++static void vfs_gluster_rewinddir(struct vfs_handle_struct *handle,
++                                DIR *dirp)
++{
++      glfs_seekdir((void *)dirp, 0);
++}
++
++static void vfs_gluster_init_search_op(struct vfs_handle_struct *handle,
++                                     DIR *dirp)
++{
++      return;
++}
++
++static int vfs_gluster_mkdir(struct vfs_handle_struct *handle, const char *path,
++                           mode_t mode)
++{
++      return glfs_mkdir(handle->data, path, mode);
++}
++
++static int vfs_gluster_rmdir(struct vfs_handle_struct *handle, const char *path)
++{
++      return glfs_rmdir(handle->data, path);
++}
++
++static int vfs_gluster_open(struct vfs_handle_struct *handle,
++                          struct smb_filename *smb_fname, files_struct *fsp,
++                          int flags, mode_t mode)
++{
++      glfs_fd_t *glfd;
++
++      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 (glfd == NULL) {
++              DEBUG(0, ("glfs_{open[dir],creat}(%s) failed: %s\n",
++                        smb_fname->base_name, strerror(errno)));
++              return -1;
++      }
++
++      return glfd_fd_store(glfd);
++}
++
++static int vfs_gluster_close(struct vfs_handle_struct *handle,
++                           files_struct *fsp)
++{
++      return glfs_close(glfd_fd_clear(fsp->fh->fd));
++}
++
++static ssize_t vfs_gluster_read(struct vfs_handle_struct *handle,
++                              files_struct *fsp, void *data, size_t n)
++{
++      return glfs_read(glfd_fd_get(fsp->fh->fd), data, n, 0);
++}
++
++static ssize_t vfs_gluster_pread(struct vfs_handle_struct *handle,
++                               files_struct *fsp, void *data, size_t n,
++                               off_t offset)
++{
++      return glfs_pread(glfd_fd_get(fsp->fh->fd), data, n, offset, 0);
++}
++
++static ssize_t vfs_gluster_write(struct vfs_handle_struct *handle,
++                               files_struct *fsp, const void *data, size_t n)
++{
++      return glfs_write(glfd_fd_get(fsp->fh->fd), data, n, 0);
++}
++
++static ssize_t vfs_gluster_pwrite(struct vfs_handle_struct *handle,
++                                files_struct *fsp, const void *data, size_t n,
++                                off_t offset)
++{
++      return glfs_pwrite(glfd_fd_get(fsp->fh->fd), data, n, offset, 0);
++}
++
++static off_t vfs_gluster_lseek(struct vfs_handle_struct *handle,
++                             files_struct *fsp, off_t offset, int whence)
++{
++      return glfs_lseek(glfd_fd_get(fsp->fh->fd), offset, whence);
++}
++
++static ssize_t vfs_gluster_sendfile(struct vfs_handle_struct *handle, int tofd,
++                                  files_struct *fromfsp, const DATA_BLOB *hdr,
++                                  off_t offset, size_t n)
++{
++      errno = ENOTSUP;
++      return -1;
++}
++
++static ssize_t vfs_gluster_recvfile(struct vfs_handle_struct *handle,
++                                  int fromfd, files_struct *tofsp,
++                                  off_t offset, size_t n)
++{
++      errno = ENOTSUP;
++      return -1;
++}
++
++static int vfs_gluster_rename(struct vfs_handle_struct *handle,
++                            const struct smb_filename *smb_fname_src,
++                            const struct smb_filename *smb_fname_dst)
++{
++      return glfs_rename(handle->data, smb_fname_src->base_name,
++                         smb_fname_dst->base_name);
++}
++
++static int vfs_gluster_fsync(struct vfs_handle_struct *handle,
++                           files_struct *fsp)
++{
++      return glfs_fsync(glfd_fd_get(fsp->fh->fd));
++}
++
++static int vfs_gluster_stat(struct vfs_handle_struct *handle,
++                          struct smb_filename *smb_fname)
++{
++      struct stat st;
++      int ret;
++
++      ret = glfs_stat(handle->data, smb_fname->base_name, &st);
++      if (ret == 0) {
++              smb_stat_ex_from_stat(&smb_fname->st, &st);
++      }
++      if (ret < 0 && errno != ENOENT) {
++              DEBUG(0, ("glfs_stat(%s) failed: %s\n",
++                        smb_fname->base_name, strerror(errno)));
++      }
++      return ret;
++}
++
++static int vfs_gluster_fstat(struct vfs_handle_struct *handle,
++                           files_struct *fsp, SMB_STRUCT_STAT *sbuf)
++{
++      struct stat st;
++      int ret;
++
++      ret = glfs_fstat(glfd_fd_get(fsp->fh->fd), &st);
++      if (ret == 0) {
++              smb_stat_ex_from_stat(sbuf, &st);
++      }
++      if (ret < 0) {
++              DEBUG(0, ("glfs_ftat(%d) failed: %s\n",
++                        fsp->fh->fd, strerror(errno)));
++      }
++      return ret;
++}
++
++static int vfs_gluster_lstat(struct vfs_handle_struct *handle,
++                           struct smb_filename *smb_fname)
++{
++      struct stat st;
++      int ret;
++
++      ret = glfs_lstat(handle->data, smb_fname->base_name, &st);
++      if (ret == 0) {
++              smb_stat_ex_from_stat(&smb_fname->st, &st);
++      }
++      if (ret < 0 && errno != ENOENT) {
++              DEBUG(0, ("glfs_lstat(%s) failed: %s\n",
++                        smb_fname->base_name, strerror(errno)));
++      }
++
++      return ret;
++}
++
++static uint64_t vfs_gluster_get_alloc_size(struct vfs_handle_struct *handle,
++                                         files_struct *fsp,
++                                         const SMB_STRUCT_STAT *sbuf)
++{
++      return sbuf->st_ex_blocks * 512;
++}
++
++static int vfs_gluster_unlink(struct vfs_handle_struct *handle,
++                            const struct smb_filename *smb_fname)
++{
++      return glfs_unlink(handle->data, smb_fname->base_name);
++}
++
++static int vfs_gluster_chmod(struct vfs_handle_struct *handle,
++                           const char *path, mode_t mode)
++{
++      return glfs_chmod(handle->data, path, mode);
++}
++
++static int vfs_gluster_fchmod(struct vfs_handle_struct *handle,
++                            files_struct *fsp, mode_t mode)
++{
++      return glfs_fchmod(glfd_fd_get(fsp->fh->fd), mode);
++}
++
++static int vfs_gluster_chown(struct vfs_handle_struct *handle,
++                           const char *path, uid_t uid, gid_t gid)
++{
++      return glfs_chown(handle->data, path, uid, gid);
++}
++
++static int vfs_gluster_fchown(struct vfs_handle_struct *handle,
++                            files_struct *fsp, uid_t uid, gid_t gid)
++{
++      return glfs_fchown(glfd_fd_get(fsp->fh->fd), uid, gid);
++}
++
++static int vfs_gluster_lchown(struct vfs_handle_struct *handle,
++                            const char *path, uid_t uid, gid_t gid)
++{
++      return glfs_lchown(handle->data, path, uid, gid);
++}
++
++static int vfs_gluster_chdir(struct vfs_handle_struct *handle, const char *path)
++{
++      return glfs_chdir(handle->data, path);
++}
++
++static char *vfs_gluster_getwd(struct vfs_handle_struct *handle, char *path)
++{
++      return glfs_getcwd(handle->data, path, PATH_MAX);
++}
++
++static int vfs_gluster_ntimes(struct vfs_handle_struct *handle,
++                            const struct smb_filename *smb_fname,
++                            struct smb_file_time *ft)
++{
++      struct timespec times[2];
++
++      times[0].tv_sec = ft->atime.tv_sec;
++      times[0].tv_nsec = ft->atime.tv_nsec;
++      times[1].tv_sec = ft->mtime.tv_sec;
++      times[1].tv_nsec = ft->mtime.tv_nsec;
++
++      return glfs_utimens(handle->data, smb_fname->base_name, times);
++}
++
++static int vfs_gluster_ftruncate(struct vfs_handle_struct *handle,
++                               files_struct *fsp, off_t offset)
++{
++      return glfs_ftruncate(glfd_fd_get(fsp->fh->fd), offset);
++}
++
++static int vfs_gluster_fallocate(struct vfs_handle_struct *handle,
++                               struct files_struct *fsp,
++                               enum vfs_fallocate_mode mode,
++                               off_t offset, off_t len)
++{
++      errno = ENOTSUP;
++      return -1;
++}
++
++static char *vfs_gluster_realpath(struct vfs_handle_struct *handle,
++                                const char *path)
++{
++      return glfs_realpath(handle->data, path, 0);
++}
++
++static bool vfs_gluster_lock(struct vfs_handle_struct *handle,
++                           files_struct *fsp, int op, off_t offset,
++                           off_t count, int type)
++{
++      struct flock flock = { 0, };
++      int ret;
++
++      flock.l_type = type;
++      flock.l_whence = SEEK_SET;
++      flock.l_start = offset;
++      flock.l_len = count;
++      flock.l_pid = 0;
++
++      ret = glfs_posix_lock(glfd_fd_get(fsp->fh->fd), op, &flock);
++
++      if (op == F_GETLK) {
++              /* lock query, true if someone else has locked */
++              if ((ret != -1) &&
++                  (flock.l_type != F_UNLCK) &&
++                  (flock.l_pid != 0) && (flock.l_pid != getpid()))
++                      return true;
++              /* not me */
++              return false;
++      }
++
++      if (ret == -1) {
++              return false;
++      }
++
++      return true;
++}
++
++static int vfs_gluster_kernel_flock(struct vfs_handle_struct *handle,
++                                  files_struct *fsp, uint32 share_mode,
++                                  uint32_t access_mask)
++{
++      return 0;
++}
++
++static int vfs_gluster_linux_setlease(struct vfs_handle_struct *handle,
++                                    files_struct *fsp, int leasetype)
++{
++      errno = ENOSYS;
++      return -1;
++}
++
++static bool vfs_gluster_getlock(struct vfs_handle_struct *handle,
++                              files_struct *fsp, off_t *poffset,
++                              off_t *pcount, int *ptype, pid_t *ppid)
++{
++      struct flock flock = { 0, };
++      int ret;
++
++      flock.l_type = *ptype;
++      flock.l_whence = SEEK_SET;
++      flock.l_start = *poffset;
++      flock.l_len = *pcount;
++      flock.l_pid = 0;
++
++      ret = glfs_posix_lock(glfd_fd_get(fsp->fh->fd), F_GETLK, &flock);
++
++      if (ret == -1) {
++              return false;
++      }
++
++      *ptype = flock.l_type;
++      *poffset = flock.l_start;
++      *pcount = flock.l_len;
++      *ppid = flock.l_pid;
++
++      return true;
++}
++
++static int vfs_gluster_symlink(struct vfs_handle_struct *handle,
++                             const char *oldpath, const char *newpath)
++{
++      return glfs_symlink(handle->data, oldpath, newpath);
++}
++
++static int vfs_gluster_readlink(struct vfs_handle_struct *handle,
++                              const char *path, char *buf, size_t bufsiz)
++{
++      return glfs_readlink(handle->data, path, buf, bufsiz);
++}
++
++static int vfs_gluster_link(struct vfs_handle_struct *handle,
++                          const char *oldpath, const char *newpath)
++{
++      return glfs_link(handle->data, oldpath, newpath);
++}
++
++static int vfs_gluster_mknod(struct vfs_handle_struct *handle, const char *path,
++                           mode_t mode, SMB_DEV_T dev)
++{
++      return glfs_mknod(handle->data, path, mode, dev);
++}
++
++static NTSTATUS vfs_gluster_notify_watch(struct vfs_handle_struct *vfs_handle,
++                                       struct sys_notify_context *ctx,
++                                       struct notify_entry *e,
++                                       void (*callback) (struct sys_notify_context *ctx,
++                                                         void *private_data,
++                                                         struct notify_event *ev),
++                                       void *private_data, void *handle)
++{
++      return NT_STATUS_NOT_IMPLEMENTED;
++}
++
++static int vfs_gluster_chflags(struct vfs_handle_struct *handle,
++                             const char *path, unsigned int flags)
++{
++      errno = ENOSYS;
++      return -1;
++}
++
++static int vfs_gluster_get_real_filename(struct vfs_handle_struct *handle,
++                                       const char *path, const char *name,
++                                       TALLOC_CTX *mem_ctx, char **found_name)
++{
++      int ret;
++      char key_buf[NAME_MAX + 64];
++      char val_buf[NAME_MAX + 1];
++
++      if (strlen(name) >= NAME_MAX) {
++              errno = ENAMETOOLONG;
++              return -1;
++      }
++
++      snprintf(key_buf, NAME_MAX + 64,
++               "user.glusterfs.get_real_filename:%s", name);
++
++      ret = glfs_getxattr(handle->data, path, key_buf, val_buf, NAME_MAX + 1);
++      if (ret == -1 && errno == ENODATA) {
++              errno = EOPNOTSUPP;
++              return -1;
++      }
++
++      *found_name = talloc_strdup(mem_ctx, val_buf);
++      if (found_name[0] == NULL) {
++              errno = ENOMEM;
++              return -1;
++      }
++      return 0;
++}
++
++static const char *vfs_gluster_connectpath(struct vfs_handle_struct *handle,
++                                         const char *filename)
++{
++      return handle->conn->connectpath;
++}
++
++/* EA Operations */
++
++static ssize_t vfs_gluster_getxattr(struct vfs_handle_struct *handle,
++                                  const char *path, const char *name,
++                                  void *value, size_t size)
++{
++      return glfs_getxattr(handle->data, path, name, value, size);
++}
++
++static ssize_t vfs_gluster_lgetxattr(struct vfs_handle_struct *handle,
++                                   const char *path, const char *name,
++                                   void *value, size_t size)
++{
++      return glfs_lgetxattr(handle->data, path, name, value, size);
++}
++
++static ssize_t vfs_gluster_fgetxattr(struct vfs_handle_struct *handle,
++                                   files_struct *fsp, const char *name,
++                                   void *value, size_t size)
++{
++      return glfs_fgetxattr(glfd_fd_get(fsp->fh->fd), name, value, size);
++}
++
++static ssize_t vfs_gluster_listxattr(struct vfs_handle_struct *handle,
++                                   const char *path, char *list, size_t size)
++{
++      return glfs_listxattr(handle->data, path, list, size);
++}
++
++static ssize_t vfs_gluster_llistxattr(struct vfs_handle_struct *handle,
++                                    const char *path, char *list, size_t size)
++{
++      return glfs_llistxattr(handle->data, path, list, size);
++}
++
++static ssize_t vfs_gluster_flistxattr(struct vfs_handle_struct *handle,
++                                    files_struct *fsp, char *list,
++                                    size_t size)
++{
++      return glfs_flistxattr(glfd_fd_get(fsp->fh->fd), list, size);
++}
++
++static int vfs_gluster_removexattr(struct vfs_handle_struct *handle,
++                                 const char *path, const char *name)
++{
++      return glfs_removexattr(handle->data, path, name);
++}
++
++static int vfs_gluster_lremovexattr(struct vfs_handle_struct *handle,
++                                  const char *path, const char *name)
++{
++      return glfs_lremovexattr(handle->data, path, name);
++}
++
++static int vfs_gluster_fremovexattr(struct vfs_handle_struct *handle,
++                                  files_struct *fsp, const char *name)
++{
++      return glfs_fremovexattr(glfd_fd_get(fsp->fh->fd), name);
++}
++
++static int vfs_gluster_setxattr(struct vfs_handle_struct *handle,
++                              const char *path, const char *name,
++                              const void *value, size_t size, int flags)
++{
++      return glfs_setxattr(handle->data, path, name, value, size, flags);
++}
++
++static int vfs_gluster_lsetxattr(struct vfs_handle_struct *handle,
++                               const char *path, const char *name,
++                               const void *value, size_t size, int flags)
++{
++      return glfs_lsetxattr(handle->data, path, name, value, size, flags);
++}
++
++static int vfs_gluster_fsetxattr(struct vfs_handle_struct *handle,
++                               files_struct *fsp, const char *name,
++                               const void *value, size_t size, int flags)
++{
++      return glfs_fsetxattr(glfd_fd_get(fsp->fh->fd), name, value, size,
++                            flags);
++}
++
++/* AIO Operations */
++
++static bool vfs_gluster_aio_force(struct vfs_handle_struct *handle,
++                                files_struct *fsp)
++{
++      return false;
++}
++
++/* Offline Operations */
++
++static bool vfs_gluster_is_offline(struct vfs_handle_struct *handle,
++                                 const struct smb_filename *fname,
++                                 SMB_STRUCT_STAT *sbuf)
++{
++      return false;
++}
++
++static int vfs_gluster_set_offline(struct vfs_handle_struct *handle,
++                                 const struct smb_filename *fname)
++{
++      errno = ENOTSUP;
++      return -1;
++}
++
++/* Posix ACL Operations */
++
++#define GLUSTER_ACL_VERSION 2
++#define GLUSTER_ACL_READ    0x04
++#define GLUSTER_ACL_WRITE   0x02
++#define GLUSTER_ACL_EXECUTE 0x01
++
++#define GLUSTER_ACL_UNDEFINED_TAG  0x00
++#define GLUSTER_ACL_USER_OBJ       0x01
++#define GLUSTER_ACL_USER           0x02
++#define GLUSTER_ACL_GROUP_OBJ      0x04
++#define GLUSTER_ACL_GROUP          0x08
++#define GLUSTER_ACL_MASK           0x10
++#define GLUSTER_ACL_OTHER          0x20
++
++#define GLUSTER_ACL_UNDEFINED_ID  (-1)
++
++struct gluster_ace {
++      uint16_t tag;
++      uint16_t perm;
++      uint32_t id;
++};
++
++struct gluster_acl_header {
++      uint32_t version;
++      struct gluster_ace entries[];
++};
++
++static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size)
++{
++      int count;
++      size_t size;
++      struct gluster_ace *ace;
++      struct smb_acl_entry *smb_ace;
++      struct gluster_acl_header *hdr;
++      struct smb_acl_t *result;
++      int i;
++      uint16_t tag;
++      uint16_t perm;
++      uint32_t id;
++
++      size = xattr_size;
++
++      if (size < sizeof(*hdr)) {
++              /* ACL should be at least as big as the header */
++              errno = EINVAL;
++              return NULL;
++      }
++
++      size -= sizeof(*hdr);
++
++      if (size % sizeof(*ace)) {
++              /* Size of entries must strictly be a multiple of
++                 size of an ACE
++              */
++              errno = EINVAL;
++              return NULL;
++      }
++
++      count = size / sizeof(*ace);
++
++      hdr = (void *)buf;
++
++      if (ntohl(hdr->version) != GLUSTER_ACL_VERSION) {
++              DEBUG(0, ("Unknown gluster ACL version: %d\n",
++                        ntohl(hdr->version)));
++              return NULL;
++      }
++
++      result = SMB_MALLOC(sizeof(struct smb_acl_t) + (sizeof(struct smb_acl_entry) * count));
++      if (!result) {
++              errno = ENOMEM;
++              return NULL;
++      }
++
++      result->count = count;
++
++      smb_ace = result->acl;
++      ace = hdr->entries;
++
++      for (i = 0; i < count; i++) {
++              tag = ntohs(ace->tag);
++
++              switch(tag) {
++              case GLUSTER_ACL_USER:
++                      smb_ace->a_type = SMB_ACL_USER;
++                      break;
++              case GLUSTER_ACL_USER_OBJ:
++                      smb_ace->a_type = SMB_ACL_USER_OBJ;
++                      break;
++              case GLUSTER_ACL_GROUP:
++                      smb_ace->a_type = SMB_ACL_GROUP;
++                      break;
++              case GLUSTER_ACL_GROUP_OBJ:
++                      smb_ace->a_type = SMB_ACL_GROUP_OBJ;
++                      break;
++              case GLUSTER_ACL_OTHER:
++                      smb_ace->a_type = SMB_ACL_OTHER;
++                      break;
++              case GLUSTER_ACL_MASK:
++                      smb_ace->a_type = SMB_ACL_MASK;
++                      break;
++              default:
++                      DEBUG(0, ("unknown tag type %d\n", (unsigned int) tag));
++                      return NULL;
++              }
++
++              id = ntohl(ace->id);
++
++              switch(smb_ace->a_type) {
++              case SMB_ACL_USER:
++                      smb_ace->uid = id;
++                      break;
++              case SMB_ACL_GROUP:
++                      smb_ace->gid = id;
++                      break;
++              default:
++                      break;
++              }
++
++              perm = ntohs(ace->perm);
++
++              smb_ace->a_perm = 0;
++              smb_ace->a_perm |=
++                      ((perm & GLUSTER_ACL_READ) ? SMB_ACL_READ : 0);
++              smb_ace->a_perm |=
++                      ((perm & GLUSTER_ACL_WRITE) ? SMB_ACL_WRITE : 0);
++              smb_ace->a_perm |=
++                      ((perm & GLUSTER_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
++
++              ace++;
++              smb_ace++;
++      }
++
++      return result;
++}
++
++static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
++{
++      ssize_t size;
++      struct gluster_ace *ace;
++      struct smb_acl_entry *smb_ace;
++      struct gluster_acl_header *hdr;
++      int i;
++      int count;
++      uint16_t tag;
++      uint16_t perm;
++      uint32_t id;
++
++      count = theacl->count;
++
++      size = sizeof(*hdr) + (count * sizeof(*ace));
++      if (!buf) {
++              return size;
++      }
++
++      if (len < size) {
++              errno = ERANGE;
++              return -1;
++      }
++
++      hdr = (void *)buf;
++      ace = hdr->entries;
++      smb_ace = theacl->acl;
++
++      hdr->version = htonl(GLUSTER_ACL_VERSION);
++
++      for (i = 0; i < count; i++) {
++              switch(smb_ace->a_type) {
++              case SMB_ACL_USER:
++                      tag = GLUSTER_ACL_USER;
++                      break;
++              case SMB_ACL_USER_OBJ:
++                      tag = GLUSTER_ACL_USER_OBJ;
++                      break;
++              case SMB_ACL_GROUP:
++                      tag = GLUSTER_ACL_GROUP;
++                      break;
++              case SMB_ACL_GROUP_OBJ:
++                      tag = GLUSTER_ACL_GROUP_OBJ;
++                      break;
++              case SMB_ACL_OTHER:
++                      tag = GLUSTER_ACL_OTHER;
++                      break;
++              case SMB_ACL_MASK:
++                      tag = GLUSTER_ACL_MASK;
++                      break;
++              default:
++                      DEBUG(0, ("Unknown tag value %d\n",
++                                smb_ace->a_type));
++                      errno = EINVAL;
++                      return -1;
++              }
++
++              ace->tag = ntohs(tag);
++
++              switch(smb_ace->a_type) {
++              case SMB_ACL_USER:
++                      id = smb_ace->uid;
++                      break;
++              case SMB_ACL_GROUP:
++                      id = smb_ace->gid;
++                      break;
++              default:
++                      id = GLUSTER_ACL_UNDEFINED_ID;
++                      break;
++              }
++
++              ace->id = ntohl(id);
++
++              ace->perm = 0;
++              ace->perm |=
++                      ((smb_ace->a_perm & SMB_ACL_READ) ? GLUSTER_ACL_READ : 0);
++              ace->perm |=
++                      ((smb_ace->a_perm & SMB_ACL_WRITE) ? GLUSTER_ACL_WRITE : 0);
++              ace->perm |=
++                      ((smb_ace->a_perm & SMB_ACL_EXECUTE) ? GLUSTER_ACL_EXECUTE : 0);
++
++              ace++;
++              smb_ace++;
++      }
++
++      return size;
++}
++
++
++static SMB_ACL_T vfs_gluster_sys_acl_get_file(struct vfs_handle_struct *handle,
++                                            const char *path_p,
++                                            SMB_ACL_TYPE_T type)
++{
++      struct smb_acl_t *result;
++      char *buf;
++      char *key;
++      ssize_t ret;
++
++      switch (type) {
++      case SMB_ACL_TYPE_ACCESS:
++              key = "system.posix_acl_access";
++              break;
++      case SMB_ACL_TYPE_DEFAULT:
++              key = "system.posix_acl_default";
++              break;
++      default:
++              errno = EINVAL;
++              return NULL;
++      }
++
++      ret = glfs_getxattr(handle->data, path_p, key, 0, 0);
++      if (ret <= 0) {
++              return NULL;
++      }
++
++      buf = alloca(ret);
++      ret = glfs_getxattr(handle->data, path_p, key, buf, ret);
++      if (ret <= 0) {
++              return NULL;
++      }
++
++      result = gluster_to_smb_acl(buf, ret);
++
++      return result;
++}
++
++static SMB_ACL_T vfs_gluster_sys_acl_get_fd(struct vfs_handle_struct *handle,
++                                          struct files_struct *fsp)
++{
++      struct smb_acl_t *result;
++      int ret;
++      char *buf;
++
++      ret = glfs_fgetxattr(glfd_fd_get(fsp->fh->fd),
++                           "system.posix_acl_access", 0, 0);
++      if (ret <= 0) {
++              return NULL;
++      }
++
++      buf = alloca(ret);
++      ret = glfs_fgetxattr(glfd_fd_get(fsp->fh->fd),
++                           "system.posix_acl_access", buf, ret);
++      if (ret <= 0) {
++              return NULL;
++      }
++
++      result = gluster_to_smb_acl(buf, ret);
++
++      return result;
++}
++
++static int vfs_gluster_sys_acl_set_file(struct vfs_handle_struct *handle,
++                                      const char *name,
++                                      SMB_ACL_TYPE_T acltype,
++                                      SMB_ACL_T theacl)
++{
++      int ret;
++      char *key;
++      char *buf;
++      ssize_t size;
++
++      switch (acltype) {
++      case SMB_ACL_TYPE_ACCESS:
++              key = "system.posix_acl_access";
++              break;
++      case SMB_ACL_TYPE_DEFAULT:
++              key = "system.posix_acl_default";
++              break;
++      default:
++              errno = EINVAL;
++              return -1;
++      }
++
++      size = smb_to_gluster_acl(theacl, 0, 0);
++      buf = alloca(size);
++
++      size = smb_to_gluster_acl(theacl, buf, size);
++      if (size == -1) {
++              return -1;
++      }
++
++      ret = glfs_setxattr(handle->data, name, key, buf, size, 0);
++
++      return ret;
++}
++
++static int vfs_gluster_sys_acl_set_fd(struct vfs_handle_struct *handle,
++                                    struct files_struct *fsp,
++                                    SMB_ACL_T theacl)
++{
++      int ret;
++      char *buf;
++      ssize_t size;
++
++      size = smb_to_gluster_acl(theacl, 0, 0);
++      buf = alloca(size);
++
++      size = smb_to_gluster_acl(theacl, buf, size);
++      if (size == -1) {
++              return -1;
++      }
++
++      ret = glfs_fsetxattr(glfd_fd_get(fsp->fh->fd),
++                           "system.posix_acl_access", buf, size, 0);
++      return ret;
++}
++
++static int vfs_gluster_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
++                                             const char *path)
++{
++      return glfs_removexattr(handle->data, path, "system.posix_acl_default");
++}
++
++static struct vfs_fn_pointers glusterfs_fns = {
++
++      /* Disk Operations */
++
++      .connect_fn = vfs_gluster_connect,
++      .disconnect = vfs_gluster_disconnect,
++      .disk_free = vfs_gluster_disk_free,
++      .get_quota = vfs_gluster_get_quota,
++      .set_quota = vfs_gluster_set_quota,
++      .statvfs = vfs_gluster_statvfs,
++      .fs_capabilities = vfs_gluster_fs_capabilities,
++
++      /* Directory Operations */
++
++      .opendir = vfs_gluster_opendir,
++      .fdopendir = vfs_gluster_fdopendir,
++      .readdir = vfs_gluster_readdir,
++      .seekdir = vfs_gluster_seekdir,
++      .telldir = vfs_gluster_telldir,
++      .rewind_dir = vfs_gluster_rewinddir,
++      .mkdir = vfs_gluster_mkdir,
++      .rmdir = vfs_gluster_rmdir,
++      .closedir = vfs_gluster_closedir,
++      .init_search_op = vfs_gluster_init_search_op,
++
++      /* File Operations */
++
++      .open_fn = vfs_gluster_open,
++      .create_file = NULL,
++      .close_fn = vfs_gluster_close,
++      .vfs_read = vfs_gluster_read,
++      .pread = vfs_gluster_pread,
++      .write = vfs_gluster_write,
++      .pwrite = vfs_gluster_pwrite,
++      .lseek = vfs_gluster_lseek,
++      .sendfile = vfs_gluster_sendfile,
++      .recvfile = vfs_gluster_recvfile,
++      .rename = vfs_gluster_rename,
++      .fsync = vfs_gluster_fsync,
++      .stat = vfs_gluster_stat,
++      .fstat = vfs_gluster_fstat,
++      .lstat = vfs_gluster_lstat,
++      .get_alloc_size = vfs_gluster_get_alloc_size,
++      .unlink = vfs_gluster_unlink,
++
++      .chmod = vfs_gluster_chmod,
++      .fchmod = vfs_gluster_fchmod,
++      .chown = vfs_gluster_chown,
++      .fchown = vfs_gluster_fchown,
++      .lchown = vfs_gluster_lchown,
++      .chdir = vfs_gluster_chdir,
++      .getwd = vfs_gluster_getwd,
++      .ntimes = vfs_gluster_ntimes,
++      .ftruncate = vfs_gluster_ftruncate,
++      .fallocate = vfs_gluster_fallocate,
++      .lock = vfs_gluster_lock,
++      .kernel_flock = vfs_gluster_kernel_flock,
++      .linux_setlease = vfs_gluster_linux_setlease,
++      .getlock = vfs_gluster_getlock,
++      .symlink = vfs_gluster_symlink,
++      .vfs_readlink = vfs_gluster_readlink,
++      .link = vfs_gluster_link,
++      .mknod = vfs_gluster_mknod,
++      .realpath = vfs_gluster_realpath,
++      .notify_watch = vfs_gluster_notify_watch,
++      .chflags = vfs_gluster_chflags,
++      .file_id_create = NULL,
++      .streaminfo = NULL,
++      .get_real_filename = vfs_gluster_get_real_filename,
++      .connectpath = vfs_gluster_connectpath,
++
++      .brl_lock_windows = NULL,
++      .brl_unlock_windows = NULL,
++      .brl_cancel_windows = NULL,
++      .strict_lock = NULL,
++      .strict_unlock = NULL,
++      .translate_name = NULL,
++
++      /* NT ACL Operations */
++      .fget_nt_acl = NULL,
++      .get_nt_acl = NULL,
++      .fset_nt_acl = NULL,
++
++      /* Posix ACL Operations */
++      .chmod_acl = NULL,      /* passthrough to default */
++      .fchmod_acl = NULL,     /* passthrough to default */
++
++      .sys_acl_get_entry = NULL,
++      .sys_acl_get_tag_type = NULL,
++      .sys_acl_get_permset = NULL,
++      .sys_acl_get_qualifier = NULL,
++      .sys_acl_get_file = vfs_gluster_sys_acl_get_file,
++      .sys_acl_get_fd = vfs_gluster_sys_acl_get_fd,
++      .sys_acl_clear_perms = NULL,
++      .sys_acl_add_perm = NULL,
++      .sys_acl_to_text = NULL,
++      .sys_acl_init = NULL,
++      .sys_acl_create_entry = NULL,
++      .sys_acl_set_tag_type = NULL,
++      .sys_acl_set_qualifier = NULL,
++      .sys_acl_set_permset = NULL,
++      .sys_acl_valid = NULL,
++      .sys_acl_set_file = vfs_gluster_sys_acl_set_file,
++      .sys_acl_set_fd = vfs_gluster_sys_acl_set_fd,
++      .sys_acl_delete_def_file = vfs_gluster_sys_acl_delete_def_file,
++      .sys_acl_get_perm = NULL,
++      .sys_acl_free_text = NULL,
++      .sys_acl_free_acl = NULL,
++      .sys_acl_free_qualifier = NULL,
++
++      /* EA Operations */
++      .getxattr = vfs_gluster_getxattr,
++      .lgetxattr = vfs_gluster_lgetxattr,
++      .fgetxattr = vfs_gluster_fgetxattr,
++      .listxattr = vfs_gluster_listxattr,
++      .llistxattr = vfs_gluster_llistxattr,
++      .flistxattr = vfs_gluster_flistxattr,
++      .removexattr = vfs_gluster_removexattr,
++      .lremovexattr = vfs_gluster_lremovexattr,
++      .fremovexattr = vfs_gluster_fremovexattr,
++      .setxattr = vfs_gluster_setxattr,
++      .lsetxattr = vfs_gluster_lsetxattr,
++      .fsetxattr = vfs_gluster_fsetxattr,
++
++      /* AIO Operations */
++      .aio_read = NULL,
++      .aio_write = NULL,
++      .aio_return_fn = NULL,
++      .aio_cancel = NULL,
++      .aio_error_fn = NULL,
++      .aio_fsync = NULL,
++      .aio_suspend = NULL,
++      .aio_force = vfs_gluster_aio_force,
++
++      /* Offline Operations */
++      .is_offline = vfs_gluster_is_offline,
++      .set_offline = vfs_gluster_set_offline,
++};
++
++NTSTATUS vfs_glusterfs_init(void);
++NTSTATUS vfs_glusterfs_init(void)
++{
++      return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
++                              "glusterfs", &glusterfs_fns);
++}
+diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build
+index ff7163f..31c93be 100644
+--- a/source3/modules/wscript_build
++++ b/source3/modules/wscript_build
+@@ -50,6 +50,7 @@ VFS_SCANNEDONLY_SRC = 'vfs_scannedonly.c'
+ VFS_CROSSRENAME_SRC = 'vfs_crossrename.c'
+ VFS_LINUX_XFS_SGID_SRC = 'vfs_linux_xfs_sgid.c'
+ VFS_TIME_AUDIT_SRC = 'vfs_time_audit.c'
++VFS_GLUSTERFS_SRC = 'vfs_glusterfs.c'
+ bld.SAMBA3_SUBSYSTEM('NFS4_ACLS',
+@@ -408,6 +409,14 @@ bld.SAMBA3_MODULE('vfs_time_audit',
+                  internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_time_audit'),
+                  enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_time_audit'))
++bld.SAMBA3_MODULE('vfs_glusterfs',
++                  subsystem='vfs',
++                  source=VFS_GLUSTERFS_SRC,
++                  deps='samba-util gfapi',
++                  init_function='',
++                  internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_glusterfs'),
++                  enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_glusterfs'),
++                  allow_undefined_symbols=False)
+ CHARSET_WEIRD_SRC = 'weird.c'
+diff --git a/source3/wscript b/source3/wscript
+index bcc6ce1..7e34db5 100644
+--- a/source3/wscript
++++ b/source3/wscript
+@@ -60,6 +60,7 @@ def set_options(opt):
+     opt.SAMBA3_ADD_OPTION('automount')
+     opt.SAMBA3_ADD_OPTION('aio-support')
+     opt.SAMBA3_ADD_OPTION('profiling-data')
++    opt.SAMBA3_ADD_OPTION('glusterfs', with_name="enable", without_name="disable", default=True)
+     opt.SAMBA3_ADD_OPTION('cluster-support')
+@@ -1701,6 +1702,24 @@ main() {
+         conf.undefine('CLUSTER_SUPPORT')
++    #
++    # Checking for GlusterFS
++    #
++    if Options.options.with_glusterfs:
++        conf.check_cfg(package='glusterfs-api', args='"glusterfs-api >= 4" --cflags --libs',
++                       msg='Checking for glusterfs-api >= 4', uselib_store="GFAPI")
++        conf.CHECK_HEADERS('api/glfs.h', lib='gfapi')
++        conf.CHECK_LIB('gfapi', shlib=True)
++
++        if conf.CONFIG_SET('HAVE_API_GLFS_H'):
++            conf.DEFINE('HAVE_GLUSTERFS', '1')
++        else:
++            conf.SET_TARGET_TYPE('gfapi', 'EMPTY')
++            conf.undefine('HAVE_GLUSTERFS')
++    else:
++        conf.SET_TARGET_TYPE('gfapi', 'EMPTY')
++        conf.undefine('HAVE_GLUSTERFS')
++
+     conf.CHECK_CODE('__attribute__((destructor)) static void cleanup(void) { }',
+                   'HAVE_FUNCTION_ATTRIBUTE_DESTRUCTOR',
+@@ -1794,6 +1813,9 @@ main() {
+     if conf.CONFIG_SET('HAVE_GPFS'):
+       default_shared_modules.extend(TO_LIST('vfs_gpfs vfs_gpfs_hsm_notify'))
++    if conf.CONFIG_SET('HAVE_GLUSTERFS'):
++        default_shared_modules.extend(TO_LIST('vfs_glusterfs'))
++
+     explicit_shared_modules = TO_LIST(Options.options.shared_modules, delimiter=',')
+     explicit_static_modules = TO_LIST(Options.options.static_modules, delimiter=',')
+-- 
+1.9.3
+
+
+From e2b70ae1e9b072173de2b7d6140381b910d436b4 Mon Sep 17 00:00:00 2001
+From: Raghavendra Talur <rtalur@redhat.com>
+Date: Thu, 20 Jun 2013 17:58:15 -0700
+Subject: [PATCH 2/9] PATCHSET13: vfs_glusterfs: New file creation fix.
+
+When a new document is created in explorer, a check for file_exist is made.
+vfs_gluster_get_real_filename was returning 0 even when the file did not
+exist.
+---
+ source3/modules/vfs_glusterfs.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
+index 4beac1d..3752940 100644
+--- a/source3/modules/vfs_glusterfs.c
++++ b/source3/modules/vfs_glusterfs.c
+@@ -839,8 +839,10 @@ static int vfs_gluster_get_real_filename(struct vfs_handle_struct *handle,
+                "user.glusterfs.get_real_filename:%s", name);
+       ret = glfs_getxattr(handle->data, path, key_buf, val_buf, NAME_MAX + 1);
+-      if (ret == -1 && errno == ENODATA) {
+-              errno = EOPNOTSUPP;
++      if (ret == -1) {
++              if (errno == ENODATA) {
++                      errno = EOPNOTSUPP;
++              }
+               return -1;
+       }
+-- 
+1.9.3
+
+
+From e963ec42b17cdc7369e4b79387447bb3ddc99d2a Mon Sep 17 00:00:00 2001
+From: susant <spalai@redhat.com>
+Date: Wed, 7 Aug 2013 01:00:31 -0500
+Subject: [PATCH 3/9] PATCHSET13: vfs_glusterfs: Volume capacity reported to
+ Windows is incorrect
+
+VFS plugin was sending the actual size of the volume instead of the
+total number of block units because of which windows was getting the
+wrong volume capacity.
+
+Signed-off-by: susant <spalai@redhat.com>
+Reviewed-by: Anand Avati <avati@redhat.com>
+---
+ source3/modules/vfs_glusterfs.c | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
+index 3752940..1502776 100644
+--- a/source3/modules/vfs_glusterfs.c
++++ b/source3/modules/vfs_glusterfs.c
+@@ -297,7 +297,6 @@ vfs_gluster_disk_free(struct vfs_handle_struct *handle, const char *path,
+                     uint64_t *dsize_p)
+ {
+       struct statvfs statvfs = { 0, };
+-      uint64_t dfree = 0;
+       int ret;
+       ret = glfs_statvfs(handle->data, path, &statvfs);
+@@ -307,19 +306,17 @@ vfs_gluster_disk_free(struct vfs_handle_struct *handle, const char *path,
+               return -1;
+       }
+-      dfree = statvfs.f_bsize * statvfs.f_bavail;
+-
+       if (bsize_p) {
+-              *bsize_p = statvfs.f_bsize;
++              *bsize_p = (uint64_t)statvfs.f_bsize; /* Block size */
+       }
+       if (dfree_p) {
+-              *dfree_p = dfree;
++              *dfree_p = (uint64_t)statvfs.f_bavail; /* Available Block units */
+       }
+       if (dsize_p) {
+-              *dsize_p = statvfs.f_bsize * statvfs.f_blocks;
++              *dsize_p = (uint64_t)statvfs.f_blocks; /* Total Block units */
+       }
+-      return dfree;
++      return (uint64_t)statvfs.f_bavail;
+ }
+ static int
+-- 
+1.9.3
+
+
+From 1d41227866ede7ae14857105abd6b322e8e41525 Mon Sep 17 00:00:00 2001
+From: Anand Avati <avati@redhat.com>
+Date: Mon, 12 Aug 2013 14:59:24 -0500
+Subject: [PATCH 4/9] PATCHSET13: vfs_glusterfs: Implement proper
+ mashalling/unmarshalling of ACLs
+
+Use the primitives available in Samba byteorder.h for implementing
+proper (un)marshalling of ACL xattrs.
+
+Signed-off-by: Anand Avati <avati@redhat.com>
+Reviewed-by: Raghavendra Talur <rtalur@redhat.com>
+Reviewed-by: Jeremy Allison <jra@samba.org>
+Tested-by: "Jose A. Rivera" <jarrpa@redhat.com>
+---
+ source3/modules/vfs_glusterfs.c | 154 +++++++++++++++++++++++++++++-----------
+ 1 file changed, 112 insertions(+), 42 deletions(-)
+
+diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
+index 1502776..1b81d06 100644
+--- a/source3/modules/vfs_glusterfs.c
++++ b/source3/modules/vfs_glusterfs.c
+@@ -963,13 +963,36 @@ static int vfs_gluster_set_offline(struct vfs_handle_struct *handle,
+       return -1;
+ }
+-/* Posix ACL Operations */
++/*
++  Gluster ACL Format:
++
++  Size = 4 (header) + N * 8 (entry)
++
++  Offset  Size    Field (Little Endian)
++  -------------------------------------
++  0-3     4-byte  Version
++
++  4-5     2-byte  Entry-1 tag
++  6-7     2-byte  Entry-1 perm
++  8-11    4-byte  Entry-1 id
++
++  12-13   2-byte  Entry-2 tag
++  14-15   2-byte  Entry-2 perm
++  16-19   4-byte  Entry-2 id
++  ...
++
++ */
++
++/* header version */
+ #define GLUSTER_ACL_VERSION 2
++
++/* perm bits */
+ #define GLUSTER_ACL_READ    0x04
+ #define GLUSTER_ACL_WRITE   0x02
+ #define GLUSTER_ACL_EXECUTE 0x01
++/* tag values */
+ #define GLUSTER_ACL_UNDEFINED_TAG  0x00
+ #define GLUSTER_ACL_USER_OBJ       0x01
+ #define GLUSTER_ACL_USER           0x02
+@@ -980,57 +1003,48 @@ static int vfs_gluster_set_offline(struct vfs_handle_struct *handle,
+ #define GLUSTER_ACL_UNDEFINED_ID  (-1)
+-struct gluster_ace {
+-      uint16_t tag;
+-      uint16_t perm;
+-      uint32_t id;
+-};
+-
+-struct gluster_acl_header {
+-      uint32_t version;
+-      struct gluster_ace entries[];
+-};
++#define GLUSTER_ACL_HEADER_SIZE    4
++#define GLUSTER_ACL_ENTRY_SIZE     8
+ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size)
+ {
+       int count;
+       size_t size;
+-      struct gluster_ace *ace;
+       struct smb_acl_entry *smb_ace;
+-      struct gluster_acl_header *hdr;
+       struct smb_acl_t *result;
+       int i;
++      int offset;
+       uint16_t tag;
+       uint16_t perm;
+       uint32_t id;
+       size = xattr_size;
+-      if (size < sizeof(*hdr)) {
+-              /* ACL should be at least as big as the header */
++      if (size < GLUSTER_ACL_HEADER_SIZE) {
++              /* ACL should be at least as big as the header (4 bytes) */
+               errno = EINVAL;
+               return NULL;
+       }
+-      size -= sizeof(*hdr);
++      size -= GLUSTER_ACL_HEADER_SIZE; /* size of header = 4 bytes */
+-      if (size % sizeof(*ace)) {
++      if (size % GLUSTER_ACL_ENTRY_SIZE) {
+               /* Size of entries must strictly be a multiple of
+-                 size of an ACE
++                 size of an ACE (8 bytes)
+               */
+               errno = EINVAL;
+               return NULL;
+       }
+-      count = size / sizeof(*ace);
+-
+-      hdr = (void *)buf;
++      count = size / GLUSTER_ACL_ENTRY_SIZE;
+-      if (ntohl(hdr->version) != GLUSTER_ACL_VERSION) {
++      /* Version is the first 4 bytes of the ACL */
++      if (IVAL(buf, 0) != GLUSTER_ACL_VERSION) {
+               DEBUG(0, ("Unknown gluster ACL version: %d\n",
+-                        ntohl(hdr->version)));
++                        IVAL(buf, 0)));
+               return NULL;
+       }
++      offset = GLUSTER_ACL_HEADER_SIZE;
+       result = SMB_MALLOC(sizeof(struct smb_acl_t) + (sizeof(struct smb_acl_entry) * count));
+       if (!result) {
+@@ -1041,10 +1055,19 @@ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size)
+       result->count = count;
+       smb_ace = result->acl;
+-      ace = hdr->entries;
+       for (i = 0; i < count; i++) {
+-              tag = ntohs(ace->tag);
++              /* TAG is the first 2 bytes of an entry */
++              tag = SVAL(buf, offset);
++              offset += 2;
++
++              /* PERM is the next 2 bytes of an entry */
++              perm = SVAL(buf, offset);
++              offset += 2;
++
++              /* ID is the last 4 bytes of an entry */
++              id = IVAL(buf, offset);
++              offset += 4;
+               switch(tag) {
+               case GLUSTER_ACL_USER:
+@@ -1070,7 +1093,6 @@ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size)
+                       return NULL;
+               }
+-              id = ntohl(ace->id);
+               switch(smb_ace->a_type) {
+               case SMB_ACL_USER:
+@@ -1083,8 +1105,6 @@ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size)
+                       break;
+               }
+-              perm = ntohs(ace->perm);
+-
+               smb_ace->a_perm = 0;
+               smb_ace->a_perm |=
+                       ((perm & GLUSTER_ACL_READ) ? SMB_ACL_READ : 0);
+@@ -1093,28 +1113,61 @@ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size)
+               smb_ace->a_perm |=
+                       ((perm & GLUSTER_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
+-              ace++;
+               smb_ace++;
+       }
+       return result;
+ }
++
++static int gluster_ace_cmp(const void *left, const void *right)
++{
++      int ret = 0;
++      uint16_t tag_left, tag_right;
++      uint32_t id_left, id_right;
++
++      /*
++        Sorting precedence:
++
++         - Smaller TAG values must be earlier.
++
++         - Within same TAG, smaller identifiers must be earlier, E.g:
++           UID 0 entry must be earlier than UID 200
++           GID 17 entry must be earlier than GID 19
++      */
++
++      /* TAG is the first element in the entry */
++      tag_left = SVAL(left, 0);
++      tag_right = SVAL(right, 0);
++
++      ret = (tag_left - tag_right);
++      if (!ret) {
++              /* ID is the third element in the entry, after two short
++                 integers (tag and perm), i.e at offset 4.
++              */
++              id_left = IVAL(left, 4);
++              id_right = IVAL(right, 4);
++              ret = id_left - id_right;
++      }
++
++      return ret;
++}
++
++
+ static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
+ {
+       ssize_t size;
+-      struct gluster_ace *ace;
+       struct smb_acl_entry *smb_ace;
+-      struct gluster_acl_header *hdr;
+       int i;
+       int count;
+       uint16_t tag;
+       uint16_t perm;
+       uint32_t id;
++      int offset;
+       count = theacl->count;
+-      size = sizeof(*hdr) + (count * sizeof(*ace));
++      size = GLUSTER_ACL_HEADER_SIZE + (count * GLUSTER_ACL_ENTRY_SIZE);
+       if (!buf) {
+               return size;
+       }
+@@ -1124,13 +1177,14 @@ static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
+               return -1;
+       }
+-      hdr = (void *)buf;
+-      ace = hdr->entries;
+       smb_ace = theacl->acl;
+-      hdr->version = htonl(GLUSTER_ACL_VERSION);
++      /* Version is the first 4 bytes of the ACL */
++      SIVAL(buf, 0, GLUSTER_ACL_VERSION);
++      offset = GLUSTER_ACL_HEADER_SIZE;
+       for (i = 0; i < count; i++) {
++              /* Calculate tag */
+               switch(smb_ace->a_type) {
+               case SMB_ACL_USER:
+                       tag = GLUSTER_ACL_USER;
+@@ -1157,8 +1211,8 @@ static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
+                       return -1;
+               }
+-              ace->tag = ntohs(tag);
++              /* Calculate id */
+               switch(smb_ace->a_type) {
+               case SMB_ACL_USER:
+                       id = smb_ace->uid;
+@@ -1171,20 +1225,36 @@ static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
+                       break;
+               }
+-              ace->id = ntohl(id);
++              /* Calculate perm */
++              perm = 0;
+-              ace->perm = 0;
+-              ace->perm |=
++              perm |=
+                       ((smb_ace->a_perm & SMB_ACL_READ) ? GLUSTER_ACL_READ : 0);
+-              ace->perm |=
++              perm |=
+                       ((smb_ace->a_perm & SMB_ACL_WRITE) ? GLUSTER_ACL_WRITE : 0);
+-              ace->perm |=
++              perm |=
+                       ((smb_ace->a_perm & SMB_ACL_EXECUTE) ? GLUSTER_ACL_EXECUTE : 0);
+-              ace++;
++
++              /* TAG is the first 2 bytes of an entry */
++              SSVAL(buf, offset, tag);
++              offset += 2;
++
++              /* PERM is the next 2 bytes of an entry */
++              SSVAL(buf, offset, perm);
++              offset += 2;
++
++              /* ID is the last 4 bytes of an entry */
++              SIVAL(buf, offset, id);
++              offset += 4;
++
+               smb_ace++;
+       }
++      /* Skip the header, sort @count number of 8-byte entries */
++      qsort(buf+GLUSTER_ACL_HEADER_SIZE, count, GLUSTER_ACL_ENTRY_SIZE,
++            gluster_ace_cmp);
++
+       return size;
+ }
+-- 
+1.9.3
+
+
+From 26673935299da8ce830ff9d0ea5df18f52092092 Mon Sep 17 00:00:00 2001
+From: "Christopher R. Hertel" <crh@redhat.com>
+Date: Thu, 29 Aug 2013 11:01:24 -0500
+Subject: [PATCH 5/9] PATCHSET13: vfs_glusterfs: Fix excessive debug output
+ from vfs_gluster_open().
+
+The vfs_gluster_open() function generates a debug message (at level 0)
+for every failed attempt to open a pathname.  This includes cases in
+which attempts are made to open a directory as a file (those attempts
+are retried calling vfs_gluster_opendir()).  The result is that the log
+file fills with messages about failed attempts to open directories,
+because they are directories.  This patch ensures that failed attempts
+to open directories as files are logged at log level 4, not 0.  In
+addition, other failed open attempts are logged at level 1, not 0.
+
+Signed-off-by: Christopher R. Hertel <crh@redhat.com>
+Reviewed-by : Susant Palai <spalai@redhat.com>
+Reviewed-by : Raghavendra Talur <rtalur@redhat.com>
+Reviewed-by : Jose A. Rivera <jarrpa@redhat.com>
+---
+ source3/modules/vfs_glusterfs.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
+index 1b81d06..b92c7fd 100644
+--- a/source3/modules/vfs_glusterfs.c
++++ b/source3/modules/vfs_glusterfs.c
+@@ -488,11 +488,8 @@ static int vfs_gluster_open(struct vfs_handle_struct *handle,
+       }
+       if (glfd == NULL) {
+-              DEBUG(0, ("glfs_{open[dir],creat}(%s) failed: %s\n",
+-                        smb_fname->base_name, strerror(errno)));
+               return -1;
+       }
+-
+       return glfd_fd_store(glfd);
+ }
+-- 
+1.9.3
+
+
+From f396be725dd8e8f93b0eed1b23fcf0a0f61303a9 Mon Sep 17 00:00:00 2001
+From: Andreas Schneider <asn@samba.org>
+Date: Mon, 4 Nov 2013 12:32:05 +0100
+Subject: [PATCH 6/9] PATCHSET13: vfs: Fix some build warnings in glusterfs.
+
+Signed-off-by: Andreas Schneider <asn@samba.org>
+Reviewed-by: David Disseldorp <ddiss@samba.org>
+---
+ source3/modules/vfs_glusterfs.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
+index b92c7fd..4b8da4a 100644
+--- a/source3/modules/vfs_glusterfs.c
++++ b/source3/modules/vfs_glusterfs.c
+@@ -1262,7 +1262,7 @@ static SMB_ACL_T vfs_gluster_sys_acl_get_file(struct vfs_handle_struct *handle,
+ {
+       struct smb_acl_t *result;
+       char *buf;
+-      char *key;
++      const char *key;
+       ssize_t ret;
+       switch (type) {
+@@ -1324,7 +1324,7 @@ static int vfs_gluster_sys_acl_set_file(struct vfs_handle_struct *handle,
+                                       SMB_ACL_T theacl)
+ {
+       int ret;
+-      char *key;
++      const char *key;
+       char *buf;
+       ssize_t size;
+-- 
+1.9.3
+
+
+From 2b136f8999e171d15736d0a532353799b7251ae2 Mon Sep 17 00:00:00 2001
+From: Andreas Schneider <asn@samba.org>
+Date: Fri, 15 Nov 2013 17:02:19 +0100
+Subject: [PATCH 7/9] PATCHSET13: s3-vfs: Make glfs_set_preopened() static.
+
+Signed-off-by: Andreas Schneider <asn@samba.org>
+Reviewed-by: Jeremy Allison <jra@samba.org>
+---
+ source3/modules/vfs_glusterfs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
+index 4b8da4a..ef505a3 100644
+--- a/source3/modules/vfs_glusterfs.c
++++ b/source3/modules/vfs_glusterfs.c
+@@ -141,7 +141,7 @@ static struct glfs_preopened {
+ } *glfs_preopened;
+-int glfs_set_preopened(const char *volume, glfs_t *fs)
++static int glfs_set_preopened(const char *volume, glfs_t *fs)
+ {
+       struct glfs_preopened *entry = NULL;
+-- 
+1.9.3
+
+
+From 9b2c8854a5a27e4fdbe5191abf174d3152b0edfd Mon Sep 17 00:00:00 2001
+From: Poornima Gurusiddaiah <pgurusid@redhat.com>
+Date: Sun, 24 Nov 2013 21:37:53 +0000
+Subject: [PATCH 8/9] PATCHSET13: vfs_glusterfs: Enable per client log file
+
+In Samba configuration file, one of the options of gluster type is
+log file, the value of this option was not allowed to contain any
+variables, as a result all the clients would have a single log file,
+which complicated debugging.
+In this patch, variable substitution is performed for gluster log file.
+Hence allowing user to customise the gluster log file name.
+
+Signed-off-by: Poornima Gurusiddaiah <pgurusid@redhat.com>
+Reviewed-by: Ira Cooper <ira@samba.org>
+---
+ source3/modules/vfs_glusterfs.c | 41 ++++++++++++++++++++++-------------------
+ 1 file changed, 22 insertions(+), 19 deletions(-)
+
+diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
+index ef505a3..3757968 100644
+--- a/source3/modules/vfs_glusterfs.c
++++ b/source3/modules/vfs_glusterfs.c
+@@ -205,12 +205,12 @@ static int vfs_gluster_connect(struct vfs_handle_struct *handle,
+ {
+       const char *volfile_server;
+       const char *volume;
+-      const char *logfile;
++      char *logfile;
+       int loglevel;
+       glfs_t *fs;
+-      int ret;
++      int ret = 0;
+-      logfile = lp_parm_const_string(SNUM(handle->conn), "glusterfs",
++      logfile = lp_parm_talloc_string(SNUM(handle->conn), "glusterfs",
+                                      "logfile", NULL);
+       loglevel = lp_parm_int(SNUM(handle->conn), "glusterfs", "loglevel", -1);
+@@ -229,57 +229,60 @@ static int vfs_gluster_connect(struct vfs_handle_struct *handle,
+       fs = glfs_find_preopened(volume);
+       if (fs) {
+-              goto found;
++              goto done;
+       }
+       fs = glfs_new(volume);
+       if (fs == NULL) {
+-              return -1;
++              ret = -1;
++              goto done;
+       }
+       ret = glfs_set_volfile_server(fs, "tcp", volfile_server, 0);
+       if (ret < 0) {
+               DEBUG(0, ("Failed to set volfile_server %s\n", volfile_server));
+-              glfs_fini(fs);
+-              return -1;
++              goto done;
+       }
+       ret = glfs_set_xlator_option(fs, "*-md-cache", "cache-posix-acl",
+                                    "true");
+       if (ret < 0) {
+               DEBUG(0, ("%s: Failed to set xlator options\n", volume));
+-              glfs_fini(fs);
+-              return -1;
++              goto done;
+       }
+       ret = glfs_set_logging(fs, logfile, loglevel);
+       if (ret < 0) {
+               DEBUG(0, ("%s: Failed to set logfile %s loglevel %d\n",
+                         volume, logfile, loglevel));
+-              glfs_fini(fs);
+-              return -1;
++              goto done;
+       }
+       ret = glfs_init(fs);
+       if (ret < 0) {
+               DEBUG(0, ("%s: Failed to initialize volume (%s)\n",
+                         volume, strerror(errno)));
+-              glfs_fini(fs);
+-              return -1;
++              goto done;
+       }
+       ret = glfs_set_preopened(volume, fs);
+       if (ret < 0) {
+               DEBUG(0, ("%s: Failed to register volume (%s)\n",
+                         volume, strerror(errno)));
+-              glfs_fini(fs);
++              goto done;
++      }
++done:
++      talloc_free(logfile);
++      if (ret < 0) {
++              if (fs)
++                      glfs_fini(fs);
+               return -1;
++      } else {
++              DEBUG(0, ("%s: Initialized volume from server %s\n",
++                         volume, volfile_server));
++              handle->data = fs;
++              return 0;
+       }
+-found:
+-      DEBUG(0, ("%s: Initialized volume from server %s\n",
+-                volume, volfile_server));
+-      handle->data = fs;
+-      return 0;
+ }
+ static void vfs_gluster_disconnect(struct vfs_handle_struct *handle)
+-- 
+1.9.3
+
+
+From 8577c573dcd44e26579a6594b83a6d582faef14c Mon Sep 17 00:00:00 2001
+From: Niels de Vos <ndevos@redhat.com>
+Date: Fri, 10 Jan 2014 16:26:18 +0100
+Subject: [PATCH 9/9] PATCHSET13: vfs/glusterfs: in case atime is not passed,
+ set it to the current atime
+
+The Linux CIFS client does not pass an updated atime when a write() is
+done. This causes the vfs/glusterfs module to set the atime to -1 on the
+Gluster backend, resulting in an atime far in the future (year 2106).
+
+Signed-off-by: Niels de Vos <ndevos@redhat.com>
+Reviewed-by: Ira Cooper <ira@samba.org>
+Reviewed-by: Jeremy Allison <jra@samba.org>
+
+Autobuild-User(master): Jeremy Allison <jra@samba.org>
+Autobuild-Date(master): Wed Jan 15 21:31:30 CET 2014 on sn-devel-104
+---
+ source3/modules/vfs_glusterfs.c | 26 ++++++++++++++++++++++----
+ 1 file changed, 22 insertions(+), 4 deletions(-)
+
+diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
+index 3757968..24f80dd 100644
+--- a/source3/modules/vfs_glusterfs.c
++++ b/source3/modules/vfs_glusterfs.c
+@@ -675,10 +675,28 @@ static int vfs_gluster_ntimes(struct vfs_handle_struct *handle,
+ {
+       struct timespec times[2];
+-      times[0].tv_sec = ft->atime.tv_sec;
+-      times[0].tv_nsec = ft->atime.tv_nsec;
+-      times[1].tv_sec = ft->mtime.tv_sec;
+-      times[1].tv_nsec = ft->mtime.tv_nsec;
++      if (null_timespec(ft->atime)) {
++              times[0].tv_sec = smb_fname->st.st_ex_atime.tv_sec;
++              times[0].tv_nsec = smb_fname->st.st_ex_atime.tv_nsec;
++      } else {
++              times[0].tv_sec = ft->atime.tv_sec;
++              times[0].tv_nsec = ft->atime.tv_nsec;
++      }
++
++      if (null_timespec(ft->mtime)) {
++              times[1].tv_sec = smb_fname->st.st_ex_mtime.tv_sec;
++              times[1].tv_nsec = smb_fname->st.st_ex_mtime.tv_nsec;
++      } else {
++              times[1].tv_sec = ft->mtime.tv_sec;
++              times[1].tv_nsec = ft->mtime.tv_nsec;
++      }
++
++      if ((timespec_compare(&times[0],
++                            &smb_fname->st.st_ex_atime) == 0) &&
++          (timespec_compare(&times[1],
++                            &smb_fname->st.st_ex_mtime) == 0)) {
++              return 0;
++      }
+       return glfs_utimens(handle->data, smb_fname->base_name, times);
+ }
+-- 
+1.9.3
+