summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;