diff options
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 148 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.h | 7 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-mem-types.h | 1 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-resolve.c | 43 | 
4 files changed, 173 insertions, 26 deletions
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index 3e271ff69..ae3dd4c0b 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -30,6 +30,53 @@  static int gf_fuse_conn_err_log;  static int gf_fuse_xattr_enotsup_log; +fuse_fd_ctx_t * +__fuse_fd_ctx_check_n_create (fd_t *fd, xlator_t *this) +{ +        uint64_t       val    = 0; +        int32_t        ret    = 0; +        fuse_fd_ctx_t *fd_ctx = NULL; + +        ret = __fd_ctx_get (fd, this, &val); + +        fd_ctx = (fuse_fd_ctx_t *)(unsigned long) val; + +        if (fd_ctx == NULL) { +                fd_ctx = GF_CALLOC (1, sizeof (*fd_ctx), +                                    gf_fuse_mt_fd_ctx_t); + +                ret = __fd_ctx_set (fd, this, +                                    (uint64_t)(unsigned long)fd_ctx); +                if (ret < 0) { +                        gf_log ("glusterfs-fuse", GF_LOG_DEBUG, +                                "fd-ctx-set failed"); +                        GF_FREE (fd_ctx); +                        fd_ctx = NULL; +                } +        } + +        return fd_ctx; +} + +fuse_fd_ctx_t * +fuse_fd_ctx_check_n_create (fd_t *fd, xlator_t *this) +{ +        fuse_fd_ctx_t *fd_ctx = NULL; + +        if ((fd == NULL) || (this == NULL)) { +                goto out; +        } + +        LOCK (&fd->lock); +        { +                fd_ctx = __fuse_fd_ctx_check_n_create (fd, this); +        } +        UNLOCK (&fd->lock); + +out: +        return fd_ctx; +} +  /*   * iov_out should contain a fuse_out_header at zeroth position. @@ -531,14 +578,61 @@ fuse_getattr (xlator_t *this, fuse_in_header_t *finh, void *msg)  } +static int32_t +fuse_fd_inherit_directio (xlator_t *this, fd_t *fd, struct fuse_open_out *foo) +{ +        int32_t        ret    = 0; +        fuse_fd_ctx_t *fdctx  = NULL, *tmp_fdctx = NULL; +        fd_t          *tmp_fd = NULL; +        uint64_t       val    = 0; + +        GF_VALIDATE_OR_GOTO_WITH_ERROR ("glusterfs-fuse", this, out, ret, +                                        -EINVAL); +        GF_VALIDATE_OR_GOTO_WITH_ERROR ("glusterfs-fuse", fd, out, ret, +                                        -EINVAL); +        GF_VALIDATE_OR_GOTO_WITH_ERROR ("glusterfs-fuse", foo, out, ret, +                                        -EINVAL); + +        fdctx = fuse_fd_ctx_check_n_create (fd, this); +        if (!fdctx) { +                ret = -ENOMEM; +                goto out; +        } + +        tmp_fd = fd_lookup (fd->inode, 0); +        if (tmp_fd) { +                ret = fd_ctx_get (tmp_fd, this, &val); +                if (!ret) { +                        tmp_fdctx = (fuse_fd_ctx_t *)(unsigned long)val; +                        if (tmp_fdctx) { +                                foo->open_flags &= ~FOPEN_DIRECT_IO; +                                foo->open_flags |= (tmp_fdctx->open_flags +                                                    & FOPEN_DIRECT_IO); +                        } +                } +        } + +        fdctx->open_flags |= (foo->open_flags & FOPEN_DIRECT_IO); + +        if (tmp_fd != NULL) { +                fd_unref (tmp_fd); +        } + +        ret = 0; +out: +        return ret; +} + +  static int  fuse_fd_cbk (call_frame_t *frame, void *cookie, xlator_t *this,               int32_t op_ret, int32_t op_errno, fd_t *fd)  { -        fuse_state_t          *state; -        fuse_in_header_t      *finh; -        fuse_private_t        *priv = NULL; -        struct fuse_open_out   foo = {0, }; +        fuse_state_t         *state = NULL; +        fuse_in_header_t     *finh  = NULL; +        fuse_private_t       *priv  = NULL; +        int32_t               ret   = 0; +        struct fuse_open_out  foo   = {0, };          priv = this->private;          state = frame->root->state; @@ -572,16 +666,27 @@ fuse_fd_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                          "%"PRIu64": %s() %s => %p", frame->root->unique,                          gf_fop_list[frame->root->op], state->loc.path, fd); +                ret = fuse_fd_inherit_directio (this, fd, &foo); +                if (ret < 0) { +                        op_errno = -ret; +                        gf_log ("glusterfs-fuse", GF_LOG_WARNING, +                                "cannot inherit direct-io values from fds " +                                "already opened"); +                        goto err; +                } +                  fd_ref (fd); +                  if (send_fuse_obj (this, finh, &foo) == ENOENT) {                          gf_log ("glusterfs-fuse", GF_LOG_DEBUG,                                  "open(%s) got EINTR", state->loc.path);                          fd_unref (fd); -                                goto out; +                        goto out;                  }                  fd_bind (fd);          } else { +        err:                  gf_log ("glusterfs-fuse", GF_LOG_WARNING,                          "%"PRIu64": %s() %s => -1 (%s)", frame->root->unique,                          gf_fop_list[frame->root->op], state->loc.path, @@ -1953,9 +2058,10 @@ fuse_release (xlator_t *this, fuse_in_header_t *finh, void *msg)          struct fuse_release_in *fri        = msg;          fd_t                   *new_fd     = NULL;          fd_t                   *fd         = NULL; -        uint64_t                tmp_fd_ctx = 0; +        uint64_t                val        = 0;          int                     ret        = 0;          fuse_state_t           *state      = NULL; +        fuse_fd_ctx_t          *fdctx      = NULL;          GET_STATE (this, finh, state);          fd = FH_TO_FD (fri->fh); @@ -1965,10 +2071,17 @@ fuse_release (xlator_t *this, fuse_in_header_t *finh, void *msg)          gf_log ("glusterfs-fuse", GF_LOG_TRACE,                  "%"PRIu64": RELEASE %p", finh->unique, state->fd); -        ret = fd_ctx_get (fd, this, &tmp_fd_ctx); +        ret = fd_ctx_del (fd, this, &val);          if (!ret) { -                new_fd = (fd_t *)(long)tmp_fd_ctx; -                fd_unref (new_fd); +                fdctx = (fuse_fd_ctx_t *)(unsigned long)val; +                if (fdctx) { +                        new_fd = fdctx->fd; +                        if (new_fd) { +                                fd_unref (new_fd); +                        } + +                        GF_FREE (fdctx); +                }          }          fd_unref (fd); @@ -2181,9 +2294,10 @@ fuse_releasedir (xlator_t *this, fuse_in_header_t *finh, void *msg)  {          struct fuse_release_in *fri        = msg;          fd_t                   *new_fd     = NULL; -        uint64_t                tmp_fd_ctx = 0; +        uint64_t                val        = 0;          int                     ret        = 0;          fuse_state_t           *state      = NULL; +        fuse_fd_ctx_t          *fdctx      = NULL;          GET_STATE (this, finh, state);          state->fd = FH_TO_FD (fri->fh); @@ -2192,10 +2306,18 @@ fuse_releasedir (xlator_t *this, fuse_in_header_t *finh, void *msg)          gf_log ("glusterfs-fuse", GF_LOG_TRACE,                  "%"PRIu64": RELEASEDIR %p", finh->unique, state->fd); -        ret = fd_ctx_get (state->fd, this, &tmp_fd_ctx); +        ret = fd_ctx_del (state->fd, this, &val); +          if (!ret) { -                new_fd = (fd_t *)(long)tmp_fd_ctx; -                fd_unref (new_fd); +                fdctx = (fuse_fd_ctx_t *)(unsigned long)val; +                if (fdctx) { +                        new_fd = fdctx->fd; +                        if (new_fd) { +                                fd_unref (new_fd); +                        } + +                        GF_FREE (fdctx); +                }          }          fd_unref (state->fd); diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h index 2b8323a8c..b7ca9b08e 100644 --- a/xlators/mount/fuse/src/fuse-bridge.h +++ b/xlators/mount/fuse/src/fuse-bridge.h @@ -277,6 +277,11 @@ typedef struct {          uuid_t         gfid;  } fuse_state_t; +typedef struct fuse_fd_ctx { +        uint32_t  open_flags; +        fd_t     *fd; +} fuse_fd_ctx_t; +  typedef void (*fuse_resume_fn_t) (fuse_state_t *state);  GF_MUST_CHECK int32_t @@ -296,4 +301,6 @@ int fuse_gfid_set (fuse_state_t *state);  int fuse_flip_xattr_ns (struct fuse_private *priv, char *okey, char **nkey);  int fuse_flip_user_to_trusted (char *okey, char **nkey);  int fuse_xattr_alloc_default (char *okey, char **nkey); +fuse_fd_ctx_t * __fuse_fd_ctx_check_n_create (fd_t *fd, xlator_t *this); +fuse_fd_ctx_t * fuse_fd_ctx_check_n_create (fd_t *fd, xlator_t *this);  #endif /* _GF_FUSE_BRIDGE_H_ */ diff --git a/xlators/mount/fuse/src/fuse-mem-types.h b/xlators/mount/fuse/src/fuse-mem-types.h index 56cf9579c..1fb959c3a 100644 --- a/xlators/mount/fuse/src/fuse-mem-types.h +++ b/xlators/mount/fuse/src/fuse-mem-types.h @@ -29,6 +29,7 @@ enum gf_fuse_mem_types_ {          gf_fuse_mt_char,          gf_fuse_mt_iov_base,          gf_fuse_mt_fuse_state_t, +        gf_fuse_mt_fd_ctx_t,          gf_fuse_mt_end  };  #endif diff --git a/xlators/mount/fuse/src/fuse-resolve.c b/xlators/mount/fuse/src/fuse-resolve.c index 89ed790aa..33606f879 100644 --- a/xlators/mount/fuse/src/fuse-resolve.c +++ b/xlators/mount/fuse/src/fuse-resolve.c @@ -125,12 +125,13 @@ 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; +        fuse_state_t   *state      = NULL;          fuse_resolve_t *resolve    = NULL; -        fd_t         *old_fd     = NULL; -        fd_t         *tmp_fd     = NULL; -        uint64_t      tmp_fd_ctx = 0; -        int           ret        = 0; +        fd_t           *old_fd     = NULL; +        fd_t           *tmp_fd     = NULL; +        fuse_fd_ctx_t  *tmp_fd_ctx = 0; +        uint64_t        val        = 0; +        int             ret        = 0;          state = frame->root->state;          resolve = state->resolve_now; @@ -150,15 +151,31 @@ fuse_resolve_newfd_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          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); + +        LOCK (&old_fd->lock); +        { +                ret = __fd_ctx_get (old_fd, state->this, &val); +                if (!ret) { +                        tmp_fd_ctx = (fuse_fd_ctx_t *)(unsigned long)val; +                        tmp_fd = tmp_fd_ctx->fd; +                        if (tmp_fd) { +                                fd_unref (tmp_fd); +                                tmp_fd_ctx->fd = NULL; +                        } +                } else { +                        tmp_fd_ctx = __fuse_fd_ctx_check_n_create (old_fd, +                                                                   state->this); +                } + +                if (tmp_fd_ctx) { +                        tmp_fd_ctx->fd = fd; +                } else { +                        gf_log ("resolve", GF_LOG_WARNING, +                                "failed to set the fd ctx with resolved 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"); +        UNLOCK (&old_fd->lock); +  out:          fuse_resolve_all (state);          return 0;  | 
