summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac63
-rw-r--r--contrib/Makefile.am3
-rw-r--r--contrib/fuse-include/fuse-misc.h13
-rw-r--r--contrib/fuse-include/fuse-mount.h11
-rw-r--r--contrib/fuse-include/fuse_kernel.h573
-rw-r--r--contrib/fuse-lib/COPYING.LIB482
-rw-r--r--contrib/fuse-lib/misc.c51
-rw-r--r--contrib/fuse-lib/mount.c616
-rw-r--r--contrib/fuse-util/COPYING340
-rw-r--r--contrib/fuse-util/Makefile.am12
-rw-r--r--contrib/fuse-util/fusermount.c965
-rw-r--r--contrib/fuse-util/mount_util.h17
-rw-r--r--doc/user-guide/user-guide.texi45
-rw-r--r--glusterfsd/src/glusterfsd.c3
-rw-r--r--xlators/mount/fuse/src/Makefile.am11
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.c1758
-rw-r--r--xlators/mount/fuse/src/fuse-extra.c155
-rw-r--r--xlators/mount/fuse/src/fuse-extra.h42
19 files changed, 4146 insertions, 1016 deletions
diff --git a/Makefile.am b/Makefile.am
index b4f0587ca..44506dfd0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
EXTRA_DIST = autogen.sh COPYING INSTALL README AUTHORS THANKS NEWS glusterfs.spec
-SUBDIRS = argp-standalone libglusterfs $(LIBGLUSTERFSCLIENT_SUBDIR) xlators scheduler transport auth glusterfsd $(GF_BOOSTER_SUBDIR) doc extras
+SUBDIRS = argp-standalone libglusterfs $(LIBGLUSTERFSCLIENT_SUBDIR) xlators scheduler transport auth glusterfsd $(GF_BOOSTER_SUBDIR) $(FUSERMOUNT_SUBDIR) doc extras
CLEANFILES =
diff --git a/configure.ac b/configure.ac
index 71f663fa7..6a9510968 100644
--- a/configure.ac
+++ b/configure.ac
@@ -124,6 +124,8 @@ AC_CONFIG_FILES([Makefile
extras/init.d/glusterfsd-Redhat
extras/init.d/glusterfsd-SuSE
extras/benchmarking/Makefile
+ contrib/Makefile
+ contrib/fuse-util/Makefile
glusterfs.spec])
AC_CANONICAL_HOST
@@ -206,53 +208,32 @@ AC_ARG_ENABLE([fuse-client],
AC_HELP_STRING([--disable-fuse-client],
[Do not build the fuse client. NOTE: you cannot mount glusterfs without the client]))
+BUILD_FUSE_CLIENT=no
if test "x$enable_fuse_client" != "xno"; then
- AC_CHECK_LIB([fuse],
- [fuse_req_interrupt_func],
- [HAVE_LIBFUSE="yes"],
- [HAVE_LIBFUSE="no"])
-
- if test "x$HAVE_LIBFUSE" = "xyes"; then
- AC_TRY_COMPILE([#define FUSE_USE_VERSION 26
- #define _FILE_OFFSET_BITS 64
- #include <fuse.h>],
- #define _GLFS_FUSE_VERSION_28 28
- #if (FUSE_VERSION < _GLFS_FUSE_VERSION_28)
- #error "fuse version 2.8 not found"
- #endif
- ,
- [HAVE_FUSE_VERSION_28="yes"],
- [HAVE_FUSE_VERSION_28="no"])
-
- AC_CHECK_LIB([fuse],
- [fuse_reply_iov],
- [HAVE_FUSE_REPLY_IOV="yes"],
- [HAVE_FUSE_REPLY_IOV="no"])
-
- fi
+ FUSE_CLIENT_SUBDIR=fuse
+ BUILD_FUSE_CLIENT="yes"
fi
-if test "x$HAVE_FUSE_REPLY_IOV" = "xyes"; then
- AC_DEFINE(HAVE_FUSE_REPLY_IOV, 1, [found fuse_reply_iov])
-fi
+AC_SUBST(FUSE_CLIENT_SUBDIR)
+# end FUSE section
-if test "x$HAVE_LIBFUSE" = "xyes" -a "x$HAVE_FUSE_VERSION_28" = "xyes"; then
- AC_DEFINE(HAVE_FUSE_VERSION_28, 1, [found fuse 2.8 version])
-fi
-if test "x$enable_fuse_client" = "xyes" -a "x$HAVE_LIBFUSE" = "xno"; then
- echo "FUSE requested but not found."
- exit 1
-fi
+# FUSERMOUNT section
+AC_ARG_ENABLE([fusermount],
+ AC_HELP_STRING([--enable-fusermount],
+ [Build fusermount]),
+ [], [enable_fusermount=no])
-BUILD_FUSE_CLIENT=no
-if test "x$enable_fuse_client" != "xno" -a "x$HAVE_LIBFUSE" = "xyes"; then
- FUSE_CLIENT_SUBDIR=fuse
- BUILD_FUSE_CLIENT="yes"
+BUILD_FUSERMOUNT="no"
+
+if test "x$enable_fusermount" != "xno"; then
+ FUSERMOUNT_SUBDIR="contrib"
+ BUILD_FUSERMOUNT="yes"
+ AC_DEFINE(GF_FUSERMOUNT, 1, [Use our own fusermount])
fi
-AC_SUBST(FUSE_CLIENT_SUBDIR)
-# end FUSE section
+AC_SUBST(FUSERMOUNT_SUBDIR)
+#end FUSERMOUNT section
# EPOLL section
@@ -493,6 +474,9 @@ AC_SUBST(GF_LDADD)
AC_SUBST(GF_FUSE_LDADD)
AC_SUBST(GF_BOOSTER_SUBDIR)
+CONTRIBDIR='$(top_srcdir)/contrib'
+AC_SUBST(CONTRIBDIR)
+
AM_CONDITIONAL([GF_DARWIN_HOST_OS], test "${GF_HOST_OS}" = "GF_DARWIN_HOST_OS")
AC_OUTPUT
@@ -506,4 +490,5 @@ echo "epoll IO multiplex : $BUILD_EPOLL"
echo "Berkeley-DB : $BUILD_BDB"
echo "libglusterfsclient : $BUILD_LIBGLUSTERFSCLIENT"
echo "argp-standalone : $BUILD_ARGP_STANDALONE"
+echo "fusermount : $BUILD_FUSERMOUNT"
echo
diff --git a/contrib/Makefile.am b/contrib/Makefile.am
new file mode 100644
index 000000000..a3d5cfbf8
--- /dev/null
+++ b/contrib/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = fuse-util
+
+CLEANFILES =
diff --git a/contrib/fuse-include/fuse-misc.h b/contrib/fuse-include/fuse-misc.h
new file mode 100644
index 000000000..16b473472
--- /dev/null
+++ b/contrib/fuse-include/fuse-misc.h
@@ -0,0 +1,13 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU LGPLv2.
+ See the file COPYING.LIB
+*/
+
+#define OFFSET_MAX 0x7fffffffffffffffLL
+
+unsigned long calc_timeout_sec (double t);
+unsigned int calc_timeout_nsec (double t);
+void convert_fuse_file_lock (struct fuse_file_lock *fl, struct flock *flock);
diff --git a/contrib/fuse-include/fuse-mount.h b/contrib/fuse-include/fuse-mount.h
new file mode 100644
index 000000000..d263a8039
--- /dev/null
+++ b/contrib/fuse-include/fuse-mount.h
@@ -0,0 +1,11 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.com>
+
+ This program can be distributed under the terms of the GNU LGPLv2.
+ See the file COPYING.LIB.
+*/
+
+void gf_fuse_unmount (const char *mountpoint, int fd);
+int gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param);
diff --git a/contrib/fuse-include/fuse_kernel.h b/contrib/fuse-include/fuse_kernel.h
new file mode 100644
index 000000000..dac35d8b9
--- /dev/null
+++ b/contrib/fuse-include/fuse_kernel.h
@@ -0,0 +1,573 @@
+/*
+ This file defines the kernel interface of FUSE
+ Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+
+ This -- and only this -- header file may also be distributed under
+ the terms of the BSD Licence as follows:
+
+ Copyright (C) 2001-2007 Miklos Szeredi. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+*/
+
+/*
+ * This file defines the kernel interface of FUSE
+ *
+ * Protocol changelog:
+ *
+ * 7.9:
+ * - new fuse_getattr_in input argument of GETATTR
+ * - add lk_flags in fuse_lk_in
+ * - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in
+ * - add blksize field to fuse_attr
+ * - add file flags field to fuse_read_in and fuse_write_in
+ *
+ * 7.10
+ * - add nonseekable open flag
+ *
+ * 7.11
+ * - add IOCTL message
+ * - add unsolicited notification support
+ * - add POLL message and NOTIFY_POLL notification
+ *
+ * 7.12
+ * - add umask flag to input argument of open, mknod and mkdir
+ * - add notification messages for invalidation of inodes and
+ * directory entries
+ */
+
+#ifndef _LINUX_FUSE_H
+#define _LINUX_FUSE_H
+
+#include <sys/types.h>
+#define __u64 uint64_t
+#define __s64 int64_t
+#define __u32 uint32_t
+#define __s32 int32_t
+
+/** Version number of this interface */
+#define FUSE_KERNEL_VERSION 7
+
+/** Minor version number of this interface */
+#define FUSE_KERNEL_MINOR_VERSION 12
+
+/** The node ID of the root inode */
+#define FUSE_ROOT_ID 1
+
+/* Make sure all structures are padded to 64bit boundary, so 32bit
+ userspace works under 64bit kernels */
+
+struct fuse_attr {
+ __u64 ino;
+ __u64 size;
+ __u64 blocks;
+ __u64 atime;
+ __u64 mtime;
+ __u64 ctime;
+ __u32 atimensec;
+ __u32 mtimensec;
+ __u32 ctimensec;
+ __u32 mode;
+ __u32 nlink;
+ __u32 uid;
+ __u32 gid;
+ __u32 rdev;
+ __u32 blksize;
+ __u32 padding;
+};
+
+struct fuse_kstatfs {
+ __u64 blocks;
+ __u64 bfree;
+ __u64 bavail;
+ __u64 files;
+ __u64 ffree;
+ __u32 bsize;
+ __u32 namelen;
+ __u32 frsize;
+ __u32 padding;
+ __u32 spare[6];
+};
+
+struct fuse_file_lock {
+ __u64 start;
+ __u64 end;
+ __u32 type;
+ __u32 pid; /* tgid */
+};
+
+/**
+ * Bitmasks for fuse_setattr_in.valid
+ */
+#define FATTR_MODE (1 << 0)
+#define FATTR_UID (1 << 1)
+#define FATTR_GID (1 << 2)
+#define FATTR_SIZE (1 << 3)
+#define FATTR_ATIME (1 << 4)
+#define FATTR_MTIME (1 << 5)
+#define FATTR_FH (1 << 6)
+#define FATTR_ATIME_NOW (1 << 7)
+#define FATTR_MTIME_NOW (1 << 8)
+#define FATTR_LOCKOWNER (1 << 9)
+
+/**
+ * Flags returned by the OPEN request
+ *
+ * FOPEN_DIRECT_IO: bypass page cache for this open file
+ * FOPEN_KEEP_CACHE: don't invalidate the data cache on open
+ * FOPEN_NONSEEKABLE: the file is not seekable
+ */
+#define FOPEN_DIRECT_IO (1 << 0)
+#define FOPEN_KEEP_CACHE (1 << 1)
+#define FOPEN_NONSEEKABLE (1 << 2)
+
+/**
+ * INIT request/reply flags
+ *
+ * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".."
+ * FUSE_DONT_MASK: don't apply umask to file mode on create operations
+ */
+#define FUSE_ASYNC_READ (1 << 0)
+#define FUSE_POSIX_LOCKS (1 << 1)
+#define FUSE_FILE_OPS (1 << 2)
+#define FUSE_ATOMIC_O_TRUNC (1 << 3)
+#define FUSE_EXPORT_SUPPORT (1 << 4)
+#define FUSE_BIG_WRITES (1 << 5)
+#define FUSE_DONT_MASK (1 << 6)
+
+/**
+ * CUSE INIT request/reply flags
+ *
+ * CUSE_UNRESTRICTED_IOCTL: use unrestricted ioctl
+ */
+#define CUSE_UNRESTRICTED_IOCTL (1 << 0)
+
+/**
+ * Release flags
+ */
+#define FUSE_RELEASE_FLUSH (1 << 0)
+
+/**
+ * Getattr flags
+ */
+#define FUSE_GETATTR_FH (1 << 0)
+
+/**
+ * Lock flags
+ */
+#define FUSE_LK_FLOCK (1 << 0)
+
+/**
+ * WRITE flags
+ *
+ * FUSE_WRITE_CACHE: delayed write from page cache, file handle is guessed
+ * FUSE_WRITE_LOCKOWNER: lock_owner field is valid
+ */
+#define FUSE_WRITE_CACHE (1 << 0)
+#define FUSE_WRITE_LOCKOWNER (1 << 1)
+
+/**
+ * Read flags
+ */
+#define FUSE_READ_LOCKOWNER (1 << 1)
+
+/**
+ * Ioctl flags
+ *
+ * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine
+ * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed
+ * FUSE_IOCTL_RETRY: retry with new iovecs
+ *
+ * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs
+ */
+#define FUSE_IOCTL_COMPAT (1 << 0)
+#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
+#define FUSE_IOCTL_RETRY (1 << 2)
+
+#define FUSE_IOCTL_MAX_IOV 256
+
+/**
+ * Poll flags
+ *
+ * FUSE_POLL_SCHEDULE_NOTIFY: request poll notify
+ */
+#define FUSE_POLL_SCHEDULE_NOTIFY (1 << 0)
+
+enum fuse_opcode {
+ FUSE_LOOKUP = 1,
+ FUSE_FORGET = 2, /* no reply */
+ FUSE_GETATTR = 3,
+ FUSE_SETATTR = 4,
+ FUSE_READLINK = 5,
+ FUSE_SYMLINK = 6,
+ FUSE_MKNOD = 8,
+ FUSE_MKDIR = 9,
+ FUSE_UNLINK = 10,
+ FUSE_RMDIR = 11,
+ FUSE_RENAME = 12,
+ FUSE_LINK = 13,
+ FUSE_OPEN = 14,
+ FUSE_READ = 15,
+ FUSE_WRITE = 16,
+ FUSE_STATFS = 17,
+ FUSE_RELEASE = 18,
+ FUSE_FSYNC = 20,
+ FUSE_SETXATTR = 21,
+ FUSE_GETXATTR = 22,
+ FUSE_LISTXATTR = 23,
+ FUSE_REMOVEXATTR = 24,
+ FUSE_FLUSH = 25,
+ FUSE_INIT = 26,
+ FUSE_OPENDIR = 27,
+ FUSE_READDIR = 28,
+ FUSE_RELEASEDIR = 29,
+ FUSE_FSYNCDIR = 30,
+ FUSE_GETLK = 31,
+ FUSE_SETLK = 32,
+ FUSE_SETLKW = 33,
+ FUSE_ACCESS = 34,
+ FUSE_CREATE = 35,
+ FUSE_INTERRUPT = 36,
+ FUSE_BMAP = 37,
+ FUSE_DESTROY = 38,
+ FUSE_IOCTL = 39,
+ FUSE_POLL = 40,
+
+ /* CUSE specific operations */
+ CUSE_INIT = 4096,
+};
+
+enum fuse_notify_code {
+ FUSE_NOTIFY_POLL = 1,
+ FUSE_NOTIFY_INVAL_INODE = 2,
+ FUSE_NOTIFY_INVAL_ENTRY = 3,
+ FUSE_NOTIFY_CODE_MAX,
+};
+
+/* The read buffer is required to be at least 8k, but may be much larger */
+#define FUSE_MIN_READ_BUFFER 8192
+
+#define FUSE_COMPAT_ENTRY_OUT_SIZE 120
+
+struct fuse_entry_out {
+ __u64 nodeid; /* Inode ID */
+ __u64 generation; /* Inode generation: nodeid:gen must
+ be unique for the fs's lifetime */
+ __u64 entry_valid; /* Cache timeout for the name */
+ __u64 attr_valid; /* Cache timeout for the attributes */
+ __u32 entry_valid_nsec;
+ __u32 attr_valid_nsec;
+ struct fuse_attr attr;
+};
+
+struct fuse_forget_in {
+ __u64 nlookup;
+};
+
+struct fuse_getattr_in {
+ __u32 getattr_flags;
+ __u32 dummy;
+ __u64 fh;
+};
+
+#define FUSE_COMPAT_ATTR_OUT_SIZE 96
+
+struct fuse_attr_out {
+ __u64 attr_valid; /* Cache timeout for the attributes */
+ __u32 attr_valid_nsec;
+ __u32 dummy;
+ struct fuse_attr attr;
+};
+
+#define FUSE_COMPAT_MKNOD_IN_SIZE 8
+
+struct fuse_mknod_in {
+ __u32 mode;
+ __u32 rdev;
+ __u32 umask;
+ __u32 padding;
+};
+
+struct fuse_mkdir_in {
+ __u32 mode;
+ __u32 umask;
+};
+
+struct fuse_rename_in {
+ __u64 newdir;
+};
+
+struct fuse_link_in {
+ __u64 oldnodeid;
+};
+
+struct fuse_setattr_in {
+ __u32 valid;
+ __u32 padding;
+ __u64 fh;
+ __u64 size;
+ __u64 lock_owner;
+ __u64 atime;
+ __u64 mtime;
+ __u64 unused2;
+ __u32 atimensec;
+ __u32 mtimensec;
+ __u32 unused3;
+ __u32 mode;
+ __u32 unused4;
+ __u32 uid;
+ __u32 gid;
+ __u32 unused5;
+};
+
+struct fuse_open_in {
+ __u32 flags;
+ __u32 unused;
+};
+
+struct fuse_create_in {
+ __u32 flags;
+ __u32 mode;
+ __u32 umask;
+ __u32 padding;
+};
+
+struct fuse_open_out {
+ __u64 fh;
+ __u32 open_flags;
+ __u32 padding;
+};
+
+struct fuse_release_in {
+ __u64 fh;
+ __u32 flags;
+ __u32 release_flags;
+ __u64 lock_owner;
+};
+
+struct fuse_flush_in {
+ __u64 fh;
+ __u32 unused;
+ __u32 padding;
+ __u64 lock_owner;
+};
+
+struct fuse_read_in {
+ __u64 fh;
+ __u64 offset;
+ __u32 size;
+ __u32 read_flags;
+ __u64 lock_owner;
+ __u32 flags;
+ __u32 padding;
+};
+
+#define FUSE_COMPAT_WRITE_IN_SIZE 24
+
+struct fuse_write_in {
+ __u64 fh;
+ __u64 offset;
+ __u32 size;
+ __u32 write_flags;
+ __u64 lock_owner;
+ __u32 flags;
+ __u32 padding;
+};
+
+struct fuse_write_out {
+ __u32 size;
+ __u32 padding;
+};
+
+#define FUSE_COMPAT_STATFS_SIZE 48
+
+struct fuse_statfs_out {
+ struct fuse_kstatfs st;
+};
+
+struct fuse_fsync_in {
+ __u64 fh;
+ __u32 fsync_flags;
+ __u32 padding;
+};
+
+struct fuse_setxattr_in {
+ __u32 size;
+ __u32 flags;
+};
+
+struct fuse_getxattr_in {
+ __u32 size;
+ __u32 padding;
+};
+
+struct fuse_getxattr_out {
+ __u32 size;
+ __u32 padding;
+};
+
+struct fuse_lk_in {
+ __u64 fh;
+ __u64 owner;
+ struct fuse_file_lock lk;
+ __u32 lk_flags;
+ __u32 padding;
+};
+
+struct fuse_lk_out {
+ struct fuse_file_lock lk;
+};
+
+struct fuse_access_in {
+ __u32 mask;
+ __u32 padding;
+};
+
+struct fuse_init_in {
+ __u32 major;
+ __u32 minor;
+ __u32 max_readahead;
+ __u32 flags;
+};
+
+struct fuse_init_out {
+ __u32 major;
+ __u32 minor;
+ __u32 max_readahead;
+ __u32 flags;
+ __u32 unused;
+ __u32 max_write;
+};
+
+#define CUSE_INIT_INFO_MAX 4096
+
+struct cuse_init_in {
+ __u32 major;
+ __u32 minor;
+ __u32 unused;
+ __u32 flags;
+};
+
+struct cuse_init_out {
+ __u32 major;
+ __u32 minor;
+ __u32 unused;
+ __u32 flags;
+ __u32 max_read;
+ __u32 max_write;
+ __u32 dev_major; /* chardev major */
+ __u32 dev_minor; /* chardev minor */
+ __u32 spare[10];
+};
+
+struct fuse_interrupt_in {
+ __u64 unique;
+};
+
+struct fuse_bmap_in {
+ __u64 block;
+ __u32 blocksize;
+ __u32 padding;
+};
+
+struct fuse_bmap_out {
+ __u64 block;
+};
+
+struct fuse_ioctl_in {
+ __u64 fh;
+ __u32 flags;
+ __u32 cmd;
+ __u64 arg;
+ __u32 in_size;
+ __u32 out_size;
+};
+
+struct fuse_ioctl_out {
+ __s32 result;
+ __u32 flags;
+ __u32 in_iovs;
+ __u32 out_iovs;
+};
+
+struct fuse_poll_in {
+ __u64 fh;
+ __u64 kh;
+ __u32 flags;
+ __u32 padding;
+};
+
+struct fuse_poll_out {
+ __u32 revents;
+ __u32 padding;
+};
+
+struct fuse_notify_poll_wakeup_out {
+ __u64 kh;
+};
+
+struct fuse_in_header {
+ __u32 len;
+ __u32 opcode;
+ __u64 unique;
+ __u64 nodeid;
+ __u32 uid;
+ __u32 gid;
+ __u32 pid;
+ __u32 padding;
+};
+
+struct fuse_out_header {
+ __u32 len;
+ __s32 error;
+ __u64 unique;
+};
+
+struct fuse_dirent {
+ __u64 ino;
+ __u64 off;
+ __u32 namelen;
+ __u32 type;
+ char name[0];
+};
+
+#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
+#define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1))
+#define FUSE_DIRENT_SIZE(d) \
+ FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
+
+struct fuse_notify_inval_inode_out {
+ __u64 ino;
+ __s64 off;
+ __s64 len;
+};
+
+struct fuse_notify_inval_entry_out {
+ __u64 parent;
+ __u32 namelen;
+ __u32 padding;
+};
+
+#endif /* _LINUX_FUSE_H */
diff --git a/contrib/fuse-lib/COPYING.LIB b/contrib/fuse-lib/COPYING.LIB
new file mode 100644
index 000000000..161a3d1d4
--- /dev/null
+++ b/contrib/fuse-lib/COPYING.LIB
@@ -0,0 +1,482 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/contrib/fuse-lib/misc.c b/contrib/fuse-lib/misc.c
new file mode 100644
index 000000000..877c3880d
--- /dev/null
+++ b/contrib/fuse-lib/misc.c
@@ -0,0 +1,51 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU LGPLv2.
+ See the file COPYING.LIB
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <fcntl.h>
+#include "fuse_kernel.h"
+#include "fuse-misc.h"
+
+unsigned long
+calc_timeout_sec (double t)
+{
+ if (t > (double) ULONG_MAX)
+ return ULONG_MAX;
+ else if (t < 0.0)
+ return 0;
+ else
+ return (unsigned long) t;
+}
+
+unsigned int
+calc_timeout_nsec (double t)
+{
+ double f = t - (double) calc_timeout_sec (t);
+ if (f < 0.0)
+ return 0;
+ else if (f >= 0.999999999)
+ return 999999999;
+ else
+ return (unsigned int) (f * 1.0e9);
+}
+
+void
+convert_fuse_file_lock (struct fuse_file_lock *fl, struct flock *flock)
+{
+ memset (flock, 0, sizeof (struct flock));
+ flock->l_type = fl->type;
+ flock->l_whence = SEEK_SET;
+ flock->l_start = fl->start;
+ if (fl->end == OFFSET_MAX)
+ flock->l_len = 0;
+ else
+ flock->l_len = fl->end - fl->start + 1;
+ flock->l_pid = fl->pid;
+}
diff --git a/contrib/fuse-lib/mount.c b/contrib/fuse-lib/mount.c
new file mode 100644
index 000000000..c6de43607
--- /dev/null
+++ b/contrib/fuse-lib/mount.c
@@ -0,0 +1,616 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.com>
+
+ This program can be distributed under the terms of the GNU LGPLv2.
+ See the file COPYING.LIB.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <mntent.h>
+#include <sys/stat.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <sys/mount.h>
+
+#ifdef FUSE_UTIL
+#define MALLOC(size) malloc (size)
+#define FREE(ptr) free (ptr)
+#define GFFUSE_LOGERR(...) fprintf (stderr, ## __VA_ARGS__)
+#else /* FUSE_UTIL */
+#include "glusterfs.h"
+#include "logging.h"
+#include "common-utils.h"
+
+#ifdef GF_FUSERMOUNT
+#define FUSERMOUNT_PROG FUSERMOUNT_DIR "/fusermount-glusterfs"
+#else
+#define FUSERMOUNT_PROG "fusermount"
+#endif
+#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
+
+#define GFFUSE_LOGERR(...) \
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR, ## __VA_ARGS__)
+#endif /* !FUSE_UTIL */
+
+/*
+ * Functions below, until following note, were taken from libfuse
+ * (http://git.gluster.com/?p=users/csaba/fuse.git;a=commit;h=b988bbf9)
+ * almost verbatim. What has been changed:
+ * - style adopted to that of glusterfs
+ * - s/fprintf/gf_log/
+ * - s/free/FREE/, s/malloc/MALLOC/
+ * - there are some other minor things
+ */
+
+static int
+mtab_needs_update (const char *mnt)
+{
+ int res;
+ struct stat stbuf;
+
+ /* If mtab is within new mount, don't touch it */
+ if (strncmp (mnt, _PATH_MOUNTED, strlen (mnt)) == 0 &&
+ _PATH_MOUNTED[strlen (mnt)] == '/')
+ return 0;
+
+ /*
+ * Skip mtab update if /etc/mtab:
+ *
+ * - doesn't exist,
+ * - is a symlink,
+ * - is on a read-only filesystem.
+ */
+ res = lstat (_PATH_MOUNTED, &stbuf);
+ if (res == -1) {
+ if (errno == ENOENT)
+ return 0;
+ } else {
+ if (S_ISLNK (stbuf.st_mode))
+ return 0;
+
+ res = access (_PATH_MOUNTED, W_OK);
+ if (res == -1 && errno == EROFS)
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifndef FUSE_UTIL
+static
+#endif
+int
+fuse_mnt_add_mount (const char *progname, const char *fsname,
+ const char *mnt, const char *type, const char *opts)
+{
+ int res;
+ int status;
+ sigset_t blockmask;
+ sigset_t oldmask;
+
+ if (!mtab_needs_update (mnt))
+ return 0;
+
+ sigemptyset (&blockmask);
+ sigaddset (&blockmask, SIGCHLD);
+ res = sigprocmask (SIG_BLOCK, &blockmask, &oldmask);
+ if (res == -1) {
+ GFFUSE_LOGERR ("%s: sigprocmask: %s",
+ progname, strerror (errno));
+ return -1;
+ }
+
+ res = fork ();
+ if (res == -1) {
+ GFFUSE_LOGERR ("%s: fork: %s", progname, strerror (errno));
+ goto out_restore;
+ }
+ if (res == 0) {
+ char templ[] = "/tmp/fusermountXXXXXX";
+ char *tmp;
+
+ sigprocmask (SIG_SETMASK, &oldmask, NULL);
+ setuid (geteuid ());
+
+ /*
+ * hide in a directory, where mount isn't able to resolve
+ * fsname as a valid path
+ */
+ tmp = mkdtemp (templ);
+ if (!tmp) {
+ GFFUSE_LOGERR ("%s: failed to create temporary directory",
+ progname);
+ exit (1);
+ }
+ if (chdir (tmp)) {
+ GFFUSE_LOGERR ("%s: failed to chdir to %s: %s",
+ progname, tmp, strerror (errno));
+ exit (1);
+ }
+ rmdir (tmp);
+ execl ("/bin/mount", "/bin/mount", "-i", "-f", "-t", type,
+ "-o", opts, fsname, mnt, NULL);
+ GFFUSE_LOGERR ("%s: failed to execute /bin/mount: %s",
+ progname, strerror (errno));
+ exit (1);
+ }
+ res = waitpid (res, &status, 0);
+ if (res == -1)
+ GFFUSE_LOGERR ("%s: waitpid: %s", progname, strerror (errno));
+
+ if (status != 0)
+ res = -1;
+
+ out_restore:
+ sigprocmask (SIG_SETMASK, &oldmask, NULL);
+ return res;
+}
+
+#ifndef FUSE_UTIL
+static
+#endif
+char
+*fuse_mnt_resolve_path (const char *progname, const char *orig)
+{
+ char buf[PATH_MAX];
+ char *copy;
+ char *dst;
+ char *end;
+ char *lastcomp;
+ const char *toresolv;
+
+ if (!orig[0]) {
+ GFFUSE_LOGERR ("%s: invalid mountpoint '%s'", progname, orig);
+ return NULL;
+ }
+
+ copy = strdup (orig);
+ if (copy == NULL) {
+ GFFUSE_LOGERR ("%s: failed to allocate memory", progname);
+ return NULL;
+ }
+
+ toresolv = copy;
+ lastcomp = NULL;
+ for (end = copy + strlen (copy) - 1; end > copy && *end == '/'; end --);
+ if (end[0] != '/') {
+ char *tmp;
+ end[1] = '\0';
+ tmp = strrchr (copy, '/');
+ if (tmp == NULL) {
+ lastcomp = copy;
+ toresolv = ".";
+ } else {
+ lastcomp = tmp + 1;
+ if (tmp == copy)
+ toresolv = "/";
+ }
+ if (strcmp (lastcomp, ".") == 0 || strcmp (lastcomp, "..") == 0) {
+ lastcomp = NULL;
+ toresolv = copy;
+ }
+ else if (tmp)
+ tmp[0] = '\0';
+ }
+ if (realpath (toresolv, buf) == NULL) {
+ GFFUSE_LOGERR ("%s: bad mount point %s: %s", progname, orig,
+ strerror (errno));
+ FREE (copy);
+ return NULL;
+ }
+ if (lastcomp == NULL)
+ dst = strdup (buf);
+ else {
+ dst = (char *) MALLOC (strlen (buf) + 1 + strlen (lastcomp) + 1);
+ if (dst) {
+ unsigned buflen = strlen (buf);
+ if (buflen && buf[buflen-1] == '/')
+ sprintf (dst, "%s%s", buf, lastcomp);
+ else
+ sprintf (dst, "%s/%s", buf, lastcomp);
+ }
+ }
+ FREE (copy);
+ if (dst == NULL)
+ GFFUSE_LOGERR ("%s: failed to allocate memory", progname);
+ return dst;
+}
+
+#ifndef FUSE_UTIL
+/* return value:
+ * >= 0 => fd
+ * -1 => error
+ */
+static int
+receive_fd (int fd)
+{
+ struct msghdr msg;
+ struct iovec iov;
+ char buf[1];
+ int rv;
+ size_t ccmsg[CMSG_SPACE (sizeof (int)) / sizeof (size_t)];
+ struct cmsghdr *cmsg;
+
+ iov.iov_base = buf;
+ iov.iov_len = 1;
+
+ msg.msg_name = 0;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ /* old BSD implementations should use msg_accrights instead of
+ * msg_control; the interface is different. */
+ msg.msg_control = ccmsg;
+ msg.msg_controllen = sizeof (ccmsg);
+
+ while (((rv = recvmsg (fd, &msg, 0)) == -1) && errno == EINTR);
+ if (rv == -1) {
+ GFFUSE_LOGERR ("recvmsg failed: %s", strerror (errno));
+ return -1;
+ }
+ if (!rv) {
+ /* EOF */
+ return -1;
+ }
+
+ cmsg = CMSG_FIRSTHDR (&msg);
+ if (!cmsg->cmsg_type == SCM_RIGHTS) {
+ GFFUSE_LOGERR ("got control message of unknown type %d",
+ cmsg->cmsg_type);
+ return -1;
+ }
+ return *(int*)CMSG_DATA (cmsg);
+}
+
+static int
+fuse_mount_fusermount (const char *mountpoint, const char *opts)
+{
+ int fds[2], pid;
+ int res;
+ int rv;
+
+ res = socketpair (PF_UNIX, SOCK_STREAM, 0, fds);
+ if (res == -1) {
+ GFFUSE_LOGERR ("socketpair() failed: %s", strerror (errno));
+ return -1;
+ }
+
+ pid = fork ();
+ if (pid == -1) {
+ GFFUSE_LOGERR ("fork() failed: %s", strerror (errno));
+ close (fds[0]);
+ close (fds[1]);
+ return -1;
+ }
+
+ if (pid == 0) {
+ char env[10];
+ const char *argv[32];
+ int a = 0;
+
+ argv[a++] = FUSERMOUNT_PROG;
+ if (opts) {
+ argv[a++] = "-o";
+ argv[a++] = opts;
+ }
+ argv[a++] = "--";
+ argv[a++] = mountpoint;
+ argv[a++] = NULL;
+
+ close (fds[1]);
+ fcntl (fds[0], F_SETFD, 0);
+ snprintf (env, sizeof (env), "%i", fds[0]);
+ setenv (FUSE_COMMFD_ENV, env, 1);
+ execvp (FUSERMOUNT_PROG, (char **)argv);
+ GFFUSE_LOGERR ("failed to exec fusermount: %s",
+ strerror (errno));
+ _exit (1);
+ }
+
+ close (fds[0]);
+ rv = receive_fd (fds[1]);
+ close (fds[1]);
+ waitpid (pid, NULL, 0); /* bury zombie */
+
+ return rv;
+}
+#endif
+
+#ifndef FUSE_UTIL
+static
+#endif
+int
+fuse_mnt_umount (const char *progname, const char *mnt, int lazy)
+{
+ int res;
+ int status;
+ sigset_t blockmask;
+ sigset_t oldmask;
+
+ if (!mtab_needs_update (mnt)) {
+ res = umount2 (mnt, lazy ? 2 : 0);
+ if (res == -1)
+ GFFUSE_LOGERR ("%s: failed to unmount %s: %s",
+ progname, mnt, strerror (errno));
+ return res;
+ }
+
+ sigemptyset (&blockmask);
+ sigaddset (&blockmask, SIGCHLD);
+ res = sigprocmask (SIG_BLOCK, &blockmask, &oldmask);
+ if (res == -1) {
+ GFFUSE_LOGERR ("%s: sigprocmask: %s", progname,
+ strerror (errno));
+ return -1;
+ }
+
+ res = fork ();
+ if (res == -1) {
+ GFFUSE_LOGERR ("%s: fork: %s", progname, strerror (errno));
+ goto out_restore;
+ }
+ if (res == 0) {
+ sigprocmask (SIG_SETMASK, &oldmask, NULL);
+ setuid (geteuid ());
+ execl ("/bin/umount", "/bin/umount", "-i", mnt,
+ lazy ? "-l" : NULL, NULL);
+ GFFUSE_LOGERR ("%s: failed to execute /bin/umount: %s",
+ progname, strerror (errno));
+ exit (1);
+ }
+ res = waitpid (res, &status, 0);
+ if (res == -1)
+ GFFUSE_LOGERR ("%s: waitpid: %s", progname, strerror (errno));
+
+ if (status != 0)
+ res = -1;
+
+ out_restore:
+ sigprocmask (SIG_SETMASK, &oldmask, NULL);
+ return res;
+}
+
+#ifdef FUSE_UTIL
+int
+fuse_mnt_check_empty (const char *progname, const char *mnt,
+ mode_t rootmode, off_t rootsize)
+{
+ int isempty = 1;
+
+ if (S_ISDIR (rootmode)) {
+ struct dirent *ent;
+ DIR *dp = opendir (mnt);
+ if (dp == NULL) {
+ fprintf (stderr,
+ "%s: failed to open mountpoint for reading: %s\n",
+ progname, strerror (errno));
+ return -1;
+ }
+ while ((ent = readdir (dp)) != NULL) {
+ if (strcmp (ent->d_name, ".") != 0 &&
+ strcmp (ent->d_name, "..") != 0) {
+ isempty = 0;
+ break;
+ }
+ }
+ closedir (dp);
+ } else if (rootsize)
+ isempty = 0;
+
+ if (!isempty) {
+ fprintf (stderr, "%s: mountpoint is not empty\n", progname);
+ fprintf (stderr, "%s: if you are sure this is safe, "
+ "use the 'nonempty' mount option\n", progname);
+ return -1;
+ }
+ return 0;
+}
+
+int
+fuse_mnt_check_fuseblk (void)
+{
+ char buf[256];
+ FILE *f = fopen ("/proc/filesystems", "r");
+ if (!f)
+ return 1;
+
+ while (fgets (buf, sizeof (buf), f))
+ if (strstr (buf, "fuseblk\n")) {
+ fclose (f);
+ return 1;
+ }
+
+ fclose (f);
+ return 0;
+}
+#endif
+
+#ifndef FUSE_UTIL
+void
+gf_fuse_unmount (const char *mountpoint, int fd)
+{
+ int res;
+ int pid;
+
+ if (!mountpoint)
+ return;
+
+ if (fd != -1) {
+ struct pollfd pfd;
+
+ pfd.fd = fd;
+ pfd.events = 0;
+ res = poll (&pfd, 1, 0);
+ /* If file poll returns POLLERR on the device file descriptor,
+ then the filesystem is already unmounted */
+ if (res == 1 && (pfd.revents & POLLERR))
+ return;
+
+ /* Need to close file descriptor, otherwise synchronous umount
+ would recurse into filesystem, and deadlock */
+ close (fd);
+ }
+
+ if (geteuid () == 0) {
+ fuse_mnt_umount ("fuse", mountpoint, 1);
+ return;
+ }
+
+ res = umount2 (mountpoint, 2);
+ if (res == 0)
+ return;
+
+ pid = fork ();
+ if (pid == -1)
+ return;
+
+ if (pid == 0) {
+ const char *argv[] = { FUSERMOUNT_PROG, "-u", "-q", "-z",
+ "--", mountpoint, NULL };
+
+ execvp (FUSERMOUNT_PROG, (char **)argv);
+ _exit (1);
+ }
+ waitpid (pid, NULL, 0);
+}
+#endif
+
+/*
+ * Functions below are loosely modelled after similar functions of libfuse
+ */
+
+#ifndef FUSE_UTIL
+static int
+fuse_mount_sys (const char *mountpoint, char *fsname, char *mnt_param)
+{
+ int fd = -1, ret = -1;
+ unsigned mounted = 0;
+ char *mnt_param_mnt = NULL;
+ char *fstype = "fuse.glusterfs";
+ char *source = fsname;
+
+ fd = open ("/dev/fuse", O_RDWR);
+ if (fd == -1) {
+ GFFUSE_LOGERR ("cannot open /dev/fuse (%s)", strerror (errno));
+
+ return -1;
+ }
+
+ ret = asprintf (&mnt_param_mnt,
+ "%s,fd=%i,rootmode=%o,user_id=%i,group_id=%i",
+ mnt_param, fd, S_IFDIR, getuid (), getgid ());
+ if (ret == -1) {
+ GFFUSE_LOGERR ("Out of memory");
+
+ goto out;
+ }
+ ret = mount (source, mountpoint, fstype, 0,
+ mnt_param_mnt);
+ if (ret == -1 && errno == ENODEV) {
+ /* fs subtype support was added by 79c0b2df aka
+ v2.6.21-3159-g79c0b2d. Probably we have an
+ older kernel ... */
+ fstype = "fuse";
+ ret = asprintf (&source, "glusterfs#%s", fsname);
+ if (ret == -1) {
+ GFFUSE_LOGERR ("Out of memory");
+
+ goto out;
+ }
+ ret = mount (source, mountpoint, fstype, 0,
+ mnt_param_mnt);
+ }
+ if (ret == -1)
+ goto out;
+ else
+ mounted = 1;
+
+ if (geteuid () == 0) {
+ char *newmnt = fuse_mnt_resolve_path ("fuse", mountpoint);
+
+ if (!newmnt) {
+ ret = -1;
+
+ goto out;
+ }
+
+ ret = fuse_mnt_add_mount ("fuse", source, newmnt, fstype,
+ mnt_param);
+ FREE (newmnt);
+ if (ret == -1) {
+ GFFUSE_LOGERR ("failed to add mtab entry");
+
+ goto out;
+ }
+ }
+
+ out:
+ if (ret == -1) {
+ if (mounted)
+ umount2 (mountpoint, 2); /* lazy umount */
+ close (fd);
+ fd = -1;
+ }
+ FREE (mnt_param_mnt);
+ if (source != fsname)
+ FREE (source);
+ return fd;
+}
+
+int
+gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param)
+{
+ int fd = -1, rv = -1;
+ char *fm_mnt_params = NULL, *p = NULL;
+
+ fd = fuse_mount_sys (mountpoint, fsname, mnt_param);
+ if (fd == -1) {
+ gf_log ("glusterfs-fuse", GF_LOG_NORMAL,
+ "direct mount failed (%s), "
+ "retry to mount via fusermount",
+ strerror (errno));
+
+ rv = asprintf (&fm_mnt_params,
+ "%s,fsname=%s,nonempty,subtype=glusterfs",
+ mnt_param, fsname);
+
+ if (rv == -1) {
+ GFFUSE_LOGERR ("Out of memory");
+
+ return -1;
+ }
+
+ fd = fuse_mount_fusermount (mountpoint, fm_mnt_params);
+ if (fd == -1) {
+ p = fm_mnt_params + strlen (fm_mnt_params);
+ while (*--p != ',');
+ *p = '\0';
+
+ fd = fuse_mount_fusermount (mountpoint, fm_mnt_params);
+ }
+
+ FREE (fm_mnt_params);
+
+ if (fd == -1)
+ GFFUSE_LOGERR ("mount failed");
+ }
+
+ return fd;
+}
+#endif
diff --git a/contrib/fuse-util/COPYING b/contrib/fuse-util/COPYING
new file mode 100644
index 000000000..d60c31a97
--- /dev/null
+++ b/contrib/fuse-util/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/contrib/fuse-util/Makefile.am b/contrib/fuse-util/Makefile.am
new file mode 100644
index 000000000..06b6cb6da
--- /dev/null
+++ b/contrib/fuse-util/Makefile.am
@@ -0,0 +1,12 @@
+bin_PROGRAMS = fusermount-glusterfs
+
+fusermount_glusterfs_SOURCES = fusermount.c $(CONTRIBDIR)/fuse-lib/mount.c
+noinst_HEADERS = mount_util.h
+
+AM_CFLAGS = -Wall -D_FILE_OFFSET_BITS=64 -DFUSE_UTIL $(GF_CFLAGS)
+
+install-exec-hook:
+ chown root $(DESTDIR)$(bindir)/fusermount-glusterfs
+ chmod u+s $(DESTDIR)$(bindir)/fusermount-glusterfs
+
+CLEANFILES =
diff --git a/contrib/fuse-util/fusermount.c b/contrib/fuse-util/fusermount.c
new file mode 100644
index 000000000..c3ecc86cc
--- /dev/null
+++ b/contrib/fuse-util/fusermount.c
@@ -0,0 +1,965 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+/* This program does the mounting and unmounting of FUSE filesystems */
+
+#include <config.h>
+
+#include "mount_util.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <mntent.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/fsuid.h>
+#include <sys/socket.h>
+#include <sys/utsname.h>
+
+#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
+
+#define FUSE_DEV_OLD "/proc/fs/fuse/dev"
+#define FUSE_DEV_NEW "/dev/fuse"
+#define FUSE_VERSION_FILE_OLD "/proc/fs/fuse/version"
+#define FUSE_CONF "/etc/fuse.conf"
+
+#ifndef MS_DIRSYNC
+#define MS_DIRSYNC 128
+#endif
+
+static const char *progname;
+
+static int user_allow_other = 0;
+static int mount_max = 1000;
+
+static const char *get_user_name(void)
+{
+ struct passwd *pw = getpwuid(getuid());
+ if (pw != NULL && pw->pw_name != NULL)
+ return pw->pw_name;
+ else {
+ fprintf(stderr, "%s: could not determine username\n", progname);
+ return NULL;
+ }
+}
+
+static uid_t oldfsuid;
+static gid_t oldfsgid;
+
+static void drop_privs(void)
+{
+ if (getuid() != 0) {
+ oldfsuid = setfsuid(getuid());
+ oldfsgid = setfsgid(getgid());
+ }
+}
+
+static void restore_privs(void)
+{
+ if (getuid() != 0) {
+ setfsuid(oldfsuid);
+ setfsgid(oldfsgid);
+ }
+}
+
+#ifndef IGNORE_MTAB
+static int add_mount(const char *source, const char *mnt, const char *type,
+ const char *opts)
+{
+ return fuse_mnt_add_mount(progname, source, mnt, type, opts);
+}
+
+static int unmount_fuse(const char *mnt, int quiet, int lazy)
+{
+ if (getuid() != 0) {
+ struct mntent *entp;
+ FILE *fp;
+ const char *user = NULL;
+ char uidstr[32];
+ unsigned uidlen = 0;
+ int found;
+ const char *mtab = _PATH_MOUNTED;
+
+ user = get_user_name();
+ if (user == NULL)
+ return -1;
+
+ fp = setmntent(mtab, "r");
+ if (fp == NULL) {
+ fprintf(stderr,
+ "%s: failed to open %s: %s\n", progname, mtab,
+ strerror(errno));
+ return -1;
+ }
+
+ uidlen = sprintf(uidstr, "%u", getuid());
+
+ found = 0;
+ while ((entp = getmntent(fp)) != NULL) {
+ if (!found && strcmp(entp->mnt_dir, mnt) == 0 &&
+ (strcmp(entp->mnt_type, "fuse") == 0 ||
+ strcmp(entp->mnt_type, "fuseblk") == 0 ||
+ strncmp(entp->mnt_type, "fuse.", 5) == 0 ||
+ strncmp(entp->mnt_type, "fuseblk.", 8) == 0)) {
+ char *p = strstr(entp->mnt_opts, "user=");
+ if (p &&
+ (p == entp->mnt_opts || *(p-1) == ',') &&
+ strcmp(p + 5, user) == 0) {
+ found = 1;
+ break;
+ }
+ /* /etc/mtab is a link pointing to
+ /proc/mounts: */
+ else if ((p =
+ strstr(entp->mnt_opts, "user_id=")) &&
+ (p == entp->mnt_opts ||
+ *(p-1) == ',') &&
+ strncmp(p + 8, uidstr, uidlen) == 0 &&
+ (*(p+8+uidlen) == ',' ||
+ *(p+8+uidlen) == '\0')) {
+ found = 1;
+ break;
+ }
+ }
+ }
+ endmntent(fp);
+
+ if (!found) {
+ if (!quiet)
+ fprintf(stderr,
+ "%s: entry for %s not found in %s\n",
+ progname, mnt, mtab);
+ return -1;
+ }
+ }
+
+ return fuse_mnt_umount(progname, mnt, lazy);
+}
+
+static int count_fuse_fs(void)
+{
+ struct mntent *entp;
+ int count = 0;
+ const char *mtab = _PATH_MOUNTED;
+ FILE *fp = setmntent(mtab, "r");
+ if (fp == NULL) {
+ fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab,
+ strerror(errno));
+ return -1;
+ }
+ while ((entp = getmntent(fp)) != NULL) {
+ if (strcmp(entp->mnt_type, "fuse") == 0 ||
+ strncmp(entp->mnt_type, "fuse.", 5) == 0)
+ count ++;
+ }
+ endmntent(fp);
+ return count;
+}
+
+
+#else /* IGNORE_MTAB */
+static int count_fuse_fs()
+{
+ return 0;
+}
+
+static int add_mount(const char *source, const char *mnt, const char *type,
+ const char *opts)
+{
+ (void) source;
+ (void) mnt;
+ (void) type;
+ (void) opts;
+ return 0;
+}
+
+static int unmount_fuse(const char *mnt, int quiet, int lazy)
+{
+ return fuse_mnt_umount(progname, mnt, lazy);
+}
+#endif /* IGNORE_MTAB */
+
+static void strip_line(char *line)
+{
+ char *s = strchr(line, '#');
+ if (s != NULL)
+ s[0] = '\0';
+ for (s = line + strlen(line) - 1;
+ s >= line && isspace((unsigned char) *s); s--);
+ s[1] = '\0';
+ for (s = line; isspace((unsigned char) *s); s++);
+ if (s != line)
+ memmove(line, s, strlen(s)+1);
+}
+
+static void parse_line(char *line, int linenum)
+{
+ int tmp;
+ if (strcmp(line, "user_allow_other") == 0)
+ user_allow_other = 1;
+ else if (sscanf(line, "mount_max = %i", &tmp) == 1)
+ mount_max = tmp;
+ else if(line[0])
+ fprintf(stderr,
+ "%s: unknown parameter in %s at line %i: '%s'\n",
+ progname, FUSE_CONF, linenum, line);
+}
+
+static void read_conf(void)
+{
+ FILE *fp = fopen(FUSE_CONF, "r");
+ if (fp != NULL) {
+ int linenum = 1;
+ char line[256];
+ int isnewline = 1;
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ if (isnewline) {
+ if (line[strlen(line)-1] == '\n') {
+ strip_line(line);
+ parse_line(line, linenum);
+ } else {
+ isnewline = 0;
+ }
+ } else if(line[strlen(line)-1] == '\n') {
+ fprintf(stderr, "%s: reading %s: line %i too long\n", progname, FUSE_CONF, linenum);
+
+ isnewline = 1;
+ }
+ if (isnewline)
+ linenum ++;
+ }
+ if (!isnewline) {
+ fprintf(stderr, "%s: reading %s: missing newline at end of file\n", progname, FUSE_CONF);
+
+ }
+ fclose(fp);
+ } else if (errno != ENOENT) {
+ fprintf(stderr, "%s: failed to open %s: %s\n",
+ progname, FUSE_CONF, strerror(errno));
+ }
+}
+
+static int begins_with(const char *s, const char *beg)
+{
+ if (strncmp(s, beg, strlen(beg)) == 0)
+ return 1;
+ else
+ return 0;
+}
+
+struct mount_flags {
+ const char *opt;
+ unsigned long flag;
+ int on;
+ int safe;
+};
+
+static struct mount_flags mount_flags[] = {
+ {"rw", MS_RDONLY, 0, 1},
+ {"ro", MS_RDONLY, 1, 1},
+ {"suid", MS_NOSUID, 0, 0},
+ {"nosuid", MS_NOSUID, 1, 1},
+ {"dev", MS_NODEV, 0, 0},
+ {"nodev", MS_NODEV, 1, 1},
+ {"exec", MS_NOEXEC, 0, 1},
+ {"noexec", MS_NOEXEC, 1, 1},
+ {"async", MS_SYNCHRONOUS, 0, 1},
+ {"sync", MS_SYNCHRONOUS, 1, 1},
+ {"atime", MS_NOATIME, 0, 1},
+ {"noatime", MS_NOATIME, 1, 1},
+ {"dirsync", MS_DIRSYNC, 1, 1},
+ {NULL, 0, 0, 0}
+};
+
+static int find_mount_flag(const char *s, unsigned len, int *on, int *flag)
+{
+ int i;
+
+ for (i = 0; mount_flags[i].opt != NULL; i++) {
+ const char *opt = mount_flags[i].opt;
+ if (strlen(opt) == len && strncmp(opt, s, len) == 0) {
+ *on = mount_flags[i].on;
+ *flag = mount_flags[i].flag;
+ if (!mount_flags[i].safe && getuid() != 0) {
+ *flag = 0;
+ fprintf(stderr,
+ "%s: unsafe option %s ignored\n",
+ progname, opt);
+ }
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int add_option(char **optsp, const char *opt, unsigned expand)
+{
+ char *newopts;
+ if (*optsp == NULL)
+ newopts = strdup(opt);
+ else {
+ unsigned oldsize = strlen(*optsp);
+ unsigned newsize = oldsize + 1 + strlen(opt) + expand + 1;
+ newopts = (char *) realloc(*optsp, newsize);
+ if (newopts)
+ sprintf(newopts + oldsize, ",%s", opt);
+ }
+ if (newopts == NULL) {
+ fprintf(stderr, "%s: failed to allocate memory\n", progname);
+ return -1;
+ }
+ *optsp = newopts;
+ return 0;
+}
+
+static int get_mnt_opts(int flags, char *opts, char **mnt_optsp)
+{
+ int i;
+ int l;
+
+ if (!(flags & MS_RDONLY) && add_option(mnt_optsp, "rw", 0) == -1)
+ return -1;
+
+ for (i = 0; mount_flags[i].opt != NULL; i++) {
+ if (mount_flags[i].on && (flags & mount_flags[i].flag) &&
+ add_option(mnt_optsp, mount_flags[i].opt, 0) == -1)
+ return -1;
+ }
+
+ if (add_option(mnt_optsp, opts, 0) == -1)
+ return -1;
+ /* remove comma from end of opts*/
+ l = strlen(*mnt_optsp);
+ if ((*mnt_optsp)[l-1] == ',')
+ (*mnt_optsp)[l-1] = '\0';
+ if (getuid() != 0) {
+ const char *user = get_user_name();
+ if (user == NULL)
+ return -1;
+
+ if (add_option(mnt_optsp, "user=", strlen(user)) == -1)
+ return -1;
+ strcat(*mnt_optsp, user);
+ }
+ return 0;
+}
+
+static int opt_eq(const char *s, unsigned len, const char *opt)
+{
+ if(strlen(opt) == len && strncmp(s, opt, len) == 0)
+ return 1;
+ else
+ return 0;
+}
+
+static int get_string_opt(const char *s, unsigned len, const char *opt,
+ char **val)
+{
+ unsigned opt_len = strlen(opt);
+
+ if (*val)
+ free(*val);
+ *val = (char *) malloc(len - opt_len + 1);
+ if (!*val) {
+ fprintf(stderr, "%s: failed to allocate memory\n", progname);
+ return 0;
+ }
+
+ memcpy(*val, s + opt_len, len - opt_len);
+ (*val)[len - opt_len] = '\0';
+ return 1;
+}
+
+static int do_mount(const char *mnt, char **typep, mode_t rootmode,
+ int fd, const char *opts, const char *dev, char **sourcep,
+ char **mnt_optsp, off_t rootsize)
+{
+ int res;
+ int flags = MS_NOSUID | MS_NODEV;
+ char *optbuf;
+ char *mnt_opts = NULL;
+ const char *s;
+ char *d;
+ char *fsname = NULL;
+ char *subtype = NULL;
+ char *source = NULL;
+ char *type = NULL;
+ int check_empty = 1;
+ int blkdev = 0;
+
+ optbuf = (char *) malloc(strlen(opts) + 128);
+ if (!optbuf) {
+ fprintf(stderr, "%s: failed to allocate memory\n", progname);
+ return -1;
+ }
+
+ for (s = opts, d = optbuf; *s;) {
+ unsigned len;
+ const char *fsname_str = "fsname=";
+ const char *subtype_str = "subtype=";
+ for (len = 0; s[len] && s[len] != ','; len++);
+ if (begins_with(s, fsname_str)) {
+ if (!get_string_opt(s, len, fsname_str, &fsname))
+ goto err;
+ } else if (begins_with(s, subtype_str)) {
+ if (!get_string_opt(s, len, subtype_str, &subtype))
+ goto err;
+ } else if (opt_eq(s, len, "blkdev")) {
+ if (getuid() != 0) {
+ fprintf(stderr,
+ "%s: option blkdev is privileged\n",
+ progname);
+ goto err;
+ }
+ blkdev = 1;
+ } else if (opt_eq(s, len, "nonempty")) {
+ check_empty = 0;
+ } else if (!begins_with(s, "fd=") &&
+ !begins_with(s, "rootmode=") &&
+ !begins_with(s, "user_id=") &&
+ !begins_with(s, "group_id=")) {
+ int on;
+ int flag;
+ int skip_option = 0;
+ if (opt_eq(s, len, "large_read")) {
+ struct utsname utsname;
+ unsigned kmaj, kmin;
+ res = uname(&utsname);
+ if (res == 0 &&
+ sscanf(utsname.release, "%u.%u",
+ &kmaj, &kmin) == 2 &&
+ (kmaj > 2 || (kmaj == 2 && kmin > 4))) {
+ fprintf(stderr, "%s: note: 'large_read' mount option is deprecated for %i.%i kernels\n", progname, kmaj, kmin);
+ skip_option = 1;
+ }
+ }
+ if (getuid() != 0 && !user_allow_other &&
+ (opt_eq(s, len, "allow_other") ||
+ opt_eq(s, len, "allow_root"))) {
+ fprintf(stderr, "%s: option %.*s only allowed if 'user_allow_other' is set in /etc/fuse.conf\n", progname, len, s);
+ goto err;
+ }
+ if (!skip_option) {
+ if (find_mount_flag(s, len, &on, &flag)) {
+ if (on)
+ flags |= flag;
+ else
+ flags &= ~flag;
+ } else {
+ memcpy(d, s, len);
+ d += len;
+ *d++ = ',';
+ }
+ }
+ }
+ s += len;
+ if (*s)
+ s++;
+ }
+ *d = '\0';
+ res = get_mnt_opts(flags, optbuf, &mnt_opts);
+ if (res == -1)
+ goto err;
+
+ sprintf(d, "fd=%i,rootmode=%o,user_id=%i,group_id=%i",
+ fd, rootmode, getuid(), getgid());
+
+ if (check_empty &&
+ fuse_mnt_check_empty(progname, mnt, rootmode, rootsize) == -1)
+ goto err;
+
+ source = malloc((fsname ? strlen(fsname) : 0) +
+ (subtype ? strlen(subtype) : 0) + strlen(dev) + 32);
+
+ type = malloc((subtype ? strlen(subtype) : 0) + 32);
+ if (!type || !source) {
+ fprintf(stderr, "%s: failed to allocate memory\n", progname);
+ goto err;
+ }
+
+ if (subtype)
+ sprintf(type, "%s.%s", blkdev ? "fuseblk" : "fuse", subtype);
+ else
+ strcpy(type, blkdev ? "fuseblk" : "fuse");
+
+ if (fsname)
+ strcpy(source, fsname);
+ else
+ strcpy(source, subtype ? subtype : dev);
+
+ res = mount(source, mnt, type, flags, optbuf);
+ if (res == -1 && errno == ENODEV && subtype) {
+ /* Probably missing subtype support */
+ strcpy(type, blkdev ? "fuseblk" : "fuse");
+ if (fsname) {
+ if (!blkdev)
+ sprintf(source, "%s#%s", subtype, fsname);
+ } else {
+ strcpy(source, type);
+ }
+
+ res = mount(source, mnt, type, flags, optbuf);
+ }
+ if (res == -1 && errno == EINVAL) {
+ /* It could be an old version not supporting group_id */
+ sprintf(d, "fd=%i,rootmode=%o,user_id=%i",
+ fd, rootmode, getuid());
+ res = mount(source, mnt, type, flags, optbuf);
+ }
+ if (res == -1) {
+ int errno_save = errno;
+ if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk())
+ fprintf(stderr, "%s: 'fuseblk' support missing\n",
+ progname);
+ else
+ fprintf(stderr, "%s: mount failed: %s\n", progname,
+ strerror(errno_save));
+ goto err;
+ } else {
+ *sourcep = source;
+ *typep = type;
+ *mnt_optsp = mnt_opts;
+ }
+ free(fsname);
+ free(optbuf);
+
+ return res;
+
+err:
+ free(fsname);
+ free(subtype);
+ free(source);
+ free(type);
+ free(mnt_opts);
+ free(optbuf);
+ return -1;
+}
+
+static int check_version(const char *dev)
+{
+ int res;
+ int majorver;
+ int minorver;
+ const char *version_file;
+ FILE *vf;
+
+ if (strcmp(dev, FUSE_DEV_OLD) != 0)
+ return 0;
+
+ version_file = FUSE_VERSION_FILE_OLD;
+ vf = fopen(version_file, "r");
+ if (vf == NULL) {
+ fprintf(stderr, "%s: kernel interface too old\n", progname);
+ return -1;
+ }
+ res = fscanf(vf, "%i.%i", &majorver, &minorver);
+ fclose(vf);
+ if (res != 2) {
+ fprintf(stderr, "%s: error reading %s\n", progname,
+ version_file);
+ return -1;
+ }
+ if (majorver < 3) {
+ fprintf(stderr, "%s: kernel interface too old\n", progname);
+ return -1;
+ }
+ return 0;
+}
+
+static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_fd,
+ int *mountpoint_fd)
+{
+ int res;
+ const char *mnt = *mntp;
+ const char *origmnt = mnt;
+
+ res = lstat(mnt, stbuf);
+ if (res == -1) {
+ fprintf(stderr, "%s: failed to access mountpoint %s: %s\n",
+ progname, mnt, strerror(errno));
+ return -1;
+ }
+
+ /* No permission checking is done for root */
+ if (getuid() == 0)
+ return 0;
+
+ if (S_ISDIR(stbuf->st_mode)) {
+ *currdir_fd = open(".", O_RDONLY);
+ if (*currdir_fd == -1) {
+ fprintf(stderr,
+ "%s: failed to open current directory: %s\n",
+ progname, strerror(errno));
+ return -1;
+ }
+ res = chdir(mnt);
+ if (res == -1) {
+ fprintf(stderr,
+ "%s: failed to chdir to mountpoint: %s\n",
+ progname, strerror(errno));
+ return -1;
+ }
+ mnt = *mntp = ".";
+ res = lstat(mnt, stbuf);
+ if (res == -1) {
+ fprintf(stderr,
+ "%s: failed to access mountpoint %s: %s\n",
+ progname, origmnt, strerror(errno));
+ return -1;
+ }
+
+ if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) {
+ fprintf(stderr, "%s: mountpoint %s not owned by user\n",
+ progname, origmnt);
+ return -1;
+ }
+
+ res = access(mnt, W_OK);
+ if (res == -1) {
+ fprintf(stderr, "%s: user has no write access to mountpoint %s\n",
+ progname, origmnt);
+ return -1;
+ }
+ } else if (S_ISREG(stbuf->st_mode)) {
+ static char procfile[256];
+ *mountpoint_fd = open(mnt, O_WRONLY);
+ if (*mountpoint_fd == -1) {
+ fprintf(stderr, "%s: failed to open %s: %s\n",
+ progname, mnt, strerror(errno));
+ return -1;
+ }
+ res = fstat(*mountpoint_fd, stbuf);
+ if (res == -1) {
+ fprintf(stderr,
+ "%s: failed to access mountpoint %s: %s\n",
+ progname, mnt, strerror(errno));
+ return -1;
+ }
+ if (!S_ISREG(stbuf->st_mode)) {
+ fprintf(stderr,
+ "%s: mountpoint %s is no longer a regular file\n",
+ progname, mnt);
+ return -1;
+ }
+
+ sprintf(procfile, "/proc/self/fd/%i", *mountpoint_fd);
+ *mntp = procfile;
+ } else {
+ fprintf(stderr,
+ "%s: mountpoint %s is not a directory or a regular file\n",
+ progname, mnt);
+ return -1;
+ }
+
+
+ return 0;
+}
+
+static int try_open(const char *dev, char **devp, int silent)
+{
+ int fd = open(dev, O_RDWR);
+ if (fd != -1) {
+ *devp = strdup(dev);
+ if (*devp == NULL) {
+ fprintf(stderr, "%s: failed to allocate memory\n",
+ progname);
+ close(fd);
+ fd = -1;
+ }
+ } else if (errno == ENODEV ||
+ errno == ENOENT)/* check for ENOENT too, for the udev case */
+ return -2;
+ else if (!silent) {
+ fprintf(stderr, "%s: failed to open %s: %s\n", progname, dev,
+ strerror(errno));
+ }
+ return fd;
+}
+
+static int try_open_fuse_device(char **devp)
+{
+ int fd;
+ int err;
+
+ drop_privs();
+ fd = try_open(FUSE_DEV_NEW, devp, 0);
+ restore_privs();
+ if (fd >= 0)
+ return fd;
+
+ err = fd;
+ fd = try_open(FUSE_DEV_OLD, devp, 1);
+ if (fd >= 0)
+ return fd;
+
+ return err;
+}
+
+static int open_fuse_device(char **devp)
+{
+ int fd = try_open_fuse_device(devp);
+ if (fd >= -1)
+ return fd;
+
+ fprintf(stderr,
+ "%s: fuse device not found, try 'modprobe fuse' first\n",
+ progname);
+
+ return -1;
+}
+
+
+static int mount_fuse(const char *mnt, const char *opts)
+{
+ int res;
+ int fd;
+ char *dev;
+ struct stat stbuf;
+ char *type = NULL;
+ char *source = NULL;
+ char *mnt_opts = NULL;
+ const char *real_mnt = mnt;
+ int currdir_fd = -1;
+ int mountpoint_fd = -1;
+
+ fd = open_fuse_device(&dev);
+ if (fd == -1)
+ return -1;
+
+ drop_privs();
+ read_conf();
+
+ if (getuid() != 0 && mount_max != -1) {
+ int mount_count = count_fuse_fs();
+ if (mount_count >= mount_max) {
+ fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in /etc/fuse.conf\n", progname);
+ close(fd);
+ return -1;
+ }
+ }
+
+ res = check_version(dev);
+ if (res != -1) {
+ res = check_perm(&real_mnt, &stbuf, &currdir_fd,
+ &mountpoint_fd);
+ restore_privs();
+ if (res != -1)
+ res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT,
+ fd, opts, dev, &source, &mnt_opts,
+ stbuf.st_size);
+ } else
+ restore_privs();
+
+ if (currdir_fd != -1) {
+ fchdir(currdir_fd);
+ close(currdir_fd);
+ }
+ if (mountpoint_fd != -1)
+ close(mountpoint_fd);
+
+ if (res == -1) {
+ close(fd);
+ return -1;
+ }
+
+ if (geteuid() == 0) {
+ res = add_mount(source, mnt, type, mnt_opts);
+ if (res == -1) {
+ umount2(mnt, 2); /* lazy umount */
+ close(fd);
+ return -1;
+ }
+ }
+
+ free(source);
+ free(type);
+ free(mnt_opts);
+ free(dev);
+
+ return fd;
+}
+
+static int send_fd(int sock_fd, int fd)
+{
+ int retval;
+ struct msghdr msg;
+ struct cmsghdr *p_cmsg;
+ struct iovec vec;
+ size_t cmsgbuf[CMSG_SPACE(sizeof(fd)) / sizeof(size_t)];
+ int *p_fds;
+ char sendchar = 0;
+
+ msg.msg_control = cmsgbuf;
+ msg.msg_controllen = sizeof(cmsgbuf);
+ p_cmsg = CMSG_FIRSTHDR(&msg);
+ p_cmsg->cmsg_level = SOL_SOCKET;
+ p_cmsg->cmsg_type = SCM_RIGHTS;
+ p_cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ p_fds = (int *) CMSG_DATA(p_cmsg);
+ *p_fds = fd;
+ msg.msg_controllen = p_cmsg->cmsg_len;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &vec;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+ /* "To pass file descriptors or credentials you need to send/read at
+ * least one byte" (man 7 unix) */
+ vec.iov_base = &sendchar;
+ vec.iov_len = sizeof(sendchar);
+ while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
+ if (retval != 1) {
+ perror("sending file descriptor");
+ return -1;
+ }
+ return 0;
+}
+
+static void usage(void)
+{
+ fprintf(stderr,
+ "%s: [options] mountpoint\n"
+ "Options:\n"
+ " -h print help\n"
+ " -V print version\n"
+ " -o opt[,opt...] mount options\n"
+ " -u unmount\n"
+ " -q quiet\n"
+ " -z lazy unmount\n",
+ progname);
+ exit(1);
+}
+
+static void show_version(void)
+{
+ printf("fusermount version: %s\n", PACKAGE_VERSION);
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ int ch;
+ int fd;
+ int res;
+ char *origmnt;
+ char *mnt;
+ static int unmount = 0;
+ static int lazy = 0;
+ static int quiet = 0;
+ char *commfd;
+ int cfd;
+ const char *opts = "";
+
+ static const struct option long_opts[] = {
+ {"unmount", no_argument, NULL, 'u'},
+ {"lazy", no_argument, NULL, 'z'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {0, 0, 0, 0}};
+
+ progname = strdup(argv[0]);
+ if (progname == NULL) {
+ fprintf(stderr, "%s: failed to allocate memory\n", argv[0]);
+ exit(1);
+ }
+
+ while ((ch = getopt_long(argc, argv, "hVo:uzq", long_opts,
+ NULL)) != -1) {
+ switch (ch) {
+ case 'h':
+ usage();
+ break;
+
+ case 'V':
+ show_version();
+ break;
+
+ case 'o':
+ opts = optarg;
+ break;
+
+ case 'u':
+ unmount = 1;
+ break;
+
+ case 'z':
+ lazy = 1;
+ break;
+
+ case 'q':
+ quiet = 1;
+ break;
+
+ default:
+ exit(1);
+ }
+ }
+
+ if (lazy && !unmount) {
+ fprintf(stderr, "%s: -z can only be used with -u\n", progname);
+ exit(1);
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "%s: missing mountpoint argument\n", progname);
+ exit(1);
+ } else if (argc > optind + 1) {
+ fprintf(stderr, "%s: extra arguments after the mountpoint\n",
+ progname);
+ exit(1);
+ }
+
+ origmnt = argv[optind];
+
+ drop_privs();
+ mnt = fuse_mnt_resolve_path(progname, origmnt);
+ restore_privs();
+ if (mnt == NULL)
+ exit(1);
+
+ umask(033);
+ if (unmount) {
+ if (geteuid() == 0)
+ res = unmount_fuse(mnt, quiet, lazy);
+ else {
+ res = umount2(mnt, lazy ? 2 : 0);
+ if (res == -1 && !quiet)
+ fprintf(stderr,
+ "%s: failed to unmount %s: %s\n",
+ progname, mnt, strerror(errno));
+ }
+ if (res == -1)
+ exit(1);
+ return 0;
+ }
+
+ commfd = getenv(FUSE_COMMFD_ENV);
+ if (commfd == NULL) {
+ fprintf(stderr, "%s: old style mounting not supported\n",
+ progname);
+ exit(1);
+ }
+
+ fd = mount_fuse(mnt, opts);
+ if (fd == -1)
+ exit(1);
+
+ cfd = atoi(commfd);
+ res = send_fd(cfd, fd);
+ if (res == -1)
+ exit(1);
+
+ return 0;
+}
diff --git a/contrib/fuse-util/mount_util.h b/contrib/fuse-util/mount_util.h
new file mode 100644
index 000000000..cf54d9d0d
--- /dev/null
+++ b/contrib/fuse-util/mount_util.h
@@ -0,0 +1,17 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU LGPLv2.
+ See the file COPYING.LIB.
+*/
+
+#include <sys/types.h>
+
+int fuse_mnt_add_mount(const char *progname, const char *fsname,
+ const char *mnt, const char *type, const char *opts);
+int fuse_mnt_umount(const char *progname, const char *mnt, int lazy);
+char *fuse_mnt_resolve_path(const char *progname, const char *orig);
+int fuse_mnt_check_empty(const char *progname, const char *mnt,
+ mode_t rootmode, off_t rootsize);
+int fuse_mnt_check_fuseblk(void);
diff --git a/doc/user-guide/user-guide.texi b/doc/user-guide/user-guide.texi
index 943b446d9..800354116 100644
--- a/doc/user-guide/user-guide.texi
+++ b/doc/user-guide/user-guide.texi
@@ -212,16 +212,39 @@ Before installing GlusterFS make sure you have the
following components installed.
@subsection @acronym{FUSE}
-You'll need @acronym{FUSE} version 2.6.0 or higher to
-use GlusterFS. You can omit installing @acronym{FUSE} if you want to
-build @emph{only} the server. Note that you won't be able to mount
-a GlusterFS filesystem on a machine that does not have @acronym{FUSE}
-installed.
+GlusterFS has now built-in support for the @acronym{FUSE} protocol.
+You need a kernel with @acronym{FUSE} support to mount GlusterFS.
+You do not need the @acronym{FUSE} package (library and utilities),
+but be aware of the following issues:
-@acronym{FUSE} can be downloaded from: @indicateurl{http://fuse.sourceforge.net/}
+@itemize
+@item If you want unprivileged users to be able to mount GlusterFS filesystems,
+you need a recent version of the @command{fusermount} utility. You already have
+it if you have @acronym{FUSE} version 2.7.0 or higher installed; if that's not
+the case, one will be compiled along with GlusterFS if you pass
+@command{--enable-fusermount} to the @command{configure} script. @item You
+need to ensure @acronym{FUSE} support is configured properly on your system. In
+details:
+@itemize
+@item If your kernel has @acronym{FUSE} as a loadable module, make sure it's
+loaded.
+@item Create @command{/dev/fuse} (major 10, minor 229) either by means of udev
+rules or by hand.
+@item Optionally, if you want runtime control over your @acronym{FUSE} mounts,
+mount the fusectl auxiliary filesystem:
-To get the best performance from GlusterFS, however, it is recommended that you use
-our patched version of @acronym{FUSE}. See Patched FUSE for details.
+@example
+# mount -t fusectl none /sys/fs/fuse/connections
+@end example
+@end itemize
+
+The @acronym{FUSE} packages shipped by the various distributions usually take care
+about these things, so the easiest way to get the above tasks handled is still
+installing the @acronym{FUSE} package(s).
+@end itemize
+
+To get the best performance from GlusterFS,it is recommended that you use
+our patched version of the @acronym{FUSE} kernel module. See Patched FUSE for details.
@subsection Patched FUSE
@@ -323,6 +346,9 @@ Use poll instead of epoll.
@item --disable-libglusterfsclient
Disable building of libglusterfsclient
+@item --enable-fusermount
+Build fusermount
+
@end table
@end cartouche
@@ -483,7 +509,8 @@ Advanced Options
Attribute timeout for inodes in the kernel, in seconds. Defaults to 1 second.
@item --disable-direct-io-mode
- Disable direct @acronym{I/O} mode in @acronym{FUSE} kernel module.
+ Disable direct @acronym{I/O} mode in @acronym{FUSE} kernel module. This is set
+ automatically if kernel supports big writes (>= 2.6.26).
@item -e, --entry-timeout=<n>
Entry timeout for directory entries in the kernel, in seconds.
diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c
index 899561372..3c9e77822 100644
--- a/glusterfsd/src/glusterfsd.c
+++ b/glusterfsd/src/glusterfsd.c
@@ -140,7 +140,8 @@ static struct argp_option gf_options[] = {
{0, 0, 0, 0, "Fuse options:"},
{"disable-direct-io-mode", ARGP_DISABLE_DIRECT_IO_MODE_KEY, 0, 0,
- "Disable direct I/O mode in fuse kernel module"},
+ "Disable direct I/O mode in fuse kernel module"
+ " [default if big writes are supported]"},
{"entry-timeout", ARGP_ENTRY_TIMEOUT_KEY, "SECONDS", 0,
"Set entry timeout to SECONDS in fuse kernel module [default: 1]"},
{"attribute-timeout", ARGP_ATTRIBUTE_TIMEOUT_KEY, "SECONDS", 0,
diff --git a/xlators/mount/fuse/src/Makefile.am b/xlators/mount/fuse/src/Makefile.am
index 9d8d45e4f..a4d1fd760 100644
--- a/xlators/mount/fuse/src/Makefile.am
+++ b/xlators/mount/fuse/src/Makefile.am
@@ -1,13 +1,14 @@
-
-noinst_HEADERS = fuse-extra.h
+noinst_HEADERS = $(CONTRIBDIR)/fuse-include/fuse_kernel.h
xlator_LTLIBRARIES = fuse.la
xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/mount
-fuse_la_SOURCES = fuse-bridge.c fuse-extra.c
-fuse_la_LDFLAGS = -module -avoidversion -shared -nostartfiles $(GF_FUSE_LDADD)
+fuse_la_SOURCES = fuse-bridge.c $(CONTRIBDIR)/fuse-lib/misc.c \
+ $(CONTRIBDIR)/fuse-lib/mount.c
+fuse_la_LDFLAGS = -module -avoidversion -shared -nostartfiles
AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D$(GF_HOST_OS) -Wall \
- -I$(top_srcdir)/libglusterfs/src $(GF_CFLAGS) -DFUSE_USE_VERSION=26
+ -I$(top_srcdir)/libglusterfs/src -I$(CONTRIBDIR)/fuse-include \
+ $(GF_CFLAGS) -DFUSERMOUNT_DIR=\"$(bindir)\"
CLEANFILES =
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
index b0ac84ea8..d20876a3b 100644
--- a/xlators/mount/fuse/src/fuse-bridge.c
+++ b/xlators/mount/fuse/src/fuse-bridge.c
@@ -28,6 +28,9 @@
#include <stdint.h>
#include <signal.h>
#include <pthread.h>
+#include <stddef.h>
+#include <dirent.h>
+#include <sys/mount.h>
#ifndef _CONFIG_H
#define _CONFIG_H
@@ -37,13 +40,13 @@
#include "glusterfs.h"
#include "logging.h"
#include "xlator.h"
-#include "glusterfs.h"
#include "defaults.h"
#include "common-utils.h"
-#include <fuse/fuse_lowlevel.h>
+#include "fuse_kernel.h"
+#include "fuse-misc.h"
+#include "fuse-mount.h"
-#include "fuse-extra.h"
#include "list.h"
#include "dict.h"
@@ -57,11 +60,16 @@
#define ZR_DIRECT_IO_OPT "direct-io-mode"
#define ZR_STRICT_VOLFILE_CHECK "strict-volfile-check"
+#define FUSE_712_OP_HIGH (FUSE_POLL + 1)
+#define GLUSTERFS_XATTR_LEN_MAX 65536
+
+typedef struct fuse_in_header fuse_in_header_t;
+typedef void (fuse_handler_t) (xlator_t *this, fuse_in_header_t *finh,
+ void *msg);
+
struct fuse_private {
int fd;
- struct fuse *fuse;
- struct fuse_session *se;
- struct fuse_chan *ch;
+ uint32_t proto_minor;
char *volfile;
size_t volfile_size;
char *mount_point;
@@ -69,6 +77,7 @@ struct fuse_private {
pthread_t fuse_thread;
char fuse_thread_started;
uint32_t direct_io_mode;
+ size_t *msg0_len_p;
double entry_timeout;
double attribute_timeout;
pthread_cond_t first_call_cond;
@@ -78,16 +87,16 @@ struct fuse_private {
};
typedef struct fuse_private fuse_private_t;
-#define _FI_TO_FD(fi) ((fd_t *)((long)fi->fh))
+#define _FH_TO_FD(fh) ((fd_t *)(uintptr_t)(fh))
-#define FI_TO_FD(fi) ((_FI_TO_FD (fi))?(fd_ref (_FI_TO_FD(fi))):((fd_t *) 0))
+#define FH_TO_FD(fh) ((_FH_TO_FD (fh))?(fd_ref (_FH_TO_FD (fh))):((fd_t *) 0))
#define FUSE_FOP(state, ret, op_num, fop, args ...) \
do { \
call_frame_t *frame = NULL; \
xlator_t *xl = NULL; \
\
- frame = get_call_frame_for_req (state, 1); \
+ frame = get_call_frame_for_req (state); \
if (!frame) { \
/* This is not completely clean, as some \
* earlier allocations might remain unfreed \
@@ -97,9 +106,11 @@ typedef struct fuse_private fuse_private_t;
*/ \
gf_log ("glusterfs-fuse", \
GF_LOG_ERROR, \
- "FUSE message unique %"PRIu64":" \
+ "FUSE message" \
+ " unique %"PRIu64" opcode %d:" \
" frame allocation failed", \
- req_callid (state->req)); \
+ state->finh->unique, \
+ state->finh->opcode); \
free_state (state); \
return; \
} \
@@ -114,20 +125,21 @@ typedef struct fuse_private fuse_private_t;
(((_errno == ENOENT) || (_errno == ESTALE))? \
GF_LOG_DEBUG)
-#define STATE_FROM_REQ(req, state) \
- do { \
- state = state_from_req (req); \
- if (!state) { \
- gf_log ("glusterfs-fuse", \
- GF_LOG_ERROR, \
- "FUSE message unique %"PRIu64":" \
- " state allocation failed", \
- req_callid (req)); \
- \
- fuse_reply_err (req, ENOMEM); \
- \
- return; \
- } \
+#define GET_STATE(this, finh, state) \
+ do { \
+ state = get_state (this, finh); \
+ if (!state) { \
+ gf_log ("glusterfs-fuse", \
+ GF_LOG_ERROR, \
+ "FUSE message unique %"PRIu64" opcode %d:" \
+ " state allocation failed", \
+ finh->unique, finh->opcode); \
+ \
+ send_fuse_err (this, finh, ENOMEM); \
+ FREE (finh); \
+ \
+ return; \
+ } \
} while (0)
@@ -137,7 +149,7 @@ typedef struct {
inode_table_t *itable;
loc_t loc;
loc_t loc2;
- fuse_req_t req;
+ fuse_in_header_t *finh;
int32_t flags;
off_t off;
size_t size;
@@ -148,8 +160,6 @@ typedef struct {
char is_revalidate;
} fuse_state_t;
-int fuse_chan_receive (struct fuse_chan *ch, char *buf, int32_t size);
-
static void
free_state (fuse_state_t *state)
@@ -170,6 +180,10 @@ free_state (fuse_state_t *state)
fd_unref (state->fd);
state->fd = (void *)0xfdfdfdfd;
}
+ if (state->finh) {
+ FREE (state->finh);
+ state->finh = NULL;
+ }
#ifdef DEBUG
memset (state, 0x90, sizeof (*state));
#endif
@@ -179,66 +193,45 @@ free_state (fuse_state_t *state)
fuse_state_t *
-state_from_req (fuse_req_t req)
+get_state (xlator_t *this, fuse_in_header_t *finh)
{
fuse_state_t *state = NULL;
- xlator_t *this = NULL;
-
- this = fuse_req_userdata (req);
state = (void *)calloc (1, sizeof (*state));
if (!state)
return NULL;
state->pool = this->ctx->pool;
state->itable = this->itable;
- state->req = req;
+ state->finh = finh;
state->this = this;
return state;
}
-static pid_t
-get_pid_from_req (fuse_req_t req)
-{
- const struct fuse_ctx *ctx = NULL;
-
- ctx = fuse_req_ctx (req);
- return ctx->pid;
-}
-
-
static call_frame_t *
-get_call_frame_for_req (fuse_state_t *state, char d)
+get_call_frame_for_req (fuse_state_t *state)
{
call_pool_t *pool = NULL;
- fuse_req_t req = NULL;
- const struct fuse_ctx *ctx = NULL;
+ fuse_in_header_t *finh = NULL;
call_frame_t *frame = NULL;
xlator_t *this = NULL;
fuse_private_t *priv = NULL;
pool = state->pool;
- req = state->req;
-
- if (req) {
- this = fuse_req_userdata (req);
- } else {
- this = state->this;
- }
+ finh = state->finh;
+ this = state->this;
priv = this->private;
frame = create_frame (this, pool);
if (!frame)
return NULL;
- if (req) {
- ctx = fuse_req_ctx (req);
-
- frame->root->uid = ctx->uid;
- frame->root->gid = ctx->gid;
- frame->root->pid = ctx->pid;
- frame->root->unique = req_callid (req);
+ if (finh) {
+ frame->root->uid = finh->uid;
+ frame->root->gid = finh->gid;
+ frame->root->pid = finh->pid;
+ frame->root->unique = finh->unique;
}
frame->root->type = GF_OP_TYPE_FOP_REQUEST;
@@ -247,6 +240,66 @@ get_call_frame_for_req (fuse_state_t *state, char d)
}
+/*
+ * iov_out should contain a fuse_out_header at zeroth position.
+ * The error value of this header is sent to kernel.
+ */
+static int
+send_fuse_iov (xlator_t *this, fuse_in_header_t *finh, struct iovec *iov_out,
+ int count)
+{
+ fuse_private_t *priv = NULL;
+ struct fuse_out_header *fouh = NULL;
+ int res, i;
+
+ priv = this->private;
+
+ fouh = iov_out[0].iov_base;
+ iov_out[0].iov_len = sizeof (*fouh);
+ fouh->len = 0;
+ for (i = 0; i < count; i++)
+ fouh->len += iov_out[i].iov_len;
+ fouh->unique = finh->unique;
+
+ res = writev (priv->fd, iov_out, count);
+
+ if (res == -1)
+ return errno;
+ if (res != fouh->len)
+ return EINVAL;
+ return 0;
+}
+
+static int
+send_fuse_data (xlator_t *this, fuse_in_header_t *finh, void *data, size_t size)
+{
+ struct fuse_out_header fouh = {0, };
+ struct iovec iov_out[2];
+
+ fouh.error = 0;
+ iov_out[0].iov_base = &fouh;
+ iov_out[1].iov_base = data;
+ iov_out[1].iov_len = size;
+
+ return send_fuse_iov (this, finh, iov_out, 2);
+}
+
+#define send_fuse_obj(this, finh, obj) \
+ send_fuse_data (this, finh, obj, sizeof (*(obj)))
+
+static int
+send_fuse_err (xlator_t *this, fuse_in_header_t *finh, int error)
+{
+ struct fuse_out_header fouh = {0, };
+ struct iovec iov_out;
+
+ fouh.error = -error;
+ iov_out.iov_base = &fouh;
+
+ return send_fuse_iov (this, finh, &iov_out, 1);
+}
+
+
GF_MUST_CHECK static int32_t
fuse_loc_fill (loc_t *loc, fuse_state_t *state, ino_t ino,
ino_t par, const char *name)
@@ -351,6 +404,26 @@ need_fresh_lookup (int32_t op_ret, int32_t op_errno,
return 0;
}
+/* courtesy of folly */
+static void
+stat2attr (struct stat *st, struct fuse_attr *fa)
+{
+ fa->ino = st->st_ino;
+ fa->size = st->st_size;
+ fa->blocks = st->st_blocks;
+ fa->atime = st->st_atime;
+ fa->mtime = st->st_mtime;
+ fa->ctime = st->st_ctime;
+ fa->atimensec = ST_ATIM_NSEC (st);
+ fa->mtimensec = ST_MTIM_NSEC (st);
+ fa->ctimensec = ST_CTIM_NSEC (st);
+ fa->mode = st->st_mode;
+ fa->nlink = st->st_nlink;
+ fa->uid = st->st_uid;
+ fa->gid = st->st_gid;
+ fa->rdev = st->st_rdev;
+ fa->blksize = st->st_blksize;
+}
static int
fuse_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
@@ -363,13 +436,14 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
inode_t *inode, struct stat *buf)
{
fuse_state_t *state = NULL;
- fuse_req_t req = NULL;
- struct fuse_entry_param e = {0, };
+ fuse_in_header_t *finh = NULL;
+ struct fuse_entry_out feo = {0, };
+ struct fuse_attr_out *fao = NULL;
fuse_private_t *priv = NULL;
priv = this->private;
state = frame->root->state;
- req = state->req;
+ finh = state->finh;
if (!op_ret && state->loc.ino == 1) {
buf->st_ino = 1;
@@ -391,7 +465,7 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRId64": %s() %s => %"PRId64" (%"PRId64")",
+ "%"PRIu64": %s() %s => %"PRId64" (%"PRId64")",
frame->root->unique, gf_fop_list[frame->root->op],
state->loc.path, buf->st_ino, state->loc.ino);
@@ -399,38 +473,62 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
inode_lookup (inode);
- /* TODO: make these timeouts configurable (via meta?) */
- e.ino = inode->ino;
-
-#ifdef GF_DARWIN_HOST_OS
- e.generation = 0;
-#else
- e.generation = buf->st_ctime;
-#endif
-
buf->st_blksize = this->ctx->page_size;
- e.entry_timeout = priv->entry_timeout;
- e.attr_timeout = priv->attribute_timeout;
- e.attr = *buf;
+ stat2attr (buf, &feo.attr);
- if (!e.ino || !buf->st_ino) {
+ if (!inode->ino || !buf->st_ino) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRId64": %s() %s returning inode 0",
+ "%"PRIu64": %s() %s returning inode 0",
frame->root->unique,
gf_fop_list[frame->root->op], state->loc.path);
}
- if (state->loc.parent)
- fuse_reply_entry (req, &e);
- else
- fuse_reply_attr (req, buf, priv->attribute_timeout);
+ if (state->loc.parent) {
+ /* TODO: make these timeouts configurable (via meta?) */
+ feo.nodeid = inode->ino;
+
+#ifdef GF_DARWIN_HOST_OS
+ feo.generation = 0;
+#else
+ feo.generation = buf->st_ctime;
+#endif
+
+ feo.entry_valid =
+ calc_timeout_sec (priv->entry_timeout);
+ feo.entry_valid_nsec =
+ calc_timeout_nsec (priv->entry_timeout);
+ feo.attr_valid =
+ calc_timeout_sec (priv->attribute_timeout);
+ feo.attr_valid_nsec =
+ calc_timeout_nsec (priv->attribute_timeout);
+
+ priv->proto_minor >= 9 ?
+ send_fuse_obj (this, finh, &feo) :
+ send_fuse_data (this, finh, &feo,
+ FUSE_COMPAT_ENTRY_OUT_SIZE);
+ } else {
+ /* Refurbish the entry_out as attr_out. Too hacky?... */
+ fao = (struct fuse_attr_out *)
+ ((char *)&feo.attr -
+ offsetof (struct fuse_attr_out, attr));
+
+ fao->attr_valid =
+ calc_timeout_sec (priv->attribute_timeout);
+ fao->attr_valid_nsec =
+ calc_timeout_nsec (priv->attribute_timeout);
+
+ priv->proto_minor >= 9 ?
+ send_fuse_obj (this, finh, fao) :
+ send_fuse_data (this, finh, fao,
+ FUSE_COMPAT_ATTR_OUT_SIZE);
+ }
} else {
gf_log ("glusterfs-fuse",
(op_errno == ENOENT ? GF_LOG_TRACE : GF_LOG_WARNING),
- "%"PRId64": %s() %s => -1 (%s)", frame->root->unique,
+ "%"PRIu64": %s() %s => -1 (%s)", frame->root->unique,
gf_fop_list[frame->root->op], state->loc.path,
strerror (op_errno));
- fuse_reply_err (req, op_errno);
+ send_fuse_err (this, state->finh, op_errno);
}
free_state (state);
@@ -450,27 +548,29 @@ fuse_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
static void
-fuse_lookup (fuse_req_t req, fuse_ino_t par, const char *name)
+fuse_lookup (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ char *name = msg;
+
fuse_state_t *state = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
+ GET_STATE (this, finh, state);
- ret = fuse_loc_fill (&state->loc, state, 0, par, name);
+ ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
if (ret < 0) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRIu64": LOOKUP %"PRId64"/%s (fuse_loc_fill() failed)",
- req_callid (req), (ino_t)par, name);
+ "%"PRIu64": LOOKUP %"PRIu64"/%s (fuse_loc_fill() failed)",
+ finh->unique, finh->nodeid, name);
free_state (state);
- fuse_reply_err (req, ENOENT);
+ send_fuse_err (this, finh, ENOENT);
return;
}
if (!state->loc.inode) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": LOOKUP %s", req_callid (req),
+ "%"PRIu64": LOOKUP %s", finh->unique,
state->loc.path);
state->loc.inode = inode_new (state->itable);
@@ -478,7 +578,7 @@ fuse_lookup (fuse_req_t req, fuse_ino_t par, const char *name)
state->is_revalidate = -1;
} else {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": LOOKUP %s(%"PRId64")", req_callid (req),
+ "%"PRIu64": LOOKUP %s(%"PRId64")", finh->unique,
state->loc.path, state->loc.inode->ino);
state->is_revalidate = 1;
}
@@ -491,30 +591,30 @@ fuse_lookup (fuse_req_t req, fuse_ino_t par, const char *name)
static void
-fuse_forget (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup)
+fuse_forget (xlator_t *this, fuse_in_header_t *finh, void *msg)
+
{
- inode_t *fuse_inode;
- xlator_t *this = NULL;
+ struct fuse_forget_in *ffi = msg;
- this = fuse_req_userdata (req);
+ inode_t *fuse_inode;
- if (ino == 1) {
- fuse_reply_none (req);
+ if (finh->nodeid == 1) {
+ FREE (finh);
return;
}
- fuse_inode = inode_search (this->itable, ino, NULL);
+ fuse_inode = inode_search (this->itable, finh->nodeid, NULL);
if (fuse_inode) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "got forget on inode (%lu)", ino);
- inode_forget (fuse_inode, nlookup);
+ "got forget on inode (%"PRIu64")", finh->nodeid);
+ inode_forget (fuse_inode, ffi->nlookup);
inode_unref (fuse_inode);
} else {
gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
- "got forget, but inode (%lu) not found", ino);
+ "got forget, but inode (%"PRIu64") not found", finh->nodeid);
}
- fuse_reply_none (req);
+ FREE (finh);
}
@@ -522,17 +622,18 @@ static int
fuse_attr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct stat *buf)
{
- fuse_state_t *state;
- fuse_req_t req;
- fuse_private_t *priv = NULL;
+ fuse_state_t *state;
+ fuse_in_header_t *finh;
+ fuse_private_t *priv = NULL;
+ struct fuse_attr_out fao;
priv = this->private;
state = frame->root->state;
- req = state->req;
+ finh = state->finh;
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRId64": %s() %s => %"PRId64, frame->root->unique,
+ "%"PRIu64": %s() %s => %"PRId64, frame->root->unique,
gf_fop_list[frame->root->op],
state->loc.path ? state->loc.path : "ERR",
buf->st_ino);
@@ -540,16 +641,24 @@ fuse_attr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
/* TODO: make these timeouts configurable via meta */
/* TODO: what if the inode number has changed by now */
buf->st_blksize = this->ctx->page_size;
+ stat2attr (buf, &fao.attr);
+
+ fao.attr_valid = calc_timeout_sec (priv->attribute_timeout);
+ fao.attr_valid_nsec =
+ calc_timeout_nsec (priv->attribute_timeout);
- fuse_reply_attr (req, buf, priv->attribute_timeout);
+ priv->proto_minor >= 9 ?
+ send_fuse_obj (this, finh, &fao) :
+ send_fuse_data (this, finh, &fao,
+ FUSE_COMPAT_ATTR_OUT_SIZE);
} else {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRId64": %s() %s => -1 (%s)", frame->root->unique,
+ "%"PRIu64": %s() %s => -1 (%s)", frame->root->unique,
gf_fop_list[frame->root->op],
state->loc.path ? state->loc.path : "ERR",
strerror (op_errno));
- fuse_reply_err (req, op_errno);
+ send_fuse_err (this, finh, op_errno);
}
free_state (state);
@@ -559,21 +668,21 @@ fuse_attr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
static void
-fuse_getattr (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
+fuse_getattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
fuse_state_t *state;
fd_t *fd = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
+ GET_STATE (this, finh, state);
- if (ino == 1) {
- ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
+ if (finh->nodeid == 1) {
+ ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
if (ret < 0) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRIu64": GETATTR %"PRId64" (fuse_loc_fill() failed)",
- req_callid (req), (ino_t)ino);
- fuse_reply_err (req, ENOENT);
+ "%"PRIu64": GETATTR %"PRIu64" (fuse_loc_fill() failed)",
+ finh->unique, finh->nodeid);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
@@ -590,17 +699,17 @@ fuse_getattr (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
return;
}
- ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
+ ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
if (!state->loc.inode) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRIu64": GETATTR %"PRId64" (%s) (fuse_loc_fill() returned NULL inode)",
- req_callid (req), (int64_t)ino, state->loc.path);
- fuse_reply_err (req, ENOENT);
+ "%"PRIu64": GETATTR %"PRIu64" (%s) (fuse_loc_fill() returned NULL inode)",
+ finh->unique, finh->nodeid, state->loc.path);
+ send_fuse_err (this, finh, ENOENT);
return;
}
- fd = fd_lookup (state->loc.inode, get_pid_from_req (req));
+ fd = fd_lookup (state->loc.inode, finh->pid);
state->fd = fd;
if (!fd || S_ISDIR (state->loc.inode->st_mode)) {
/* this is the @ret of fuse_loc_fill, checked here
@@ -608,16 +717,16 @@ fuse_getattr (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
*/
if (ret < 0) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRIu64": GETATTR %"PRId64" (fuse_loc_fill() failed)",
- req_callid (req), (ino_t)ino);
- fuse_reply_err (req, ENOENT);
+ "%"PRIu64": GETATTR %"PRIu64" (fuse_loc_fill() failed)",
+ finh->unique, finh->nodeid);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": GETATTR %"PRId64" (%s)",
- req_callid (req), (int64_t)ino, state->loc.path);
+ "%"PRIu64": GETATTR %"PRIu64" (%s)",
+ finh->unique, finh->nodeid, state->loc.path);
FUSE_FOP (state, fuse_attr_cbk, GF_FOP_STAT,
@@ -625,8 +734,8 @@ fuse_getattr (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
} else {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": FGETATTR %"PRId64" (%s/%p)",
- req_callid (req), (int64_t)ino, state->loc.path, fd);
+ "%"PRIu64": FGETATTR %"PRIu64" (%s/%p)",
+ finh->unique, finh->nodeid, state->loc.path, fd);
FUSE_FOP (state,fuse_attr_cbk, GF_FOP_FSTAT,
fstat, fd);
@@ -639,30 +748,30 @@ fuse_fd_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, fd_t *fd)
{
fuse_state_t *state;
- fuse_req_t req;
+ fuse_in_header_t *finh;
fuse_private_t *priv = NULL;
- struct fuse_file_info fi = {0, };
+ struct fuse_open_out foo = {0, };
priv = this->private;
state = frame->root->state;
- req = state->req;
+ finh = state->finh;
if (op_ret >= 0) {
- fi.fh = (unsigned long) fd;
- fi.flags = state->flags;
+ foo.fh = (uintptr_t) fd;
+ foo.open_flags = 0;
if (!S_ISDIR (fd->inode->st_mode)) {
- if (((fi.flags & O_ACCMODE) != O_RDONLY) &&
+ if (((state->flags & O_ACCMODE) != O_RDONLY) &&
priv->direct_io_mode)
- fi.direct_io = 1;
+ foo.open_flags |= FOPEN_DIRECT_IO;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRId64": %s() %s => %p", frame->root->unique,
+ "%"PRIu64": %s() %s => %p", frame->root->unique,
gf_fop_list[frame->root->op], state->loc.path, fd);
fd_ref (fd);
- if (fuse_reply_open (req, &fi) == -ENOENT) {
+ if (send_fuse_obj (this, finh, &foo) == ENOENT) {
gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
"open(%s) got EINTR", state->loc.path);
fd_unref (fd);
@@ -672,11 +781,11 @@ fuse_fd_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
fd_bind (fd);
} else {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRId64": %s() %s => -1 (%s)", frame->root->unique,
+ "%"PRIu64": %s() %s => -1 (%s)", frame->root->unique,
gf_fop_list[frame->root->op], state->loc.path,
strerror (op_errno));
- fuse_reply_err (req, op_errno);
+ send_fuse_err (this, finh, op_errno);
}
out:
free_state (state);
@@ -686,53 +795,51 @@ out:
static void
-do_chmod (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
- struct fuse_file_info *fi)
+do_chmod (xlator_t *this, fuse_in_header_t *finh, struct fuse_setattr_in *fsi)
{
fuse_state_t *state = NULL;
fd_t *fd = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
- if (fi) {
- fd = FI_TO_FD (fi);
+ GET_STATE (this, finh, state);
+ if (fsi->valid & FATTR_FH) {
+ fd = FH_TO_FD (fsi->fh);
state->fd = fd;
}
if (fd) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": FCHMOD %p", req_callid (req), fd);
+ "%"PRIu64": FCHMOD %p", finh->unique, fd);
FUSE_FOP (state, fuse_attr_cbk, GF_FOP_FCHMOD,
- fchmod, fd, attr->st_mode);
+ fchmod, fd, fsi->mode);
} else {
- ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
+ ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRIu64": CHMOD %"PRId64" (%s) (fuse_loc_fill() failed)",
- req_callid (req), (int64_t)ino,
+ "%"PRIu64": CHMOD %"PRIu64" (%s) (fuse_loc_fill() failed)",
+ finh->unique, finh->nodeid,
state->loc.path);
- fuse_reply_err (req, ENOENT);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": CHMOD %s", req_callid (req),
+ "%"PRIu64": CHMOD %s", finh->unique,
state->loc.path);
FUSE_FOP (state, fuse_attr_cbk, GF_FOP_CHMOD,
- chmod, &state->loc, attr->st_mode);
+ chmod, &state->loc, fsi->mode);
}
}
static void
-do_chown (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
- int valid, struct fuse_file_info *fi)
+do_chown (xlator_t *this, fuse_in_header_t *finh, struct fuse_setattr_in *fsi)
{
fuse_state_t *state = NULL;
fd_t *fd = NULL;
@@ -740,36 +847,36 @@ do_chown (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
uid_t uid = 0;
gid_t gid = 0;
- uid = (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t) -1;
- gid = (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t) -1;
- STATE_FROM_REQ (req, state);
+ uid = (fsi->valid & FATTR_UID) ? fsi->uid : (uid_t) -1;
+ gid = (fsi->valid & FATTR_GID) ? fsi->gid : (gid_t) -1;
+ GET_STATE (this, finh, state);
- if (fi) {
- fd = FI_TO_FD (fi);
+ if (fsi->valid & FATTR_FH) {
+ fd = FH_TO_FD (fsi->fh);
state->fd = fd;
}
if (fd) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": FCHOWN %p", req_callid (req), fd);
+ "%"PRIu64": FCHOWN %p", finh->unique, fd);
FUSE_FOP (state, fuse_attr_cbk, GF_FOP_FCHOWN,
fchown, fd, uid, gid);
} else {
- ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
+ ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRIu64": CHOWN %"PRId64" (%s) (fuse_loc_fill() failed)",
- req_callid (req), (int64_t)ino,
+ "%"PRIu64": CHOWN %"PRIu64" (%s) (fuse_loc_fill() failed)",
+ finh->unique, finh->nodeid,
state->loc.path);
- fuse_reply_err (req, ENOENT);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": CHOWN %s", req_callid (req),
+ "%"PRIu64": CHOWN %s", finh->unique,
state->loc.path);
FUSE_FOP (state, fuse_attr_cbk, GF_FOP_CHOWN,
@@ -779,47 +886,46 @@ do_chown (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
static void
-do_truncate (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
- struct fuse_file_info *fi)
+do_truncate (xlator_t *this, fuse_in_header_t *finh, struct fuse_setattr_in *fsi)
{
fuse_state_t *state = NULL;
fd_t *fd = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
+ GET_STATE (this, finh, state);
- if (fi) {
- fd = FI_TO_FD (fi);
+ if (fsi->valid & FATTR_FH) {
+ fd = FH_TO_FD (fsi->fh);
state->fd = fd;
}
if (fd) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": FTRUNCATE %p/%"PRId64, req_callid (req),
- fd, attr->st_size);
+ "%"PRIu64": FTRUNCATE %p/%"PRId64, finh->unique,
+ fd, fsi->size);
FUSE_FOP (state, fuse_attr_cbk, GF_FOP_FTRUNCATE,
- ftruncate, fd, attr->st_size);
+ ftruncate, fd, fsi->size);
} else {
- ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
+ ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64": TRUNCATE %s/%"PRId64" (fuse_loc_fill() failed)",
- req_callid (req), state->loc.path,
- attr->st_size);
- fuse_reply_err (req, ENOENT);
+ finh->unique, state->loc.path,
+ fsi->size);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": TRUNCATE %s/%"PRId64"(%lu)",
- req_callid (req),
- state->loc.path, attr->st_size, ino);
+ "%"PRIu64": TRUNCATE %s/%"PRId64"(%"PRIu64")",
+ finh->unique,
+ state->loc.path, fsi->size, finh->nodeid);
FUSE_FOP (state, fuse_attr_cbk, GF_FOP_TRUNCATE,
- truncate, &state->loc, attr->st_size);
+ truncate, &state->loc, fsi->size);
}
return;
@@ -827,32 +933,32 @@ do_truncate (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
static void
-do_utimes (fuse_req_t req, fuse_ino_t ino, struct stat *attr)
+do_utimes (xlator_t *this, fuse_in_header_t *finh, struct fuse_setattr_in *fsi)
{
fuse_state_t *state = NULL;
struct timespec tv[2];
int32_t ret = -1;
- tv[0].tv_sec = attr->st_atime;
- tv[0].tv_nsec = ST_ATIM_NSEC (attr);
- tv[1].tv_sec = attr->st_mtime;
- tv[1].tv_nsec = ST_ATIM_NSEC (attr);
+ tv[0].tv_sec = fsi->atime;
+ tv[0].tv_nsec = fsi->atimensec;
+ tv[1].tv_sec = fsi->mtime;
+ tv[1].tv_nsec = fsi->mtimensec;
- STATE_FROM_REQ (req, state);
- ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
+ GET_STATE (this, finh, state);
+ ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64": UTIMENS %s (fuse_loc_fill() failed)",
- req_callid (req), state->loc.path);
- fuse_reply_err (req, ENOENT);
+ finh->unique, state->loc.path);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": UTIMENS (%lu)%s", req_callid (req),
- ino, state->loc.path);
+ "%"PRIu64": UTIMENS (%"PRIu64")%s", finh->unique,
+ finh->nodeid, state->loc.path);
FUSE_FOP (state, fuse_attr_cbk, GF_FOP_UTIMENS,
utimens, &state->loc, tv);
@@ -860,20 +966,24 @@ do_utimes (fuse_req_t req, fuse_ino_t ino, struct stat *attr)
static void
-fuse_setattr (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
- int valid, struct fuse_file_info *fi)
-{
-
- if (valid & FUSE_SET_ATTR_MODE)
- do_chmod (req, ino, attr, fi);
- else if (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))
- do_chown (req, ino, attr, valid, fi);
- else if (valid & FUSE_SET_ATTR_SIZE)
- do_truncate (req, ino, attr, fi);
- else if (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))
- do_utimes (req, ino, attr);
+fuse_setattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
+{
+ struct fuse_setattr_in *fsi = msg;
+
+ if (fsi->valid & FATTR_MODE)
+ do_chmod (this, finh, fsi);
+ else if (fsi->valid & (FATTR_UID | FATTR_GID))
+ do_chown (this, finh, fsi);
+ else if (fsi->valid & FATTR_SIZE)
+ do_truncate (this, finh, fsi);
+ else if (fsi->valid & (FATTR_ATIME | FATTR_MTIME))
+ do_utimes (this, finh, fsi);
else
- fuse_getattr (req, ino, fi);
+ /* As of now, getattr uses only the header.
+ * If it happens to change, we'll have to
+ * do some refactoring...
+ */
+ fuse_getattr (this, finh, NULL);
}
@@ -884,15 +994,15 @@ fuse_err_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno)
{
fuse_state_t *state = frame->root->state;
- fuse_req_t req = state->req;
+ fuse_in_header_t *finh = state->finh;
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRId64": %s() %s => 0", frame->root->unique,
+ "%"PRIu64": %s() %s => 0", frame->root->unique,
gf_fop_list[frame->root->op],
state->loc.path ? state->loc.path : "ERR");
- fuse_reply_err (req, 0);
+ send_fuse_err (this, finh, 0);
} else {
if (frame->root->op == GF_FOP_SETXATTR) {
op_ret = gf_compat_setxattr (state->dict);
@@ -913,7 +1023,7 @@ fuse_err_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
goto nolog;
}
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRId64": %s() %s => -1 (%s)",
+ "%"PRIu64": %s() %s => -1 (%s)",
frame->root->unique,
gf_fop_list[frame->root->op],
state->loc.path ? state->loc.path : "ERR",
@@ -921,7 +1031,7 @@ fuse_err_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
}
nolog:
- fuse_reply_err (req, op_errno);
+ send_fuse_err (this, finh, op_errno);
}
free_state (state);
@@ -935,11 +1045,11 @@ static int
fuse_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno)
{
- fuse_state_t *state = NULL;
- fuse_req_t req = NULL;
+ fuse_state_t *state = NULL;
+ fuse_in_header_t *finh = NULL;
state = frame->root->state;
- req = state->req;
+ finh = state->finh;
if (op_ret == 0)
inode_unlink (state->loc.inode, state->loc.parent,
@@ -947,18 +1057,18 @@ fuse_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRId64": %s() %s => 0", frame->root->unique,
+ "%"PRIu64": %s() %s => 0", frame->root->unique,
gf_fop_list[frame->root->op], state->loc.path);
- fuse_reply_err (req, 0);
+ send_fuse_err (this, finh, 0);
} else {
gf_log ("glusterfs-fuse",
op_errno == ENOTEMPTY ? GF_LOG_DEBUG : GF_LOG_WARNING,
- "%"PRId64": %s() %s => -1 (%s)", frame->root->unique,
+ "%"PRIu64": %s() %s => -1 (%s)", frame->root->unique,
gf_fop_list[frame->root->op], state->loc.path,
strerror (op_errno));
- fuse_reply_err (req, op_errno);
+ send_fuse_err (this, finh, op_errno);
}
free_state (state);
@@ -969,31 +1079,33 @@ fuse_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
static void
-fuse_access (fuse_req_t req, fuse_ino_t ino, int mask)
+fuse_access (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_access_in *fai = msg;
+
fuse_state_t *state = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
+ GET_STATE (this, finh, state);
- ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
+ ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRIu64": ACCESS %"PRId64" (%s) (fuse_loc_fill() failed)",
- req_callid (req), (int64_t)ino, state->loc.path);
- fuse_reply_err (req, ENOENT);
+ "%"PRIu64": ACCESS %"PRIu64" (%s) (fuse_loc_fill() failed)",
+ finh->unique, finh->nodeid, state->loc.path);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64" ACCESS %s/%lu mask=%d", req_callid (req),
- state->loc.path, ino, mask);
+ "%"PRIu64" ACCESS %s/%"PRIu64" mask=%d", finh->unique,
+ state->loc.path, finh->nodeid, fai->mask);
FUSE_FOP (state, fuse_err_cbk,
GF_FOP_ACCESS, access,
- &state->loc, mask);
+ &state->loc, fai->mask);
return;
}
@@ -1003,26 +1115,26 @@ static int
fuse_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, const char *linkname)
{
- fuse_state_t *state = NULL;
- fuse_req_t req = NULL;
+ fuse_state_t *state = NULL;
+ fuse_in_header_t *finh = NULL;
state = frame->root->state;
- req = state->req;
+ finh = state->finh;
if (op_ret > 0) {
((char *)linkname)[op_ret] = '\0';
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRId64": %s => %s", frame->root->unique,
+ "%"PRIu64": %s => %s", frame->root->unique,
state->loc.path, linkname);
- fuse_reply_readlink (req, linkname);
+ send_fuse_data (this, finh, (void *)linkname, op_ret + 1);
} else {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRId64": %s => -1 (%s)", frame->root->unique,
+ "%"PRIu64": %s => -1 (%s)", frame->root->unique,
state->loc.path, strerror (op_errno));
- fuse_reply_err (req, op_errno);
+ send_fuse_err (this, finh, op_errno);
}
free_state (state);
@@ -1033,26 +1145,26 @@ fuse_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
static void
-fuse_readlink (fuse_req_t req, fuse_ino_t ino)
+fuse_readlink (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
fuse_state_t *state = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
- ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
+ GET_STATE (this, finh, state);
+ ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64" READLINK %s/%"PRId64" (fuse_loc_fill() returned NULL inode)",
- req_callid (req), state->loc.path,
+ finh->unique, state->loc.path,
state->loc.inode->ino);
- fuse_reply_err (req, ENOENT);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64" READLINK %s/%"PRId64, req_callid (req),
+ "%"PRIu64" READLINK %s/%"PRId64, finh->unique,
state->loc.path, state->loc.inode->ino);
FUSE_FOP (state, fuse_readlink_cbk, GF_FOP_READLINK,
@@ -1063,19 +1175,26 @@ fuse_readlink (fuse_req_t req, fuse_ino_t ino)
static void
-fuse_mknod (fuse_req_t req, fuse_ino_t par, const char *name,
- mode_t mode, dev_t rdev)
+fuse_mknod (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
- fuse_state_t *state = NULL;
- int32_t ret = -1;
+ struct fuse_mknod_in *fmi = msg;
+ char *name = (char *)(fmi + 1);
+
+ fuse_state_t *state = NULL;
+ fuse_private_t *priv = NULL;
+ int32_t ret = -1;
+
+ priv = this->private;
+ if (priv->proto_minor < 12)
+ name = (char *)msg + FUSE_COMPAT_MKNOD_IN_SIZE;
- STATE_FROM_REQ (req, state);
- ret = fuse_loc_fill (&state->loc, state, 0, par, name);
+ GET_STATE (this, finh, state);
+ ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
if (ret < 0) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64" MKNOD %s (fuse_loc_fill() failed)",
- req_callid (req), state->loc.path);
- fuse_reply_err (req, ENOENT);
+ finh->unique, state->loc.path);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
@@ -1083,29 +1202,32 @@ fuse_mknod (fuse_req_t req, fuse_ino_t par, const char *name,
state->loc.inode = inode_new (state->itable);
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": MKNOD %s", req_callid (req),
+ "%"PRIu64": MKNOD %s", finh->unique,
state->loc.path);
FUSE_FOP (state, fuse_entry_cbk, GF_FOP_MKNOD,
- mknod, &state->loc, mode, rdev);
+ mknod, &state->loc, fmi->mode, fmi->rdev);
return;
}
static void
-fuse_mkdir (fuse_req_t req, fuse_ino_t par, const char *name, mode_t mode)
+fuse_mkdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_mknod_in *fmi = msg;
+ char *name = (char *)(fmi + 1);
+
fuse_state_t *state;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
- ret = fuse_loc_fill (&state->loc, state, 0, par, name);
+ GET_STATE (this, finh, state);
+ ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
if (ret < 0) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64" MKDIR %s (fuse_loc_fill() failed)",
- req_callid (req), state->loc.path);
- fuse_reply_err (req, ENOENT);
+ finh->unique, state->loc.path);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
@@ -1113,38 +1235,40 @@ fuse_mkdir (fuse_req_t req, fuse_ino_t par, const char *name, mode_t mode)
state->loc.inode = inode_new (state->itable);
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": MKDIR %s", req_callid (req),
+ "%"PRIu64": MKDIR %s", finh->unique,
state->loc.path);
FUSE_FOP (state, fuse_entry_cbk, GF_FOP_MKDIR,
- mkdir, &state->loc, mode);
+ mkdir, &state->loc, fmi->mode);
return;
}
static void
-fuse_unlink (fuse_req_t req, fuse_ino_t par, const char *name)
+fuse_unlink (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ char *name = msg;
+
fuse_state_t *state = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
+ GET_STATE (this, finh, state);
- ret = fuse_loc_fill (&state->loc, state, 0, par, name);
+ ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64": UNLINK %s (fuse_loc_fill() returned NULL inode)",
- req_callid (req), state->loc.path);
- fuse_reply_err (req, ENOENT);
+ finh->unique, state->loc.path);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": UNLINK %s", req_callid (req),
+ "%"PRIu64": UNLINK %s", finh->unique,
state->loc.path);
FUSE_FOP (state, fuse_unlink_cbk, GF_FOP_UNLINK,
@@ -1155,25 +1279,27 @@ fuse_unlink (fuse_req_t req, fuse_ino_t par, const char *name)
static void
-fuse_rmdir (fuse_req_t req, fuse_ino_t par, const char *name)
+fuse_rmdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ char *name = msg;
+
fuse_state_t *state = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
- ret = fuse_loc_fill (&state->loc, state, 0, par, name);
+ GET_STATE (this, finh, state);
+ ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64": RMDIR %s (fuse_loc_fill() failed)",
- req_callid (req), state->loc.path);
- fuse_reply_err (req, ENOENT);
+ finh->unique, state->loc.path);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": RMDIR %s", req_callid (req),
+ "%"PRIu64": RMDIR %s", finh->unique,
state->loc.path);
FUSE_FOP (state, fuse_unlink_cbk, GF_FOP_RMDIR,
@@ -1184,19 +1310,21 @@ fuse_rmdir (fuse_req_t req, fuse_ino_t par, const char *name)
static void
-fuse_symlink (fuse_req_t req, const char *linkname, fuse_ino_t par,
- const char *name)
+fuse_symlink (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ char *name = msg;
+ char *linkname = name + strlen (name) + 1;
+
fuse_state_t *state = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
- ret = fuse_loc_fill (&state->loc, state, 0, par, name);
+ GET_STATE (this, finh, state);
+ ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
if (ret < 0) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64" SYMLINK %s -> %s (fuse_loc_fill() failed)",
- req_callid (req), state->loc.path, linkname);
- fuse_reply_err (req, ENOENT);
+ finh->unique, state->loc.path, linkname);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
@@ -1204,7 +1332,7 @@ fuse_symlink (fuse_req_t req, const char *linkname, fuse_ino_t par,
state->loc.inode = inode_new (state->itable);
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": SYMLINK %s -> %s", req_callid (req),
+ "%"PRIu64": SYMLINK %s -> %s", finh->unique,
state->loc.path, linkname);
FUSE_FOP (state, fuse_entry_cbk, GF_FOP_SYMLINK,
@@ -1218,15 +1346,15 @@ int
fuse_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct stat *buf)
{
- fuse_state_t *state = NULL;
- fuse_req_t req = NULL;
+ fuse_state_t *state = NULL;
+ fuse_in_header_t *finh = NULL;
state = frame->root->state;
- req = state->req;
+ finh = state->finh;
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRId64": %s -> %s => 0 (buf->st_ino=%"PRId64" , loc->ino=%"PRId64")",
+ "%"PRIu64": %s -> %s => 0 (buf->st_ino=%"PRId64" , loc->ino=%"PRId64")",
frame->root->unique, state->loc.path, state->loc2.path,
buf->st_ino, state->loc.ino);
@@ -1244,13 +1372,13 @@ fuse_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state->loc2.parent, state->loc2.name,
state->loc.inode, buf);
- fuse_reply_err (req, 0);
+ send_fuse_err (this, finh, 0);
} else {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRId64": %s -> %s => -1 (%s)", frame->root->unique,
+ "%"PRIu64": %s -> %s => -1 (%s)", frame->root->unique,
state->loc.path, state->loc2.path,
strerror (op_errno));
- fuse_reply_err (req, op_errno);
+ send_fuse_err (this, finh, op_errno);
}
free_state (state);
@@ -1260,42 +1388,45 @@ fuse_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
static void
-fuse_rename (fuse_req_t req, fuse_ino_t oldpar, const char *oldname,
- fuse_ino_t newpar, const char *newname)
+fuse_rename (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_rename_in *fri = msg;
+ char *oldname = (char *)(fri + 1);
+ char *newname = oldname + strlen (oldname) + 1;
+
fuse_state_t *state = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
+ GET_STATE (this, finh, state);
- ret = fuse_loc_fill (&state->loc, state, 0, oldpar, oldname);
+ ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, oldname);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"for %s %"PRIu64": RENAME `%s' -> `%s' (fuse_loc_fill() failed)",
- state->loc.path, req_callid (req), state->loc.path,
+ state->loc.path, finh->unique, state->loc.path,
state->loc2.path);
- fuse_reply_err (req, ENOENT);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
- ret = fuse_loc_fill (&state->loc2, state, 0, newpar, newname);
+ ret = fuse_loc_fill (&state->loc2, state, 0, fri->newdir, newname);
if (ret < 0) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"for %s %"PRIu64": RENAME `%s' -> `%s' (fuse_loc_fill() failed)",
- state->loc.path, req_callid (req), state->loc.path,
+ state->loc.path, finh->unique, state->loc.path,
state->loc2.path);
- fuse_reply_err (req, ENOENT);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
"%"PRIu64": RENAME `%s (%"PRId64")' -> `%s (%"PRId64")'",
- req_callid (req), state->loc.path, state->loc.ino,
+ finh->unique, state->loc.path, state->loc.ino,
state->loc2.path, state->loc2.ino);
FUSE_FOP (state, fuse_rename_cbk, GF_FOP_RENAME,
@@ -1306,24 +1437,28 @@ fuse_rename (fuse_req_t req, fuse_ino_t oldpar, const char *oldname,
static void
-fuse_link (fuse_req_t req, fuse_ino_t ino, fuse_ino_t par, const char *name)
+fuse_link (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_link_in *fli = msg;
+ char *name = (char *)(fli + 1);
+
fuse_state_t *state = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
+ GET_STATE (this, finh, state);
- ret = fuse_loc_fill (&state->loc, state, 0, par, name);
+ ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
if (ret == 0)
- ret = fuse_loc_fill (&state->loc2, state, ino, 0, NULL);
+ ret = fuse_loc_fill (&state->loc2, state, fli->oldnodeid, 0,
+ NULL);
if ((state->loc2.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"fuse_loc_fill() failed for %s %"PRIu64": LINK %s %s",
- state->loc2.path, req_callid (req),
+ state->loc2.path, finh->unique,
state->loc2.path, state->loc.path);
- fuse_reply_err (req, ENOENT);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
@@ -1331,7 +1466,7 @@ fuse_link (fuse_req_t req, fuse_ino_t ino, fuse_ino_t par, const char *name)
state->loc.inode = inode_ref (state->loc2.inode);
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
"%"PRIu64": LINK() %s (%"PRId64") -> %s (%"PRId64")",
- req_callid (req), state->loc2.path, state->loc2.ino,
+ finh->unique, state->loc2.path, state->loc2.ino,
state->loc.path, state->loc.ino);
FUSE_FOP (state, fuse_entry_cbk, GF_FOP_LINK,
@@ -1347,42 +1482,46 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
fd_t *fd, inode_t *inode, struct stat *buf)
{
fuse_state_t *state = NULL;
- fuse_req_t req = NULL;
+ fuse_in_header_t *finh = NULL;
fuse_private_t *priv = NULL;
- struct fuse_file_info fi = {0, };
- struct fuse_entry_param e = {0, };
+ struct fuse_out_header fouh = {0, };
+ struct fuse_entry_out feo = {0, };
+ struct fuse_open_out foo = {0, };
+ struct iovec iov_out[3];
state = frame->root->state;
priv = this->private;
- req = state->req;
- fi.flags = state->flags;
+ finh = state->finh;
+ foo.open_flags = 0;
if (op_ret >= 0) {
- fi.fh = (unsigned long) fd;
+ foo.fh = (uintptr_t) fd;
- if (((fi.flags & O_ACCMODE) != O_RDONLY)
- && priv->direct_io_mode)
- fi.direct_io = 1;
+ if (((state->flags & O_ACCMODE) != O_RDONLY) &&
+ priv->direct_io_mode)
+ foo.open_flags |= FOPEN_DIRECT_IO;
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRId64": %s() %s => %p (ino=%"PRId64")",
+ "%"PRIu64": %s() %s => %p (ino=%"PRId64")",
frame->root->unique, gf_fop_list[frame->root->op],
state->loc.path, fd, buf->st_ino);
- e.ino = buf->st_ino;
+ buf->st_blksize = this->ctx->page_size;
+ stat2attr (buf, &feo.attr);
+
+ feo.nodeid = buf->st_ino;
#ifdef GF_DARWIN_HOST_OS
- e.generation = 0;
+ feo.generation = 0;
#else
- e.generation = buf->st_ctime;
+ feo.generation = buf->st_ctime;
#endif
- buf->st_blksize = this->ctx->page_size;
- e.entry_timeout = priv->entry_timeout;
- e.attr_timeout = priv->attribute_timeout;
- e.attr = *buf;
-
- fi.keep_cache = 0;
+ feo.entry_valid = calc_timeout_sec (priv->entry_timeout);
+ feo.entry_valid_nsec = calc_timeout_nsec (priv->entry_timeout);
+ feo.attr_valid = calc_timeout_sec (priv->attribute_timeout);
+ feo.attr_valid_nsec =
+ calc_timeout_nsec (priv->attribute_timeout);
inode_link (inode, state->loc.parent,
state->loc.name, buf);
@@ -1390,7 +1529,16 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
inode_lookup (inode);
fd_ref (fd);
- if (fuse_reply_create (req, &e, &fi) == -ENOENT) {
+
+ fouh.error = 0;
+ iov_out[0].iov_base = &fouh;
+ iov_out[1].iov_base = &feo;
+ iov_out[1].iov_len = priv->proto_minor >= 9 ?
+ sizeof (feo) :
+ FUSE_COMPAT_ENTRY_OUT_SIZE;
+ iov_out[2].iov_base = &foo;
+ iov_out[2].iov_len = sizeof (foo);
+ if (send_fuse_iov (this, finh, iov_out, 3) == ENOENT) {
gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
"create(%s) got EINTR", state->loc.path);
inode_forget (inode, 1);
@@ -1401,9 +1549,9 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
fd_bind (fd);
} else {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRIu64": %s => -1 (%s)", req_callid (req),
+ "%"PRIu64": %s => -1 (%s)", finh->unique,
state->loc.path, strerror (op_errno));
- fuse_reply_err (req, op_errno);
+ send_fuse_err (this, finh, op_errno);
}
out:
free_state (state);
@@ -1414,75 +1562,84 @@ out:
static void
-fuse_create (fuse_req_t req, fuse_ino_t par, const char *name,
- mode_t mode, struct fuse_file_info *fi)
+fuse_create (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_create_in *fci = msg;
+ char *name = (char *)(fci + 1);
+
+ fuse_private_t *priv = NULL;
fuse_state_t *state = NULL;
fd_t *fd = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
- state->flags = fi->flags;
+ priv = this->private;
+ if (priv->proto_minor < 12)
+ name = (char *)((struct fuse_open_in *)msg + 1);
+
+ GET_STATE (this, finh, state);
+ state->flags = fci->flags;
- ret = fuse_loc_fill (&state->loc, state, 0, par, name);
+ ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
if (ret < 0) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64" CREATE %s (fuse_loc_fill() failed)",
- req_callid (req), state->loc.path);
- fuse_reply_err (req, ENOENT);
+ finh->unique, state->loc.path);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
state->loc.inode = inode_new (state->itable);
- fd = fd_create (state->loc.inode, get_pid_from_req (req));
+ fd = fd_create (state->loc.inode, finh->pid);
state->fd = fd;
fd->flags = state->flags;
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": CREATE %s", req_callid (req),
+ "%"PRIu64": CREATE %s", finh->unique,
state->loc.path);
FUSE_FOP (state, fuse_create_cbk, GF_FOP_CREATE,
- create, &state->loc, state->flags, mode, fd);
+ create, &state->loc, state->flags, fci->mode, fd);
return;
}
static void
-fuse_open (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
+fuse_open (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_open_in *foi = msg;
+
fuse_state_t *state = NULL;
fd_t *fd = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
- state->flags = fi->flags;
+ GET_STATE (this, finh, state);
+ state->flags = foi->flags;
- ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
+ ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64": OPEN %s (fuse_loc_fill() failed)",
- req_callid (req), state->loc.path);
+ finh->unique, state->loc.path);
- fuse_reply_err (req, ENOENT);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
- fd = fd_create (state->loc.inode, get_pid_from_req (req));
+ fd = fd_create (state->loc.inode, finh->pid);
state->fd = fd;
- fd->flags = fi->flags;
+ fd->flags = foi->flags;
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": OPEN %s", req_callid (req),
+ "%"PRIu64": OPEN %s", finh->unique,
state->loc.path);
FUSE_FOP (state, fuse_fd_cbk, GF_FOP_OPEN,
- open, &state->loc, fi->flags, fd);
+ open, &state->loc, foi->flags, fd);
return;
}
@@ -1495,28 +1652,34 @@ fuse_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
struct stat *stbuf, struct iobref *iobref)
{
fuse_state_t *state = NULL;
- fuse_req_t req = NULL;
+ fuse_in_header_t *finh = NULL;
+ struct fuse_out_header fouh = {0, };
+ struct iovec *iov_out = NULL;
state = frame->root->state;
- req = state->req;
+ finh = state->finh;
if (op_ret >= 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRId64": READ => %d/%"GF_PRI_SIZET",%"PRId64"/%"PRId64,
+ "%"PRIu64": READ => %d/%"GF_PRI_SIZET",%"PRId64"/%"PRId64,
frame->root->unique,
op_ret, state->size, state->off, stbuf->st_size);
-#ifdef HAVE_FUSE_REPLY_IOV
- fuse_reply_iov (req, vector, count);
-#else
- fuse_reply_vec (req, vector, count);
-#endif
+ iov_out = CALLOC (count + 1, sizeof (*iov_out));
+ if (iov_out) {
+ fouh.error = 0;
+ iov_out[0].iov_base = &fouh;
+ memcpy (iov_out + 1, vector, count * sizeof (*iov_out));
+ send_fuse_iov (this, finh, iov_out, count + 1);
+ FREE (iov_out);
+ } else
+ send_fuse_err (this, finh, ENOMEM);
} else {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRId64": READ => %d (%s)", frame->root->unique,
+ "%"PRIu64": READ => %d (%s)", frame->root->unique,
op_ret, strerror (op_errno));
- fuse_reply_err (req, op_errno);
+ send_fuse_err (this, finh, op_errno);
}
free_state (state);
@@ -1527,25 +1690,26 @@ fuse_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
static void
-fuse_readv (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
- struct fuse_file_info *fi)
+fuse_readv (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_read_in *fri = msg;
+
fuse_state_t *state = NULL;
fd_t *fd = NULL;
- STATE_FROM_REQ (req, state);
- state->size = size;
- state->off = off;
+ GET_STATE (this, finh, state);
+ state->size = fri->size;
+ state->off = fri->offset;
- fd = FI_TO_FD (fi);
+ fd = FH_TO_FD (fri->fh);
state->fd = fd;
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": READ (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")",
- req_callid (req), fd, size, off);
+ "%"PRIu64": READ (%p, size=%"PRIu32", offset=%"PRIu64")",
+ finh->unique, fd, fri->size, fri->offset);
FUSE_FOP (state, fuse_readv_cbk, GF_FOP_READ,
- readv, fd, size, off);
+ readv, fd, fri->size, fri->offset);
}
@@ -1556,24 +1720,26 @@ fuse_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
struct stat *stbuf)
{
fuse_state_t *state = NULL;
- fuse_req_t req = NULL;
+ fuse_in_header_t *finh = NULL;
+ struct fuse_write_out fwo = {0, };
state = frame->root->state;
- req = state->req;
+ finh = state->finh;
if (op_ret >= 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRId64": WRITE => %d/%"GF_PRI_SIZET",%"PRId64"/%"PRId64,
+ "%"PRIu64": WRITE => %d/%"GF_PRI_SIZET",%"PRId64"/%"PRId64,
frame->root->unique,
op_ret, state->size, state->off, stbuf->st_size);
- fuse_reply_write (req, op_ret);
+ fwo.size = op_ret;
+ send_fuse_obj (this, finh, &fwo);
} else {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRId64": WRITE => -1 (%s)", frame->root->unique,
+ "%"PRIu64": WRITE => -1 (%s)", frame->root->unique,
strerror (op_errno));
- fuse_reply_err (req, op_errno);
+ send_fuse_err (this, finh, op_errno);
}
free_state (state);
@@ -1584,33 +1750,40 @@ fuse_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
static void
-fuse_write (fuse_req_t req, fuse_ino_t ino, const char *buf,
- size_t size, off_t off,
- struct fuse_file_info *fi)
+fuse_write (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ /* WRITE is special, metadata is attached to in_header,
+ * and msg is the payload as-is.
+ */
+ struct fuse_write_in *fwi = (struct fuse_write_in *)
+ (finh + 1);
+
+ fuse_private_t *priv = NULL;
fuse_state_t *state = NULL;
struct iovec vector;
fd_t *fd = NULL;
struct iobref *iobref = NULL;
struct iobuf *iobuf = NULL;
- STATE_FROM_REQ (req, state);
- state->size = size;
- state->off = off;
- fd = FI_TO_FD (fi);
+ priv = this->private;
+
+ GET_STATE (this, finh, state);
+ state->size = fwi->size;
+ state->off = fwi->offset;
+ fd = FH_TO_FD (fwi->fh);
state->fd = fd;
- vector.iov_base = (void *)buf;
- vector.iov_len = size;
+ vector.iov_base = msg;
+ vector.iov_len = fwi->size;
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": WRITE (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")",
- req_callid (req), fd, size, off);
+ "%"PRIu64": WRITE (%p, size=%"PRIu32", offset=%"PRId64")",
+ finh->unique, fd, fwi->size, fwi->offset);
iobref = iobref_new ();
if (!iobref) {
- gf_log("glusterfs-fuse", GF_LOG_ERROR,
- "%"PRIu64": WRITE iobref allocation failed",
- req_callid (req));
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "%"PRIu64": WRITE iobref allocation failed",
+ finh->unique);
free_state (state);
return;
@@ -1619,7 +1792,7 @@ fuse_write (fuse_req_t req, fuse_ino_t ino, const char *buf,
iobref_add (iobref, iobuf);
FUSE_FOP (state, fuse_writev_cbk, GF_FOP_WRITE,
- writev, fd, &vector, 1, off, iobref);
+ writev, fd, &vector, 1, fwi->offset, iobref);
iobref_unref (iobref);
return;
@@ -1627,17 +1800,19 @@ fuse_write (fuse_req_t req, fuse_ino_t ino, const char *buf,
static void
-fuse_flush (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
+fuse_flush (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_flush_in *ffi = msg;
+
fuse_state_t *state = NULL;
fd_t *fd = NULL;
- STATE_FROM_REQ (req, state);
- fd = FI_TO_FD (fi);
+ GET_STATE (this, finh, state);
+ fd = FH_TO_FD (ffi->fh);
state->fd = fd;
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": FLUSH %p", req_callid (req), fd);
+ "%"PRIu64": FLUSH %p", finh->unique, fd);
FUSE_FOP (state, fuse_err_cbk, GF_FOP_FLUSH,
flush, fd);
@@ -1647,19 +1822,21 @@ fuse_flush (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
static void
-fuse_release (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
+fuse_release (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_release_in *fri = msg;
+
fuse_state_t *state = NULL;
- STATE_FROM_REQ (req, state);
- state->fd = FI_TO_FD (fi);
+ GET_STATE (this, finh, state);
+ state->fd = FH_TO_FD (fri->fh);
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": RELEASE %p", req_callid (req), state->fd);
+ "%"PRIu64": RELEASE %p", finh->unique, state->fd);
fd_unref (state->fd);
- fuse_reply_err (req, 0);
+ send_fuse_err (this, finh, 0);
free_state (state);
return;
@@ -1667,51 +1844,57 @@ fuse_release (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
static void
-fuse_fsync (fuse_req_t req, fuse_ino_t ino, int datasync,
- struct fuse_file_info *fi)
+fuse_fsync (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_fsync_in *fsi = msg;
+
fuse_state_t *state = NULL;
fd_t *fd = NULL;
- STATE_FROM_REQ (req, state);
- fd = FI_TO_FD (fi);
+ GET_STATE (this, finh, state);
+ fd = FH_TO_FD (fsi->fh);
state->fd = fd;
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": FSYNC %p", req_callid (req), fd);
+ "%"PRIu64": FSYNC %p", finh->unique, fd);
+ /* fsync_flags: 1 means "datasync" (no defines for this) */
FUSE_FOP (state, fuse_err_cbk, GF_FOP_FSYNC,
- fsync, fd, datasync);
+ fsync, fd, fsi->fsync_flags & 1);
return;
}
static void
-fuse_opendir (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
+fuse_opendir (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ /*
+ struct fuse_open_in *foi = msg;
+ */
+
fuse_state_t *state = NULL;
fd_t *fd = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
- ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
+ GET_STATE (this, finh, state);
+ ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64": OPENDIR %s (fuse_loc_fill() failed)",
- req_callid (req), state->loc.path);
+ finh->unique, state->loc.path);
- fuse_reply_err (req, ENOENT);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
- fd = fd_create (state->loc.inode, get_pid_from_req (req));
+ fd = fd_create (state->loc.inode, finh->pid);
state->fd = fd;
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": OPENDIR %s", req_callid (req),
+ "%"PRIu64": OPENDIR %s", finh->unique,
state->loc.path);
FUSE_FOP (state, fuse_fd_cbk, GF_FOP_OPENDIR,
@@ -1724,53 +1907,54 @@ fuse_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, gf_dirent_t *entries)
{
fuse_state_t *state = NULL;
- fuse_req_t req = NULL;
+ fuse_in_header_t *finh = NULL;
int size = 0;
- int entry_size = 0;
char *buf = NULL;
gf_dirent_t *entry = NULL;
- struct stat stbuf = {0, };
+ struct fuse_dirent *fde = NULL;
state = frame->root->state;
- req = state->req;
+ finh = state->finh;
if (op_ret < 0) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRId64": READDIR => -1 (%s)", frame->root->unique,
+ "%"PRIu64": READDIR => -1 (%s)", frame->root->unique,
strerror (op_errno));
- fuse_reply_err (req, op_errno);
+ send_fuse_err (this, finh, op_errno);
goto out;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRId64": READDIR => %d/%"GF_PRI_SIZET",%"PRId64,
+ "%"PRIu64": READDIR => %d/%"GF_PRI_SIZET",%"PRId64,
frame->root->unique, op_ret, state->size, state->off);
list_for_each_entry (entry, &entries->list, list) {
- size += fuse_dirent_size (strlen (entry->d_name));
+ size += FUSE_DIRENT_ALIGN (FUSE_NAME_OFFSET +
+ strlen (entry->d_name));
}
buf = CALLOC (1, size);
if (!buf) {
gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
- "%"PRId64": READDIR => -1 (%s)", frame->root->unique,
+ "%"PRIu64": READDIR => -1 (%s)", frame->root->unique,
strerror (ENOMEM));
- fuse_reply_err (req, ENOMEM);
+ send_fuse_err (this, finh, ENOMEM);
goto out;
}
size = 0;
list_for_each_entry (entry, &entries->list, list) {
- stbuf.st_ino = entry->d_ino;
- entry_size = fuse_dirent_size (strlen (entry->d_name));
- fuse_add_direntry (req, buf + size, entry_size,
- entry->d_name, &stbuf,
- entry->d_off);
- size += entry_size;
+ fde = (struct fuse_dirent *)(buf + size);
+ fde->ino = entry->d_ino;
+ fde->off = entry->d_off;
+ fde->type = entry->d_type;
+ fde->namelen = strlen (entry->d_name);
+ strncpy (fde->name, entry->d_name, fde->namelen);
+ size += FUSE_DIRENT_SIZE (fde);
}
- fuse_reply_buf (req, (void *)buf, size);
+ send_fuse_data (this, finh, buf, size);
out:
free_state (state);
@@ -1783,41 +1967,44 @@ out:
static void
-fuse_readdir (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
- struct fuse_file_info *fi)
+fuse_readdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_read_in *fri = msg;
+
fuse_state_t *state = NULL;
fd_t *fd = NULL;
- STATE_FROM_REQ (req, state);
- state->size = size;
- state->off = off;
- fd = FI_TO_FD (fi);
+ GET_STATE (this, finh, state);
+ state->size = fri->size;
+ state->off = fri->offset;
+ fd = FH_TO_FD (fri->fh);
state->fd = fd;
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": READDIR (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")",
- req_callid (req), fd, size, off);
+ "%"PRIu64": READDIR (%p, size=%"PRIu32", offset=%"PRId64")",
+ finh->unique, fd, fri->size, fri->offset);
FUSE_FOP (state, fuse_readdir_cbk, GF_FOP_READDIR,
- readdir, fd, size, off);
+ readdir, fd, fri->size, fri->offset);
}
static void
-fuse_releasedir (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
+fuse_releasedir (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_release_in *fri = msg;
+
fuse_state_t *state = NULL;
- STATE_FROM_REQ (req, state);
- state->fd = FI_TO_FD (fi);
+ GET_STATE (this, finh, state);
+ state->fd = FH_TO_FD (fri->fh);
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": RELEASEDIR %p", req_callid (req), state->fd);
+ "%"PRIu64": RELEASEDIR %p", finh->unique, state->fd);
fd_unref (state->fd);
- fuse_reply_err (req, 0);
+ send_fuse_err (this, finh, 0);
free_state (state);
@@ -1826,19 +2013,20 @@ fuse_releasedir (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
static void
-fuse_fsyncdir (fuse_req_t req, fuse_ino_t ino, int datasync,
- struct fuse_file_info *fi)
+fuse_fsyncdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_fsync_in *fsi = msg;
+
fuse_state_t *state = NULL;
fd_t *fd = NULL;
- fd = FI_TO_FD (fi);
+ fd = FH_TO_FD (fsi->fh);
- STATE_FROM_REQ (req, state);
+ GET_STATE (this, finh, state);
state->fd = fd;
FUSE_FOP (state, fuse_err_cbk, GF_FOP_FSYNCDIR,
- fsyncdir, fd, datasync);
+ fsyncdir, fd, fsi->fsync_flags & 1);
return;
}
@@ -1849,10 +2037,13 @@ fuse_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct statvfs *buf)
{
fuse_state_t *state = NULL;
- fuse_req_t req = NULL;
+ fuse_in_header_t *finh = NULL;
+ fuse_private_t *priv = NULL;
+ struct fuse_statfs_out fso = {{0, }, };
state = frame->root->state;
- req = state->req;
+ priv = this->private;
+ finh = state->finh;
/*
Filesystems (like ZFS on solaris) reports
different ->f_frsize and ->f_bsize. Old coreutils
@@ -1881,13 +2072,23 @@ fuse_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
buf->f_frsize = buf->f_bsize =this->ctx->page_size;
#endif /* GF_DARWIN_HOST_OS */
- fuse_reply_statfs (req, buf);
-
+ fso.st.bsize = buf->f_bsize;
+ fso.st.frsize = buf->f_frsize;
+ fso.st.blocks = buf->f_blocks;
+ fso.st.bfree = buf->f_bfree;
+ fso.st.bavail = buf->f_bavail;
+ fso.st.files = buf->f_files;
+ fso.st.ffree = buf->f_ffree;
+ fso.st.namelen = buf->f_namemax;
+
+ priv->proto_minor >= 4 ?
+ send_fuse_obj (this, finh, &fso) :
+ send_fuse_data (this, finh, &fso, FUSE_COMPAT_STATFS_SIZE);
} else {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRId64": ERR => -1 (%s)", frame->root->unique,
+ "%"PRIu64": ERR => -1 (%s)", frame->root->unique,
strerror (op_errno));
- fuse_reply_err (req, op_errno);
+ send_fuse_err (this, finh, op_errno);
}
free_state (state);
@@ -1898,26 +2099,26 @@ fuse_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
static void
-fuse_statfs (fuse_req_t req, fuse_ino_t ino)
+fuse_statfs (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
fuse_state_t *state = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
+ GET_STATE (this, finh, state);
ret = fuse_loc_fill (&state->loc, state, 1, 0, NULL);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64": STATFS (fuse_loc_fill() fail)",
- req_callid (req));
+ finh->unique);
- fuse_reply_err (req, ENOENT);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": STATFS", req_callid (req));
+ "%"PRIu64": STATFS", finh->unique);
FUSE_FOP (state, fuse_statfs_cbk, GF_FOP_STATFS,
statfs, &state->loc);
@@ -1925,77 +2126,84 @@ fuse_statfs (fuse_req_t req, fuse_ino_t ino)
static void
-fuse_setxattr (fuse_req_t req, fuse_ino_t ino, const char *name,
- const char *value, size_t size, int flags)
+fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_setxattr_in *fsi = msg;
+ char *name = (char *)(fsi + 1);
+ char *value = name + strlen (name) + 1;
+
fuse_state_t *state = NULL;
char *dict_value = NULL;
int32_t ret = -1;
#ifdef DISABLE_POSIX_ACL
if (!strncmp (name, "system.", 7)) {
- fuse_reply_err (req, EOPNOTSUPP);
+ send_fuse_err (this, finh, EOPNOTSUPP);
return;
}
#endif
- STATE_FROM_REQ (req, state);
- state->size = size;
- ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
+ GET_STATE (this, finh, state);
+ state->size = fsi->size;
+ ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRIu64": SETXATTR %s/%"PRId64" (%s) (fuse_loc_fill() failed)",
- req_callid (req),
- state->loc.path, (int64_t)ino, name);
+ "%"PRIu64": SETXATTR %s/%"PRIu64" (%s) (fuse_loc_fill() failed)",
+ finh->unique,
+ state->loc.path, finh->nodeid, name);
- fuse_reply_err (req, ENOENT);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
state->dict = get_new_dict ();
if (!state->dict) {
- gf_log("glusterfs-fuse", GF_LOG_ERROR,
- "%"PRIu64": SETXATTR dict allocation failed",
- req_callid (req));
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "%"PRIu64": SETXATTR dict allocation failed",
+ finh->unique);
free_state (state);
return;
}
- dict_value = memdup (value, size);
+ dict_value = memdup (value, fsi->size);
dict_set (state->dict, (char *)name,
- data_from_dynptr ((void *)dict_value, size));
+ data_from_dynptr ((void *)dict_value, fsi->size));
dict_ref (state->dict);
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": SETXATTR %s/%"PRId64" (%s)", req_callid (req),
- state->loc.path, (int64_t)ino, name);
+ "%"PRIu64": SETXATTR %s/%"PRIu64" (%s)", finh->unique,
+ state->loc.path, finh->nodeid, name);
FUSE_FOP (state, fuse_err_cbk, GF_FOP_SETXATTR,
- setxattr, &state->loc, state->dict, flags);
+ setxattr, &state->loc, state->dict, fsi->flags);
return;
}
static void
-fuse_reply_xattr_buf (fuse_state_t *state, fuse_req_t req, const char *value,
- size_t ret)
+send_fuse_xattr (xlator_t *this, fuse_in_header_t *finh, const char *value,
+ size_t size, size_t expected)
{
+ struct fuse_getxattr_out fgxo;
+
/* linux kernel limits the size of xattr value to 64k */
- if (ret > GLUSTERFS_XATTR_LEN_MAX)
- fuse_reply_err (req, E2BIG);
- else if (state->size) {
+ if (size > GLUSTERFS_XATTR_LEN_MAX)
+ send_fuse_err (this, finh, E2BIG);
+ else if (expected) {
/* if callback for getxattr and asks for value */
- if (ret > state->size)
+ if (size > expected)
/* reply would be bigger than
* what was asked by kernel */
- fuse_reply_err (req, ERANGE);
+ send_fuse_err (this, finh, ERANGE);
else
- fuse_reply_buf (req, value, ret);
- } else
- fuse_reply_xattr (req, ret);
+ send_fuse_data (this, finh, (void *)value, size);
+ } else {
+ fgxo.size = size;
+ send_fuse_obj (this, finh, &fgxo);
+ }
}
static int
@@ -2005,7 +2213,7 @@ fuse_xattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int need_to_free_dict = 0;
char *value = "";
fuse_state_t *state = NULL;
- fuse_req_t req = NULL;
+ fuse_in_header_t *finh = NULL;
int32_t dummy_ret = 0;
data_t *value_data = NULL;
fuse_private_t *priv = NULL;
@@ -2019,7 +2227,7 @@ fuse_xattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
priv = this->private;
ret = op_ret;
state = frame->root->state;
- req = state->req;
+ finh = state->finh;
dummy_ret = 0;
#ifdef GF_DARWIN_HOST_OS
@@ -2048,7 +2256,7 @@ fuse_xattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
if (ret >= 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRId64": %s() %s => %d", frame->root->unique,
+ "%"PRIu64": %s() %s => %d", frame->root->unique,
gf_fop_list[frame->root->op], state->loc.path, op_ret);
/* if successful */
@@ -2059,7 +2267,7 @@ fuse_xattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
ret = value_data->len; /* Don't return the value for '\0' */
value = value_data->data;
- fuse_reply_xattr_buf (state, req, value, ret);
+ send_fuse_xattr (this, finh, value, ret, state->size);
/* if(ret >...)...else if...else */
} else if (!strcmp (state->name, "user.glusterfs-booster-volfile")) {
if (!priv->volfile) {
@@ -2070,7 +2278,7 @@ fuse_xattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
gf_log (this->name,
GF_LOG_ERROR,
"fstat on fd (%d) failed (%s)", fd, strerror (errno));
- fuse_reply_err (req, ENODATA);
+ send_fuse_err (this, finh, ENODATA);
}
priv->volfile_size = st.st_size;
@@ -2081,16 +2289,17 @@ fuse_xattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
}
}
- fuse_reply_xattr_buf (state, req, priv->volfile, priv->volfile_size);
+ send_fuse_xattr (this, finh, priv->volfile,
+ priv->volfile_size, state->size);
/* if(ret >...)...else if...else */
} else if (!strcmp (state->name, "user.glusterfs-booster-path")) {
- fuse_reply_xattr_buf (state, req, state->loc.path,
- strlen (state->loc.path) + 1);
+ send_fuse_xattr (this, finh, state->loc.path,
+ strlen (state->loc.path) + 1, state->size);
} else if (!strcmp (state->name, "user.glusterfs-booster-mount")) {
- fuse_reply_xattr_buf (state, req, priv->mount_point,
- strlen(priv->mount_point) + 1);
+ send_fuse_xattr (this, finh, priv->mount_point,
+ strlen (priv->mount_point) + 1, state->size);
} else {
- fuse_reply_err (req, ENODATA);
+ send_fuse_err (this, finh, ENODATA);
} /* if(value_data)...else */
} else {
/* if callback for listxattr */
@@ -2109,7 +2318,7 @@ fuse_xattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
len += strlen (trav->key) + 1;
trav = trav->next;
} /* while(trav) */
- fuse_reply_xattr_buf (state, req, value, len);
+ send_fuse_xattr (this, finh, value, len, state->size);
} /* if(state->name)...else */
} else {
/* if failure - no need to check if listxattr or getxattr */
@@ -2126,20 +2335,20 @@ fuse_xattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
else
{
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRId64": %s() %s => -1 (%s)",
+ "%"PRIu64": %s() %s => -1 (%s)",
frame->root->unique,
gf_fop_list[frame->root->op],
state->loc.path, strerror (op_errno));
}
} else {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRId64": %s() %s => -1 (%s)",
+ "%"PRIu64": %s() %s => -1 (%s)",
frame->root->unique,
gf_fop_list[frame->root->op], state->loc.path,
strerror (op_errno));
} /* if(op_errno!= ENODATA)...else */
- fuse_reply_err (req, op_errno);
+ send_fuse_err (this, finh, op_errno);
} /* if(op_ret>=0)...else */
if (need_to_free_dict)
@@ -2153,37 +2362,40 @@ fuse_xattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
static void
-fuse_getxattr (fuse_req_t req, fuse_ino_t ino, const char *name, size_t size)
+fuse_getxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_getxattr_in *fgxi = msg;
+ char *name = (char *)(msg + 1);
+
fuse_state_t *state = NULL;
int32_t ret = -1;
#ifdef DISABLE_POSIX_ACL
if (!strncmp (name, "system.", 7)) {
- fuse_reply_err (req, ENODATA);
+ send_fuse_err (this, finh, ENODATA);
return;
}
#endif
- STATE_FROM_REQ (req, state);
- state->size = size;
+ GET_STATE (this, finh, state);
+ state->size = fgxi->size;
state->name = strdup (name);
- ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
+ ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRIu64": GETXATTR %s/%"PRId64" (%s) (fuse_loc_fill() failed)",
- req_callid (req), state->loc.path, (int64_t)ino, name);
+ "%"PRIu64": GETXATTR %s/%"PRIu64" (%s) (fuse_loc_fill() failed)",
+ finh->unique, state->loc.path, finh->nodeid, name);
- fuse_reply_err (req, ENOENT);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": GETXATTR %s/%"PRId64" (%s)", req_callid (req),
- state->loc.path, (int64_t)ino, name);
+ "%"PRIu64": GETXATTR %s/%"PRIu64" (%s)", finh->unique,
+ state->loc.path, finh->nodeid, name);
FUSE_FOP (state, fuse_xattr_cbk, GF_FOP_GETXATTR,
getxattr, &state->loc, name);
@@ -2193,28 +2405,30 @@ fuse_getxattr (fuse_req_t req, fuse_ino_t ino, const char *name, size_t size)
static void
-fuse_listxattr (fuse_req_t req, fuse_ino_t ino, size_t size)
+fuse_listxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_getxattr_in *fgxi = msg;
+
fuse_state_t *state = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
- state->size = size;
- ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
+ GET_STATE (this, finh, state);
+ state->size = fgxi->size;
+ ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRIu64": LISTXATTR %s/%"PRId64" (fuse_loc_fill() failed)",
- req_callid (req), state->loc.path, (int64_t)ino);
+ "%"PRIu64": LISTXATTR %s/%"PRIu64" (fuse_loc_fill() failed)",
+ finh->unique, state->loc.path, finh->nodeid);
- fuse_reply_err (req, ENOENT);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": LISTXATTR %s/%"PRId64, req_callid (req),
- state->loc.path, (int64_t)ino);
+ "%"PRIu64": LISTXATTR %s/%"PRIu64, finh->unique,
+ state->loc.path, finh->nodeid);
FUSE_FOP (state, fuse_xattr_cbk, GF_FOP_GETXATTR,
getxattr, &state->loc, NULL);
@@ -2224,28 +2438,30 @@ fuse_listxattr (fuse_req_t req, fuse_ino_t ino, size_t size)
static void
-fuse_removexattr (fuse_req_t req, fuse_ino_t ino, const char *name)
+fuse_removexattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ char *name = msg;
+
fuse_state_t *state = NULL;
int32_t ret = -1;
- STATE_FROM_REQ (req, state);
- ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
+ GET_STATE (this, finh, state);
+ ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
if ((state->loc.inode == NULL) ||
(ret < 0)) {
gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
- "%"PRIu64": REMOVEXATTR %s/%"PRId64" (%s) (fuse_loc_fill() failed)",
- req_callid (req), state->loc.path, (int64_t)ino, name);
+ "%"PRIu64": REMOVEXATTR %s/%"PRIu64" (%s) (fuse_loc_fill() failed)",
+ finh->unique, state->loc.path, finh->nodeid, name);
- fuse_reply_err (req, ENOENT);
+ send_fuse_err (this, finh, ENOENT);
free_state (state);
return;
}
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": REMOVEXATTR %s/%"PRId64" (%s)", req_callid (req),
- state->loc.path, (int64_t)ino, name);
+ "%"PRIu64": REMOVEXATTR %s/%"PRIu64" (%s)", finh->unique,
+ state->loc.path, finh->nodeid, name);
FUSE_FOP (state, fuse_err_cbk, GF_FOP_REMOVEXATTR,
removexattr, &state->loc, name);
@@ -2263,11 +2479,22 @@ fuse_getlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
fuse_state_t *state = NULL;
state = frame->root->state;
+ struct fuse_lk_out flo = {{0, }, };
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRId64": ERR => 0", frame->root->unique);
- fuse_reply_lock (state->req, lock);
+ "%"PRIu64": ERR => 0", frame->root->unique);
+ flo.lk.type = lock->l_type;
+ flo.lk.pid = lock->l_pid;
+ if (lock->l_type == F_UNLCK)
+ flo.lk.start = flo.lk.end = 0;
+ else {
+ flo.lk.start = lock->l_start;
+ flo.lk.end = lock->l_len ?
+ (lock->l_start + lock->l_len - 1) :
+ OFFSET_MAX;
+ }
+ send_fuse_obj (this, state->finh, &flo);
} else {
if (op_errno == ENOSYS) {
gf_fuse_lk_enosys_log++;
@@ -2279,10 +2506,10 @@ fuse_getlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
}
} else {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "%"PRId64": ERR => -1 (%s)",
+ "%"PRIu64": ERR => -1 (%s)",
frame->root->unique, strerror (op_errno));
}
- fuse_reply_err (state->req, op_errno);
+ send_fuse_err (this, state->finh, op_errno);
}
free_state (state);
@@ -2293,22 +2520,24 @@ fuse_getlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
static void
-fuse_getlk (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi,
- struct flock *lock)
+fuse_getlk (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_lk_in *fli = msg;
+
fuse_state_t *state = NULL;
fd_t *fd = NULL;
+ struct flock lock = {0, };
- fd = FI_TO_FD (fi);
- STATE_FROM_REQ (req, state);
- state->req = req;
+ fd = FH_TO_FD (fli->fh);
+ GET_STATE (this, finh, state);
state->fd = fd;
+ convert_fuse_file_lock (&fli->lk, &lock);
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": GETLK %p", req_callid (req), fd);
+ "%"PRIu64": GETLK %p", finh->unique, fd);
FUSE_FOP (state, fuse_getlk_cbk, GF_FOP_LK,
- lk, fd, F_GETLK, lock);
+ lk, fd, F_GETLK, &lock);
return;
}
@@ -2324,8 +2553,8 @@ fuse_setlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRId64": ERR => 0", frame->root->unique);
- fuse_reply_err (state->req, 0);
+ "%"PRIu64": ERR => 0", frame->root->unique);
+ send_fuse_err (this, state->finh, 0);
} else {
if (op_errno == ENOSYS) {
gf_fuse_lk_enosys_log++;
@@ -2335,13 +2564,13 @@ fuse_setlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
"'features/posix-locks' on server side "
"will add SETLK support.");
}
- } else if (op_errno != EAGAIN) {
- gf_log ("glusterfs-fuse", GF_LOG_ERROR,
- "%"PRId64": ERR => -1 (%s)",
+ } else {
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING,
+ "%"PRIu64": ERR => -1 (%s)",
frame->root->unique, strerror (op_errno));
}
- fuse_reply_err (state->req, op_errno);
+ send_fuse_err (this, state->finh, op_errno);
}
free_state (state);
@@ -2352,77 +2581,111 @@ fuse_setlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
static void
-fuse_setlk (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi,
- struct flock *lock, int sleep)
+fuse_setlk (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ struct fuse_lk_in *fli = msg;
+
fuse_state_t *state = NULL;
fd_t *fd = NULL;
+ struct flock lock = {0, };
- fd = FI_TO_FD (fi);
- STATE_FROM_REQ (req, state);
- state->req = req;
+ fd = FH_TO_FD (fli->fh);
+ GET_STATE (this, finh, state);
+ state->finh = finh;
state->fd = fd;
+ convert_fuse_file_lock (&fli->lk, &lock);
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": SETLK %p (sleep=%d)", req_callid (req), fd,
- sleep);
+ "%"PRIu64": SETLK%s %p", finh->unique,
+ finh->opcode == FUSE_SETLK ? "" : "W", fd);
FUSE_FOP (state, fuse_setlk_cbk, GF_FOP_LK,
- lk, fd, (sleep ? F_SETLKW : F_SETLK), lock);
+ lk, fd, finh->opcode == FUSE_SETLK ? F_SETLK : F_SETLKW,
+ &lock);
return;
}
static void
-fuse_init (void *data, struct fuse_conn_info *conn)
+fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
- return;
+ struct fuse_init_in *fini = msg;
+
+ struct fuse_init_out fino;
+ fuse_private_t *priv = NULL;
+ int ret;
+
+ priv = this->private;
+
+ if (!priv->first_call) {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "got INIT after first message");
+
+ close (priv->fd);
+ goto out;
+ }
+
+ if (fini->major != FUSE_KERNEL_VERSION) {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "unsupported FUSE protocol version %d.%d",
+ fini->major, fini->minor);
+
+ close (priv->fd);
+ goto out;
+ }
+ priv->proto_minor = fini->minor;
+
+ fino.major = FUSE_KERNEL_VERSION;
+ fino.minor = FUSE_KERNEL_MINOR_VERSION;
+ fino.max_readahead = 1 << 17;
+ fino.max_write = 1 << 17;
+ fino.flags = FUSE_ASYNC_READ | FUSE_POSIX_LOCKS;
+ if (fini->minor >= 6 /* fuse_init_in has flags */ &&
+ fini->flags & FUSE_BIG_WRITES) {
+ /* no need for direct I/O mode if big writes are supported */
+ priv->direct_io_mode = 0;
+ fino.flags |= FUSE_BIG_WRITES;
+ }
+ if (fini->minor < 9)
+ *priv->msg0_len_p = sizeof(*finh) + FUSE_COMPAT_WRITE_IN_SIZE;
+
+ ret = send_fuse_obj (this, finh, &fino);
+ if (ret == 0)
+ gf_log ("glusterfs-fuse", GF_LOG_INFO,
+ "FUSE inited with protocol versions:"
+ " glusterfs %d.%d kernel %d.%d",
+ FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION,
+ fini->major, fini->minor);
+ else {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "FUSE init failed (%s)", strerror (ret));
+
+ close (priv->fd);
+ }
+
+ out:
+ FREE (finh);
}
+
static void
-fuse_destroy (void *data)
-{
-
-}
-
-static struct fuse_lowlevel_ops fuse_ops = {
- .init = fuse_init,
- .destroy = fuse_destroy,
- .lookup = fuse_lookup,
- .forget = fuse_forget,
- .getattr = fuse_getattr,
- .setattr = fuse_setattr,
- .opendir = fuse_opendir,
- .readdir = fuse_readdir,
- .releasedir = fuse_releasedir,
- .access = fuse_access,
- .readlink = fuse_readlink,
- .mknod = fuse_mknod,
- .mkdir = fuse_mkdir,
- .unlink = fuse_unlink,
- .rmdir = fuse_rmdir,
- .symlink = fuse_symlink,
- .rename = fuse_rename,
- .link = fuse_link,
- .create = fuse_create,
- .open = fuse_open,
- .read = fuse_readv,
- .write = fuse_write,
- .flush = fuse_flush,
- .release = fuse_release,
- .fsync = fuse_fsync,
- .fsyncdir = fuse_fsyncdir,
- .statfs = fuse_statfs,
- .setxattr = fuse_setxattr,
- .getxattr = fuse_getxattr,
- .listxattr = fuse_listxattr,
- .removexattr = fuse_removexattr,
- .getlk = fuse_getlk,
- .setlk = fuse_setlk
-};
+fuse_enosys (xlator_t *this, fuse_in_header_t *finh, void *msg)
+{
+ send_fuse_err (this, finh, ENOSYS);
+
+ FREE (finh);
+}
+static void
+fuse_discard (xlator_t *this, fuse_in_header_t *finh, void *msg)
+{
+ FREE (finh);
+}
+
+static fuse_handler_t *fuse_ops[FUSE_712_OP_HIGH];
+
int
fuse_root_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
@@ -2493,33 +2756,54 @@ fuse_root_lookup (xlator_t *this)
}
+
static void *
fuse_thread_proc (void *data)
{
char *mount_point = NULL;
xlator_t *this = NULL;
fuse_private_t *priv = NULL;
- int32_t res = 0;
+ ssize_t res = 0;
struct iobuf *iobuf = NULL;
- size_t chan_size = 0;
+ fuse_in_header_t *finh;
+ struct iovec iov_in[2];
+ void *msg = NULL;
+ const size_t msg0_size = sizeof (*finh) + 128;
this = data;
priv = this->private;
- chan_size = fuse_chan_bufsize (priv->ch);
THIS = this;
- while (!fuse_session_exited (priv->se)) {
+ iov_in[0].iov_len = sizeof (*finh) + sizeof (struct fuse_write_in);
+ iov_in[1].iov_len = ((struct iobuf_pool *)this->ctx->iobuf_pool)
+ ->page_size;
+ priv->msg0_len_p = &iov_in[0].iov_len;
+
+ for (;;) {
iobuf = iobuf_get (this->ctx->iobuf_pool);
+ /* Add extra 128 byte to the first iov so that it can
+ * accomodate "ordinary" non-write requests. It's not
+ * guaranteed to be big enough, as SETXATTR and namespace
+ * operations with very long names may grow behind it,
+ * but it's good enough in most cases (and we can handle
+ * rest via realloc).
+ */
+ iov_in[0].iov_base = CALLOC (1, msg0_size);
- if (!iobuf) {
+ if (!iobuf || !iov_in[0].iov_base) {
gf_log (this->name, GF_LOG_ERROR,
"Out of memory");
+ if (iobuf)
+ iobuf_unref (iobuf);
+ FREE (iov_in[0].iov_base);
sleep (10);
continue;
}
- res = fuse_chan_receive (priv->ch, iobuf->ptr, chan_size);
+ iov_in[1].iov_base = iobuf->ptr;
+
+ res = readv (priv->fd, iov_in, 2);
if (priv->first_call) {
if (priv->first_call > 1) {
@@ -2530,27 +2814,73 @@ fuse_thread_proc (void *data)
}
if (res == -1) {
+ if (errno == ENODEV || errno == EBADF) {
+ gf_log ("glusterfs-fuse", GF_LOG_NORMAL,
+ "terminating upon getting %s when "
+ "reading /dev/fuse",
+ errno == ENODEV ? "ENODEV" : "EBADF");
+
+ break;
+ }
if (errno != EINTR) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "fuse_chan_receive() returned -1 (%d)", errno);
- }
- if (errno == ENODEV) {
- iobuf_unref (iobuf);
- break;
+ "read from /dev/fuse returned -1 (%s)",
+ strerror (errno));
}
- continue;
+
+ goto cont_err;
+ }
+ if (res < sizeof (finh)) {
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING, "short read on /dev/fuse");
+ break;
+ }
+
+ finh = (fuse_in_header_t *)iov_in[0].iov_base;
+ if (res != finh->len) {
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING, "inconsistent read on /dev/fuse");
+ break;
}
priv->iobuf = iobuf;
- if (res && res != -1) {
- fuse_session_process (priv->se, iobuf->ptr,
- res, priv->ch);
+ if (finh->opcode == FUSE_WRITE)
+ msg = iov_in[1].iov_base;
+ else {
+ if (res > msg0_size) {
+ iov_in[0].iov_base =
+ realloc (iov_in[0].iov_base, res);
+ if (iov_in[0].iov_base)
+ finh = (fuse_in_header_t *)
+ iov_in[0].iov_base;
+ else {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "Out of memory");
+ send_fuse_err (this, finh, ENOMEM);
+
+ goto cont_err;
+ }
+ }
+
+ if (res > iov_in[0].iov_len)
+ memcpy (iov_in[0].iov_base + iov_in[0].iov_len,
+ iov_in[1].iov_base,
+ res - iov_in[0].iov_len);
+
+ msg = finh + 1;
}
+ fuse_ops[finh->opcode] (this, finh, msg);
iobuf_unref (iobuf);
+ continue;
+
+ cont_err:
+ iobuf_unref (iobuf);
+ FREE (iov_in[0].iov_base);
}
+ iobuf_unref (iobuf);
+ FREE (iov_in[0].iov_base);
+
if (dict_get (this->options, ZR_MOUNTPOINT_OPT))
mount_point = data_to_str (dict_get (this->options,
ZR_MOUNTPOINT_OPT));
@@ -2560,10 +2890,6 @@ fuse_thread_proc (void *data)
dict_del (this->options, ZR_MOUNTPOINT_OPT);
}
- fuse_session_remove_chan (priv->ch);
- fuse_session_destroy (priv->se);
- // fuse_unmount (priv->mount_point, priv->ch);
-
raise (SIGTERM);
return NULL;
@@ -2628,18 +2954,6 @@ notify (xlator_t *this, int32_t event, void *data, ...)
return 0;
}
-static struct fuse_opt subtype_workaround[] = {
- FUSE_OPT_KEY ("subtype=", 0),
- FUSE_OPT_KEY ("fssubtype=", 0),
- FUSE_OPT_END
-};
-
-static int
-subtype_workaround_optproc (void *data, const char *arg, int key,
- struct fuse_args *outargs)
-{
- return key ? 1 : 0;
-}
int
init (xlator_t *this_xl)
@@ -2648,10 +2962,9 @@ init (xlator_t *this_xl)
dict_t *options = NULL;
char *value_string = NULL;
char *fsname = NULL;
- char *fsname_opt = NULL;
fuse_private_t *priv = NULL;
struct stat stbuf = {0,};
- struct fuse_args args = FUSE_ARGS_INIT (0, NULL);
+ int i = 0;
int xl_name_allocated = 0;
if (this_xl == NULL)
@@ -2665,78 +2978,24 @@ init (xlator_t *this_xl)
if (this_xl->name == NULL) {
this_xl->name = strdup ("fuse");
if (!this_xl->name) {
- gf_log("glusterfs-fuse", GF_LOG_ERROR,
- "Out of memory");
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "Out of memory");
goto cleanup_exit;
}
xl_name_allocated = 1;
}
- fsname = this_xl->ctx->cmd_args.volume_file;
- fsname = (fsname ? fsname : this_xl->ctx->cmd_args.volfile_server);
- fsname = (fsname ? fsname : "glusterfs");
- ret = asprintf (&fsname_opt, "-ofsname=%s", fsname);
-
- if (ret != -1)
- ret = fuse_opt_add_arg (&args, "glusterfs");
- if (ret != -1)
- ret = fuse_opt_add_arg (&args, fsname_opt);
- if (ret != -1)
- ret = fuse_opt_add_arg (&args, "-oallow_other");
- if (ret != -1)
- ret = fuse_opt_add_arg (&args, "-odefault_permissions");
-#ifdef GF_DARWIN_HOST_OS
- if (ret != -1)
- ret = fuse_opt_add_arg (&args, "-ofssubtype=glusterfs");
- if (ret != -1 && !dict_get (options, "macfuse-local"))
- /* This way, GlusterFS will be detected as 'servers' instead
- * of 'devices'. This method is useful if you want to do
- * 'umount <mount_point>' over network, instead of 'eject'ing
- * it from desktop. Works better for servers
- */
- ret = fuse_opt_add_arg (&args, "-olocal");
-#else /* ! DARWIN_OS */
- if (ret != -1)
- ret = fuse_opt_add_arg (&args, "-osubtype=glusterfs");
- if (ret != -1)
- ret = fuse_opt_add_arg (&args, "-omax_readahead=131072");
- if (ret != -1)
- ret = fuse_opt_add_arg (&args, "-omax_read=131072");
- if (ret != -1)
- ret = fuse_opt_add_arg (&args, "-omax_write=131072");
- if (ret != -1)
- ret = fuse_opt_add_arg (&args, "-osuid");
-#if GF_LINUX_HOST_OS /* LINUX */
- /* '-o dev', '-o nonempty' is supported only on Linux */
- if (ret != -1)
- ret = fuse_opt_add_arg (&args, "-ononempty");
- if (ret != -1)
- ret = fuse_opt_add_arg (&args, "-odev");
-#ifdef HAVE_FUSE_VERSION_28
- if (ret != -1)
- ret = fuse_opt_add_arg (&args, "-obig_writes");
-#endif /* FUSE 2.8 */
-
-#endif /* LINUX */
-#endif /* ! DARWIN_OS */
-
- if (ret == -1) {
- gf_log("glusterfs-fuse", GF_LOG_ERROR,
- "Out of memory");
-
- goto cleanup_exit;
- }
-
priv = CALLOC (1, sizeof (*priv));
if (!priv) {
- gf_log("glusterfs-fuse", GF_LOG_ERROR,
- "Out of memory");
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "Out of memory");
goto cleanup_exit;
}
this_xl->private = (void *) priv;
priv->mount_point = NULL;
+ priv->fd = -1;
/* get options from option dictionary */
ret = dict_get_str (options, ZR_MOUNTPOINT_OPT, &value_string);
@@ -2773,8 +3032,8 @@ init (xlator_t *this_xl)
}
priv->mount_point = strdup (value_string);
if (!priv->mount_point) {
- gf_log("glusterfs-fuse", GF_LOG_ERROR,
- "Out of memory");
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "Out of memory");
goto cleanup_exit;
}
@@ -2803,102 +3062,74 @@ init (xlator_t *this_xl)
&priv->strict_volfile_check);
}
+ fsname = this_xl->ctx->cmd_args.volume_file;
+ fsname = (fsname ? fsname : this_xl->ctx->cmd_args.volfile_server);
+ fsname = (fsname ? fsname : "glusterfs");
+
this_xl->itable = inode_table_new (0, this_xl);
if (!this_xl->itable) {
- gf_log("glusterfs-fuse", GF_LOG_ERROR,
- "Out of memory");
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "Out of memory");
goto cleanup_exit;
}
- priv->ch = fuse_mount (priv->mount_point, &args);
- if (priv->ch == NULL) {
- if (errno == ENOTCONN) {
- gf_log ("glusterfs-fuse", GF_LOG_ERROR,
- "A stale mount is present on %s. "
- "Run 'umount %s' and try again",
- priv->mount_point,
- priv->mount_point);
- } else {
- if (errno == ENOENT) {
- gf_log ("glusterfs-fuse", GF_LOG_ERROR,
- "Unable to mount on %s. Run "
- "'modprobe fuse' and try again",
- priv->mount_point);
- } else {
- gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
- "fuse_mount() failed with error %s "
- "on mount point %s",
- strerror (errno),
- priv->mount_point);
- }
- }
-
+ priv->fd = gf_fuse_mount (priv->mount_point, fsname,
+ "allow_other,default_permissions,"
+ "max_read=131072");
+ if (priv->fd == -1)
goto cleanup_exit;
- }
-
- errno = 0;
-
- priv->se = fuse_lowlevel_new (&args, &fuse_ops,
- sizeof (fuse_ops), this_xl);
- if (priv->se == NULL && !errno) {
- /*
- * Option parsing misery. Can happen if libfuse is of
- * FUSE < 2.7.0, as then the "-o subtype" option is not
- * handled.
- *
- * Best we can do to is to handle it at runtime -- this is not
- * a binary incompatibility issue (which should dealt with at
- * compile time), but a behavioural incompatibility issue. Ie.
- * we can't tell in advance whether the lib we use supports
- * "-o subtype". So try to be clever now.
- *
- * Delete the subtype option, and try again.
- */
- if (fuse_opt_parse (&args, NULL, subtype_workaround,
- subtype_workaround_optproc) == 0)
- priv->se = fuse_lowlevel_new (&args, &fuse_ops,
- sizeof (fuse_ops),
- this_xl);
- }
-
- if (priv->se == NULL) {
- gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
- "fuse_lowlevel_new() failed with error %s on "
- "mount point %s",
- strerror (errno), priv->mount_point);
- goto umount_exit;
- }
-
- ret = fuse_set_signal_handlers (priv->se);
- if (ret == -1) {
- gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
- "fuse_set_signal_handlers() failed on mount point %s",
- priv->mount_point);
- goto umount_exit;
- }
-
- fuse_opt_free_args (&args);
- FREE (fsname_opt);
-
- fuse_session_add_chan (priv->se, priv->ch);
-
- priv->fd = fuse_chan_fd (priv->ch);
this_xl->ctx->top = this_xl;
priv->first_call = 2;
+
+ for (i = 0; i < FUSE_712_OP_HIGH; i++)
+ fuse_ops[i] = fuse_enosys;
+ fuse_ops[FUSE_INIT] = fuse_init;
+ fuse_ops[FUSE_DESTROY] = fuse_discard;
+ fuse_ops[FUSE_LOOKUP] = fuse_lookup;
+ fuse_ops[FUSE_FORGET] = fuse_forget;
+ fuse_ops[FUSE_GETATTR] = fuse_getattr;
+ fuse_ops[FUSE_SETATTR] = fuse_setattr;
+ fuse_ops[FUSE_OPENDIR] = fuse_opendir;
+ fuse_ops[FUSE_READDIR] = fuse_readdir;
+ fuse_ops[FUSE_RELEASEDIR] = fuse_releasedir;
+ fuse_ops[FUSE_ACCESS] = fuse_access;
+ fuse_ops[FUSE_READLINK] = fuse_readlink;
+ fuse_ops[FUSE_MKNOD] = fuse_mknod;
+ fuse_ops[FUSE_MKDIR] = fuse_mkdir;
+ fuse_ops[FUSE_UNLINK] = fuse_unlink;
+ fuse_ops[FUSE_RMDIR] = fuse_rmdir;
+ fuse_ops[FUSE_SYMLINK] = fuse_symlink;
+ fuse_ops[FUSE_RENAME] = fuse_rename;
+ fuse_ops[FUSE_LINK] = fuse_link;
+ fuse_ops[FUSE_CREATE] = fuse_create;
+ fuse_ops[FUSE_OPEN] = fuse_open;
+ fuse_ops[FUSE_READ] = fuse_readv;
+ fuse_ops[FUSE_WRITE] = fuse_write;
+ fuse_ops[FUSE_FLUSH] = fuse_flush;
+ fuse_ops[FUSE_RELEASE] = fuse_release;
+ fuse_ops[FUSE_FSYNC] = fuse_fsync;
+ fuse_ops[FUSE_FSYNCDIR] = fuse_fsyncdir;
+ fuse_ops[FUSE_STATFS] = fuse_statfs;
+ fuse_ops[FUSE_SETXATTR] = fuse_setxattr;
+ fuse_ops[FUSE_GETXATTR] = fuse_getxattr;
+ fuse_ops[FUSE_LISTXATTR] = fuse_listxattr;
+ fuse_ops[FUSE_REMOVEXATTR] = fuse_removexattr;
+ fuse_ops[FUSE_GETLK] = fuse_getlk;
+ fuse_ops[FUSE_SETLK] = fuse_setlk;
+ fuse_ops[FUSE_SETLKW] = fuse_setlk;
+
return 0;
-umount_exit:
- fuse_unmount (priv->mount_point, priv->ch);
cleanup_exit:
if (xl_name_allocated)
FREE (this_xl->name);
- fuse_opt_free_args (&args);
- FREE (fsname_opt);
- if (priv)
+ if (priv) {
FREE (priv->mount_point);
+ close (priv->fd);
+ }
FREE (priv);
return -1;
}
@@ -2924,8 +3155,7 @@ fini (xlator_t *this_xl)
"Unmounting '%s'.", mount_point);
dict_del (this_xl->options, ZR_MOUNTPOINT_OPT);
- fuse_session_exit (priv->se);
- fuse_unmount (mount_point, priv->ch);
+ gf_fuse_unmount (mount_point, priv->fd);
}
}
diff --git a/xlators/mount/fuse/src/fuse-extra.c b/xlators/mount/fuse/src/fuse-extra.c
deleted file mode 100644
index 422ff4b56..000000000
--- a/xlators/mount/fuse/src/fuse-extra.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com>
- This file is part of GlusterFS.
-
- GlusterFS 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.
-
- GlusterFS 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/>.
-*/
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-#include "config.h"
-#endif /* _CONFIG_H */
-
-#include "fuse-extra.h"
-#include "common-utils.h"
-#include <stdio.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-#include "common-utils.h"
-
-struct fuse_req;
-struct fuse_ll;
-
-struct fuse_req {
- struct fuse_ll *f;
- uint64_t unique;
- int ctr;
- pthread_mutex_t lock;
- struct fuse_ctx ctx;
- struct fuse_chan *ch;
- int interrupted;
- union {
- struct {
- uint64_t unique;
- } i;
- struct {
- fuse_interrupt_func_t func;
- void *data;
- } ni;
- } u;
- struct fuse_req *next;
- struct fuse_req *prev;
-};
-
-#ifdef HAVE_FUSE_VERSION_28
-struct fuse_ll {
- int debug;
- int allow_root;
- int atomic_o_trunc;
- int big_writes;
- struct fuse_lowlevel_ops op;
- int got_init;
- void *userdata;
- uid_t owner;
- struct fuse_conn_info conn;
- struct fuse_req list;
- struct fuse_req interrupts;
- pthread_mutex_t lock;
- int got_destroy;
-};
-#else
-struct fuse_ll {
- int debug;
- int allow_root;
- struct fuse_lowlevel_ops op;
- int got_init;
- void *userdata;
- uid_t owner;
- struct fuse_conn_info conn;
- struct fuse_req list;
- struct fuse_req interrupts;
- pthread_mutex_t lock;
- int got_destroy;
-};
-#endif /* FUSE 2.8 */
-
-struct fuse_out_header {
- uint32_t len;
- int32_t error;
- uint64_t unique;
-};
-
-uint64_t req_callid (fuse_req_t req)
-{
- return req->unique;
-}
-
-static void destroy_req(fuse_req_t req)
-{
- pthread_mutex_destroy (&req->lock);
- FREE (req);
-}
-
-static void list_del_req(struct fuse_req *req)
-{
- struct fuse_req *prev = req->prev;
- struct fuse_req *next = req->next;
- prev->next = next;
- next->prev = prev;
-}
-
-static void
-free_req (fuse_req_t req)
-{
- int ctr;
- struct fuse_ll *f = req->f;
-
- pthread_mutex_lock(&req->lock);
- req->u.ni.func = NULL;
- req->u.ni.data = NULL;
- pthread_mutex_unlock(&req->lock);
-
- pthread_mutex_lock(&f->lock);
- list_del_req(req);
- ctr = --req->ctr;
- pthread_mutex_unlock(&f->lock);
- if (!ctr)
- destroy_req(req);
-}
-
-int32_t
-fuse_reply_vec (fuse_req_t req,
- struct iovec *vector,
- int32_t count)
-{
- int32_t error = 0;
- struct fuse_out_header out;
- struct iovec *iov;
- int res;
-
- iov = alloca ((count + 1) * sizeof (*vector));
- out.unique = req->unique;
- out.error = error;
- iov[0].iov_base = &out;
- iov[0].iov_len = sizeof(struct fuse_out_header);
- memcpy (&iov[1], vector, count * sizeof (*vector));
- count++;
- out.len = iov_length(iov, count);
- res = fuse_chan_send(req->ch, iov, count);
- free_req(req);
-
- return res;
-}
diff --git a/xlators/mount/fuse/src/fuse-extra.h b/xlators/mount/fuse/src/fuse-extra.h
deleted file mode 100644
index 5688e34c7..000000000
--- a/xlators/mount/fuse/src/fuse-extra.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- Copyright (c) 2007-2009 Z RESEARCH, Inc. <http://www.zresearch.com>
- This file is part of GlusterFS.
-
- GlusterFS 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.
-
- GlusterFS 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/>.
-*/
-
-#ifndef _FUSE_EXTRA_H
-#define _FUSE_EXTRA_H
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-#include "config.h"
-#endif /* _CONFIG_H */
-
-#include <stdlib.h>
-#include <fuse/fuse_lowlevel.h>
-
-#define GLUSTERFS_XATTR_LEN_MAX 65536
-
-uint64_t req_callid (fuse_req_t req);
-
-size_t fuse_dirent_size (size_t dname_len);
-
-int32_t
-fuse_reply_vec (fuse_req_t req,
- struct iovec *vector,
- int32_t count);
-
-#endif /* _FUSE_EXTRA_H */