diff options
| -rw-r--r-- | libglusterfs/src/fd.c | 39 | ||||
| -rw-r--r-- | libglusterfs/src/fd.h | 11 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/Makefile.am | 11 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 1292 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.h | 277 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-helpers.c | 300 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-resolve.c | 747 | ||||
| -rw-r--r-- | xlators/performance/write-behind/src/write-behind.c | 2 | 
8 files changed, 1919 insertions, 760 deletions
diff --git a/libglusterfs/src/fd.c b/libglusterfs/src/fd.c index 231b7c5b00c..c9ac947341f 100644 --- a/libglusterfs/src/fd.c +++ b/libglusterfs/src/fd.c @@ -419,9 +419,9 @@ fd_destroy (fd_t *fd)  	 tmp_pool = fd->inode->table->fd_mem_pool;          if (IA_ISDIR (fd->inode->ia_type)) { -		for (i = 0; i < fd->inode->table->xl->graph->xl_count; i++) { +		for (i = 0; i < fd->xl_count; i++) {  			if (fd->_ctx[i].key) { -				xl = (xlator_t *)(long)fd->_ctx[i].key; +				xl = fd->_ctx[i].xl_key;                                  old_THIS = THIS;                                  THIS = xl;  				if (xl->cbks->releasedir) @@ -430,9 +430,9 @@ fd_destroy (fd_t *fd)  			}  		}          } else { -		for (i = 0; i < fd->inode->table->xl->graph->xl_count; i++) { +		for (i = 0; i < fd->xl_count; i++) {  			if (fd->_ctx[i].key) { -				xl = (xlator_t *)(long)fd->_ctx[i].key; +				xl = fd->_ctx[i].xl_key;                                  old_THIS = THIS;                                  THIS = xl;  				if (xl->cbks->release) @@ -513,8 +513,9 @@ fd_create (inode_t *inode, pid_t pid)          if (!fd)                  goto out; -        fd->_ctx = GF_CALLOC (1, (sizeof (struct _fd_ctx) * -                                  inode->table->xl->graph->xl_count), +        fd->xl_count = inode->table->xl->graph->xl_count + 1; + +        fd->_ctx = GF_CALLOC (1, (sizeof (struct _fd_ctx) * fd->xl_count),                                gf_common_mt_fd_ctx);          if (!fd->_ctx) {                  GF_FREE (fd); @@ -596,14 +597,14 @@ __fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value)  	if (!fd || !xlator)  		return -1; -        for (index = 0; index < xlator->graph->xl_count; index++) { +        for (index = 0; index < fd->xl_count; index++) {                  if (!fd->_ctx[index].key) {                          if (set_idx == -1)                                  set_idx = index;                          /* dont break, to check if key already exists                             further on */                  } -                if (fd->_ctx[index].key == (uint64_t)(long) xlator) { +                if (fd->_ctx[index].xl_key == xlator) {                          set_idx = index;                          break;                  } @@ -614,8 +615,8 @@ __fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value)                  goto out;          } -        fd->_ctx[set_idx].key   = (uint64_t)(long) xlator; -        fd->_ctx[set_idx].value = value; +        fd->_ctx[set_idx].xl_key = xlator; +        fd->_ctx[set_idx].value1  = value;  out:  	return ret; @@ -649,18 +650,18 @@ __fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value)  	if (!fd || !xlator)  		return -1; -        for (index = 0; index < xlator->graph->xl_count; index++) { -                if (fd->_ctx[index].key == (uint64_t)(long)xlator) +        for (index = 0; index < fd->xl_count; index++) { +                if (fd->_ctx[index].xl_key == xlator)                          break;          } -        if (index == xlator->graph->xl_count) { +        if (index == fd->xl_count) {                  ret = -1;                  goto out;          }          if (value) -                *value = fd->_ctx[index].value; +                *value = fd->_ctx[index].value1;  out:  	return ret; @@ -694,21 +695,21 @@ __fd_ctx_del (fd_t *fd, xlator_t *xlator, uint64_t *value)  	if (!fd || !xlator)  		return -1; -        for (index = 0; index < xlator->graph->xl_count; index++) { -                if (fd->_ctx[index].key == (uint64_t)(long)xlator) +        for (index = 0; index < fd->xl_count; index++) { +                if (fd->_ctx[index].xl_key == xlator)                          break;          } -        if (index == xlator->graph->xl_count) { +        if (index == fd->xl_count) {                  ret = -1;                  goto out;          }          if (value) -                *value = fd->_ctx[index].value; +                *value = fd->_ctx[index].value1;          fd->_ctx[index].key   = 0; -        fd->_ctx[index].value = 0; +        fd->_ctx[index].value1 = 0;  out:  	return ret; diff --git a/libglusterfs/src/fd.h b/libglusterfs/src/fd.h index c2181d8af17..e01ef753e28 100644 --- a/libglusterfs/src/fd.h +++ b/libglusterfs/src/fd.h @@ -35,8 +35,14 @@ struct _inode;  struct _dict;  struct _fd_ctx { -	uint64_t  key; -	uint64_t  value; +        union { +                uint64_t  key; +                void     *xl_key; +        }; +        union { +                uint64_t  value1; +                void     *ptr1; +        };  };  /* If this structure changes, please have mercy on the booster maintainer @@ -53,6 +59,7 @@ struct _fd {          gf_lock_t         lock; /* used ONLY for manipulating                                     'struct _fd_ctx' array (_ctx).*/  	struct _fd_ctx   *_ctx; +        int               xl_count; /* Number of xl referred in this fd */  };  typedef struct _fd fd_t; diff --git a/xlators/mount/fuse/src/Makefile.am b/xlators/mount/fuse/src/Makefile.am index 58e33a4e116..66d044e32f9 100644 --- a/xlators/mount/fuse/src/Makefile.am +++ b/xlators/mount/fuse/src/Makefile.am @@ -1,6 +1,7 @@  noinst_HEADERS = $(CONTRIBDIR)/fuse-include/fuse_kernel.h\  	$(CONTRIBDIR)/fuse-include/fuse-mount.h\ -	$(CONTRIBDIR)/fuse-include/fuse-misc.h fuse-mem-types.h +	$(CONTRIBDIR)/fuse-include/fuse-misc.h fuse-mem-types.h \ +	fuse-bridge.h  xlator_LTLIBRARIES = fuse.la  xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/mount @@ -11,8 +12,9 @@ else      mount_source=$(CONTRIBDIR)/fuse-lib/mount.c  endif -fuse_la_SOURCES = fuse-bridge.c $(CONTRIBDIR)/fuse-lib/misc.c \ -	$(mount_source) +fuse_la_SOURCES = fuse-helpers.c fuse-resolve.c fuse-bridge.c \ +	$(CONTRIBDIR)/fuse-lib/misc.c $(mount_source) +  fuse_la_LDFLAGS = -module -avoidversion -shared -nostartfiles  AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D$(GF_HOST_OS) -Wall \ @@ -20,5 +22,4 @@ AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D$(GF_HOST_OS) -Wall \  	-I$(top_srcdir)/glusterfsd/src $(GF_CFLAGS) $(GF_FUSE_CFLAGS) -CLEANFILES =  - +CLEANFILES = diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index b1de4692a10..ea5b5ae38ad 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -25,283 +25,11 @@   * fuse_loc_fill() and inode_path() return success/failure.   */ - -#include <stdint.h> -#include <signal.h> -#include <pthread.h> -#include <stddef.h> -#include <dirent.h> -#include <sys/mount.h> -#include <sys/time.h> - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif /* _CONFIG_H */ - -#include "glusterfs.h" -#include "logging.h" -#include "xlator.h" -#include "defaults.h" -#include "common-utils.h" -#include "glusterfsd-common.h" -#include "statedump.h" - -#ifdef GF_DARWIN_HOST_OS -/* This is MacFUSE's marker for MacFUSE-specific code */ -#define __FreeBSD__ 10 -#include "fuse_kernel_macfuse.h" -#else -#include "fuse_kernel.h" -#endif -#include "fuse-misc.h" -#include "fuse-mount.h" -#include "fuse-mem-types.h" - -#include "list.h" -#include "dict.h" - -/* TODO: when supporting posix acl, remove this definition */ -#define DISABLE_POSIX_ACL - -#ifdef GF_LINUX_HOST_OS -#define FUSE_OP_HIGH (FUSE_POLL + 1) -#endif -#ifdef GF_DARWIN_HOST_OS -#define FUSE_OP_HIGH (FUSE_DESTROY + 1) -#endif -#define GLUSTERFS_XATTR_LEN_MAX  65536 - -#define MAX_FUSE_PROC_DELAY 1 +#include "fuse-bridge.h"  static int gf_fuse_conn_err_log;  static int gf_fuse_xattr_enotsup_log; -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; -        uint32_t             proto_minor; -        char                *volfile; -        size_t               volfile_size; -        char                *mount_point; -        struct iobuf        *iobuf; - -        pthread_t            fuse_thread; -        char                 fuse_thread_started; - -        uint32_t             direct_io_mode; -        size_t              *msg0_len_p; - -        double               entry_timeout; -        double               attribute_timeout; - -        pthread_cond_t       sync_cond; -        pthread_mutex_t      sync_mutex; -        char                 child_up; - -        char                 init_recvd; - -        gf_boolean_t         strict_volfile_check; - -        fuse_handler_t     **fuse_ops; -        fuse_handler_t     **fuse_ops0; -        pthread_mutex_t      fuse_dump_mutex; -        int                  fuse_dump_fd; - -        glusterfs_graph_t   *next_graph; -        xlator_t            *active_subvol; -}; -typedef struct fuse_private fuse_private_t; - -#define _FH_TO_FD(fh) ((fd_t *)(uintptr_t)(fh)) - -#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);                 \ -                if (!frame) {                                           \ -                         /* This is not completely clean, as some       \ -                          * earlier allocations might remain unfreed    \ -                          * if we return at this point, but still       \ -                          * better than trying to go on with a NULL     \ -                          * frame ...                                   \ -                          */                                            \ -                        gf_log ("glusterfs-fuse",                       \ -                                GF_LOG_ERROR,                           \ -                                "FUSE message"                          \ -                                " unique %"PRIu64" opcode %d:"          \ -                                " frame allocation failed",             \ -                                state->finh->unique,                    \ -                                state->finh->opcode);                   \ -                        free_state (state);                             \ -                        return;                                         \ -                }                                                       \ -                xl = fuse_state_subvol (state);                         \ -                                                                        \ -                frame->root->state = state;                             \ -                frame->root->op    = op_num;                            \ -		frame->op          = op_num;				\ -                STACK_WIND (frame, ret, xl, xl->fops->fop, args);       \ -        } while (0) - -#define GF_SELECT_LOG_LEVEL(_errno)                     \ -        (((_errno == ENOENT) || (_errno == ESTALE))?    \ -         GF_LOG_DEBUG) - -#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);                \ -                        GF_FREE (finh);                                       \ -                                                                           \ -                        return;                                            \ -                }                                                          \ -        } while (0) - - -typedef struct { -        void          *pool; -        xlator_t      *this; -        inode_table_t *itable; -        loc_t          loc; -        loc_t          loc2; -        fuse_in_header_t *finh; -        int32_t        flags; -        off_t          off; -        size_t         size; -        unsigned long  nlookup; -        fd_t          *fd; -        dict_t        *dict; -        char          *name; -        char           is_revalidate; -        gf_boolean_t   truncate_needed; -        gf_lock_t      lock; -        uint64_t       lk_owner; -} fuse_state_t; - - -xlator_t * -fuse_state_subvol (fuse_state_t *state) -{ -        xlator_t *subvol = NULL; - -        if (!state) -                return NULL; - -        if (state->loc.inode) -                subvol = state->loc.inode->table->xl; - -        if (state->fd) -                subvol = state->fd->inode->table->xl; - -        return subvol; -} - - -xlator_t * -fuse_active_subvol (xlator_t *fuse) -{ -        fuse_private_t *priv = NULL; - -        priv = fuse->private; - -        return priv->active_subvol; -} - - -static void -free_state (fuse_state_t *state) -{ -        loc_wipe (&state->loc); - -        loc_wipe (&state->loc2); - -        if (state->dict) { -                dict_unref (state->dict); -                state->dict = (void *)0xaaaaeeee; -        } -        if (state->name) { -                GF_FREE (state->name); -                state->name = NULL; -        } -        if (state->fd) { -                fd_unref (state->fd); -                state->fd = (void *)0xfdfdfdfd; -        } -        if (state->finh) { -                GF_FREE (state->finh); -                state->finh = NULL; -        } -#ifdef DEBUG -        memset (state, 0x90, sizeof (*state)); -#endif -        GF_FREE (state); -        state = NULL; -} - - -fuse_state_t * -get_state (xlator_t *this, fuse_in_header_t *finh) -{ -        fuse_state_t *state = NULL; - -        state = (void *)GF_CALLOC (1, sizeof (*state), -                                   gf_fuse_mt_fuse_state_t); -        if (!state) -                return NULL; -        state->pool = this->ctx->pool; -        state->finh = finh; -        state->this = this; - -        LOCK_INIT (&state->lock); - -        return state; -} - - -static call_frame_t * -get_call_frame_for_req (fuse_state_t *state) -{ -        call_pool_t           *pool = NULL; -        fuse_in_header_t      *finh = NULL; -        call_frame_t          *frame = NULL; -        xlator_t              *this = NULL; - -        pool = state->pool; -        finh = state->finh; -        this = state->this; - -        frame = create_frame (this, pool); -        if (!frame) -                return NULL; - -        if (finh) { -                frame->root->uid      = finh->uid; -                frame->root->gid      = finh->gid; -                frame->root->pid      = finh->pid; -                frame->root->lk_owner = state->lk_owner; -                frame->root->unique   = finh->unique; -        } - -        frame->root->type = GF_OP_TYPE_FOP; - -        return frame; -} -  /*   * iov_out should contain a fuse_out_header at zeroth position. @@ -378,142 +106,6 @@ send_fuse_err (xlator_t *this, fuse_in_header_t *finh, int error)          return send_fuse_iov (this, finh, &iov_out, 1);  } -static inode_t * -fuse_ino_to_inode (uint64_t ino, xlator_t *fuse) -{ -        inode_t  *inode = NULL; -        xlator_t *active_subvol = NULL; - -        if (ino == 1) { -                active_subvol = fuse_active_subvol (fuse); -                inode = active_subvol->itable->root; -        } else { -                inode = (inode_t *) (unsigned long) ino; -                inode_ref (inode); -        } - -        return inode; -} - -static uint64_t -inode_to_nodeid (inode_t *inode) -{ -        if (!inode || inode->ino == 1) -                return 1; - -        return (unsigned long) inode; -} - - -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) -{ -        inode_t  *inode = NULL; -        inode_t  *parent = NULL; -        int32_t   ret = -1; -        char     *path = NULL; - -        /* resistance against multiple invocation of loc_fill not to get -           reference leaks via inode_search() */ - -        if (name) { -                parent = loc->parent; -                if (!parent) { -                        parent = fuse_ino_to_inode (par, state->this); -                        loc->parent = parent; -                } - -                inode = loc->inode; -                if (!inode) { -                        inode = inode_grep (parent->table, parent, name); -                        loc->inode = inode; -                } - -                ret = inode_path (parent, name, &path); -                if (ret <= 0) { -                        gf_log ("glusterfs-fuse", GF_LOG_DEBUG, -                                "inode_path failed for %"PRId64"/%s", -                                parent->ino, name); -                        goto fail; -                } -                loc->path = path; -        } else { -                inode = loc->inode; -                if (!inode) { -                        inode = fuse_ino_to_inode (ino, state->this); -                        loc->inode = inode; -                } - -                parent = loc->parent; -                if (!parent) { -                        parent = inode_parent (inode, par, name); -                        loc->parent = parent; -                } - -                ret = inode_path (inode, NULL, &path); -                if (ret <= 0) { -                        gf_log ("glusterfs-fuse", GF_LOG_DEBUG, -                                "inode_path failed for %"PRId64, -                                inode->ino); -                        goto fail; -                } -                loc->path = path; -        } - -        if (inode) -                loc->ino = inode->ino; - -        if (loc->path) { -                loc->name = strrchr (loc->path, '/'); -                if (loc->name) -                        loc->name++; -                else -                        loc->name = ""; -        } - -        if ((ino != 1) && (parent == NULL)) { -                gf_log ("fuse-bridge", GF_LOG_DEBUG, -                        "failed to search parent for %"PRId64"/%s (%"PRId64")", -                        (ino_t)par, name, (ino_t)ino); -                ret = -1; -                goto fail; -        } -        ret = 0; -fail: -        return ret; -} - - -/* courtesy of folly */ -static void -stat2attr (struct iatt *st, struct fuse_attr *fa) -{ -        fa->ino        = st->ia_ino; -        fa->size       = st->ia_size; -        fa->blocks     = st->ia_blocks; -        fa->atime      = st->ia_atime; -        fa->mtime      = st->ia_mtime; -        fa->ctime      = st->ia_ctime; -        fa->atimensec  = st->ia_atime_nsec; -        fa->mtimensec  = st->ia_mtime_nsec; -        fa->ctimensec  = st->ia_ctime_nsec; -        fa->mode       = st_mode_from_ia (st->ia_prot, st->ia_type); -        fa->nlink      = st->ia_nlink; -        fa->uid        = st->ia_uid; -        fa->gid        = st->ia_gid; -        fa->rdev       = st->ia_rdev; -#if FUSE_KERNEL_MINOR_VERSION >= 9 -        fa->blksize    = st->ia_blksize; -#endif -#ifdef GF_DARWIN_HOST_OS -        fa->crtime     = (uint64_t)-1; -        fa->crtimensec = (uint32_t)-1; -        fa->flags      = 0; -#endif -} - -  static int  fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  int32_t op_ret, int32_t op_errno, @@ -540,7 +132,7 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                          state->loc.path, buf->ia_ino, state->loc.ino);                  buf->ia_blksize = this->ctx->page_size; -                stat2attr (buf, &feo.attr); +                gf_fuse_stat2attr (buf, &feo.attr);                  if (!buf->ia_ino) {                          gf_log ("glusterfs-fuse", GF_LOG_WARNING, @@ -566,7 +158,8 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  inode_lookup (linked_inode);                  /* TODO: make these timeouts configurable (via meta?) */ -                feo.nodeid = inode_to_nodeid (linked_inode); +                /* should we do linked_node or inode */ +                feo.nodeid = inode_to_fuse_nodeid (linked_inode);                  feo.generation = linked_inode->generation; @@ -598,7 +191,7 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  send_fuse_err (this, state->finh, op_errno);          } -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0;  } @@ -644,14 +237,24 @@ fuse_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          return 0;  } +void +fuse_lookup_resume (fuse_state_t *state) +{ +        if (!state->loc.inode) +                state->loc.inode = inode_new (state->loc.parent->table); + +        state->dict = dict_new (); + +        FUSE_FOP (state, fuse_lookup_cbk, GF_FOP_LOOKUP, +                  lookup, &state->loc, state->dict); +}  static void  fuse_lookup (xlator_t *this, fuse_in_header_t *finh, void *msg)  { -        char *name = msg; - -        fuse_state_t *state = NULL; -        int32_t       ret = -1; +        char         *name      = msg; +        fuse_state_t *state     = NULL; +        int32_t       ret       = -1;          GET_STATE (this, finh, state); @@ -662,27 +265,23 @@ fuse_lookup (xlator_t *this, fuse_in_header_t *finh, void *msg)                          "%"PRIu64": LOOKUP %"PRIu64"/%s (fuse_loc_fill() failed)",                          finh->unique, finh->nodeid, name);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        if (!state->loc.inode) { -                gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                        "%"PRIu64": LOOKUP %s", finh->unique, -                        state->loc.path); - -                state->loc.inode = inode_new (state->loc.parent->table); -        } else { +        if (state->loc.inode) {                  gf_log ("glusterfs-fuse", GF_LOG_TRACE,                          "%"PRIu64": LOOKUP %s(%"PRId64")", finh->unique,                          state->loc.path, state->loc.inode->ino);                  state->is_revalidate = 1; +        } else { +                gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                        "%"PRIu64": LOOKUP %s", finh->unique, +                        state->loc.path);          } -        state->dict = dict_new (); +        fuse_resolve_and_resume (state, fuse_lookup_resume); -        FUSE_FOP (state, fuse_lookup_cbk, GF_FOP_LOOKUP, -                  lookup, &state->loc, state->dict);  } @@ -732,7 +331,7 @@ fuse_truncate_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 */                  postbuf->ia_blksize = this->ctx->page_size; -                stat2attr (postbuf, &fao.attr); +                gf_fuse_stat2attr (postbuf, &fao.attr);                  fao.attr_valid = calc_timeout_sec (priv->attribute_timeout);                  fao.attr_valid_nsec = @@ -756,7 +355,7 @@ fuse_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  send_fuse_err (this, finh, op_errno);          } -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0; @@ -786,7 +385,7 @@ 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->ia_blksize = this->ctx->page_size; -                stat2attr (buf, &fao.attr); +                gf_fuse_stat2attr (buf, &fao.attr);                  fao.attr_valid = calc_timeout_sec (priv->attribute_timeout);                  fao.attr_valid_nsec = @@ -812,7 +411,7 @@ fuse_attr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  send_fuse_err (this, finh, op_errno);          } -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0; @@ -830,6 +429,28 @@ fuse_root_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          return 0;  } +void +fuse_getattr_resume (fuse_state_t *state) +{ +        if (!state->fd || IA_ISDIR (state->loc.inode->ia_type)) { +                gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                        "%"PRIu64": GETATTR %"PRIu64" (%s)", +                        state->finh->unique, state->finh->nodeid, +                        state->loc.path); + +                FUSE_FOP (state, fuse_attr_cbk, GF_FOP_STAT, +                          stat, &state->loc); +        } else { + +                gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                        "%"PRIu64": FGETATTR %"PRIu64" (%s/%p)", +                        state->finh->unique, state->finh->nodeid, +                        state->loc.path, state->fd); + +                FUSE_FOP (state, fuse_attr_cbk, GF_FOP_FSTAT, +                          fstat, state->fd); +        } +}  static void  fuse_getattr (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -844,10 +465,10 @@ fuse_getattr (xlator_t *this, fuse_in_header_t *finh, void *msg)                  ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);                  if (ret < 0) {                          gf_log ("glusterfs-fuse", GF_LOG_WARNING, -                                "%"PRIu64": GETATTR %"PRIu64" (fuse_loc_fill() failed)", -                                finh->unique, finh->nodeid); +                                "%"PRIu64": GETATTR on / (fuse_loc_fill() failed)", +                                finh->unique);                          send_fuse_err (this, finh, ENOENT); -                        free_state (state); +                        free_fuse_state (state);                          return;                  } @@ -858,18 +479,18 @@ fuse_getattr (xlator_t *this, fuse_in_header_t *finh, void *msg)                  return;          } -        ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL); +        ret = fuse_loc_fill (&state->loc, state, state->finh->nodeid, 0, NULL);          if (!state->loc.inode) {                  gf_log ("glusterfs-fuse", GF_LOG_WARNING,                          "%"PRIu64": GETATTR %"PRIu64" (%s) (fuse_loc_fill() returned NULL inode)", -                        finh->unique, finh->nodeid, state->loc.path); -                send_fuse_err (this, finh, ENOENT); -                free_state (state); +                        state->finh->unique, state->finh->nodeid, state->loc.path); +                send_fuse_err (state->this, state->finh, ENOENT); +                free_fuse_state (state);                  return;          } -        fd = fd_lookup (state->loc.inode, finh->pid); +        fd = fd_lookup (state->loc.inode, state->finh->pid);          state->fd = fd;          if (!fd || IA_ISDIR (state->loc.inode->ia_type)) {                  /* this is the @ret of fuse_loc_fill, checked here @@ -878,28 +499,15 @@ fuse_getattr (xlator_t *this, fuse_in_header_t *finh, void *msg)                  if (ret < 0) {                          gf_log ("glusterfs-fuse", GF_LOG_WARNING,                                  "%"PRIu64": GETATTR %"PRIu64" (fuse_loc_fill() failed)", -                                finh->unique, finh->nodeid); -                        send_fuse_err (this, finh, ENOENT); -                        free_state (state); +                                state->finh->unique, state->finh->nodeid); +                        send_fuse_err (state->this, state->finh, ENOENT); +                        free_fuse_state (state);                          return;                  } - -                gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                        "%"PRIu64": GETATTR %"PRIu64" (%s)", -                        finh->unique, finh->nodeid, state->loc.path); - - -                FUSE_FOP (state, fuse_attr_cbk, GF_FOP_STAT, -                          stat, &state->loc); -        } else { - -                gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                        "%"PRIu64": FGETATTR %"PRIu64" (%s/%p)", -                        finh->unique, finh->nodeid, state->loc.path, fd); - -                FUSE_FOP (state,fuse_attr_cbk, GF_FOP_FSTAT, -                          fstat, fd); +                state->fd = NULL;          } + +        fuse_resolve_and_resume (state, fuse_getattr_resume);  } @@ -960,7 +568,7 @@ fuse_fd_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  send_fuse_err (this, finh, op_errno);          }  out: -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0;  } @@ -1009,7 +617,7 @@ fuse_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  statpost->ia_blksize = this->ctx->page_size; -                stat2attr (statpost, &fao.attr); +                gf_fuse_stat2attr (statpost, &fao.attr);                  fao.attr_valid = calc_timeout_sec (priv->attribute_timeout);                  fao.attr_valid_nsec = @@ -1040,7 +648,7 @@ fuse_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          }          if (op_done) { -                free_state (state); +                free_fuse_state (state);          }          STACK_DESTROY (frame->root); @@ -1081,18 +689,40 @@ fattr_to_gf_set_attr (int32_t valid)                        | FATTR_ATIME | FATTR_MTIME       \                        | FATTR_MODE) +void +fuse_setattr_resume (fuse_state_t *state) +{ +        if ((state->valid & (FATTR_MASK)) != FATTR_SIZE) { +                if (state->fd && +                    !((state->valid & FATTR_ATIME) || +                      (state->valid & FATTR_MTIME))) { +                        /* +                            there is no "futimes" call, so don't send +                            fsetattr if ATIME or MTIME is set +                         */ + +                        FUSE_FOP (state, fuse_setattr_cbk, GF_FOP_FSETATTR, +                                  fsetattr, state->fd, &state->attr, +                                  fattr_to_gf_set_attr (state->valid)); +                } else { +                        FUSE_FOP (state, fuse_setattr_cbk, GF_FOP_SETATTR, +                                  setattr, &state->loc, &state->attr, +                                  fattr_to_gf_set_attr (state->valid)); +                } +        } else { +                fuse_do_truncate (state, state->size); +        } + +}  static void  fuse_setattr (xlator_t *this, fuse_in_header_t *finh, void *msg)  {          struct fuse_setattr_in *fsi = msg; -        struct iatt attr = {0, }; -          fuse_private_t  *priv = NULL;          fuse_state_t *state = NULL;          int32_t       ret   = -1; -        int32_t       valid = 0;          GET_STATE (this, finh, state); @@ -1132,7 +762,7 @@ fuse_setattr (xlator_t *this, fuse_in_header_t *finh, void *msg)                          finh->unique, state->loc.path);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } @@ -1141,48 +771,32 @@ fuse_setattr (xlator_t *this, fuse_in_header_t *finh, void *msg)                  "%"PRIu64": SETATTR (%"PRIu64")%s", finh->unique,                  finh->nodeid, state->loc.path); -        valid = fsi->valid; +        state->valid = fsi->valid;          if (fsi->valid & FATTR_FH) {                  state->fd = FH_TO_FD (fsi->fh);          } -        if ((valid & (FATTR_MASK)) != FATTR_SIZE) { -                if (valid & FATTR_SIZE) { +        if ((fsi->valid & (FATTR_MASK)) != FATTR_SIZE) { +                if (fsi->valid & FATTR_SIZE) {                          state->size            = fsi->size;                          state->truncate_needed = _gf_true;                  } -                attr.ia_size  = fsi->size; -                attr.ia_atime = fsi->atime; -                attr.ia_mtime = fsi->mtime; -                attr.ia_atime_nsec = fsi->atimensec; -                attr.ia_mtime_nsec = fsi->mtimensec; +                state->attr.ia_size  = fsi->size; +                state->attr.ia_atime = fsi->atime; +                state->attr.ia_mtime = fsi->mtime; +                state->attr.ia_atime_nsec = fsi->atimensec; +                state->attr.ia_mtime_nsec = fsi->mtimensec; -                attr.ia_prot = ia_prot_from_st_mode (fsi->mode); -                attr.ia_uid  = fsi->uid; -                attr.ia_gid  = fsi->gid; - -                if (state->fd && -                    !((fsi->valid & FATTR_ATIME) || (fsi->valid & FATTR_MTIME))) { - -                         /* -                            there is no "futimes" call, so don't send -                            fsetattr if ATIME or MTIME is set -                         */ - -                        FUSE_FOP (state, fuse_setattr_cbk, GF_FOP_FSETATTR, -                                  fsetattr, state->fd, &attr, -                                  fattr_to_gf_set_attr (fsi->valid)); -                } else { -                        FUSE_FOP (state, fuse_setattr_cbk, GF_FOP_SETATTR, -                                  setattr, &state->loc, &attr, -                                  fattr_to_gf_set_attr (fsi->valid)); -                } +                state->attr.ia_prot = ia_prot_from_st_mode (fsi->mode); +                state->attr.ia_uid  = fsi->uid; +                state->attr.ia_gid  = fsi->gid;          } else { -                fuse_do_truncate (state, fsi->size); +                state->size = fsi->size;          } +        fuse_resolve_and_resume (state, fuse_setattr_resume);  } @@ -1211,7 +825,7 @@ fuse_err_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  send_fuse_err (this, finh, op_errno);          } -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0; @@ -1272,12 +886,24 @@ fuse_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  send_fuse_err (this, finh, op_errno);          } -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0;  } +void +fuse_access_resume (fuse_state_t *state) +{ +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64" ACCESS %s/%"PRIu64" mask=%d", +                state->finh->unique, state->loc.path, +                state->finh->nodeid, state->mask); + +        FUSE_FOP (state, fuse_err_cbk, GF_FOP_ACCESS, access, +                  &state->loc, state->mask); + +}  static void  fuse_access (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -1296,18 +922,13 @@ fuse_access (xlator_t *this, fuse_in_header_t *finh, void *msg)                          "%"PRIu64": ACCESS %"PRIu64" (%s) (fuse_loc_fill() failed)",                          finh->unique, finh->nodeid, state->loc.path);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"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, fai->mask); +        state->mask = fai->mask; +        fuse_resolve_and_resume (state, fuse_access_resume);          return;  } @@ -1339,12 +960,23 @@ fuse_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  send_fuse_err (this, finh, op_errno);          } -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0;  } +void +fuse_readlink_resume (fuse_state_t *state) +{ +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64" READLINK %s/%"PRId64, state->finh->unique, +                state->loc.path, state->loc.inode->ino); + +        FUSE_FOP (state, fuse_readlink_cbk, GF_FOP_READLINK, +                  readlink, &state->loc, 4096); + +}  static void  fuse_readlink (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -1360,20 +992,31 @@ fuse_readlink (xlator_t *this, fuse_in_header_t *finh, void *msg)                          "%"PRIu64" READLINK %s (fuse_loc_fill() returned NULL inode)",                          finh->unique, state->loc.path);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64" READLINK %s/%"PRId64, finh->unique, -                state->loc.path, state->loc.inode->ino); - -        FUSE_FOP (state, fuse_readlink_cbk, GF_FOP_READLINK, -                  readlink, &state->loc, 4096); +        fuse_resolve_and_resume (state, fuse_readlink_resume);          return;  } +void +fuse_mknod_resume (fuse_state_t *state) +{ +        if (!state->loc.inode) +                state->loc.inode = inode_new (state->loc.parent->table); +        else +                gf_log (state->this->name, GF_LOG_ERROR, "inode already present"); + +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": MKNOD %s", state->finh->unique, +                state->loc.path); + +        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_MKNOD, +                  mknod, &state->loc, state->mode, state->rdev); + +}  static void  fuse_mknod (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -1398,22 +1041,33 @@ fuse_mknod (xlator_t *this, fuse_in_header_t *finh, void *msg)                          "%"PRIu64" MKNOD %s (fuse_loc_fill() failed)",                          finh->unique, state->loc.path);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        state->loc.inode = inode_new (state->loc.parent->table); - -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64": MKNOD %s", finh->unique, -                state->loc.path); +        state->mode = fmi->mode; +        state->rdev = fmi->rdev; -        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_MKNOD, -                  mknod, &state->loc, fmi->mode, fmi->rdev); +        fuse_resolve_and_resume (state, fuse_mknod_resume);          return;  } +void +fuse_mkdir_resume (fuse_state_t *state) +{ +        if (!state->loc.inode) +                state->loc.inode = inode_new (state->loc.parent->table); +        else +                gf_log (state->this->name, GF_LOG_ERROR, "inode already present"); + +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": MKDIR %s", state->finh->unique, +                state->loc.path); + +        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_MKDIR, +                  mkdir, &state->loc, state->mode); +}  static void  fuse_mkdir (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -1431,23 +1085,35 @@ fuse_mkdir (xlator_t *this, fuse_in_header_t *finh, void *msg)                          "%"PRIu64" MKDIR %s (fuse_loc_fill() failed)",                          finh->unique, state->loc.path);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        state->loc.inode = inode_new (state->loc.parent->table); +        state->mode = fmi->mode; + +        fuse_resolve_and_resume (state, fuse_mkdir_resume); +        return; +} + +void +fuse_unlink_resume (fuse_state_t *state) +{ +        if (!state->loc.inode) { +                gf_log ("fuse", GF_LOG_WARNING, "path resolving failed"); +                send_fuse_err (state->this, state->finh, ENOENT); +                free_fuse_state (state); +                return; +        }          gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64": MKDIR %s", finh->unique, +                "%"PRIu64": UNLINK %s", state->finh->unique,                  state->loc.path); -        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_MKDIR, -                  mkdir, &state->loc, fmi->mode); +        FUSE_FOP (state, fuse_unlink_cbk, GF_FOP_UNLINK, +                  unlink, &state->loc); -        return;  } -  static void  fuse_unlink (xlator_t *this, fuse_in_header_t *finh, void *msg)  { @@ -1457,29 +1123,38 @@ fuse_unlink (xlator_t *this, fuse_in_header_t *finh, void *msg)          int32_t       ret = -1;          GET_STATE (this, finh, state); -          ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name); - -        if ((state->loc.inode == NULL) || -            (ret < 0)) { +        if (ret < 0) {                  gf_log ("glusterfs-fuse", GF_LOG_WARNING,                          "%"PRIu64": UNLINK %s (fuse_loc_fill() returned NULL inode)",                          finh->unique, state->loc.path);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64": UNLINK %s", finh->unique, -                state->loc.path); - -        FUSE_FOP (state, fuse_unlink_cbk, GF_FOP_UNLINK, -                  unlink, &state->loc); +        fuse_resolve_and_resume (state, fuse_unlink_resume);          return;  } +void +fuse_rmdir_resume (fuse_state_t *state) +{ +        if (!state->loc.inode) { +                gf_log ("fuse", GF_LOG_WARNING, "path resolving failed"); +                send_fuse_err (state->this, state->finh, ENOENT); +                free_fuse_state (state); +                return; +        } + +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": RMDIR %s", state->finh->unique, +                state->loc.path); + +        FUSE_FOP (state, fuse_unlink_cbk, GF_FOP_RMDIR, +                  rmdir, &state->loc); +}  static void  fuse_rmdir (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -1491,26 +1166,34 @@ fuse_rmdir (xlator_t *this, fuse_in_header_t *finh, void *msg)          GET_STATE (this, finh, state);          ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name); -        if ((state->loc.inode == NULL) || -            (ret < 0)) { +        if (ret < 0) {                  gf_log ("glusterfs-fuse", GF_LOG_WARNING,                          "%"PRIu64": RMDIR %s (fuse_loc_fill() failed)",                          finh->unique, state->loc.path);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64": RMDIR %s", finh->unique, -                state->loc.path); - -        FUSE_FOP (state, fuse_unlink_cbk, GF_FOP_RMDIR, -                  rmdir, &state->loc); - +        fuse_resolve_and_resume (state, fuse_rmdir_resume);          return;  } +void +fuse_symlink_resume (fuse_state_t *state) +{ +        if (!state->loc.inode) +                state->loc.inode = inode_new (state->loc.parent->table); +        else +                gf_log (state->this->name, GF_LOG_ERROR, "inode already present"); + +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": SYMLINK %s -> %s", state->finh->unique, +                state->loc.path, state->name); + +        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_SYMLINK, +                  symlink, state->name, &state->loc); +}  static void  fuse_symlink (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -1528,19 +1211,12 @@ fuse_symlink (xlator_t *this, fuse_in_header_t *finh, void *msg)                          "%"PRIu64" SYMLINK %s -> %s (fuse_loc_fill() failed)",                          finh->unique, state->loc.path, linkname);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        state->loc.inode = inode_new (state->loc.parent->table); - -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64": SYMLINK %s -> %s", finh->unique, -                state->loc.path, linkname); - -        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_SYMLINK, -                  symlink, linkname, &state->loc); - +        state->name = gf_strdup (linkname); +        fuse_resolve_and_resume (state, fuse_symlink_resume);          return;  } @@ -1586,11 +1262,28 @@ fuse_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  send_fuse_err (this, finh, op_errno);          } -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0;  } +void +fuse_rename_resume (fuse_state_t *state) +{ +        if (!state->loc.inode) { +                send_fuse_err (state->this, state->finh, ENOENT); +                free_fuse_state (state); +                return; +        } + +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": RENAME `%s (%"PRId64")' -> `%s (%"PRId64")'", +                state->finh->unique, state->loc.path, state->loc.ino, +                state->loc2.path, state->loc2.ino); + +        FUSE_FOP (state, fuse_rename_cbk, GF_FOP_RENAME, +                  rename, &state->loc, &state->loc2); +}  static void  fuse_rename (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -1605,15 +1298,14 @@ fuse_rename (xlator_t *this, fuse_in_header_t *finh, void *msg)          GET_STATE (this, finh, state);          ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, oldname); -        if ((state->loc.inode == NULL) || -            (ret < 0)) { +        if (ret < 0) {                  gf_log ("glusterfs-fuse", GF_LOG_WARNING,                          "for %s %"PRIu64": RENAME `%s' -> `%s' (fuse_loc_fill() failed)",                          state->loc.path, finh->unique, state->loc.path,                          state->loc2.path);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } @@ -1625,21 +1317,31 @@ fuse_rename (xlator_t *this, fuse_in_header_t *finh, void *msg)                          state->loc2.path);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return; -               } - -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64": RENAME `%s (%"PRId64")' -> `%s (%"PRId64")'", -                finh->unique, state->loc.path, state->loc.ino, -                state->loc2.path, state->loc2.ino); +        } -        FUSE_FOP (state, fuse_rename_cbk, GF_FOP_RENAME, -                  rename, &state->loc, &state->loc2); +        fuse_resolve_and_resume (state, fuse_rename_resume);          return;  } +void +fuse_link_resume (fuse_state_t *state) +{ +        if (!state->loc.inode) +                state->loc.inode = inode_ref (state->loc2.inode); +        else +                gf_log (state->this->name, GF_LOG_ERROR, "inode already present"); + +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": LINK() %s (%"PRId64") -> %s (%"PRId64")", +                state->finh->unique, state->loc2.path, state->loc2.ino, +                state->loc.path, state->loc.ino); + +        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_LINK, +                  link, &state->loc2, &state->loc); +}  static void  fuse_link (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -1664,18 +1366,11 @@ fuse_link (xlator_t *this, fuse_in_header_t *finh, void *msg)                          state->loc2.path, finh->unique,                          state->loc2.path, state->loc.path);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        state->loc.inode = inode_ref (state->loc2.inode); -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64": LINK() %s (%"PRId64") -> %s (%"PRId64")", -                finh->unique, state->loc2.path, state->loc2.ino, -                state->loc.path, state->loc.ino); - -        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_LINK, -                  link, &state->loc2, &state->loc); +        fuse_resolve_and_resume (state, fuse_link_resume);          return;  } @@ -1696,7 +1391,6 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          struct iovec             iov_out[3];          inode_t                 *linked_inode = NULL; -          state    = frame->root->state;          priv     = this->private;          finh     = state->finh; @@ -1714,7 +1408,7 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                          state->loc.path, fd, buf->ia_ino);                  buf->ia_blksize = this->ctx->page_size; -                stat2attr (buf, &feo.attr); +                gf_fuse_stat2attr (buf, &feo.attr);                  linked_inode = inode_link (inode, state->loc.parent,                                             state->loc.name, buf); @@ -1738,11 +1432,12 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  inode_lookup (linked_inode); +                inode_ref (state->loc.parent);                  inode_unref (linked_inode);                  fd_ref (fd); -                feo.nodeid = inode_to_nodeid (linked_inode); +                feo.nodeid = inode_to_fuse_nodeid (linked_inode);                  feo.generation = linked_inode->generation; @@ -1780,12 +1475,34 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  send_fuse_err (this, finh, op_errno);          }  out: -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0;  } +void +fuse_create_resume (fuse_state_t *state) +{ +        fd_t *fd = NULL; + +        if (!state->loc.inode) +                state->loc.inode = inode_new (state->loc.parent->table); +        else +                gf_log (state->this->name, GF_LOG_ERROR, "inode already present"); + +        fd = fd_create (state->loc.inode, state->finh->pid); +        state->fd = fd; +        fd->flags = state->flags; + +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": CREATE %s", state->finh->unique, +                state->loc.path); + +        FUSE_FOP (state, fuse_create_cbk, GF_FOP_CREATE, +                  create, &state->loc, state->flags, state->mode, fd); + +}  static void  fuse_create (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -1799,7 +1516,6 @@ fuse_create (xlator_t *this, fuse_in_header_t *finh, void *msg)          fuse_private_t        *priv = NULL;          fuse_state_t *state = NULL; -        fd_t         *fd = NULL;          int32_t       ret = -1;          priv = this->private; @@ -1809,7 +1525,6 @@ fuse_create (xlator_t *this, fuse_in_header_t *finh, void *msg)  #endif          GET_STATE (this, finh, state); -        state->flags = fci->flags;          ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);          if (ret < 0) { @@ -1817,38 +1532,44 @@ fuse_create (xlator_t *this, fuse_in_header_t *finh, void *msg)                          "%"PRIu64" CREATE %s (fuse_loc_fill() failed)",                          finh->unique, state->loc.path);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        state->loc.inode = inode_new (state->loc.parent->table); +        state->mode = fci->mode; +        state->flags = fci->flags; + +        fuse_resolve_and_resume (state, fuse_create_resume); + +        return; +} + +void +fuse_open_resume (fuse_state_t *state) +{ +        fd_t *fd = NULL; -        fd = fd_create (state->loc.inode, finh->pid); +        fd = fd_create (state->loc.inode, state->finh->pid);          state->fd = fd;          fd->flags = state->flags;          gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64": CREATE %s", finh->unique, +                "%"PRIu64": OPEN %s", state->finh->unique,                  state->loc.path); -        FUSE_FOP (state, fuse_create_cbk, GF_FOP_CREATE, -                  create, &state->loc, state->flags, fci->mode, fd); - -        return; +        FUSE_FOP (state, fuse_fd_cbk, GF_FOP_OPEN, +                  open, &state->loc, state->flags, fd, 0);  } -  static void  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;          GET_STATE (this, finh, state); -        state->flags = foi->flags;          ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);          if ((state->loc.inode == NULL) || @@ -1858,20 +1579,12 @@ fuse_open (xlator_t *this, fuse_in_header_t *finh, void *msg)                          finh->unique, state->loc.path);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        fd = fd_create (state->loc.inode, finh->pid); -        state->fd = fd; -        fd->flags = foi->flags; - -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64": OPEN %s", finh->unique, -                state->loc.path); - -        FUSE_FOP (state, fuse_fd_cbk, GF_FOP_OPEN, -                  open, &state->loc, foi->flags, fd, 0); +        state->flags = foi->flags; +        fuse_resolve_and_resume (state, fuse_open_resume);          return;  } @@ -1915,12 +1628,22 @@ fuse_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  send_fuse_err (this, finh, op_errno);          } -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0;  } +void +fuse_readv_resume (fuse_state_t *state) +{ +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": READ (%p, size=%zu, offset=%"PRIu64")", +                state->finh->unique, state->fd, state->size, state->off); + +        FUSE_FOP (state, fuse_readv_cbk, GF_FOP_READ, +                  readv, state->fd, state->size, state->off); +}  static void  fuse_readv (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -1933,8 +1656,6 @@ fuse_readv (xlator_t *this, fuse_in_header_t *finh, void *msg)          GET_STATE (this, finh, state); -        state->size = fri->size; -        state->off = fri->offset;          fd = FH_TO_FD (fri->fh);          state->fd = fd; @@ -1946,13 +1667,10 @@ fuse_readv (xlator_t *this, fuse_in_header_t *finh, void *msg)                  state->lk_owner = fri->lock_owner;  #endif -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"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, fri->size, fri->offset); +        state->size = fri->size; +        state->off = fri->offset; +        fuse_resolve_and_resume (state, fuse_readv_resume);  } @@ -1984,12 +1702,43 @@ fuse_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  send_fuse_err (this, finh, op_errno);          } -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0;  } +void +fuse_write_resume (fuse_state_t *state) +{ +        struct iobref *iobref = NULL; +        struct iobuf  *iobuf = NULL; + +        if (!state->fd || !state->fd->inode) { +                send_fuse_err (state->this, state->finh, EBADFD); +                free_fuse_state (state); +                return; +        } + +        iobref = iobref_new (); +        if (!iobref) { +                gf_log ("glusterfs-fuse", GF_LOG_ERROR, +                        "%"PRIu64": WRITE iobref allocation failed", +                        state->finh->unique); +                send_fuse_err (state->this, state->finh, ENOMEM); + +                free_fuse_state (state); +                return; +        } + +        iobuf = ((fuse_private_t *) (state->this->private))->iobuf; +        iobref_add (iobref, iobuf); + +        FUSE_FOP (state, fuse_writev_cbk, GF_FOP_WRITE, writev, state->fd, +                  &state->vector, 1, state->off, iobref); + +        iobref_unref (iobref); +}  static void  fuse_write (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -2002,20 +1751,15 @@ fuse_write (xlator_t *this, fuse_in_header_t *finh, void *msg)          fuse_private_t  *priv = NULL;          fuse_state_t    *state = NULL; -        struct iovec     vector;          fd_t            *fd = NULL; -        struct iobref   *iobref = NULL; -        struct iobuf    *iobuf = NULL;          priv = this->private;          GET_STATE (this, finh, state); -        state->size = fwi->size; -        state->off  = fwi->offset;          fd          = FH_TO_FD (fwi->fh);          state->fd   = fd; -        vector.iov_base = msg; -        vector.iov_len  = fwi->size; +        state->size = fwi->size; +        state->off  = fwi->offset;          /* See comment by similar code in fuse_settatr */          priv = this->private; @@ -2028,25 +1772,20 @@ fuse_write (xlator_t *this, fuse_in_header_t *finh, void *msg)                  "%"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", -                        finh->unique); - -                free_state (state); -                return; -        } -        iobuf = ((fuse_private_t *) (state->this->private))->iobuf; -        iobref_add (iobref, iobuf); +        state->vector.iov_base = msg; +        state->vector.iov_len  = fwi->size; -        FUSE_FOP (state, fuse_writev_cbk, GF_FOP_WRITE, -                  writev, fd, &vector, 1, fwi->offset, iobref); +        fuse_resolve_and_resume (state, fuse_write_resume); -        iobref_unref (iobref);          return;  } +void +fuse_flush_resume (fuse_state_t *state) +{ +        FUSE_FOP (state, fuse_err_cbk, GF_FOP_FLUSH, +                  flush, state->fd); +}  static void  fuse_flush (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -2067,22 +1806,30 @@ fuse_flush (xlator_t *this, fuse_in_header_t *finh, void *msg)          gf_log ("glusterfs-fuse", GF_LOG_TRACE,                  "%"PRIu64": FLUSH %p", finh->unique, fd); -        FUSE_FOP (state, fuse_err_cbk, GF_FOP_FLUSH, -                  flush, fd); +        fuse_resolve_and_resume (state, fuse_flush_resume);          return;  } +static int +fuse_release_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                  int32_t op_ret, int32_t op_errno) +{ +        STACK_DESTROY (frame->root); + +        return 0; +}  static void  fuse_release (xlator_t *this, fuse_in_header_t *finh, void *msg)  { -        struct fuse_release_in *fri = msg; - -        fd_t     *fd = NULL; -        int do_flush = 0; - -        fuse_state_t *state = NULL; +        struct fuse_release_in *fri        = msg; +        fd_t                   *new_fd     = NULL; +        fd_t                   *fd         = NULL; +        int                     do_flush   = 0; +        uint64_t                tmp_fd_ctx = 0; +        int                     ret        = 0; +        fuse_state_t           *state      = NULL;          GET_STATE (this, finh, state);          fd = FH_TO_FD (fri->fh); @@ -2122,25 +1869,47 @@ fuse_release (xlator_t *this, fuse_in_header_t *finh, void *msg)                  do_flush = 1;  #endif +        /* TODO */          gf_log ("glusterfs-fuse", GF_LOG_TRACE,                  "%"PRIu64": RELEASE %p%s", finh->unique, fd,                  do_flush ? " (FLUSH implied)" : "");          if (do_flush) {                  state->lk_owner = (uint64_t)-1; +                ret = fd_ctx_get (fd, this, &tmp_fd_ctx); +                if (!ret) { +                        new_fd = (fd_t *)(long)tmp_fd_ctx; +                        FUSE_FOP (state, fuse_release_cbk, GF_FOP_FLUSH, flush, +                                  new_fd); +                        fd_unref (new_fd); +                } +                  FUSE_FOP (state, fuse_err_cbk, GF_FOP_FLUSH, flush, fd); +                  fd_unref (fd);          } else { +                ret = fd_ctx_get (fd, this, &tmp_fd_ctx); +                if (!ret) { +                        new_fd = (fd_t *)(long)tmp_fd_ctx; +                        fd_unref (new_fd); +                }                  fd_unref (fd);                  send_fuse_err (this, finh, 0); -                free_state (state); +                free_fuse_state (state);          }          return;  } +void +fuse_fsync_resume (fuse_state_t *state) +{ +        /* fsync_flags: 1 means "datasync" (no defines for this) */ +        FUSE_FOP (state, fuse_fsync_cbk, GF_FOP_FSYNC, +                  fsync, state->fd, state->flags & 1); +}  static void  fuse_fsync (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -2157,13 +1926,26 @@ fuse_fsync (xlator_t *this, fuse_in_header_t *finh, void *msg)          gf_log ("glusterfs-fuse", GF_LOG_TRACE,                  "%"PRIu64": FSYNC %p", finh->unique, fd); -        /* fsync_flags: 1 means "datasync" (no defines for this) */ -        FUSE_FOP (state, fuse_fsync_cbk, GF_FOP_FSYNC, -                  fsync, fd, fsi->fsync_flags & 1); - +        state->flags = fsi->fsync_flags; +        fuse_resolve_and_resume (state, fuse_fsync_resume);          return;  } +void +fuse_opendir_resume (fuse_state_t *state) +{ +        fd_t *fd = NULL; + +        fd = fd_create (state->loc.inode, state->finh->pid); +        state->fd = fd; + +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": OPENDIR %s", state->finh->unique, +                state->loc.path); + +        FUSE_FOP (state, fuse_fd_cbk, GF_FOP_OPENDIR, +                  opendir, &state->loc, fd); +}  static void  fuse_opendir (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -2173,31 +1955,21 @@ fuse_opendir (xlator_t *this, fuse_in_header_t *finh, void *msg)           */          fuse_state_t *state = NULL; -        fd_t         *fd = NULL;          int32_t       ret = -1;          GET_STATE (this, finh, state);          ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL); -        if ((state->loc.inode == NULL) || -            (ret < 0)) { +        if ((state->loc.inode == NULL) || (ret < 0)) {                  gf_log ("glusterfs-fuse", GF_LOG_WARNING,                          "%"PRIu64": OPENDIR %s (fuse_loc_fill() failed)",                          finh->unique, state->loc.path);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        fd = fd_create (state->loc.inode, finh->pid); -        state->fd = fd; - -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64": OPENDIR %s", finh->unique, -                state->loc.path); - -        FUSE_FOP (state, fuse_fd_cbk, GF_FOP_OPENDIR, -                  opendir, &state->loc, fd); +        fuse_resolve_and_resume (state, fuse_opendir_resume);  } @@ -2289,7 +2061,7 @@ fuse_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          send_fuse_data (this, finh, buf, size);  out: -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          if (buf)                  GF_FREE (buf); @@ -2297,6 +2069,16 @@ out:  } +void +fuse_readdir_resume (fuse_state_t *state) +{ +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": READDIR (%p, size=%zu, offset=%"PRId64")", +                state->finh->unique, state->fd, state->size, state->off); + +        FUSE_FOP (state, fuse_readdir_cbk, GF_FOP_READDIR, +                  readdir, state->fd, state->size, state->off); +}  static void  fuse_readdir (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -2312,37 +2094,48 @@ fuse_readdir (xlator_t *this, fuse_in_header_t *finh, void *msg)          fd = FH_TO_FD (fri->fh);          state->fd = fd; -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"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, fri->size, fri->offset); +        fuse_resolve_and_resume (state, fuse_readdir_resume);  }  static void  fuse_releasedir (xlator_t *this, fuse_in_header_t *finh, void *msg)  { -        struct fuse_release_in *fri = msg; - -        fuse_state_t *state = NULL; +        struct fuse_release_in *fri        = msg; +        fd_t                   *new_fd     = NULL; +        uint64_t                tmp_fd_ctx = 0; +        int                     ret        = 0; +        fuse_state_t           *state      = NULL;          GET_STATE (this, finh, state);          state->fd = FH_TO_FD (fri->fh); +        /* TODO: free 'new-fd' in the ctx */          gf_log ("glusterfs-fuse", GF_LOG_TRACE,                  "%"PRIu64": RELEASEDIR %p", finh->unique, state->fd); +        ret = fd_ctx_get (state->fd, this, &tmp_fd_ctx); +        if (!ret) { +                new_fd = (fd_t *)(long)tmp_fd_ctx; +                fd_unref (new_fd); +        } +          fd_unref (state->fd);          send_fuse_err (this, finh, 0); -        free_state (state); +        free_fuse_state (state);          return;  } +void +fuse_fsyncdir_resume (fuse_state_t *state) +{ +        FUSE_FOP (state, fuse_err_cbk, GF_FOP_FSYNCDIR, +                  fsyncdir, state->fd, state->flags & 1); + +}  static void  fuse_fsyncdir (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -2357,8 +2150,8 @@ fuse_fsyncdir (xlator_t *this, fuse_in_header_t *finh, void *msg)          GET_STATE (this, finh, state);          state->fd = fd; -        FUSE_FOP (state, fuse_err_cbk, GF_FOP_FSYNCDIR, -                  fsyncdir, fd, fsi->fsync_flags & 1); +        state->flags = fsi->fsync_flags; +        fuse_resolve_and_resume (state, fuse_fsyncdir_resume);          return;  } @@ -2423,13 +2216,12 @@ fuse_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  send_fuse_err (this, finh, op_errno);          } -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0;  } -  static void  fuse_statfs (xlator_t *this, fuse_in_header_t *finh, void *msg)  { @@ -2445,7 +2237,7 @@ fuse_statfs (xlator_t *this, fuse_in_header_t *finh, void *msg)                          finh->unique);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } @@ -2456,6 +2248,16 @@ fuse_statfs (xlator_t *this, fuse_in_header_t *finh, void *msg)                    statfs, &state->loc);  } +void +fuse_setxattr_resume (fuse_state_t *state) +{ +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": SETXATTR %s/%"PRIu64" (%s)", state->finh->unique, +                state->loc.path, state->finh->nodeid, state->name); + +        FUSE_FOP (state, fuse_setxattr_cbk, GF_FOP_SETXATTR, +                  setxattr, &state->loc, state->dict, state->flags); +}  static void  fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -2499,7 +2301,7 @@ fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)                          state->loc.path, finh->nodeid, name);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } @@ -2509,7 +2311,7 @@ fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)                          "%"PRIu64": SETXATTR dict allocation failed",                          finh->unique); -                free_state (state); +                free_fuse_state (state);                  return;          } @@ -2518,12 +2320,10 @@ fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)                    data_from_dynptr ((void *)dict_value, fsi->size));          dict_ref (state->dict); -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64": SETXATTR %s/%"PRIu64" (%s)", finh->unique, -                state->loc.path, finh->nodeid, name); +        state->flags = fsi->flags; +        state->name = gf_strdup (name); -        FUSE_FOP (state, fuse_setxattr_cbk, GF_FOP_SETXATTR, -                  setxattr, &state->loc, state->dict, fsi->flags); +        fuse_resolve_and_resume (state, fuse_setxattr_resume);          return;  } @@ -2638,12 +2438,22 @@ out:          if (need_to_free_dict)                  dict_unref (dict); -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0;  } +void +fuse_getxattr_resume (fuse_state_t *state) +{ +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": GETXATTR %s/%"PRIu64" (%s)", state->finh->unique, +                state->loc.path, state->finh->nodeid, state->name); + +        FUSE_FOP (state, fuse_xattr_cbk, GF_FOP_GETXATTR, +                  getxattr, &state->loc, state->name); +}  static void  fuse_getxattr (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -2683,8 +2493,6 @@ fuse_getxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)  #endif          GET_STATE (this, finh, state); -        state->size = fgxi->size; -        state->name = gf_strdup (name);          ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);          if ((state->loc.inode == NULL) || @@ -2694,20 +2502,27 @@ fuse_getxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)                          finh->unique, state->loc.path, finh->nodeid, name);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"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); +        state->size = fgxi->size; +        state->name = gf_strdup (name); +        fuse_resolve_and_resume (state, fuse_getxattr_resume);          return;  } +void +fuse_listxattr_resume (fuse_state_t *state) +{ +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": LISTXATTR %s/%"PRIu64, state->finh->unique, +                state->loc.path, state->finh->nodeid); + +        FUSE_FOP (state, fuse_xattr_cbk, GF_FOP_GETXATTR, +                  getxattr, &state->loc, NULL); +}  static void  fuse_listxattr (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -2718,7 +2533,7 @@ fuse_listxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)          int32_t       ret = -1;          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)) { @@ -2727,20 +2542,26 @@ fuse_listxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)                          finh->unique, state->loc.path, finh->nodeid);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64": LISTXATTR %s/%"PRIu64, finh->unique, -                state->loc.path, finh->nodeid); - -        FUSE_FOP (state, fuse_xattr_cbk, GF_FOP_GETXATTR, -                  getxattr, &state->loc, NULL); +        state->size = fgxi->size; +        fuse_resolve_and_resume (state, fuse_listxattr_resume);          return;  } +void +fuse_removexattr_resume (fuse_state_t *state) +{ +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": REMOVEXATTR %s/%"PRIu64" (%s)", state->finh->unique, +                state->loc.path, state->finh->nodeid, state->name); + +        FUSE_FOP (state, fuse_err_cbk, GF_FOP_REMOVEXATTR, +                  removexattr, &state->loc, state->name); +}  static void  fuse_removexattr (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -2760,17 +2581,12 @@ fuse_removexattr (xlator_t *this, fuse_in_header_t *finh, void *msg)                          finh->unique, state->loc.path, finh->nodeid, name);                  send_fuse_err (this, finh, ENOENT); -                free_state (state); +                free_fuse_state (state);                  return;          } -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"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); - +        state->name = gf_strdup (name); +        fuse_resolve_and_resume (state, fuse_removexattr_resume);          return;  } @@ -2817,12 +2633,21 @@ fuse_getlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  send_fuse_err (this, state->finh, op_errno);          } -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0;  } +void +fuse_getlk_resume (fuse_state_t *state) +{ +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": GETLK %p", state->finh->unique, state->fd); + +        FUSE_FOP (state, fuse_getlk_cbk, GF_FOP_LK, +                  lk, state->fd, F_GETLK, &state->lk_lock); +}  static void  fuse_getlk (xlator_t *this, fuse_in_header_t *finh, void *msg) @@ -2831,20 +2656,15 @@ fuse_getlk (xlator_t *this, fuse_in_header_t *finh, void *msg)          fuse_state_t *state = NULL;          fd_t         *fd = NULL; -        struct flock  lock = {0, };          fd = FH_TO_FD (fli->fh);          GET_STATE (this, finh, state);          state->fd = fd; -        convert_fuse_file_lock (&fli->lk, &lock); +        convert_fuse_file_lock (&fli->lk, &state->lk_lock);          state->lk_owner = fli->owner; -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64": GETLK %p", finh->unique, fd); - -        FUSE_FOP (state, fuse_getlk_cbk, GF_FOP_LK, -                  lk, fd, F_GETLK, &lock); +        fuse_resolve_and_resume (state, fuse_getlk_resume);          return;  } @@ -2889,13 +2709,25 @@ fuse_setlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  send_fuse_err (this, state->finh, op_errno);          } -        free_state (state); +        free_fuse_state (state);          STACK_DESTROY (frame->root);          return 0;  } +void +fuse_setlk_resume (fuse_state_t *state) +{ +        gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                "%"PRIu64": SETLK%s %p", state->finh->unique, +                state->finh->opcode == FUSE_SETLK ? "" : "W", state->fd); + +        FUSE_FOP (state, fuse_setlk_cbk, GF_FOP_LK, lk, state->fd, +                  state->finh->opcode == FUSE_SETLK ? F_SETLK : F_SETLKW, +                  &state->lk_lock); +} +  static void  fuse_setlk (xlator_t *this, fuse_in_header_t *finh, void *msg)  { @@ -2903,23 +2735,16 @@ fuse_setlk (xlator_t *this, fuse_in_header_t *finh, void *msg)          fuse_state_t *state = NULL;          fd_t         *fd = NULL; -        struct flock  lock = {0, };          fd = FH_TO_FD (fli->fh);          GET_STATE (this, finh, state);          state->finh = finh;          state->fd = fd; -        convert_fuse_file_lock (&fli->lk, &lock); +        convert_fuse_file_lock (&fli->lk, &state->lk_lock);          state->lk_owner = fli->owner; -        gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRIu64": SETLK%s %p", finh->unique, -                finh->opcode == FUSE_SETLK ? "" : "W", fd); - -        FUSE_FOP (state, fuse_setlk_cbk, GF_FOP_LK, -                  lk, fd, finh->opcode == FUSE_SETLK ? F_SETLK : F_SETLKW, -                  &lock); +        fuse_resolve_and_resume (state, fuse_setlk_resume);          return;  } @@ -3142,8 +2967,9 @@ fuse_graph_sync (xlator_t *this)  unlock:          pthread_mutex_unlock (&priv->sync_mutex); -        if (need_first_lookup) +        if (need_first_lookup) {                  fuse_first_lookup (this); +        }          return 0;  } diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h new file mode 100644 index 00000000000..8165053e06f --- /dev/null +++ b/xlators/mount/fuse/src/fuse-bridge.h @@ -0,0 +1,277 @@ +/* +   Copyright (c) 2006-2009 Gluster, Inc. <http://www.gluster.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 _GF_FUSE_BRIDGE_H_ +#define _GF_FUSE_BRIDGE_H_ + +#include <stdint.h> +#include <signal.h> +#include <pthread.h> +#include <stddef.h> +#include <dirent.h> +#include <sys/mount.h> +#include <sys/time.h> + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif /* _CONFIG_H */ + +#include "glusterfs.h" +#include "logging.h" +#include "xlator.h" +#include "defaults.h" +#include "common-utils.h" +#include "glusterfsd-common.h" +#include "statedump.h" + +#ifdef GF_DARWIN_HOST_OS +/* This is MacFUSE's marker for MacFUSE-specific code */ +#define __FreeBSD__ 10 +#include "fuse_kernel_macfuse.h" +#else +#include "fuse_kernel.h" +#endif +#include "fuse-misc.h" +#include "fuse-mount.h" +#include "fuse-mem-types.h" + +#include "list.h" +#include "dict.h" + +/* TODO: when supporting posix acl, remove this definition */ +#define DISABLE_POSIX_ACL + +#ifdef GF_LINUX_HOST_OS +#define FUSE_OP_HIGH (FUSE_POLL + 1) +#endif +#ifdef GF_DARWIN_HOST_OS +#define FUSE_OP_HIGH (FUSE_DESTROY + 1) +#endif +#define GLUSTERFS_XATTR_LEN_MAX  65536 + +#define MAX_FUSE_PROC_DELAY 1 + +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; +        uint32_t             proto_minor; +        char                *volfile; +        size_t               volfile_size; +        char                *mount_point; +        struct iobuf        *iobuf; + +        pthread_t            fuse_thread; +        char                 fuse_thread_started; + +        uint32_t             direct_io_mode; +        size_t              *msg0_len_p; + +        double               entry_timeout; +        double               attribute_timeout; + +        pthread_cond_t       sync_cond; +        pthread_mutex_t      sync_mutex; +        char                 child_up; + +        char                 init_recvd; + +        gf_boolean_t         strict_volfile_check; + +        fuse_handler_t     **fuse_ops; +        fuse_handler_t     **fuse_ops0; +        pthread_mutex_t      fuse_dump_mutex; +        int                  fuse_dump_fd; + +        glusterfs_graph_t   *next_graph; +        xlator_t            *active_subvol; +}; +typedef struct fuse_private fuse_private_t; + +#define _FH_TO_FD(fh) ((fd_t *)(uintptr_t)(fh)) + +#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);                 \ +                if (!frame) {                                           \ +                         /* This is not completely clean, as some       \ +                          * earlier allocations might remain unfreed    \ +                          * if we return at this point, but still       \ +                          * better than trying to go on with a NULL     \ +                          * frame ...                                   \ +                          */                                            \ +                        gf_log ("glusterfs-fuse",                       \ +                                GF_LOG_ERROR,                           \ +                                "FUSE message"                          \ +                                " unique %"PRIu64" opcode %d:"          \ +                                " frame allocation failed",             \ +                                state->finh->unique,                    \ +                                state->finh->opcode);                   \ +                        free_fuse_state (state);                        \ +                        return;                                         \ +                }                                                       \ +                xl = fuse_state_subvol (state);                         \ +                                                                        \ +                frame->root->state = state;                             \ +                frame->root->op    = op_num;                            \ +		frame->op          = op_num;				\ +                STACK_WIND (frame, ret, xl, xl->fops->fop, args);       \ +        } while (0) + + +#define FUSE_FOP_COOKIE(state, xl, ret, cky, op_num, fop, args ...)     \ +        do {                                                            \ +                call_frame_t *frame = NULL;                             \ +                                                                        \ +                frame = get_call_frame_for_req (state);                 \ +                if (!frame) {                                           \ +                        gf_log ("glusterfs-fuse",                       \ +                                GF_LOG_ERROR,                           \ +                                "FUSE message"                          \ +                                " unique %"PRIu64" opcode %d:"          \ +                                " frame allocation failed",             \ +                                state->finh->unique,                    \ +                                state->finh->opcode);                   \ +                        free_fuse_state (state);                        \ +                        return 0;                                       \ +                }                                                       \ +                                                                        \ +                frame->root->state = state;                             \ +                frame->root->op    = op_num;                            \ +		frame->op          = op_num;				\ +                STACK_WIND_COOKIE (frame, ret, cky, xl, xl->fops->fop, args); \ +        } while (0) + +#define GF_SELECT_LOG_LEVEL(_errno)                     \ +        (((_errno == ENOENT) || (_errno == ESTALE))?    \ +         GF_LOG_DEBUG) + +#define GET_STATE(this, finh, state)                                       \ +        do {                                                               \ +                state = get_fuse_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);                \ +                        GF_FREE (finh);                                    \ +                                                                           \ +                        return;                                            \ +                }                                                          \ +        } while (0) + + + +typedef enum { +        RESOLVE_MUST = 1, +        RESOLVE_NOT, +        RESOLVE_MAY, +        RESOLVE_DONTCARE, +        RESOLVE_EXACT +} gf_resolve_type_t; + +struct gf_resolve_comp { +        char      *basename; +        ino_t      ino; +        uint64_t   gen; +        inode_t   *inode; +}; + +typedef struct { +        gf_resolve_type_t      type; +        ino_t                  ino; +        uint64_t               gen; +        ino_t                  par; +        fd_t                  *fd; +        char                  *path; +        char                  *bname; +	char                  *resolved; +        int                    op_ret; +        int                    op_errno; +        loc_t                  deep_loc; +        struct gf_resolve_comp *components; +        int                    comp_count; +} gf_resolve_t; + + +typedef struct { +        void             *pool; +        xlator_t         *this; +        inode_table_t    *itable; +        loc_t             loc; +        loc_t             loc2; +        fuse_in_header_t *finh; +        int32_t           flags; +        off_t             off; +        size_t            size; +        unsigned long     nlookup; +        fd_t             *fd; +        dict_t           *dict; +        char             *name; +        char              is_revalidate; +        gf_boolean_t      truncate_needed; +        gf_lock_t         lock; +        uint64_t          lk_owner; + +        /* used within resolve_and_resume */ +        /* */ +        gf_resolve_t resolve; +        gf_resolve_t resolve2; + +        loc_t        *loc_now; +        gf_resolve_t *resolve_now; + +        void *resume_fn; + +        int            valid; +        int            mask; +        dev_t          rdev; +        mode_t         mode; +        struct iatt    attr; +        struct flock   lk_lock; +        struct iovec   vector; +} fuse_state_t; + +typedef void (*fuse_resume_fn_t) (fuse_state_t *state); + +GF_MUST_CHECK int32_t +fuse_loc_fill (loc_t *loc, fuse_state_t *state, ino_t ino, +               ino_t par, const char *name); +call_frame_t *get_call_frame_for_req (fuse_state_t *state); +fuse_state_t *get_fuse_state (xlator_t *this, fuse_in_header_t *finh); +void free_fuse_state (fuse_state_t *state); +void gf_fuse_stat2attr (struct iatt *st, struct fuse_attr *fa); +uint64_t inode_to_fuse_nodeid (inode_t *inode); +xlator_t *fuse_state_subvol (fuse_state_t *state); +xlator_t *fuse_active_subvol (xlator_t *fuse); +inode_t *fuse_ino_to_inode (uint64_t ino, xlator_t *fuse); +int fuse_resolve_and_resume (fuse_state_t *state, fuse_resume_fn_t fn); + +#endif /* _GF_FUSE_BRIDGE_H_ */ diff --git a/xlators/mount/fuse/src/fuse-helpers.c b/xlators/mount/fuse/src/fuse-helpers.c new file mode 100644 index 00000000000..d478d014db0 --- /dev/null +++ b/xlators/mount/fuse/src/fuse-helpers.c @@ -0,0 +1,300 @@ +/* +   Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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/>. +*/ + +#include "fuse-bridge.h" + +xlator_t * +fuse_state_subvol (fuse_state_t *state) +{ +        xlator_t *subvol = NULL; + +        if (!state) +                return NULL; + +        if (state->loc.inode) +                subvol = state->loc.inode->table->xl; + +        if (state->fd) +                subvol = state->fd->inode->table->xl; + +        return subvol; +} + + +xlator_t * +fuse_active_subvol (xlator_t *fuse) +{ +        fuse_private_t *priv = NULL; + +        priv = fuse->private; + +        return priv->active_subvol; +} + + + +static void +fuse_resolve_wipe (gf_resolve_t *resolve) +{ +        struct gf_resolve_comp *comp = NULL; + +        if (resolve->path) +                GF_FREE ((void *)resolve->path); + +        if (resolve->bname) +                GF_FREE ((void *)resolve->bname); + +        if (resolve->resolved) +                GF_FREE ((void *)resolve->resolved); + +        loc_wipe (&resolve->deep_loc); + +        comp = resolve->components; + +        if (comp) { +/* +                int                  i = 0; + +                for (i = 0; comp[i].basename; i++) { +                        if (comp[i].inode) +                                inode_unref (comp[i].inode); +                } +*/ +                GF_FREE ((void *)resolve->components); +        } +} + +void +free_fuse_state (fuse_state_t *state) +{ +        loc_wipe (&state->loc); + +        loc_wipe (&state->loc2); + +        if (state->dict) { +                dict_unref (state->dict); +                state->dict = (void *)0xaaaaeeee; +        } +        if (state->name) { +                GF_FREE (state->name); +                state->name = NULL; +        } +        if (state->fd) { +                fd_unref (state->fd); +                state->fd = (void *)0xfdfdfdfd; +        } +        if (state->finh) { +                GF_FREE (state->finh); +                state->finh = NULL; +        } + +        fuse_resolve_wipe (&state->resolve); +        fuse_resolve_wipe (&state->resolve2); + +#ifdef DEBUG +        memset (state, 0x90, sizeof (*state)); +#endif +        GF_FREE (state); +        state = NULL; +} + + +fuse_state_t * +get_fuse_state (xlator_t *this, fuse_in_header_t *finh) +{ +        fuse_state_t *state = NULL; + +        state = (void *)GF_CALLOC (1, sizeof (*state), +                                   gf_fuse_mt_fuse_state_t); +        if (!state) +                return NULL; +        state->pool = this->ctx->pool; +        state->finh = finh; +        state->this = this; + +        LOCK_INIT (&state->lock); + +        return state; +} + + +call_frame_t * +get_call_frame_for_req (fuse_state_t *state) +{ +        call_pool_t           *pool = NULL; +        fuse_in_header_t      *finh = NULL; +        call_frame_t          *frame = NULL; +        xlator_t              *this = NULL; + +        pool = state->pool; +        finh = state->finh; +        this = state->this; + +        frame = create_frame (this, pool); +        if (!frame) +                return NULL; + +        if (finh) { +                frame->root->uid      = finh->uid; +                frame->root->gid      = finh->gid; +                frame->root->pid      = finh->pid; +                frame->root->lk_owner = state->lk_owner; +                frame->root->unique   = finh->unique; +        } + +        frame->root->type = GF_OP_TYPE_FOP; + +        return frame; +} + + +inode_t * +fuse_ino_to_inode (uint64_t ino, xlator_t *fuse) +{ +        inode_t  *inode = NULL; +        xlator_t *active_subvol = NULL; + +        if (ino == 1) { +                active_subvol = fuse_active_subvol (fuse); +                inode = active_subvol->itable->root; +        } else { +                inode = (inode_t *) (unsigned long) ino; +                inode_ref (inode); +        } + +        return inode; +} + +uint64_t +inode_to_fuse_nodeid (inode_t *inode) +{ +        if (!inode || inode->ino == 1) +                return 1; + +        return (unsigned long) inode; +} + + +GF_MUST_CHECK int32_t +fuse_loc_fill (loc_t *loc, fuse_state_t *state, ino_t ino, +               ino_t par, const char *name) +{ +        inode_t  *inode = NULL; +        inode_t  *parent = NULL; +        int32_t   ret = -1; +        char     *path = NULL; + +        /* resistance against multiple invocation of loc_fill not to get +           reference leaks via inode_search() */ + +        if (name) { +                parent = loc->parent; +                if (!parent) { +                        parent = fuse_ino_to_inode (par, state->this); +                        loc->parent = parent; +                } + +                inode = loc->inode; +                if (!inode) { +                        inode = inode_grep (parent->table, parent, name); +                        loc->inode = inode; +                } + +                ret = inode_path (parent, name, &path); +                if (ret <= 0) { +                        gf_log ("glusterfs-fuse", GF_LOG_DEBUG, +                                "inode_path failed for %"PRId64"/%s", +                                parent->ino, name); +                        goto fail; +                } +                loc->path = path; +        } else { +                inode = loc->inode; +                if (!inode) { +                        inode = fuse_ino_to_inode (ino, state->this); +                        loc->inode = inode; +                } + +                parent = loc->parent; +                if (!parent) { +                        parent = inode_parent (inode, par, name); +                        loc->parent = parent; +                } + +                ret = inode_path (inode, NULL, &path); +                if (ret <= 0) { +                        gf_log ("glusterfs-fuse", GF_LOG_DEBUG, +                                "inode_path failed for %"PRId64, +                                inode->ino); +                        goto fail; +                } +                loc->path = path; +        } + +        if (inode) +                loc->ino = inode->ino; + +        if (loc->path) { +                loc->name = strrchr (loc->path, '/'); +                if (loc->name) +                        loc->name++; +                else +                        loc->name = ""; +        } + +        if ((ino != 1) && (parent == NULL)) { +                gf_log ("fuse-bridge", GF_LOG_DEBUG, +                        "failed to search parent for %"PRId64"/%s (%"PRId64")", +                        (ino_t)par, name, (ino_t)ino); +                ret = -1; +                goto fail; +        } +        ret = 0; +fail: +        return ret; +} + + +/* courtesy of folly */ +void +gf_fuse_stat2attr (struct iatt *st, struct fuse_attr *fa) +{ +        fa->ino        = st->ia_ino; +        fa->size       = st->ia_size; +        fa->blocks     = st->ia_blocks; +        fa->atime      = st->ia_atime; +        fa->mtime      = st->ia_mtime; +        fa->ctime      = st->ia_ctime; +        fa->atimensec  = st->ia_atime_nsec; +        fa->mtimensec  = st->ia_mtime_nsec; +        fa->ctimensec  = st->ia_ctime_nsec; +        fa->mode       = st_mode_from_ia (st->ia_prot, st->ia_type); +        fa->nlink      = st->ia_nlink; +        fa->uid        = st->ia_uid; +        fa->gid        = st->ia_gid; +        fa->rdev       = st->ia_rdev; +#if FUSE_KERNEL_MINOR_VERSION >= 9 +        fa->blksize    = st->ia_blksize; +#endif +#ifdef GF_DARWIN_HOST_OS +        fa->crtime     = (uint64_t)-1; +        fa->crtimensec = (uint32_t)-1; +        fa->flags      = 0; +#endif +} diff --git a/xlators/mount/fuse/src/fuse-resolve.c b/xlators/mount/fuse/src/fuse-resolve.c new file mode 100644 index 00000000000..b90ef3d5f8d --- /dev/null +++ b/xlators/mount/fuse/src/fuse-resolve.c @@ -0,0 +1,747 @@ +/* +  Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 + +#include "fuse-bridge.h" + +static int +gf_resolve_all (fuse_state_t *state); +static int +resolve_entry_simple (fuse_state_t *state); +static int +resolve_inode_simple (fuse_state_t *state); +static int +resolve_path_simple (fuse_state_t *state); + +static int +component_count (const char *path) +{ +        int         count = 0; +        const char *trav = NULL; + +        for (trav = path; *trav; trav++) { +                if (*trav == '/') +                        count++; +        } + +        return count + 2; +} + + +static int +prepare_components (fuse_state_t *state) +{ +        xlator_t               *active_xl  = NULL; +        gf_resolve_t           *resolve    = NULL; +        char                   *resolved   = NULL; +        struct gf_resolve_comp *components = NULL; +        char                   *trav       = NULL; +        int                     count      = 0; +        int                     i          = 0; + +        resolve = state->resolve_now; + +        resolved = gf_strdup (resolve->path); +        resolve->resolved = resolved; + +        count = component_count (resolve->path); +        components = GF_CALLOC (sizeof (*components), count, 0); //TODO +        if (!components) +                goto out; +        resolve->components = components; + +        active_xl = fuse_active_subvol (state->this); + +        components[0].basename = ""; +        components[0].ino      = 1; +        components[0].gen      = 0; +        components[0].inode    = inode_ref (active_xl->itable->root); + +        i = 1; +        for (trav = resolved; *trav; trav++) { +                if (*trav == '/') { +                        components[i].basename = trav + 1; +                        *trav = 0; +                        i++; +                } +        } +out: +        return 0; +} + + +static int +resolve_loc_touchup (fuse_state_t *state) +{ +        gf_resolve_t *resolve = NULL; +        loc_t        *loc     = NULL; +        char         *path    = NULL; +        int           ret     = 0; + +        resolve = state->resolve_now; +        loc     = state->loc_now; + +        if (!loc->path) { +                if (loc->parent) { +                        ret = inode_path (loc->parent, resolve->bname, &path); +                } else if (loc->inode) { +                        ret = inode_path (loc->inode, NULL, &path); +                } +                if (ret) +                        gf_log ("", GF_LOG_TRACE, +                                "return value inode_path %d", ret); + +                if (!path) +                        path = gf_strdup (resolve->path); + +                loc->path = path; +        } + +        loc->name = strrchr (loc->path, '/'); +        if (loc->name) +                loc->name++; + +        if (!loc->parent && loc->inode) { +                loc->parent = inode_parent (loc->inode, 0, NULL); +        } + +        return 0; +} + +static int +fuse_resolve_newfd_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      = NULL; +        gf_resolve_t *resolve    = NULL; +        fd_t         *old_fd     = NULL; +        fd_t         *tmp_fd     = NULL; +        uint64_t      tmp_fd_ctx = 0; +        int           ret        = 0; + +        state = frame->root->state; +        resolve = state->resolve_now; + +        STACK_DESTROY (frame->root); + +        if (op_ret == -1) { +                goto out; +        } + +        old_fd = resolve->fd; + +        state->fd = fd_ref (fd); + +        fd_bind (fd); + +        resolve->fd = NULL; +        ret = fd_ctx_del (old_fd, state->this, &tmp_fd_ctx); +        if (!ret) { +                tmp_fd = (fd_t *)(long)tmp_fd_ctx; +                fd_unref (tmp_fd); +        } +        ret = fd_ctx_set (old_fd, state->this, (uint64_t)(long)fd); +        if (ret) +                gf_log ("resolve", GF_LOG_WARNING, +                        "failed to set the fd ctx with resolved fd"); +out: +        gf_resolve_all (state); +        return 0; +} + +static void +gf_resolve_new_fd (fuse_state_t *state) +{ +        gf_resolve_t *resolve = NULL; +        fd_t         *new_fd  = NULL; +        fd_t         *fd      = NULL; + +        resolve = state->resolve_now; +        fd = resolve->fd; + +        new_fd = fd_create (state->loc.inode, state->finh->pid); +        new_fd->flags = (fd->flags & ~O_TRUNC); + +        gf_log ("resolve", GF_LOG_DEBUG, +                "%"PRIu64": OPEN %s", state->finh->unique, +                state->loc.path); + +        FUSE_FOP (state, fuse_resolve_newfd_cbk, GF_FOP_OPEN, +                  open, &state->loc, new_fd->flags, new_fd, 0); +} + +static int +resolve_deep_continue (fuse_state_t *state) +{ +        gf_resolve_t     *resolve = NULL; +        int               ret = 0; + +        resolve = state->resolve_now; + +        resolve->op_ret   = 0; +        resolve->op_errno = 0; + +        if (resolve->par) +                ret = resolve_entry_simple (state); +        else if (resolve->ino) +                ret = resolve_inode_simple (state); +        else if (resolve->path) +                ret = resolve_path_simple (state); +        if (ret) +                gf_log ("resolve", GF_LOG_TRACE, +                        "return value of resolve_*_simple %d", ret); + +        resolve_loc_touchup (state); + +        /* This function is called by either fd resolve or inode resolve */ +        if (!resolve->fd) +                gf_resolve_all (state); +        else +                gf_resolve_new_fd (state); + +        return 0; +} + + +static int +resolve_deep_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                  int op_ret, int op_errno, inode_t *inode, struct iatt *buf, +                  dict_t *xattr, struct iatt *postparent) +{ +        xlator_t               *active_xl = NULL; +        fuse_state_t           *state      = NULL; +        gf_resolve_t           *resolve    = NULL; +        struct gf_resolve_comp *components = NULL; +        inode_t                *link_inode = NULL; +        int                     i          = 0; + +        state = frame->root->state; +        resolve = state->resolve_now; +        components = resolve->components; + +        i = (long) cookie; + +        STACK_DESTROY (frame->root); + +        if (op_ret == -1) { +                goto get_out_of_here; +        } + +        if (i != 0) { +                inode_ref (inode); +                /* no linking for root inode */ +                link_inode = inode_link (inode, resolve->deep_loc.parent, +                                         resolve->deep_loc.name, buf); +                components[i].inode  = inode_ref (link_inode); +                link_inode = NULL; +        } +        inode_ref (resolve->deep_loc.parent); +        inode_ref (inode); +        loc_wipe (&resolve->deep_loc); +        i++; /* next component */ + +        if (!components[i].basename) { +                /* all components of the path are resolved */ +                goto get_out_of_here; +        } + +        /* join the current component with the path resolved until now */ +        *(components[i].basename - 1) = '/'; + +        active_xl = fuse_active_subvol (state->this); + +        resolve->deep_loc.path   = gf_strdup (resolve->resolved); +        resolve->deep_loc.parent = inode_ref (components[i-1].inode); +        resolve->deep_loc.inode  = inode_new (active_xl->itable); +        resolve->deep_loc.name   = components[i].basename; + +        FUSE_FOP_COOKIE (state, active_xl, resolve_deep_cbk, (void *)(long)i, +                         GF_FOP_LOOKUP, lookup, &resolve->deep_loc, NULL); +        return 0; + +get_out_of_here: +        resolve_deep_continue (state); +        return 0; +} + + +static int +resolve_path_deep (fuse_state_t *state) +{ +        xlator_t               *active_xl  = NULL; +        gf_resolve_t           *resolve    = NULL; +        struct gf_resolve_comp *components = NULL; +        inode_t                *inode      = NULL; +        long                    i          = 0; + +        resolve = state->resolve_now; + +        prepare_components (state); + +        components = resolve->components; + +        /* start from the root */ +        active_xl = fuse_active_subvol (state->this); +        resolve->deep_loc.inode = inode_ref (active_xl->itable->root); +        resolve->deep_loc.path  = gf_strdup ("/"); +        resolve->deep_loc.name  = ""; + +        for (i = 1; components[i].basename; i++) { +                *(components[i].basename - 1) = '/'; +                inode = inode_grep (active_xl->itable, components[i-1].inode, +                                    components[i].basename); +                if (!inode) +                        break; +                components[i].inode = inode_ref (inode); +        } + +        if (!components[i].basename) +                goto resolved; + +        resolve->deep_loc.path   = gf_strdup (resolve->resolved); +        resolve->deep_loc.parent = inode_ref (components[i-1].inode); +        resolve->deep_loc.inode  = inode_new (active_xl->itable); +        resolve->deep_loc.name   = components[i].basename; + +        FUSE_FOP_COOKIE (state, active_xl, resolve_deep_cbk, (void *)(long)i, +                         GF_FOP_LOOKUP, lookup, &resolve->deep_loc, NULL); + +        return 0; +resolved: +        resolve_deep_continue (state); +        return 0; +} + + +static int +resolve_path_simple (fuse_state_t *state) +{ +        gf_resolve_t           *resolve    = NULL; +        struct gf_resolve_comp *components = NULL; +        int                     ret        = -1; +        int                     par_idx    = 0; +        int                     ino_idx    = 0; +        int                     i          = 0; + +        resolve = state->resolve_now; +        components = resolve->components; + +        if (!components) { +                resolve->op_ret   = -1; +                resolve->op_errno = ENOENT; +                goto out; +        } + +        for (i = 0; components[i].basename; i++) { +                par_idx = ino_idx; +                ino_idx = i; +        } + +        if (!components[par_idx].inode) { +                resolve->op_ret    = -1; +                resolve->op_errno  = ENOENT; +                goto out; +        } + +        if (!components[ino_idx].inode && +            (resolve->type == RESOLVE_MUST || resolve->type == RESOLVE_EXACT)) { +                resolve->op_ret    = -1; +                resolve->op_errno  = ENOENT; +                goto out; +        } + +        if (components[ino_idx].inode && resolve->type == RESOLVE_NOT) { +                resolve->op_ret    = -1; +                resolve->op_errno  = EEXIST; +                goto out; +        } + +        if (components[ino_idx].inode) +                state->loc_now->inode  = inode_ref (components[ino_idx].inode); +        state->loc_now->parent = inode_ref (components[par_idx].inode); + +        ret = 0; + +out: +        return ret; +} + +/* +  Check if the requirements are fulfilled by entries in the inode cache itself +  Return value: +  <= 0 - simple resolution was decisive and complete (either success or failure) +  > 0  - indecisive, need to perform deep resolution +*/ + +static int +resolve_entry_simple (fuse_state_t *state) +{ +        xlator_t     *this    = NULL; +        xlator_t     *active_xl = NULL; +        gf_resolve_t *resolve = NULL; +        inode_t      *parent  = NULL; +        inode_t      *inode   = NULL; +        int           ret     = 0; + +        this  = state->this; +        resolve = state->resolve_now; + +        active_xl = fuse_active_subvol (this); + +        parent = inode_get (active_xl->itable, resolve->par, 0); +        if (!parent) { +                /* simple resolution is indecisive. need to perform +                   deep resolution */ +                resolve->op_ret   = -1; +                resolve->op_errno = ENOENT; +                ret = 1; + +                inode = inode_grep (active_xl->itable, parent, resolve->bname); +                if (inode != NULL) { +                        gf_log (this->name, GF_LOG_DEBUG, "%"PRId64": inode " +                                "(pointer:%p ino: %"PRIu64") present but parent" +                                " is NULL for path (%s)", 0L, +                                inode, inode->ino, resolve->path); +                        inode_unref (inode); +                } +                goto out; +        } + +        /* expected @parent was found from the inode cache */ +        state->loc_now->parent = inode_ref (parent); + +        inode = inode_grep (active_xl->itable, parent, resolve->bname); +        if (!inode) { +                switch (resolve->type) { +                case RESOLVE_DONTCARE: +                case RESOLVE_NOT: +                        ret = 0; +                        break; +                case RESOLVE_MAY: +                        ret = 1; +                        break; +                default: +                        resolve->op_ret   = -1; +                        resolve->op_errno = ENOENT; +                        ret = 1; +                        break; +                } + +                goto out; +        } + +        if (resolve->type == RESOLVE_NOT) { +                gf_log (this->name, GF_LOG_DEBUG, "inode (pointer: %p ino:%" +                        PRIu64") found for path (%s) while type is RESOLVE_NOT", +                        inode, inode->ino, resolve->path); +                resolve->op_ret   = -1; +                resolve->op_errno = EEXIST; +                ret = -1; +                goto out; +        } + +        ret = 0; + +        state->loc_now->inode  = inode_ref (inode); + +out: +        if (parent) +                inode_unref (parent); + +        if (inode) +                inode_unref (inode); + +        return ret; +} + + +static int +gf_resolve_entry (fuse_state_t *state) +{ +        int                 ret = 0; +        loc_t              *loc = NULL; + +        loc  = state->loc_now; + +        ret = resolve_entry_simple (state); + +        if (ret > 0) { +                loc_wipe (loc); +                resolve_path_deep (state); +                return 0; +        } + +        if (ret == 0) +                resolve_loc_touchup (state); + +        gf_resolve_all (state); + +        return 0; +} + + +static int +resolve_inode_simple (fuse_state_t *state) +{ +        xlator_t     *active_xl = NULL; +        gf_resolve_t *resolve = NULL; +        inode_t      *inode   = NULL; +        int           ret     = 0; + +        resolve = state->resolve_now; + +        active_xl = fuse_active_subvol (state->this); + +        if (resolve->type == RESOLVE_EXACT) { +                inode = inode_get (active_xl->itable, resolve->ino, +                                   resolve->gen); +        } else { +                inode = inode_get (active_xl->itable, resolve->ino, 0); +        } + +        if (!inode) { +                resolve->op_ret   = -1; +                resolve->op_errno = ENOENT; +                ret = 1; +                goto out; +        } + +        ret = 0; + +        state->loc_now->inode = inode_ref (inode); + +out: +        if (inode) +                inode_unref (inode); + +        return ret; +} + + +static int +gf_resolve_inode (fuse_state_t *state) +{ +        int                 ret = 0; +        loc_t              *loc = NULL; + +        loc  = state->loc_now; + +        ret = resolve_inode_simple (state); + +        if (ret > 0) { +                loc_wipe (loc); +                resolve_path_deep (state); +                return 0; +        } + +        if (ret == 0) +                resolve_loc_touchup (state); + +        gf_resolve_all (state); + +        return 0; +} + + +static int +gf_resolve_fd (fuse_state_t *state) +{ +        gf_resolve_t  *resolve    = NULL; +        fd_t          *fd         = NULL; +        int            ret        = 0; +        uint64_t       tmp_fd_ctx = 0; +        char          *path       = NULL; +        char          *name       = NULL; + +        resolve = state->resolve_now; + +        fd = resolve->fd; + +        ret = fd_ctx_get (fd, state->this, &tmp_fd_ctx); +        if (!ret) { +                state->fd = (fd_t *)(long)tmp_fd_ctx; +                fd_ref (state->fd); +                gf_resolve_all (state); +                goto out; +        } + +        ret = inode_path (fd->inode, 0, &path); +        if (!ret || !path) +                gf_log ("", GF_LOG_WARNING, +                        "failed to do inode-path on fd %d %s", ret, path); + +        name = strrchr (path, '/'); +        if (name) +                name++; + +        resolve->path = path; +        resolve->bname = gf_strdup (name); + +        state->loc_now     = &state->loc; + +        resolve_path_deep (state); + +out: +        return 0; +} + + +static int +gf_resolve (fuse_state_t *state) + { +        gf_resolve_t   *resolve = NULL; + +        resolve = state->resolve_now; + +        if (resolve->fd) { + +                gf_resolve_fd (state); + +        } else if (resolve->par) { + +                gf_resolve_entry (state); + +        } else if (resolve->ino) { + +                gf_resolve_inode (state); + +        } else if (resolve->path) { + +                resolve_path_deep (state); + +        } else  { + +                resolve->op_ret = -1; +                resolve->op_errno = EINVAL; + +                gf_resolve_all (state); +        } + +        return 0; +} + + +static int +gf_resolve_done (fuse_state_t *state) +{ +        fuse_resume_fn_t fn = NULL; + +        fn = state->resume_fn; +        if (fn) +                fn (state); + +        return 0; +} + + +/* + * This function is called multiple times, once per resolving one location/fd. + * state->resolve_now is used to decide which location/fd is to be resolved now + */ +static int +gf_resolve_all (fuse_state_t *state) +{ +        xlator_t     *this = NULL; + +        if (state->resolve_now == NULL) { + +                state->resolve_now = &state->resolve; +                state->loc_now     = &state->loc; + +                gf_resolve (state); + +        } else if (state->resolve_now == &state->resolve) { + +                state->resolve_now = &state->resolve2; +                state->loc_now     = &state->loc2; + +                gf_resolve (state); + +        } else if (state->resolve_now == &state->resolve2) { + +                gf_resolve_done (state); + +        } else { +                gf_log (this->name, GF_LOG_ERROR, +                        "Invalid pointer for state->resolve_now"); +        } + +        return 0; +} + + +int +fuse_resolve_and_resume (fuse_state_t *state, fuse_resume_fn_t fn) +{ +        xlator_t *inode_xl = NULL; +        xlator_t *active_xl = NULL; + +        state->resume_fn = fn; + +        active_xl = fuse_active_subvol (state->this); +        inode_xl = fuse_state_subvol (state); +        if (!inode_xl && state->loc.parent) +                inode_xl = state->loc.parent->table->xl; + +        /* If inode or fd is already in new graph, goto resume */ +        if (inode_xl == active_xl) +                goto resume; + +        /* If the resolve is for 'fd' and its open with 'write' flag +           set, don't switch to new graph yet */ +        if (state->fd && ((state->fd->flags & O_RDWR) || +                          (state->fd->flags & O_WRONLY))) +                goto resume; + +        if (state->loc.path) { +                state->resolve.path = gf_strdup (state->loc.path); +                state->resolve.bname = gf_strdup (state->loc.name); +                /* TODO: make sure there is no leaks in inode refs */ +                //loc_wipe (&state->loc); +                state->loc.inode = NULL; +                state->loc.parent = NULL; +        } + +        /* Needed for rename and link */ +        if (state->loc2.path) { +                state->resolve2.path = gf_strdup (state->loc2.path); +                state->resolve2.bname = gf_strdup (state->loc2.name); +                //loc_wipe (&state->loc2); +                state->loc2.inode = NULL; +                state->loc2.parent = NULL; +        } + +        if (state->fd) { +                state->resolve.fd = state->fd; +                /* TODO: check if its a leak, if yes, then do 'unref' */ +                state->fd = NULL; +        } + +        gf_resolve_all (state); + +        return 0; +resume: +        fn (state); + +        return 0; +} diff --git a/xlators/performance/write-behind/src/write-behind.c b/xlators/performance/write-behind/src/write-behind.c index d9fe4190707..23f2d56b95a 100644 --- a/xlators/performance/write-behind/src/write-behind.c +++ b/xlators/performance/write-behind/src/write-behind.c @@ -436,7 +436,7 @@ wb_sync (call_frame_t *frame, wb_file_t *file, list_head_t *winds)          }          if (total_count == 0) { -                gf_log (file->this->name, GF_LOG_DEBUG, "no vectors are to be" +                gf_log (file->this->name, GF_LOG_TRACE, "no vectors are to be"                          "synced");                  goto out;          }  | 
