summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaghavendra G <raghavendra@gluster.com>2011-11-24 13:50:23 +0530
committerAnand Avati <avati@gluster.com>2011-12-01 22:02:39 -0800
commitf5d5e8012a3762d0ffb95a0ca624a3fce3c262cd (patch)
tree4a1aef9270e5dc3a025233d7d51dea6e7c5892a4
parent5d194403e96d97f82681b5e7d96ddf8e48858cb7 (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.c148
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.h7
-rw-r--r--xlators/mount/fuse/src/fuse-mem-types.h1
-rw-r--r--xlators/mount/fuse/src/fuse-resolve.c43
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;