diff options
Diffstat (limited to 'xlators/mount/fuse/src/fuse-bridge.c')
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 257 | 
1 files changed, 241 insertions, 16 deletions
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index b002d264c12..8b97800a92c 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -494,7 +494,117 @@ stat2attr (struct stat *st, struct fuse_attr *fa)  static int  fuse_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                   int32_t op_ret, int32_t op_errno, -                 inode_t *inode, struct stat *stat, dict_t *dict); +                 inode_t *inode, struct stat *stat, dict_t *dict, +                 struct stat *postparent); + +         +static int +fuse_newentry_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                   int32_t op_ret, int32_t op_errno, +                   inode_t *inode, struct stat *buf, struct stat *preparent, +                   struct stat *postparent) +{ +        fuse_state_t            *state = NULL; +        fuse_in_header_t        *finh = NULL; +        struct fuse_entry_out    feo = {0, }; +        struct fuse_attr_out    *fao = NULL; +        fuse_private_t          *priv = NULL; + +        priv = this->private; +        state = frame->root->state; +        finh = state->finh; + +        if (!op_ret && state->loc.ino == 1) { +                buf->st_ino = 1; +        } + +        if (state->is_revalidate == 1 +            && need_fresh_lookup (op_ret, op_errno, &state->loc, buf)) { +                inode_unref (state->loc.inode); +                state->loc.inode = inode_new (state->itable); +                state->is_revalidate = 2; + +                STACK_WIND (frame, fuse_lookup_cbk, +                            FIRST_CHILD (this), +                            FIRST_CHILD (this)->fops->lookup, +                            &state->loc, state->dict); + +                return 0; +        } + +        if (op_ret == 0) { +                gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                        "%"PRIu64": %s() %s => %"PRId64" (%"PRId64")", +                        frame->root->unique, gf_fop_list[frame->root->op], +                        state->loc.path, buf->st_ino, state->loc.ino); + +                inode_link (inode, state->loc.parent, state->loc.name, buf); + +                inode_lookup (inode); + +                buf->st_blksize = this->ctx->page_size; +                stat2attr (buf, &feo.attr); + +                if (!inode->ino || !buf->st_ino) { +                        gf_log ("glusterfs-fuse", GF_LOG_WARNING, +                                "%"PRIu64": %s() %s returning inode 0", +                                frame->root->unique, +                                gf_fop_list[frame->root->op], state->loc.path); +                } + +                if (state->loc.parent) { +                        /* TODO: make these timeouts configurable (via meta?) */ +                        feo.nodeid = inode->ino; + +#ifdef GF_DARWIN_HOST_OS +                        feo.generation = 0; +#else +                        feo.generation = buf->st_ctime; +#endif + +                        feo.entry_valid = +                          calc_timeout_sec (priv->entry_timeout); +                        feo.entry_valid_nsec = +                          calc_timeout_nsec (priv->entry_timeout); +                        feo.attr_valid = +                          calc_timeout_sec (priv->attribute_timeout); +                        feo.attr_valid_nsec = +                          calc_timeout_nsec (priv->attribute_timeout); + +                        priv->proto_minor >= 9 ? +                        send_fuse_obj (this, finh, &feo) : +                        send_fuse_data (this, finh, &feo, +                                        FUSE_COMPAT_ENTRY_OUT_SIZE); +                } else { +                        /* Refurbish the entry_out as attr_out. Too hacky?... */ +                        fao = (struct fuse_attr_out *) +                               ((char *)&feo.attr - +                                offsetof (struct fuse_attr_out, attr)); + +                        fao->attr_valid = +                          calc_timeout_sec (priv->attribute_timeout); +                        fao->attr_valid_nsec = +                          calc_timeout_nsec (priv->attribute_timeout); + +                        priv->proto_minor >= 9 ? +                        send_fuse_obj (this, finh, fao) : +                        send_fuse_data (this, finh, fao, +                                        FUSE_COMPAT_ATTR_OUT_SIZE); +                } +        } else { +                gf_log ("glusterfs-fuse", +                        (op_errno == ENOENT ? GF_LOG_TRACE : GF_LOG_WARNING), +                        "%"PRIu64": %s() %s => -1 (%s)", frame->root->unique, +                        gf_fop_list[frame->root->op], state->loc.path, +                        strerror (op_errno)); +                send_fuse_err (this, state->finh, op_errno); +        } + +        free_state (state); +        STACK_DESTROY (frame->root); +        return 0; +} +  static int  fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this, @@ -606,7 +716,8 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  static int  fuse_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                   int32_t op_ret, int32_t op_errno, -                 inode_t *inode, struct stat *stat, dict_t *dict) +                 inode_t *inode, struct stat *stat, dict_t *dict, +                 struct stat *postparent)  {          fuse_entry_cbk (frame, cookie, this, op_ret, op_errno, inode, stat);          return 0; @@ -682,6 +793,62 @@ fuse_forget (xlator_t *this, fuse_in_header_t *finh, void *msg)          FREE (finh);  } +         +         +static int +fuse_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                   int32_t op_ret, int32_t op_errno, struct stat *buf, +                   struct stat *postbuf) +{ +        fuse_state_t     *state; +        fuse_in_header_t *finh; +        fuse_private_t   *priv = NULL; +        struct fuse_attr_out fao; + +        priv  = this->private; +        state = frame->root->state; +        finh  = state->finh; + +        if (op_ret == 0) { +                gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                        "%"PRIu64": %s() %s => %"PRId64, frame->root->unique, +                        gf_fop_list[frame->root->op], +                        state->loc.path ? state->loc.path : "ERR", +                        buf->st_ino); + +                /* TODO: make these timeouts configurable via meta */ +                /* TODO: what if the inode number has changed by now */ +                buf->st_blksize = this->ctx->page_size; +                stat2attr (buf, &fao.attr); + +                fao.attr_valid = calc_timeout_sec (priv->attribute_timeout); +                fao.attr_valid_nsec = +                  calc_timeout_nsec (priv->attribute_timeout); + +                priv->proto_minor >= 9 ? +                send_fuse_obj (this, finh, &fao) : +                send_fuse_data (this, finh, &fao, +                                FUSE_COMPAT_ATTR_OUT_SIZE); +        } else { +                gf_log ("glusterfs-fuse", GF_LOG_WARNING, +                        "%"PRIu64": %s() %s => -1 (%s)", frame->root->unique, +                        gf_fop_list[frame->root->op], +                        state->loc.path ? state->loc.path : "ERR", +                        strerror (op_errno)); + +                if (can_fuse_return (state, 0)) +                        send_fuse_err (this, finh, op_errno); +        } + +        if (state->callcount == 0) { +                free_state (state); +                STACK_DESTROY (frame->root); +        } + +        return 0; +} + +  static int @@ -926,10 +1093,10 @@ static void  fuse_do_truncate (fuse_state_t *state, struct fuse_setattr_in *fsi)  {          if (state->fd) { -                FUSE_FOP (state, fuse_attr_cbk, GF_FOP_FTRUNCATE, +                FUSE_FOP (state, fuse_truncate_cbk, GF_FOP_FTRUNCATE,                            ftruncate, state->fd, fsi->size);          } else { -                FUSE_FOP (state, fuse_attr_cbk, GF_FOP_TRUNCATE, +                FUSE_FOP (state, fuse_truncate_cbk, GF_FOP_TRUNCATE,                            truncate, &state->loc, fsi->size);          } @@ -1032,6 +1199,58 @@ fuse_setattr (xlator_t *this, fuse_in_header_t *finh, void *msg)  static int gf_fuse_xattr_enotsup_log; +static int +fuse_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                int32_t op_ret, int32_t op_errno, struct stat *prebuf, +                struct stat *postbuf) +{ +        fuse_state_t *state = frame->root->state; +        fuse_in_header_t *finh = state->finh; + +        if (op_ret == 0) { +                gf_log ("glusterfs-fuse", GF_LOG_TRACE, +                        "%"PRIu64": %s() %s => 0", frame->root->unique, +                        gf_fop_list[frame->root->op], +                        state->loc.path ? state->loc.path : "ERR"); + +                send_fuse_err (this, finh, 0); +        } else { +                if (frame->root->op == GF_FOP_SETXATTR) { +                        op_ret = gf_compat_setxattr (state->dict); +                        if (op_ret == 0) +                                op_errno = 0; +                        if (op_errno == ENOTSUP) { +                                gf_fuse_xattr_enotsup_log++; +                                if (!(gf_fuse_xattr_enotsup_log % GF_UNIVERSAL_ANSWER)) +                                        gf_log ("glusterfs-fuse", +                                                GF_LOG_CRITICAL, +                                                "extended attribute not " +                                                "supported by the backend " +                                                "storage"); +                        } +                } else { +                        if ((frame->root->op == GF_FOP_REMOVEXATTR) +                            && (op_errno == ENOATTR)) { +                                goto nolog; +                        } +                        gf_log ("glusterfs-fuse", GF_LOG_WARNING, +                                "%"PRIu64": %s() %s => -1 (%s)", +                                frame->root->unique, +                                gf_fop_list[frame->root->op], +                                state->loc.path ? state->loc.path : "ERR", +                                strerror (op_errno)); +                } +        nolog: + +                send_fuse_err (this, finh, op_errno); +        } + +        free_state (state); +        STACK_DESTROY (frame->root); + +        return 0; +} +  static int  fuse_err_cbk (call_frame_t *frame, void *cookie, xlator_t *this, @@ -1087,7 +1306,8 @@ fuse_err_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  static int  fuse_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, -                 int32_t op_ret, int32_t op_errno) +                 int32_t op_ret, int32_t op_errno, struct stat *preparent, +                 struct stat *postparent)  {          fuse_state_t     *state = NULL;          fuse_in_header_t *finh = NULL; @@ -1157,7 +1377,8 @@ fuse_access (xlator_t *this, fuse_in_header_t *finh, void *msg)  static int  fuse_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, -                   int32_t op_ret, int32_t op_errno, const char *linkname) +                   int32_t op_ret, int32_t op_errno, const char *linkname, +                   struct stat *buf)  {          fuse_state_t     *state = NULL;          fuse_in_header_t *finh = NULL; @@ -1249,7 +1470,7 @@ fuse_mknod (xlator_t *this, fuse_in_header_t *finh, void *msg)                  "%"PRIu64": MKNOD %s", finh->unique,                  state->loc.path); -        FUSE_FOP (state, fuse_entry_cbk, GF_FOP_MKNOD, +        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_MKNOD,                    mknod, &state->loc, fmi->mode, fmi->rdev);          return; @@ -1282,7 +1503,7 @@ fuse_mkdir (xlator_t *this, fuse_in_header_t *finh, void *msg)                  "%"PRIu64": MKDIR %s", finh->unique,                  state->loc.path); -        FUSE_FOP (state, fuse_entry_cbk, GF_FOP_MKDIR, +        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_MKDIR,                    mkdir, &state->loc, fmi->mode);          return; @@ -1379,7 +1600,7 @@ fuse_symlink (xlator_t *this, fuse_in_header_t *finh, void *msg)                  "%"PRIu64": SYMLINK %s -> %s", finh->unique,                  state->loc.path, linkname); -        FUSE_FOP (state, fuse_entry_cbk, GF_FOP_SYMLINK, +        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_SYMLINK,                    symlink, linkname, &state->loc);          return; @@ -1388,7 +1609,9 @@ fuse_symlink (xlator_t *this, fuse_in_header_t *finh, void *msg)  int  fuse_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, -                 int32_t op_ret, int32_t op_errno, struct stat *buf) +                 int32_t op_ret, int32_t op_errno, struct stat *buf, +                 struct stat *preoldparent, struct stat *postoldparent, +                 struct stat *prenewparent, struct stat *postnewparent)  {          fuse_state_t     *state = NULL;          fuse_in_header_t *finh = NULL; @@ -1513,7 +1736,7 @@ fuse_link (xlator_t *this, fuse_in_header_t *finh, void *msg)                  finh->unique, state->loc2.path, state->loc2.ino,                  state->loc.path, state->loc.ino); -        FUSE_FOP (state, fuse_entry_cbk, GF_FOP_LINK, +        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_LINK,                    link, &state->loc2, &state->loc);          return; @@ -1523,7 +1746,8 @@ fuse_link (xlator_t *this, fuse_in_header_t *finh, void *msg)  static int  fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                   int32_t op_ret, int32_t op_errno, -                 fd_t *fd, inode_t *inode, struct stat *buf) +                 fd_t *fd, inode_t *inode, struct stat *buf, +                 struct stat *preparent, struct stat *postparent)  {          fuse_state_t            *state = NULL;          fuse_in_header_t        *finh = NULL; @@ -1683,7 +1907,7 @@ fuse_open (xlator_t *this, fuse_in_header_t *finh, void *msg)                  state->loc.path);          FUSE_FOP (state, fuse_fd_cbk, GF_FOP_OPEN, -                  open, &state->loc, foi->flags, fd); +                  open, &state->loc, foi->flags, fd, 0);          return;  } @@ -1761,7 +1985,7 @@ fuse_readv (xlator_t *this, fuse_in_header_t *finh, void *msg)  static int  fuse_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                   int32_t op_ret, int32_t op_errno, -                 struct stat *stbuf) +                 struct stat *stbuf, struct stat *postbuf)  {          fuse_state_t *state = NULL;          fuse_in_header_t *finh = NULL; @@ -1949,7 +2173,7 @@ fuse_fsync (xlator_t *this, fuse_in_header_t *finh, void *msg)                  "%"PRIu64": FSYNC %p", finh->unique, fd);          /* fsync_flags: 1 means "datasync" (no defines for this) */ -        FUSE_FOP (state, fuse_err_cbk, GF_FOP_FSYNC, +        FUSE_FOP (state, fuse_fsync_cbk, GF_FOP_FSYNC,                    fsync, fd, fsi->fsync_flags & 1);          return; @@ -2810,7 +3034,8 @@ static fuse_handler_t *fuse_ops[FUSE_712_OP_HIGH];  int  fuse_root_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                        int32_t op_ret, int32_t op_errno, -                      inode_t *inode, struct stat *buf, dict_t *xattr) +                      inode_t *inode, struct stat *buf, dict_t *xattr, +                      struct stat *postparent)  {          fuse_private_t *priv = NULL;  | 
