diff options
author | Raghavendra G <raghavendra@gluster.com> | 2011-11-24 13:50:23 +0530 |
---|---|---|
committer | Anand Avati <avati@gluster.com> | 2011-12-01 22:02:39 -0800 |
commit | f5d5e8012a3762d0ffb95a0ca624a3fce3c262cd (patch) | |
tree | 4a1aef9270e5dc3a025233d7d51dea6e7c5892a4 | |
parent | 5d194403e96d97f82681b5e7d96ddf8e48858cb7 (diff) |
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 <jenkins@build.gluster.com>
Reviewed-by: Csaba Henk <csaba@gluster.com>
Reviewed-by: Anand Avati <avati@gluster.com>
-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; |