diff options
| author | Csaba Henk <csaba@gluster.com> | 2009-07-13 22:28:07 +0200 | 
|---|---|---|
| committer | Csaba Henk <csaba@gluster.com> | 2009-08-12 06:21:04 -0700 | 
| commit | d5910898f1602dc16ab158b06c37abcd98a0588a (patch) | |
| tree | 8ea867f1f530554e81f9b1d604a6925f55d93540 | |
| parent | 57a6cb9806ad9d99e6866a21d16fcb1bafef000c (diff) | |
basic version of direct FUSE interface (ie. not relying on libfuse)
| -rw-r--r-- | configure.ac | 41 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/Makefile.am | 6 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 1708 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-extra.c | 155 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-extra.h | 42 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse_kernel.h | 509 | 
6 files changed, 1472 insertions, 989 deletions
diff --git a/configure.ac b/configure.ac index 71f663fa710..0347eb075c6 100644 --- a/configure.ac +++ b/configure.ac @@ -206,47 +206,8 @@ 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])) -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      -fi - -if test "x$HAVE_FUSE_REPLY_IOV" = "xyes"; then -   AC_DEFINE(HAVE_FUSE_REPLY_IOV, 1, [found fuse_reply_iov]) -fi - -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 -  BUILD_FUSE_CLIENT=no -if test "x$enable_fuse_client" != "xno" -a "x$HAVE_LIBFUSE" = "xyes"; then +if test "x$enable_fuse_client" != "xno"; then     FUSE_CLIENT_SUBDIR=fuse     BUILD_FUSE_CLIENT="yes"  fi diff --git a/xlators/mount/fuse/src/Makefile.am b/xlators/mount/fuse/src/Makefile.am index 9d8d45e4f02..cc4fe9de683 100644 --- a/xlators/mount/fuse/src/Makefile.am +++ b/xlators/mount/fuse/src/Makefile.am @@ -1,10 +1,10 @@ -noinst_HEADERS = fuse-extra.h +noinst_HEADERS = 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 +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 diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index efc8ea54d1b..2700d6ed05d 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 @@ -41,9 +44,8 @@  #include "defaults.h"  #include "common-utils.h" -#include <fuse/fuse_lowlevel.h> +#include "fuse_kernel.h" -#include "fuse-extra.h"  #include "list.h"  #include "dict.h" @@ -57,11 +59,16 @@  #define ZR_DIRECT_IO_OPT        "direct-io-mode"  #define ZR_STRICT_VOLFILE_CHECK "strict-volfile-check" +#define FUSE_711_OP_HIGH (FUSE_POLL + 1) +#define OFFSET_MAX 0x7fffffffffffffffLL +#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;          char                *volfile;          size_t               volfile_size;          char                *mount_point; @@ -78,16 +85,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 +104,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 +123,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 +147,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 +158,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 +178,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 +191,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 +238,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 +402,51 @@ need_fresh_lookup (int32_t op_ret, int32_t op_errno,          return 0;  } +/* courtesy of folly/fuse */ +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; +} + +/* courtesy of fuse */ +static 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; +} + +/* courtesy of fuse */ +static 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); +}  static int  fuse_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, @@ -363,13 +459,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 +488,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 +496,56 @@ 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); + +                        send_fuse_obj (this, finh, &feo); +                } 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); + +                        send_fuse_obj (this, finh, fao); +                }          } 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 +565,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 +595,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 +608,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 +639,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 +658,21 @@ 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); +                send_fuse_obj (this, finh, &fao);          } 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 +682,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 +713,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 +731,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 +748,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 +762,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 +795,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 +809,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 +861,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 +900,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 +947,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 +980,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 +1008,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 +1037,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 +1045,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 +1059,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 +1071,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 +1093,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 +1129,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 +1159,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 +1189,21 @@ 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)  { +        struct fuse_mknod_in *fmi = msg; +        char         *name = (char *)(fmi + 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" 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 +1211,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 +1244,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 +1288,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 +1319,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 +1341,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 +1355,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 +1381,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 +1397,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 +1446,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 +1475,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 +1491,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 +1538,14 @@ 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 = sizeof (feo); +                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 +1556,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 +1569,79 @@ 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_open_in *foi = msg; +        char         *name = (char *)(foi + 1); +          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, 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, foi->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 +1654,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 +1692,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 +1722,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 +1752,34 @@ 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)  { +        struct fuse_write_in *fwi = msg; +        char            *buf = (char *)(fwi + 1); +          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); +        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_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 +1788,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 +1796,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 +1818,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 +1840,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 +1903,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 +1963,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 +2009,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 +2033,11 @@ 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; +        struct fuse_statfs_out fso = {{0, }, };          state = frame->root->state; -        req   = state->req; +        finh  = state->finh;          /*            Filesystems (like ZFS on solaris) reports            different ->f_frsize and ->f_bsize. Old coreutils @@ -1881,13 +2066,22 @@ 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; + +                send_fuse_obj (this, finh, &fso);          } 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 +2092,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 +2119,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 +2206,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 +2220,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 +2249,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 +2260,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 +2271,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 +2282,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 +2311,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 +2328,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 +2355,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 +2398,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 +2431,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 +2472,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 +2499,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); @@ -2292,23 +2512,40 @@ fuse_getlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  } +/* courtesy of fuse */ +static 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; +} +  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 +2561,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++; @@ -2337,11 +2574,11 @@ fuse_setlk_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); @@ -2352,76 +2589,102 @@ 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 || +            fini->minor < 9) { +                gf_log ("glusterfs-fuse", GF_LOG_ERROR, +                        "unsupported FUSE protocol version %d.%d", +                        fini->major, fini->minor); + +                close (priv->fd); +                goto out; +        } + +        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 | FUSE_BIG_WRITES; + +        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_711_OP_HIGH];  int  fuse_root_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, @@ -2493,33 +2756,44 @@ 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];          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 (fuse_in_header_t); +        iov_in[1].iov_len = ((struct iobuf_pool *)this->ctx->iobuf_pool) +                              ->page_size; + +        for (;;) {                  iobuf = iobuf_get (this->ctx->iobuf_pool); +                iov_in[0].iov_base = CALLOC (1, sizeof (*finh)); -                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) { @@ -2532,25 +2806,35 @@ fuse_thread_proc (void *data)                  if (res == -1) {                          if (errno != EINTR) {                                  gf_log ("glusterfs-fuse", GF_LOG_WARNING, -                                        "fuse_chan_receive() returned -1 (%d)", errno); +                                        "read from /dev/fuse returned -1 (%d)", errno);                          } -                        if (errno == ENODEV) { -                                iobuf_unref (iobuf); +                        if (errno == ENODEV || errno == EBADF)                                  break; -                        } +                        iobuf_unref (iobuf); +                        FREE (iov_in[0].iov_base);                          continue;                  } +                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); -                } +                fuse_ops[finh->opcode] (this, finh, iov_in[1].iov_base);                  iobuf_unref (iobuf);          } +        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 +2844,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 +2908,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 +2916,10 @@ init (xlator_t *this_xl)          dict_t            *options = NULL;          char              *value_string = NULL;          char              *fsname = NULL; -        char              *fsname_opt = NULL; +        char              *mount_param = 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 +2933,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 +2987,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 +3017,97 @@ 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 = open ("/dev/fuse", O_RDWR); +        if (priv->fd == -1) { +                gf_log ("glusterfs-fuse", GF_LOG_ERROR, +                        "cannot open /dev/fuse (%s)", strerror (errno));                  goto cleanup_exit;          } +        ret = asprintf (&mount_param, +                        "allow_other,default_permissions,max_read=131072," +                        "fd=%i,rootmode=%o,user_id=%i,group_id=%i", +                        priv->fd, stbuf.st_mode & S_IFMT, getuid (), getgid ()); +        if (ret == -1) { +                gf_log ("glusterfs-fuse", GF_LOG_ERROR, +                        "Out of memory"); -        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; +                goto cleanup_exit;          } - -        ret = fuse_set_signal_handlers (priv->se); +        ret = mount (fsname, priv->mount_point, "fuse.glusterfs", 0, +                     mount_param);          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); +                gf_log ("glusterfs-fuse", GF_LOG_ERROR, +                        "mount failed (%s)", strerror (errno)); -        fuse_session_add_chan (priv->se, priv->ch); +                goto cleanup_exit; +        } -        priv->fd = fuse_chan_fd (priv->ch); +        FREE (mount_param);          this_xl->ctx->top = this_xl;          priv->first_call = 2; + +        for (i = 0; i < FUSE_711_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) +        FREE (mount_param); +        if (priv) {                  FREE (priv->mount_point); +                close (priv->fd); +        }          FREE (priv);          return -1;  } @@ -2916,6 +3125,8 @@ fini (xlator_t *this_xl)          if ((priv = this_xl->private) == NULL)                  return; +        close (priv->fd); +          if (dict_get (this_xl->options, ZR_MOUNTPOINT_OPT))                  mount_point = data_to_str (dict_get (this_xl->options,                                                       ZR_MOUNTPOINT_OPT)); @@ -2924,8 +3135,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); +                umount (mount_point);          }  } diff --git a/xlators/mount/fuse/src/fuse-extra.c b/xlators/mount/fuse/src/fuse-extra.c deleted file mode 100644 index 422ff4b563d..00000000000 --- 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 5688e34c76d..00000000000 --- 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 */ diff --git a/xlators/mount/fuse/src/fuse_kernel.h b/xlators/mount/fuse/src/fuse_kernel.h new file mode 100644 index 00000000000..df558e394ff --- /dev/null +++ b/xlators/mount/fuse/src/fuse_kernel.h @@ -0,0 +1,509 @@ +/* +    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 + */ + +#ifndef _LINUX_FUSE_H +#define _LINUX_FUSE_H + +#include <sys/types.h> +#define __u64 uint64_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 11 + +/** 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 ".." + */ +#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) + +/** + * 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, +}; + +enum fuse_notify_code { +	FUSE_NOTIFY_POLL   = 1, +	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; +}; + +struct fuse_mknod_in { +	__u32	mode; +	__u32	rdev; +}; + +struct fuse_mkdir_in { +	__u32	mode; +	__u32	padding; +}; + +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	mode; +}; + +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; +}; + +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) + +#endif /* _LINUX_FUSE_H */  | 
