From f5d5e8012a3762d0ffb95a0ca624a3fce3c262cd Mon Sep 17 00:00:00 2001 From: Raghavendra G Date: Thu, 24 Nov 2011 13:50:23 +0530 Subject: mount/fuse: Inherit direct-io-mode values from fds already opened, for a new fd being opened. When an fd is being opened, it inherits direct-io-mode characterstics (either enabled or disabled) from the fds already opened on inode. If none are opened and user has not specified the mode through cmdline options, default mode is used. Change-Id: I0c9e959100e9130e46bbd16d63eca278260635b4 BUG: 801 Reviewed-on: http://review.gluster.com/55 Tested-by: Gluster Build System Reviewed-by: Csaba Henk Reviewed-by: Anand Avati --- xlators/mount/fuse/src/fuse-bridge.c | 148 +++++++++++++++++++++++++++++--- xlators/mount/fuse/src/fuse-bridge.h | 7 ++ xlators/mount/fuse/src/fuse-mem-types.h | 1 + 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; -- cgit