summaryrefslogtreecommitdiffstats
path: root/xlators/mount/fuse/src/fuse-bridge.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/mount/fuse/src/fuse-bridge.c')
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.c148
1 files changed, 135 insertions, 13 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);