summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaghavendra G <raghavendra@gluster.com>2012-01-18 10:21:21 +0530
committerAnand Avati <avati@redhat.com>2012-03-18 01:54:38 -0700
commit0190bf4726773a83081eb0935697c7a616edf0dd (patch)
treea52d22d7dfc97d7eeb4ce10dbc622deb6e2b59fa
parentb59b5256a69db2f3f5bcf32693054a32237fe843 (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 Signed-off-by: Raghavendra G <raghavendra@gluster.com> Reviewed-on: http://review.gluster.com/20 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Csaba Henk <csaba@redhat.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 acd3c68..6ac9bb5 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,
@@ -1943,9 +2048,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);
@@ -1955,10 +2061,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);
@@ -2171,9 +2284,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);
@@ -2182,10 +2296,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 41ea2c3..61249d9 100644
--- a/xlators/mount/fuse/src/fuse-bridge.h
+++ b/xlators/mount/fuse/src/fuse-bridge.h
@@ -276,6 +276,11 @@ typedef struct {
xlator_t *old_xl;
} 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
@@ -292,4 +297,6 @@ inode_t *fuse_ino_to_inode (uint64_t ino, xlator_t *fuse);
int fuse_resolve_and_resume (fuse_state_t *state, fuse_resume_fn_t fn);
int send_fuse_err (xlator_t *this, fuse_in_header_t *finh, int error);
int fuse_gfid_set (fuse_state_t *state);
+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 56cf957..1fb959c 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 358839e..a017fd6 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;