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 3e271ff6940..ae3dd4c0b52 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 2b8323a8c18..b7ca9b08e43 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 56cf9579cbc..1fb959c3a44 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 89ed790aab0..33606f87919 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; |