summaryrefslogtreecommitdiffstats
path: root/xlators/mount/fuse/src
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/mount/fuse/src')
-rw-r--r--xlators/mount/fuse/src/Makefile.am7
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.c1828
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.h141
-rw-r--r--xlators/mount/fuse/src/fuse-helpers.c107
-rw-r--r--xlators/mount/fuse/src/fuse-mem-types.h13
-rw-r--r--xlators/mount/fuse/src/fuse-resolve.c190
6 files changed, 1590 insertions, 696 deletions
diff --git a/xlators/mount/fuse/src/Makefile.am b/xlators/mount/fuse/src/Makefile.am
index a92d68e9a..653121d18 100644
--- a/xlators/mount/fuse/src/Makefile.am
+++ b/xlators/mount/fuse/src/Makefile.am
@@ -24,12 +24,13 @@ endif
fuse_la_SOURCES = fuse-helpers.c fuse-resolve.c fuse-bridge.c \
$(CONTRIBDIR)/fuse-lib/misc.c $(mount_source)
-fuse_la_LDFLAGS = -module -avoidversion -shared -nostartfiles
+fuse_la_LDFLAGS = -module -avoid-version
fuse_la_LIBADD = @GF_FUSE_LDADD@
-AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D$(GF_HOST_OS) -Wall \
+AM_CPPFLAGS = $(GF_CPPFLAGS) \
-I$(top_srcdir)/libglusterfs/src -I$(CONTRIBDIR)/fuse-include \
- -I$(CONTRIBDIR)/fuse-lib $(GF_CFLAGS) $(GF_FUSE_CFLAGS)
+ -I$(CONTRIBDIR)/fuse-lib $(GF_FUSE_CFLAGS)
+AM_CFLAGS = -Wall $(GF_CFLAGS)
CLEANFILES =
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
index 755b79511..6a5587c2d 100644
--- a/xlators/mount/fuse/src/fuse-bridge.c
+++ b/xlators/mount/fuse/src/fuse-bridge.c
@@ -1,24 +1,22 @@
/*
- Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ Copyright (c) 2006-2012 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#include <sys/wait.h>
#include "fuse-bridge.h"
+#include "mount-gluster-compat.h"
+#include "glusterfs.h"
+#include "glusterfs-acl.h"
+
+#ifdef __NetBSD__
+#undef open /* in perfuse.h, pulled from mount-gluster-compat.h */
+#endif
static int gf_fuse_conn_err_log;
static int gf_fuse_xattr_enotsup_log;
@@ -34,25 +32,67 @@ static void fuse_invalidate_inode(xlator_t *this, uint64_t fuse_ino);
static int32_t
fuse_invalidate(xlator_t *this, inode_t *inode)
{
- fuse_private_t *priv = this->private;
- uint64_t nodeid;
+ fuse_private_t *priv = this->private;
+ uint64_t nodeid;
- /*
- * NOTE: We only invalidate at the moment if fopen_keep_cache is
- * enabled because otherwise this is a departure from default
- * behavior. Specifically, the performance/write-behind xlator
- * causes unconditional invalidations on write requests.
- */
- if (!priv->fopen_keep_cache)
- return 0;
+ /*
+ * NOTE: We only invalidate at the moment if fopen_keep_cache is
+ * enabled because otherwise this is a departure from default
+ * behavior. Specifically, the performance/write-behind xlator
+ * causes unconditional invalidations on write requests.
+ */
+ if (!priv->fopen_keep_cache)
+ return 0;
- nodeid = inode_to_fuse_nodeid(inode);
- gf_log(this->name, GF_LOG_DEBUG, "Invalidate inode id %lu.", nodeid);
- fuse_invalidate_inode(this, nodeid);
+ nodeid = inode_to_fuse_nodeid(inode);
+ gf_log(this->name, GF_LOG_DEBUG, "Invalidate inode id %lu.", nodeid);
+ fuse_log_eh (this, "Sending invalidate inode id: %lu gfid: %s", nodeid,
+ uuid_utoa (inode->gfid));
+ fuse_invalidate_inode(this, nodeid);
- return 0;
+ return 0;
}
+static int32_t
+fuse_forget_cbk (xlator_t *this, inode_t *inode)
+{
+ //Nothing to free in inode ctx, hence return.
+ return 0;
+}
+
+void
+fuse_inode_set_need_lookup (inode_t *inode, xlator_t *this)
+{
+ uint64_t need_lookup = 1;
+
+ if (!inode || !this)
+ return;
+
+ inode_ctx_set (inode, this, &need_lookup);
+
+ return;
+}
+
+
+gf_boolean_t
+fuse_inode_needs_lookup (inode_t *inode, xlator_t *this)
+{
+ uint64_t need_lookup = 0;
+ gf_boolean_t ret = _gf_false;
+
+ if (!inode || !this)
+ return ret;
+
+ inode_ctx_get (inode, this, &need_lookup);
+ if (need_lookup)
+ ret = _gf_true;
+ need_lookup = 0;
+ inode_ctx_set (inode, this, &need_lookup);
+
+ return ret;
+}
+
+
fuse_fd_ctx_t *
__fuse_fd_ctx_check_n_create (xlator_t *this, fd_t *fd)
{
@@ -67,7 +107,9 @@ __fuse_fd_ctx_check_n_create (xlator_t *this, fd_t *fd)
if (fd_ctx == NULL) {
fd_ctx = GF_CALLOC (1, sizeof (*fd_ctx),
gf_fuse_mt_fd_ctx_t);
-
+ if (!fd_ctx) {
+ goto out;
+ }
ret = __fd_ctx_set (fd, this,
(uint64_t)(unsigned long)fd_ctx);
if (ret < 0) {
@@ -77,7 +119,7 @@ __fuse_fd_ctx_check_n_create (xlator_t *this, fd_t *fd)
fd_ctx = NULL;
}
}
-
+out:
return fd_ctx;
}
@@ -100,7 +142,6 @@ out:
return fd_ctx;
}
-
fuse_fd_ctx_t *
fuse_fd_ctx_get (xlator_t *this, fd_t *fd)
{
@@ -119,7 +160,6 @@ out:
return fdctx;
}
-
/*
* iov_out should contain a fuse_out_header at zeroth position.
* The error value of this header is sent to kernel.
@@ -198,8 +238,7 @@ fuse_invalidate_entry (xlator_t *this, uint64_t fuse_ino)
inode_t *inode = NULL;
size_t nlen = 0;
int rv = 0;
-
- char inval_buf[INVAL_BUF_SIZE] = {0,};
+ char inval_buf[INVAL_BUF_SIZE] = {0,};
fouh = (struct fuse_out_header *)inval_buf;
fnieo = (struct fuse_notify_inval_entry_out *)(fouh + 1);
@@ -232,7 +271,19 @@ fuse_invalidate_entry (xlator_t *this, uint64_t fuse_ino)
gf_log ("glusterfs-fuse", GF_LOG_TRACE, "INVALIDATE entry: "
"%"PRIu64"/%s", fnieo->parent, dentry->name);
+
+ if (dentry->parent) {
+ fuse_log_eh (this, "Invalidated entry %s (parent: %s)",
+ dentry->name,
+ uuid_utoa (dentry->parent->gfid));
+ } else {
+ fuse_log_eh (this, "Invalidated entry %s(nodeid: %ld)",
+ dentry->name, fnieo->parent);
+ }
}
+
+ if (inode)
+ inode_unref (inode);
}
/*
@@ -242,38 +293,51 @@ fuse_invalidate_entry (xlator_t *this, uint64_t fuse_ino)
static void
fuse_invalidate_inode(xlator_t *this, uint64_t fuse_ino)
{
- struct fuse_out_header *fouh = NULL;
- struct fuse_notify_inval_inode_out *fniio = NULL;
- fuse_private_t *priv = NULL;
- int rv = 0;
- char inval_buf[INVAL_BUF_SIZE] = {0};
+ struct fuse_out_header *fouh = NULL;
+ struct fuse_notify_inval_inode_out *fniio = NULL;
+ fuse_private_t *priv = NULL;
+ int rv = 0;
+ char inval_buf[INVAL_BUF_SIZE] = {0};
+ inode_t *inode = NULL;
- fouh = (struct fuse_out_header *) inval_buf;
- fniio = (struct fuse_notify_inval_inode_out *) (fouh + 1);
+ fouh = (struct fuse_out_header *) inval_buf;
+ fniio = (struct fuse_notify_inval_inode_out *) (fouh + 1);
- priv = this->private;
+ priv = this->private;
- if (priv->revchan_out < 0)
- return;
+ if (priv->revchan_out < 0)
+ return;
- fouh->unique = 0;
- fouh->error = FUSE_NOTIFY_INVAL_INODE;
- fouh->len = sizeof(struct fuse_out_header) +
- sizeof(struct fuse_notify_inval_inode_out);
-
- /* inval the entire mapping until we learn how to be more granular */
- fniio->ino = fuse_ino;
- fniio->off = 0;
- fniio->len = -1;
-
- rv = write(priv->revchan_out, inval_buf, fouh->len);
- if (rv != fouh->len) {
- gf_log("glusterfs-fuse", GF_LOG_ERROR, "kernel notification "
- "daemon defunct");
- close(priv->fd);
- }
+ fouh->unique = 0;
+ fouh->error = FUSE_NOTIFY_INVAL_INODE;
+ fouh->len = sizeof(struct fuse_out_header) +
+ sizeof(struct fuse_notify_inval_inode_out);
+
+ /* inval the entire mapping until we learn how to be more granular */
+ fniio->ino = fuse_ino;
+ fniio->off = 0;
+ fniio->len = -1;
+
+ inode = fuse_ino_to_inode (fuse_ino, this);
+
+ rv = write(priv->revchan_out, inval_buf, fouh->len);
+ if (rv != fouh->len) {
+ gf_log("glusterfs-fuse", GF_LOG_ERROR, "kernel notification "
+ "daemon defunct");
+ close(priv->fd);
+ }
+
+ gf_log("glusterfs-fuse", GF_LOG_TRACE, "INVALIDATE inode: %lu", fuse_ino);
- gf_log("glusterfs-fuse", GF_LOG_TRACE, "INVALIDATE inode: %lu", fuse_ino);
+ if (inode) {
+ fuse_log_eh (this, "Invalidated inode %lu (gfid: %s)",
+ fuse_ino, uuid_utoa (inode->gfid));
+ } else {
+ fuse_log_eh (this, "Invalidated inode %lu ", fuse_ino);
+ }
+
+ if (inode)
+ inode_unref (inode);
}
int
@@ -281,14 +345,32 @@ send_fuse_err (xlator_t *this, fuse_in_header_t *finh, int error)
{
struct fuse_out_header fouh = {0, };
struct iovec iov_out;
+ inode_t *inode = NULL;
fouh.error = -error;
iov_out.iov_base = &fouh;
+ inode = fuse_ino_to_inode (finh->nodeid, this);
+
+ // filter out ENOENT
+ if (error != ENOENT) {
+ if (inode) {
+ fuse_log_eh (this,"Sending %s for operation %d on "
+ "inode %s", strerror (error), finh->opcode,
+ uuid_utoa (inode->gfid));
+ } else {
+ fuse_log_eh (this, "Sending %s for operation %d on "
+ "inode %ld", strerror (error),
+ finh->opcode, finh->nodeid);
+ }
+ }
+
+ if (inode)
+ inode_unref (inode);
+
return send_fuse_iov (this, finh, &iov_out, 1);
}
-
static int
fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
@@ -304,18 +386,39 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state = frame->root->state;
finh = state->finh;
- if (!op_ret && __is_root_gfid (state->loc.inode->gfid)) {
- buf->ia_ino = 1;
+ if (op_ret == 0) {
+ if (__is_root_gfid (state->loc.inode->gfid))
+ buf->ia_ino = 1;
+ if (uuid_is_null (buf->ia_gfid)) {
+ /* With a NULL gfid inode linking is
+ not possible. Let's not pretend this
+ call was a "success".
+ */
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING,
+ "Received NULL gfid for %s. Forcing EIO",
+ state->loc.path);
+ op_ret = -1;
+ op_errno = EIO;
+ }
}
+ /* log into the event-history after the null uuid check is done, since
+ * the op_ret and op_errno are being changed if the gfid is NULL.
+ */
+ fuse_log_eh (this, "op_ret: %d op_errno: %d "
+ "%"PRIu64": %s() %s => %s", op_ret, op_errno,
+ frame->root->unique, gf_fop_list[frame->root->op],
+ state->loc.path, (op_ret == 0)?
+ uuid_utoa(buf->ia_gfid):uuid_utoa(state->loc.gfid));
+
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": %s() %s => %"PRId64,
+ "%"PRIu64": %s() %s => %"PRIu64,
frame->root->unique, gf_fop_list[frame->root->op],
state->loc.path, buf->ia_ino);
buf->ia_blksize = this->ctx->page_size;
- gf_fuse_stat2attr (buf, &feo.attr);
+ gf_fuse_stat2attr (buf, &feo.attr, priv->enable_ino32);
if (!buf->ia_ino) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
@@ -359,7 +462,8 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
"%"PRIu64": %s() %s => -1 (%s)", frame->root->unique,
gf_fop_list[frame->root->op], state->loc.path,
strerror (op_errno));
- if (op_errno == ENOENT) {
+
+ if ((op_errno == ENOENT) && (priv->negative_timeout != 0)) {
feo.entry_valid =
calc_timeout_sec (priv->negative_timeout);
feo.entry_valid_nsec =
@@ -367,7 +471,7 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
send_fuse_obj (this, finh, &feo);
} else {
send_fuse_err (this, state->finh, op_errno);
- }
+ }
}
free_fuse_state (state);
@@ -375,7 +479,6 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
-
static int
fuse_newentry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
@@ -387,7 +490,6 @@ fuse_newentry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
-
static int
fuse_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
@@ -403,6 +505,13 @@ fuse_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
if (op_ret == -1 && state->is_revalidate == 1) {
itable = state->itable;
+ /*
+ * A stale mapping might exist for a dentry/inode that has been
+ * removed from another client.
+ */
+ if (op_errno == ENOENT)
+ inode_unlink(state->loc.inode, state->loc.parent,
+ state->loc.name);
inode_unref (state->loc.inode);
state->loc.inode = inode_new (itable);
state->is_revalidate = 2;
@@ -435,7 +544,7 @@ fuse_lookup_resume (fuse_state_t *state)
/* parent was resolved, entry could not, may be a missing gfid?
* Hence try to do a regular lookup
*/
- if ((state->resolve.op_ret == -2)
+ if ((state->resolve.op_ret == -1)
&& (state->resolve.op_errno == ENODATA)) {
state->resolve.op_ret = 0;
}
@@ -462,8 +571,8 @@ fuse_lookup_resume (fuse_state_t *state)
static void
fuse_lookup (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
- char *name = msg;
- fuse_state_t *state = NULL;
+ char *name = msg;
+ fuse_state_t *state = NULL;
GET_STATE (this, finh, state);
@@ -471,16 +580,27 @@ fuse_lookup (xlator_t *this, fuse_in_header_t *finh, void *msg)
finh->nodeid, name);
fuse_resolve_and_resume (state, fuse_lookup_resume);
+
+ return;
}
+static inline void
+do_forget(xlator_t *this, uint64_t unique, uint64_t nodeid, uint64_t nlookup)
+{
+ inode_t *fuse_inode = fuse_ino_to_inode(nodeid, this);
+
+ fuse_log_eh(this, "%"PRIu64": FORGET %"PRIu64"/%"PRIu64" gfid: (%s)",
+ unique, nodeid, nlookup, uuid_utoa(fuse_inode->gfid));
+
+ inode_forget(fuse_inode, nlookup);
+ inode_unref(fuse_inode);
+}
static void
fuse_forget (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
- struct fuse_forget_in *ffi = msg;
-
- inode_t *fuse_inode;
+ struct fuse_forget_in *ffi = msg;
if (finh->nodeid == 1) {
GF_FREE (finh);
@@ -491,14 +611,30 @@ fuse_forget (xlator_t *this, fuse_in_header_t *finh, void *msg)
"%"PRIu64": FORGET %"PRIu64"/%"PRIu64,
finh->unique, finh->nodeid, ffi->nlookup);
- fuse_inode = fuse_ino_to_inode (finh->nodeid, this);
-
- inode_forget (fuse_inode, ffi->nlookup);
- inode_unref (fuse_inode);
+ do_forget(this, finh->unique, finh->nodeid, ffi->nlookup);
GF_FREE (finh);
}
+static void
+fuse_batch_forget(xlator_t *this, fuse_in_header_t *finh, void *msg)
+{
+ struct fuse_batch_forget_in *fbfi = msg;
+ struct fuse_forget_one *ffo = (struct fuse_forget_one *) (fbfi + 1);
+ int i;
+
+ gf_log("glusterfs-fuse", GF_LOG_TRACE,
+ "%"PRIu64": BATCH_FORGET %"PRIu64"/%"PRIu32,
+ finh->unique, finh->nodeid, fbfi->count);
+
+ for (i = 0; i < fbfi->count; i++) {
+ if (ffo[i].nodeid == 1)
+ continue;
+ do_forget(this, finh->unique, ffo[i].nodeid, ffo[i].nlookup);
+ }
+
+ GF_FREE(finh);
+}
static int
fuse_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
@@ -514,15 +650,17 @@ fuse_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state = frame->root->state;
finh = state->finh;
+ fuse_log_eh_fop(this, state, frame, op_ret, op_errno);
+
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": %s() %s => %"PRId64, frame->root->unique,
+ "%"PRIu64": %s() %s => %"PRIu64, frame->root->unique,
gf_fop_list[frame->root->op],
state->loc.path ? state->loc.path : "ERR",
prebuf->ia_ino);
postbuf->ia_blksize = this->ctx->page_size;
- gf_fuse_stat2attr (postbuf, &fao.attr);
+ gf_fuse_stat2attr (postbuf, &fao.attr, priv->enable_ino32);
fao.attr_valid = calc_timeout_sec (priv->attribute_timeout);
fao.attr_valid_nsec =
@@ -552,7 +690,6 @@ fuse_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
-
static int
fuse_attr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *buf, dict_t *xdata)
@@ -566,15 +703,19 @@ fuse_attr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state = frame->root->state;
finh = state->finh;
+ fuse_log_eh (this, "op_ret: %d, op_errno: %d, %"PRIu64": %s() %s => "
+ "gfid: %s", op_ret, op_errno, frame->root->unique,
+ gf_fop_list[frame->root->op], state->loc.path,
+ state->loc.inode ? uuid_utoa (state->loc.inode->gfid) : "");
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": %s() %s => %"PRId64, frame->root->unique,
+ "%"PRIu64": %s() %s => %"PRIu64, frame->root->unique,
gf_fop_list[frame->root->op],
state->loc.path ? state->loc.path : "ERR",
buf->ia_ino);
buf->ia_blksize = this->ctx->page_size;
- gf_fuse_stat2attr (buf, &fao.attr);
+ gf_fuse_stat2attr (buf, &fao.attr, priv->enable_ino32);
fao.attr_valid = calc_timeout_sec (priv->attribute_timeout);
fao.attr_valid_nsec =
@@ -589,9 +730,9 @@ fuse_attr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
send_fuse_obj (this, finh, &fao);
#endif
} else {
- GF_LOG_OCCASIONALLY ( gf_fuse_conn_err_log, "glusterfs-fuse",
- GF_LOG_WARNING,
- "%"PRIu64": %s() %s => -1 (%s)",
+ GF_LOG_OCCASIONALLY ( gf_fuse_conn_err_log, "glusterfs-fuse",
+ GF_LOG_WARNING,
+ "%"PRIu64": %s() %s => -1 (%s)",
frame->root->unique,
gf_fop_list[frame->root->op],
state->loc.path ? state->loc.path : "ERR",
@@ -606,7 +747,6 @@ fuse_attr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
-
static int
fuse_root_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
@@ -625,15 +765,15 @@ fuse_getattr_resume (fuse_state_t *state)
gf_log ("glusterfs-fuse", GF_LOG_ERROR,
"%"PRIu64": GETATTR %"PRIu64" (%s) resolution failed",
state->finh->unique, state->finh->nodeid,
- uuid_utoa (state->resolve.gfid));
+ uuid_utoa (state->resolve.gfid));
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
return;
}
- if (!IA_ISDIR (state->loc.inode->ia_type)) {
- state->fd = fd_lookup (state->loc.inode, state->finh->pid);
- }
+ if (!IA_ISDIR (state->loc.inode->ia_type)) {
+ state->fd = fd_lookup (state->loc.inode, state->finh->pid);
+ }
if (!state->fd) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
@@ -688,7 +828,6 @@ fuse_getattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
fuse_resolve_and_resume (state, fuse_getattr_resume);
}
-
static int32_t
fuse_fd_inherit_directio (xlator_t *this, fd_t *fd, struct fuse_open_out *foo)
{
@@ -703,7 +842,7 @@ fuse_fd_inherit_directio (xlator_t *this, fd_t *fd, struct fuse_open_out *foo)
GF_VALIDATE_OR_GOTO_WITH_ERROR ("glusterfs-fuse", foo, out, ret,
-EINVAL);
- fdctx = fuse_fd_ctx_check_n_create (this, fd);
+ fdctx = fuse_fd_ctx_get (this, fd);
if (!fdctx) {
ret = -ENOMEM;
goto out;
@@ -730,7 +869,6 @@ 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, dict_t *xdata)
@@ -745,6 +883,8 @@ fuse_fd_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state = frame->root->state;
finh = state->finh;
+ fuse_log_eh_fop(this, state, frame, op_ret, op_errno);
+
if (op_ret >= 0) {
foo.fh = (uintptr_t) fd;
foo.open_flags = 0;
@@ -765,17 +905,17 @@ fuse_fd_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
*
* [[Interesting...]]
*/
- if (!priv->fopen_keep_cache)
- foo.open_flags |= FOPEN_PURGE_UBC;
+ if (!priv->fopen_keep_cache)
+ foo.open_flags |= FOPEN_PURGE_UBC;
#else
- /*
- * If fopen-keep-cache is enabled, we set the associated
- * flag here such that files are not invalidated on open.
- * File invalidations occur either in fuse or explicitly
- * when the cache is set invalid on the inode.
- */
- if (priv->fopen_keep_cache)
- foo.open_flags |= FOPEN_KEEP_CACHE;
+ /*
+ * If fopen-keep-cache is enabled, we set the associated
+ * flag here such that files are not invalidated on open.
+ * File invalidations occur either in fuse or explicitly
+ * when the cache is set invalid on the inode.
+ */
+ if (priv->fopen_keep_cache)
+ foo.open_flags |= FOPEN_KEEP_CACHE;
#endif
}
@@ -787,8 +927,9 @@ fuse_fd_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
if (ret < 0) {
op_errno = -ret;
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "cannot inherit direct-io values from fds "
- "already opened");
+ "cannot inherit direct-io values for fd "
+ "(ptr:%p inode-gfid:%s) from fds already "
+ "opened", fd, uuid_utoa (fd->inode->gfid));
goto err;
}
@@ -816,7 +957,6 @@ out:
return 0;
}
-
static void
fuse_do_truncate (fuse_state_t *state, size_t size)
{
@@ -831,7 +971,6 @@ fuse_do_truncate (fuse_state_t *state, size_t size)
return;
}
-
static int
fuse_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
@@ -848,15 +987,20 @@ fuse_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state = frame->root->state;
finh = state->finh;
+ fuse_log_eh(this, "op_ret: %d, op_errno: %d, %"PRIu64", %s() %s => "
+ "gfid: %s", op_ret, op_errno, frame->root->unique,
+ gf_fop_list[frame->root->op], state->loc.path,
+ state->loc.inode ? uuid_utoa (state->loc.inode->gfid) : "");
+
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": %s() %s => %"PRId64, frame->root->unique,
+ "%"PRIu64": %s() %s => %"PRIu64, frame->root->unique,
gf_fop_list[frame->root->op],
state->loc.path ? state->loc.path : "ERR",
statpost->ia_ino);
statpost->ia_blksize = this->ctx->page_size;
- gf_fuse_stat2attr (statpost, &fao.attr);
+ gf_fuse_stat2attr (statpost, &fao.attr, priv->enable_ino32);
fao.attr_valid = calc_timeout_sec (priv->attribute_timeout);
fao.attr_valid_nsec =
@@ -895,7 +1039,6 @@ fuse_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
-
static int32_t
fattr_to_gf_set_attr (int32_t valid)
{
@@ -922,7 +1065,6 @@ fattr_to_gf_set_attr (int32_t valid)
return gf_valid;
}
-
#define FATTR_MASK (FATTR_SIZE \
| FATTR_UID | FATTR_GID \
| FATTR_ATIME | FATTR_MTIME \
@@ -935,7 +1077,7 @@ fuse_setattr_resume (fuse_state_t *state)
gf_log ("glusterfs-fuse", GF_LOG_ERROR,
"%"PRIu64": SETATTR %"PRIu64" (%s) resolution failed",
state->finh->unique, state->finh->nodeid,
- uuid_utoa (state->resolve.gfid));
+ uuid_utoa (state->resolve.gfid));
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
return;
@@ -991,10 +1133,10 @@ fuse_setattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
/* We need no loc if kernel sent us an fd and
* we are not fiddling with times */
state->fd = FH_TO_FD (fsi->fh);
- fuse_resolve_fd_init (state, &state->resolve, state->fd);
- } else {
- fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
- }
+ fuse_resolve_fd_init (state, &state->resolve, state->fd);
+ } else {
+ fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
+ }
/*
* This is just stub code demonstrating how to retrieve
@@ -1039,7 +1181,6 @@ fuse_setattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
fuse_resolve_and_resume (state, fuse_setattr_resume);
}
-
static int
fuse_err_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, dict_t *xdata)
@@ -1047,6 +1188,8 @@ fuse_err_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
fuse_state_t *state = frame->root->state;
fuse_in_header_t *finh = state->finh;
+ fuse_log_eh_fop(this, state, frame, op_ret, op_errno);
+
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
"%"PRIu64": %s() %s => 0", frame->root->unique,
@@ -1071,7 +1214,6 @@ fuse_err_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
-
static int
fuse_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
@@ -1080,7 +1222,6 @@ fuse_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return fuse_err_cbk (frame, cookie, this, op_ret, op_errno, xdata);
}
-
static int
fuse_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, dict_t *xdata)
@@ -1094,7 +1235,6 @@ fuse_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return fuse_err_cbk (frame, cookie, this, op_ret, op_errno, xdata);
}
-
static int
fuse_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *preparent,
@@ -1106,11 +1246,14 @@ fuse_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state = frame->root->state;
finh = state->finh;
- if (op_ret == 0)
- inode_unlink (state->loc.inode, state->loc.parent,
- state->loc.name);
+ fuse_log_eh (this, "op_ret: %d, op_errno: %d, %"PRIu64": %s() %s => "
+ "gfid: %s", op_ret, op_errno, frame->root->unique,
+ gf_fop_list[frame->root->op], state->loc.path,
+ state->loc.inode ? uuid_utoa (state->loc.inode->gfid) : "");
if (op_ret == 0) {
+ inode_unlink (state->loc.inode, state->loc.parent,
+ state->loc.name);
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
"%"PRIu64": %s() %s => 0", frame->root->unique,
gf_fop_list[frame->root->op], state->loc.path);
@@ -1132,7 +1275,6 @@ fuse_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
-
void
fuse_access_resume (fuse_state_t *state)
{
@@ -1140,7 +1282,7 @@ fuse_access_resume (fuse_state_t *state)
gf_log ("glusterfs-fuse", GF_LOG_ERROR,
"%"PRIu64": ACCESS %"PRIu64" (%s) resolution failed",
state->finh->unique, state->finh->nodeid,
- uuid_utoa (state->resolve.gfid));
+ uuid_utoa (state->resolve.gfid));
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
return;
@@ -1155,7 +1297,6 @@ fuse_access_resume (fuse_state_t *state)
&state->loc, state->mask, state->xdata);
}
-
static void
fuse_access (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -1173,7 +1314,6 @@ fuse_access (xlator_t *this, fuse_in_header_t *finh, void *msg)
return;
}
-
static int
fuse_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, const char *linkname,
@@ -1185,6 +1325,12 @@ fuse_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state = frame->root->state;
finh = state->finh;
+ fuse_log_eh (this, "op_ret: %d, op_errno: %d %"PRIu64": %s() => %s"
+ " linkname: %s, gfid: %s", op_ret, op_errno,
+ frame->root->unique, gf_fop_list[frame->root->op],
+ state->loc.gfid, linkname,
+ uuid_utoa (state->loc.gfid));
+
if (op_ret > 0) {
((char *)linkname)[op_ret] = '\0';
@@ -1207,7 +1353,6 @@ fuse_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
-
void
fuse_readlink_resume (fuse_state_t *state)
{
@@ -1228,7 +1373,6 @@ fuse_readlink_resume (fuse_state_t *state)
readlink, &state->loc, 4096, state->xdata);
}
-
static void
fuse_readlink (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -1236,22 +1380,21 @@ fuse_readlink (xlator_t *this, fuse_in_header_t *finh, void *msg)
GET_STATE (this, finh, state);
- fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
+ fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
fuse_resolve_and_resume (state, fuse_readlink_resume);
return;
}
-
void
fuse_mknod_resume (fuse_state_t *state)
{
if (!state->loc.parent) {
gf_log ("glusterfs-fuse", GF_LOG_ERROR,
- "MKNOD %"PRId64"/%s (%s/%s) resolution failed",
+ "MKNOD %"PRIu64"/%s (%s/%s) resolution failed",
state->finh->nodeid, state->resolve.bname,
- uuid_utoa (state->resolve.gfid), state->resolve.bname);
+ uuid_utoa (state->resolve.gfid), state->resolve.bname);
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
return;
@@ -1265,7 +1408,7 @@ fuse_mknod_resume (fuse_state_t *state)
if (state->loc.inode) {
gf_log (state->this->name, GF_LOG_DEBUG, "inode already present");
inode_unref (state->loc.inode);
- state->loc.inode = NULL;
+ state->loc.inode = NULL;
}
state->loc.inode = inode_new (state->loc.parent->table);
@@ -1279,7 +1422,6 @@ fuse_mknod_resume (fuse_state_t *state)
state->xdata);
}
-
static void
fuse_mknod (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -1300,48 +1442,14 @@ fuse_mknod (xlator_t *this, fuse_in_header_t *finh, void *msg)
uuid_generate (state->gfid);
- fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
+ fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
state->mode = fmi->mode;
state->rdev = fmi->rdev;
priv = this->private;
#if FUSE_KERNEL_MINOR_VERSION >=12
- if (priv->proto_minor >= 12)
- state->mode &= ~fmi->umask;
- if (priv->proto_minor >= 12 && priv->acl) {
- state->xdata = dict_new ();
- if (!state->xdata) {
- gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "MKNOD Failed to allocate a param dictionary");
- send_fuse_err (this, finh, ENOMEM);
- free_fuse_state (state);
- return;
- }
- state->umask = fmi->umask;
-
- /* TODO: remove this after 3.4.0 release. keeping it for the
- sake of backward compatibility with old (3.3.[01])
- releases till then. */
- ret = dict_set_int16 (state->xdata, "umask", fmi->umask);
- if (ret < 0) {
- gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "MKNOD Failed adding umask to request");
- dict_destroy (state->xdata);
- send_fuse_err (this, finh, ENOMEM);
- free_fuse_state (state);
- return;
- }
- ret = dict_set_int16 (state->xdata, "mode", fmi->mode);
- if (ret < 0) {
- gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "MKNOD Failed adding mode to request");
- dict_destroy (state->xdata);
- send_fuse_err (this, finh, ENOMEM);
- free_fuse_state (state);
- return;
- }
- }
+ FUSE_ENTRY_CREATE(this, priv, finh, state, fmi, "MKNOD");
#endif
fuse_resolve_and_resume (state, fuse_mknod_resume);
@@ -1349,15 +1457,14 @@ fuse_mknod (xlator_t *this, fuse_in_header_t *finh, void *msg)
return;
}
-
void
fuse_mkdir_resume (fuse_state_t *state)
{
if (!state->loc.parent) {
gf_log ("glusterfs-fuse", GF_LOG_ERROR,
- "MKDIR %"PRId64" (%s/%s) resolution failed",
+ "MKDIR %"PRIu64" (%s/%s) resolution failed",
state->finh->nodeid, uuid_utoa (state->resolve.gfid),
- state->resolve.bname);
+ state->resolve.bname);
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
return;
@@ -1371,7 +1478,7 @@ fuse_mkdir_resume (fuse_state_t *state)
if (state->loc.inode) {
gf_log (state->this->name, GF_LOG_DEBUG, "inode already present");
inode_unref (state->loc.inode);
- state->loc.inode = NULL;
+ state->loc.inode = NULL;
}
state->loc.inode = inode_new (state->loc.parent->table);
@@ -1384,7 +1491,6 @@ fuse_mkdir_resume (fuse_state_t *state)
mkdir, &state->loc, state->mode, state->umask, state->xdata);
}
-
static void
fuse_mkdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -1399,47 +1505,13 @@ fuse_mkdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
uuid_generate (state->gfid);
- fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
+ fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
state->mode = fmi->mode;
priv = this->private;
#if FUSE_KERNEL_MINOR_VERSION >=12
- if (priv->proto_minor >= 12)
- state->mode &= ~fmi->umask;
- if (priv->proto_minor >= 12 && priv->acl) {
- state->xdata = dict_new ();
- if (!state->xdata) {
- gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "MKDIR Failed to allocate a param dictionary");
- send_fuse_err (this, finh, ENOMEM);
- free_fuse_state (state);
- return;
- }
- state->umask = fmi->umask;
-
- /* TODO: remove this after 3.4.0 release. keeping it for the
- sake of backward compatibility with old (3.3.[01])
- releases till then. */
- ret = dict_set_int16 (state->xdata, "umask", fmi->umask);
- if (ret < 0) {
- gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "MKDIR Failed adding umask to request");
- dict_destroy (state->xdata);
- send_fuse_err (this, finh, ENOMEM);
- free_fuse_state (state);
- return;
- }
- ret = dict_set_int16 (state->xdata, "mode", fmi->mode);
- if (ret < 0) {
- gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "MKDIR Failed adding mode to request");
- dict_destroy (state->xdata);
- send_fuse_err (this, finh, ENOMEM);
- free_fuse_state (state);
- return;
- }
- }
+ FUSE_ENTRY_CREATE(this, priv, finh, state, fmi, "MKDIR");
#endif
fuse_resolve_and_resume (state, fuse_mkdir_resume);
@@ -1447,15 +1519,14 @@ fuse_mkdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
return;
}
-
void
fuse_unlink_resume (fuse_state_t *state)
{
if (!state->loc.parent || !state->loc.inode) {
gf_log ("glusterfs-fuse", GF_LOG_ERROR,
- "UNLINK %"PRId64" (%s/%s) resolution failed",
- state->finh->nodeid, uuid_utoa (state->resolve.gfid),
- state->resolve.bname);
+ "UNLINK %"PRIu64" (%s/%s) resolution failed",
+ state->finh->nodeid, uuid_utoa (state->resolve.gfid),
+ state->resolve.bname);
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
return;
@@ -1469,7 +1540,6 @@ fuse_unlink_resume (fuse_state_t *state)
unlink, &state->loc, 0, state->xdata);
}
-
static void
fuse_unlink (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -1478,7 +1548,7 @@ fuse_unlink (xlator_t *this, fuse_in_header_t *finh, void *msg)
GET_STATE (this, finh, state);
- fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
+ fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
fuse_resolve_and_resume (state, fuse_unlink_resume);
@@ -1490,9 +1560,9 @@ fuse_rmdir_resume (fuse_state_t *state)
{
if (!state->loc.parent || !state->loc.inode) {
gf_log ("glusterfs-fuse", GF_LOG_ERROR,
- "RMDIR %"PRId64" (%s/%s) resolution failed",
- state->finh->nodeid, uuid_utoa (state->resolve.gfid),
- state->resolve.bname);
+ "RMDIR %"PRIu64" (%s/%s) resolution failed",
+ state->finh->nodeid, uuid_utoa (state->resolve.gfid),
+ state->resolve.bname);
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
return;
@@ -1506,7 +1576,6 @@ fuse_rmdir_resume (fuse_state_t *state)
rmdir, &state->loc, 0, state->xdata);
}
-
static void
fuse_rmdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -1515,22 +1584,21 @@ fuse_rmdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
GET_STATE (this, finh, state);
- fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
+ fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
fuse_resolve_and_resume (state, fuse_rmdir_resume);
return;
}
-
void
fuse_symlink_resume (fuse_state_t *state)
{
if (!state->loc.parent) {
gf_log ("glusterfs-fuse", GF_LOG_ERROR,
- "SYMLINK %"PRId64" (%s/%s) -> %s resolution failed",
+ "SYMLINK %"PRIu64" (%s/%s) -> %s resolution failed",
state->finh->nodeid, uuid_utoa (state->resolve.gfid),
- state->resolve.bname, state->name);
+ state->resolve.bname, state->name);
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
return;
@@ -1544,7 +1612,7 @@ fuse_symlink_resume (fuse_state_t *state)
if (state->loc.inode) {
gf_log (state->this->name, GF_LOG_DEBUG, "inode already present");
inode_unref (state->loc.inode);
- state->loc.inode = NULL;
+ state->loc.inode = NULL;
}
state->loc.inode = inode_new (state->loc.parent->table);
@@ -1557,7 +1625,6 @@ fuse_symlink_resume (fuse_state_t *state)
symlink, state->name, &state->loc, state->umask, state->xdata);
}
-
static void
fuse_symlink (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -1569,7 +1636,7 @@ fuse_symlink (xlator_t *this, fuse_in_header_t *finh, void *msg)
uuid_generate (state->gfid);
- fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
+ fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
state->name = gf_strdup (linkname);
@@ -1578,7 +1645,6 @@ fuse_symlink (xlator_t *this, fuse_in_header_t *finh, void *msg)
return;
}
-
int
fuse_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *buf,
@@ -1592,9 +1658,18 @@ fuse_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state = frame->root->state;
finh = state->finh;
+ fuse_log_eh (this, "op_ret: %d, op_errno: %d, %"PRIu64": %s() "
+ "path: %s parent: %s ==> path: %s parent: %s"
+ "gfid: %s", op_ret, op_errno, frame->root->unique,
+ gf_fop_list[frame->root->op], state->loc.path,
+ state->loc.parent?uuid_utoa (state->loc.parent->gfid):"",
+ state->loc2.path,
+ state->loc2.parent?uuid_utoa (state->loc2.parent->gfid):"",
+ state->loc.inode?uuid_utoa (state->loc.inode->gfid):"");
+
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": %s -> %s => 0 (buf->ia_ino=%"PRId64")",
+ "%"PRIu64": %s -> %s => 0 (buf->ia_ino=%"PRIu64")",
frame->root->unique, state->loc.path, state->loc2.path,
buf->ia_ino);
@@ -1634,11 +1709,11 @@ fuse_rename_resume (fuse_state_t *state)
if (!state->loc.parent || !state->loc.inode) {
gf_log ("glusterfs-fuse", GF_LOG_ERROR,
"RENAME %"PRIu64" %s/%s -> %s/%s src resolution failed",
- state->finh->unique,
- uuid_utoa_r (state->resolve.gfid, loc_uuid),
- state->resolve.bname,
- uuid_utoa_r (state->resolve2.gfid, loc2_uuid),
- state->resolve2.bname);
+ state->finh->unique,
+ uuid_utoa_r (state->resolve.gfid, loc_uuid),
+ state->resolve.bname,
+ uuid_utoa_r (state->resolve2.gfid, loc2_uuid),
+ state->resolve2.bname);
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
@@ -1648,11 +1723,11 @@ fuse_rename_resume (fuse_state_t *state)
if (!state->loc2.parent) {
gf_log ("glusterfs-fuse", GF_LOG_ERROR,
"RENAME %"PRIu64" %s/%s -> %s/%s dst resolution failed",
- state->finh->unique,
- uuid_utoa_r (state->resolve.gfid, loc_uuid),
- state->resolve.bname,
- uuid_utoa_r (state->resolve2.gfid, loc2_uuid),
- state->resolve2.bname);
+ state->finh->unique,
+ uuid_utoa_r (state->resolve.gfid, loc_uuid),
+ state->resolve.bname,
+ uuid_utoa_r (state->resolve2.gfid, loc2_uuid),
+ state->resolve2.bname);
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
@@ -1671,7 +1746,6 @@ fuse_rename_resume (fuse_state_t *state)
rename, &state->loc, &state->loc2, state->xdata);
}
-
static void
fuse_rename (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -1682,16 +1756,15 @@ fuse_rename (xlator_t *this, fuse_in_header_t *finh, void *msg)
GET_STATE (this, finh, state);
- fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, oldname);
+ fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, oldname);
- fuse_resolve_entry_init (state, &state->resolve2, fri->newdir, newname);
+ fuse_resolve_entry_init (state, &state->resolve2, fri->newdir, newname);
fuse_resolve_and_resume (state, fuse_rename_resume);
return;
}
-
void
fuse_link_resume (fuse_state_t *state)
{
@@ -1707,11 +1780,11 @@ fuse_link_resume (fuse_state_t *state)
state->resolve.op_ret = 0;
state->resolve2.op_ret = 0;
- if (state->loc.inode) {
- inode_unref (state->loc.inode);
- state->loc.inode = NULL;
- }
- state->loc.inode = inode_ref (state->loc2.inode);
+ if (state->loc.inode) {
+ inode_unref (state->loc.inode);
+ state->loc.inode = NULL;
+ }
+ state->loc.inode = inode_ref (state->loc2.inode);
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
"%"PRIu64": LINK() %s -> %s",
@@ -1722,7 +1795,6 @@ fuse_link_resume (fuse_state_t *state)
link, &state->loc2, &state->loc, state->xdata);
}
-
static void
fuse_link (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -1732,16 +1804,15 @@ fuse_link (xlator_t *this, fuse_in_header_t *finh, void *msg)
GET_STATE (this, finh, state);
- fuse_resolve_inode_init (state, &state->resolve2, fli->oldnodeid);
+ fuse_resolve_inode_init (state, &state->resolve2, fli->oldnodeid);
- fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
+ fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
fuse_resolve_and_resume (state, fuse_link_resume);
return;
}
-
static int
fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
@@ -1762,6 +1833,8 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
finh = state->finh;
foo.open_flags = 0;
+ fuse_log_eh_fop(this, state, frame, op_ret, op_errno);
+
if (op_ret >= 0) {
foo.fh = (uintptr_t) fd;
@@ -1771,12 +1844,12 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
foo.open_flags |= FOPEN_DIRECT_IO;
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": %s() %s => %p (ino=%"PRId64")",
+ "%"PRIu64": %s() %s => %p (ino=%"PRIu64")",
frame->root->unique, gf_fop_list[frame->root->op],
state->loc.path, fd, buf->ia_ino);
buf->ia_blksize = this->ctx->page_size;
- gf_fuse_stat2attr (buf, &feo.attr);
+ gf_fuse_stat2attr (buf, &feo.attr, priv->enable_ino32);
linked_inode = inode_link (inode, state->loc.parent,
state->loc.name, buf);
@@ -1814,6 +1887,7 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
#endif
iov_out[2].iov_base = &foo;
iov_out[2].iov_len = sizeof (foo);
+
if (send_fuse_iov (this, finh, iov_out, 3) == ENOENT) {
gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
"create(%s) got EINTR", state->loc.path);
@@ -1837,18 +1911,18 @@ out:
return 0;
}
-
void
fuse_create_resume (fuse_state_t *state)
{
- fd_t *fd = NULL;
- fuse_private_t *priv = NULL;
+ fd_t *fd = NULL;
+ fuse_private_t *priv = NULL;
+ fuse_fd_ctx_t *fdctx = NULL;
if (!state->loc.parent) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64" CREATE %s/%s resolution failed",
state->finh->unique, uuid_utoa (state->resolve.gfid),
- state->resolve.bname);
+ state->resolve.bname);
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
return;
@@ -1868,6 +1942,25 @@ fuse_create_resume (fuse_state_t *state)
state->loc.inode = inode_new (state->loc.parent->table);
fd = fd_create (state->loc.inode, state->finh->pid);
+ if (fd == NULL) {
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING,
+ "%"PRIu64" CREATE cannot create a new fd",
+ state->finh->unique);
+ send_fuse_err (state->this, state->finh, ENOMEM);
+ free_fuse_state (state);
+ return;
+ }
+
+ fdctx = fuse_fd_ctx_check_n_create (state->this, fd);
+ if (fdctx == NULL) {
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING,
+ "%"PRIu64" CREATE creation of fdctx failed",
+ state->finh->unique);
+ fd_unref (fd);
+ send_fuse_err (state->this, state->finh, ENOMEM);
+ free_fuse_state (state);
+ return;
+ }
priv = state->this->private;
@@ -1886,7 +1979,6 @@ fuse_create_resume (fuse_state_t *state)
}
-
static void
fuse_create (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -1911,61 +2003,26 @@ fuse_create (xlator_t *this, fuse_in_header_t *finh, void *msg)
uuid_generate (state->gfid);
- fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
+ fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
state->mode = fci->mode;
state->flags = fci->flags;
priv = this->private;
#if FUSE_KERNEL_MINOR_VERSION >=12
- if (priv->proto_minor >= 12)
- state->mode &= ~fci->umask;
- if (priv->proto_minor >= 12 && priv->acl) {
- state->xdata = dict_new ();
- if (!state->xdata) {
- gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "CREATE Failed to allocate a param dictionary");
- send_fuse_err (this, finh, ENOMEM);
- free_fuse_state (state);
- return;
- }
- state->umask = fci->umask;
-
- /* TODO: remove this after 3.4.0 release. keeping it for the
- sake of backward compatibility with old (3.3.[01])
- releases till then. */
- ret = dict_set_int16 (state->xdata, "umask", fci->umask);
- if (ret < 0) {
- gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "CREATE Failed adding umask to request");
- dict_destroy (state->xdata);
- send_fuse_err (this, finh, ENOMEM);
- free_fuse_state (state);
- return;
- }
- ret = dict_set_int16 (state->xdata, "mode", fci->mode);
- if (ret < 0) {
- gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "CREATE Failed adding mode to request");
- dict_destroy (state->xdata);
- send_fuse_err (this, finh, ENOMEM);
- free_fuse_state (state);
- return;
- }
- }
+ FUSE_ENTRY_CREATE(this, priv, finh, state, fci, "CREATE");
#endif
-
fuse_resolve_and_resume (state, fuse_create_resume);
return;
}
-
void
fuse_open_resume (fuse_state_t *state)
{
- fd_t *fd = NULL;
- fuse_private_t *priv = NULL;
+ fd_t *fd = NULL;
+ fuse_private_t *priv = NULL;
+ fuse_fd_ctx_t *fdctx = NULL;
if (!state->loc.inode) {
gf_log ("glusterfs-fuse", GF_LOG_ERROR,
@@ -1986,6 +2043,17 @@ fuse_open_resume (fuse_state_t *state)
return;
}
+ fdctx = fuse_fd_ctx_check_n_create (state->this, fd);
+ if (fdctx == NULL) {
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING,
+ "%"PRIu64": OPEN creation of fdctx failed",
+ state->finh->unique);
+ fd_unref (fd);
+ send_fuse_err (state->this, state->finh, ENOMEM);
+ free_fuse_state (state);
+ return;
+ }
+
priv = state->this->private;
state->fd_no = gf_fd_unused_get (priv->fdtable, fd);
@@ -2000,7 +2068,6 @@ fuse_open_resume (fuse_state_t *state)
open, &state->loc, state->flags, fd, state->xdata);
}
-
static void
fuse_open (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -2009,7 +2076,7 @@ fuse_open (xlator_t *this, fuse_in_header_t *finh, void *msg)
GET_STATE (this, finh, state);
- fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
+ fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
state->flags = foi->flags;
@@ -2018,7 +2085,6 @@ fuse_open (xlator_t *this, fuse_in_header_t *finh, void *msg)
return;
}
-
static int
fuse_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
@@ -2033,9 +2099,11 @@ fuse_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state = frame->root->state;
finh = state->finh;
+ fuse_log_eh_fop(this, state, frame, op_ret, op_errno);
+
if (op_ret >= 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": READ => %d/%"GF_PRI_SIZET",%"PRId64"/%"PRId64,
+ "%"PRIu64": READ => %d/%"GF_PRI_SIZET",%"PRId64"/%"PRIu64,
frame->root->unique,
op_ret, state->size, state->off, stbuf->ia_size);
@@ -2088,7 +2156,7 @@ fuse_readv (xlator_t *this, fuse_in_header_t *finh, void *msg)
fd = FH_TO_FD (fri->fh);
state->fd = fd;
- fuse_resolve_fd_init (state, &state->resolve, fd);
+ fuse_resolve_fd_init (state, &state->resolve, fd);
/* See comment by similar code in fuse_settatr */
priv = this->private;
@@ -2105,7 +2173,6 @@ fuse_readv (xlator_t *this, fuse_in_header_t *finh, void *msg)
fuse_resolve_and_resume (state, fuse_readv_resume);
}
-
static int
fuse_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
@@ -2118,9 +2185,11 @@ fuse_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state = frame->root->state;
finh = state->finh;
+ fuse_log_eh_fop(this, state, frame, op_ret, op_errno);
+
if (op_ret >= 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": WRITE => %d/%"GF_PRI_SIZET",%"PRId64"/%"PRId64,
+ "%"PRIu64": WRITE => %d/%"GF_PRI_SIZET",%"PRId64"/%"PRIu64,
frame->root->unique,
op_ret, state->size, state->off, stbuf->ia_size);
@@ -2162,7 +2231,7 @@ fuse_write_resume (fuse_state_t *state)
iobref_add (iobref, iobuf);
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": WRITE (%p, size=%"PRId64", offset=%"PRId64")",
+ "%"PRIu64": WRITE (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")",
state->finh->unique, state->fd, state->size, state->off);
FUSE_FOP (state, fuse_writev_cbk, GF_FOP_WRITE, writev, state->fd,
@@ -2200,7 +2269,7 @@ fuse_write (xlator_t *this, fuse_in_header_t *finh, void *msg)
*/
- fuse_resolve_fd_init (state, &state->resolve, fd);
+ fuse_resolve_fd_init (state, &state->resolve, fd);
/* See comment by similar code in fuse_settatr */
priv = this->private;
@@ -2217,7 +2286,6 @@ fuse_write (xlator_t *this, fuse_in_header_t *finh, void *msg)
return;
}
-
void
fuse_flush_resume (fuse_state_t *state)
{
@@ -2225,7 +2293,6 @@ fuse_flush_resume (fuse_state_t *state)
flush, state->fd, state->xdata);
}
-
static void
fuse_flush (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -2238,7 +2305,7 @@ fuse_flush (xlator_t *this, fuse_in_header_t *finh, void *msg)
fd = FH_TO_FD (ffi->fh);
state->fd = fd;
- fuse_resolve_fd_init (state, &state->resolve, fd);
+ fuse_resolve_fd_init (state, &state->resolve, fd);
state->lk_owner = ffi->lock_owner;
@@ -2250,18 +2317,17 @@ fuse_flush (xlator_t *this, fuse_in_header_t *finh, void *msg)
return;
}
-
static void
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 val = 0;
- int ret = 0;
- fuse_state_t *state = NULL;
- fuse_fd_ctx_t *fdctx = NULL;
- fuse_private_t *priv = NULL;
+ struct fuse_release_in *fri = msg;
+ fd_t *activefd = NULL;
+ fd_t *fd = NULL;
+ uint64_t val = 0;
+ int ret = 0;
+ fuse_state_t *state = NULL;
+ fuse_fd_ctx_t *fdctx = NULL;
+ fuse_private_t *priv = NULL;
GET_STATE (this, finh, state);
fd = FH_TO_FD (fri->fh);
@@ -2269,6 +2335,9 @@ fuse_release (xlator_t *this, fuse_in_header_t *finh, void *msg)
priv = this->private;
+ fuse_log_eh (this, "RELEASE(): %"PRIu64":, fd: %p, gfid: %s",
+ finh->unique, fd, uuid_utoa (fd->inode->gfid));
+
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
"%"PRIu64": RELEASE %p", finh->unique, state->fd);
@@ -2276,9 +2345,9 @@ fuse_release (xlator_t *this, fuse_in_header_t *finh, void *msg)
if (!ret) {
fdctx = (fuse_fd_ctx_t *)(unsigned long)val;
if (fdctx) {
- new_fd = fdctx->fd;
- if (new_fd) {
- fd_unref (new_fd);
+ activefd = fdctx->activefd;
+ if (activefd) {
+ fd_unref (activefd);
}
GF_FREE (fdctx);
@@ -2296,20 +2365,18 @@ fuse_release (xlator_t *this, fuse_in_header_t *finh, void *msg)
return;
}
-
void
fuse_fsync_resume (fuse_state_t *state)
{
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
"%"PRIu64": FSYNC %p", state->finh->unique,
- state->fd);
+ state->fd);
/* fsync_flags: 1 means "datasync" (no defines for this) */
FUSE_FOP (state, fuse_fsync_cbk, GF_FOP_FSYNC,
fsync, state->fd, (state->flags & 1), state->xdata);
}
-
static void
fuse_fsync (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -2322,19 +2389,19 @@ fuse_fsync (xlator_t *this, fuse_in_header_t *finh, void *msg)
fd = FH_TO_FD (fsi->fh);
state->fd = fd;
- fuse_resolve_fd_init (state, &state->resolve, fd);
+ fuse_resolve_fd_init (state, &state->resolve, fd);
state->flags = fsi->fsync_flags;
fuse_resolve_and_resume (state, fuse_fsync_resume);
return;
}
-
void
fuse_opendir_resume (fuse_state_t *state)
{
- fd_t *fd = NULL;
- fuse_private_t *priv = NULL;
+ fd_t *fd = NULL;
+ fuse_private_t *priv = NULL;
+ fuse_fd_ctx_t *fdctx = NULL;
priv = state->this->private;
@@ -2348,6 +2415,25 @@ fuse_opendir_resume (fuse_state_t *state)
}
fd = fd_create (state->loc.inode, state->finh->pid);
+ if (fd == NULL) {
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING,
+ "%"PRIu64": OPENDIR fd creation failed",
+ state->finh->unique);
+ send_fuse_err (state->this, state->finh, ENOMEM);
+ free_fuse_state (state);
+ }
+
+ fdctx = fuse_fd_ctx_check_n_create (state->this, fd);
+ if (fdctx == NULL) {
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING,
+ "%"PRIu64": OPENDIR creation of fdctx failed",
+ state->finh->unique);
+ fd_unref (fd);
+ send_fuse_err (state->this, state->finh, ENOMEM);
+ free_fuse_state (state);
+ return;
+ }
+
state->fd = fd_ref (fd);
state->fd_no = gf_fd_unused_get (priv->fdtable, fd);
@@ -2359,7 +2445,6 @@ fuse_opendir_resume (fuse_state_t *state)
opendir, &state->loc, fd, state->xdata);
}
-
static void
fuse_opendir (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -2376,7 +2461,6 @@ fuse_opendir (xlator_t *this, fuse_in_header_t *finh, void *msg)
fuse_resolve_and_resume (state, fuse_opendir_resume);
}
-
unsigned char
d_type_from_stat (struct iatt *buf)
{
@@ -2410,7 +2494,6 @@ d_type_from_stat (struct iatt *buf)
return d_type;
}
-
static int
fuse_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, gf_dirent_t *entries,
@@ -2422,9 +2505,13 @@ fuse_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
char *buf = NULL;
gf_dirent_t *entry = NULL;
struct fuse_dirent *fde = NULL;
+ fuse_private_t *priv = NULL;
state = frame->root->state;
finh = state->finh;
+ priv = state->this->private;
+
+ fuse_log_eh_fop(this, state, frame, op_ret, op_errno);
if (op_ret < 0) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
@@ -2444,6 +2531,11 @@ fuse_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
strlen (entry->d_name));
}
+ if (size <= 0) {
+ send_fuse_data (this, finh, 0, 0);
+ goto out;
+ }
+
buf = GF_CALLOC (1, size, gf_fuse_mt_char);
if (!buf) {
gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
@@ -2456,11 +2548,7 @@ fuse_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
size = 0;
list_for_each_entry (entry, &entries->list, list) {
fde = (struct fuse_dirent *)(buf + size);
- fde->ino = entry->d_ino;
- fde->off = entry->d_off;
- fde->type = entry->d_type;
- fde->namelen = strlen (entry->d_name);
- strncpy (fde->name, entry->d_name, fde->namelen);
+ gf_fuse_fill_dirent (entry, fde, priv->enable_ino32);
size += FUSE_DIRENT_SIZE (fde);
}
@@ -2477,19 +2565,17 @@ out:
}
-
void
fuse_readdir_resume (fuse_state_t *state)
{
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": READDIR (%p, size=%zu, offset=%"PRId64")",
+ "%"PRIu64": READDIR (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")",
state->finh->unique, state->fd, state->size, state->off);
FUSE_FOP (state, fuse_readdir_cbk, GF_FOP_READDIR,
readdir, state->fd, state->size, state->off, state->xdata);
}
-
static void
fuse_readdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -2504,28 +2590,207 @@ fuse_readdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
fd = FH_TO_FD (fri->fh);
state->fd = fd;
- fuse_resolve_fd_init (state, &state->resolve, fd);
+ fuse_resolve_fd_init (state, &state->resolve, fd);
fuse_resolve_and_resume (state, fuse_readdir_resume);
}
+static int
+fuse_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, gf_dirent_t *entries,
+ dict_t *xdata)
+{
+ fuse_state_t *state = NULL;
+ fuse_in_header_t *finh = NULL;
+ int size = 0;
+ char *buf = NULL;
+ gf_dirent_t *entry = NULL;
+ struct fuse_direntplus *fde = NULL;
+ struct fuse_entry_out *feo = NULL;
+ fuse_private_t *priv = NULL;
+
+ state = frame->root->state;
+ finh = state->finh;
+ priv = this->private;
+
+ if (op_ret < 0) {
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING,
+ "%"PRIu64": READDIRP => -1 (%s)", frame->root->unique,
+ strerror (op_errno));
+
+ send_fuse_err (this, finh, op_errno);
+ goto out;
+ }
+
+ gf_log ("glusterfs-fuse", GF_LOG_TRACE,
+ "%"PRIu64": READDIRP => %d/%"GF_PRI_SIZET",%"PRId64,
+ frame->root->unique, op_ret, state->size, state->off);
+
+ list_for_each_entry (entry, &entries->list, list) {
+ size += FUSE_DIRENT_ALIGN (FUSE_NAME_OFFSET_DIRENTPLUS +
+ strlen (entry->d_name));
+ }
+
+ if (size <= 0) {
+ send_fuse_data (this, finh, 0, 0);
+ goto out;
+ }
+
+ buf = GF_CALLOC (1, size, gf_fuse_mt_char);
+ if (!buf) {
+ gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
+ "%"PRIu64": READDIRP => -1 (%s)", frame->root->unique,
+ strerror (ENOMEM));
+ send_fuse_err (this, finh, ENOMEM);
+ goto out;
+ }
+
+ size = 0;
+ list_for_each_entry (entry, &entries->list, list) {
+ inode_t *linked_inode;
+
+ fde = (struct fuse_direntplus *)(buf + size);
+ feo = &fde->entry_out;
+ fde->dirent.ino = entry->d_ino;
+ fde->dirent.off = entry->d_off;
+ fde->dirent.type = entry->d_type;
+ fde->dirent.namelen = strlen (entry->d_name);
+ strncpy (fde->dirent.name, entry->d_name, fde->dirent.namelen);
+ size += FUSE_DIRENTPLUS_SIZE (fde);
+
+ if (!entry->inode)
+ continue;
+
+ entry->d_stat.ia_blksize = this->ctx->page_size;
+ gf_fuse_stat2attr (&entry->d_stat, &feo->attr, priv->enable_ino32);
+
+ linked_inode = inode_link (entry->inode, state->fd->inode,
+ entry->d_name, &entry->d_stat);
+ if (!linked_inode)
+ continue;
+
+ inode_lookup (linked_inode);
+
+ feo->nodeid = inode_to_fuse_nodeid (linked_inode);
+
+ fuse_inode_set_need_lookup (linked_inode, this);
+
+ inode_unref (linked_inode);
+
+ feo->entry_valid =
+ calc_timeout_sec (priv->entry_timeout);
+ feo->entry_valid_nsec =
+ calc_timeout_nsec (priv->entry_timeout);
+ feo->attr_valid =
+ calc_timeout_sec (priv->attribute_timeout);
+ feo->attr_valid_nsec =
+ calc_timeout_nsec (priv->attribute_timeout);
+ }
+
+ send_fuse_data (this, finh, buf, size);
+out:
+ free_fuse_state (state);
+ STACK_DESTROY (frame->root);
+ GF_FREE (buf);
+ return 0;
+
+}
+
+
+void
+fuse_readdirp_resume (fuse_state_t *state)
+{
+ gf_log ("glusterfs-fuse", GF_LOG_TRACE,
+ "%"PRIu64": READDIRP (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")",
+ state->finh->unique, state->fd, state->size, state->off);
+
+ FUSE_FOP (state, fuse_readdirp_cbk, GF_FOP_READDIRP,
+ readdirp, state->fd, state->size, state->off, state->xdata);
+}
+
+
+static void
+fuse_readdirp (xlator_t *this, fuse_in_header_t *finh, void *msg)
+{
+ struct fuse_read_in *fri = msg;
+
+ fuse_state_t *state = NULL;
+ fd_t *fd = NULL;
+
+ GET_STATE (this, finh, state);
+ state->size = fri->size;
+ state->off = fri->offset;
+ fd = FH_TO_FD (fri->fh);
+ state->fd = fd;
+
+ fuse_resolve_fd_init (state, &state->resolve, fd);
+
+ fuse_resolve_and_resume (state, fuse_readdirp_resume);
+}
+
+static int
+fuse_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
+ struct iatt *postbuf, dict_t *xdata)
+{
+ return fuse_err_cbk(frame, cookie, this, op_ret, op_errno, xdata);
+}
+
+static void
+fuse_fallocate_resume(fuse_state_t *state)
+{
+ gf_log("glusterfs-fuse", GF_LOG_TRACE,
+ "%"PRIu64": FALLOCATE (%p, flags=%d, size=%zu, offset=%"PRId64")",
+ state->finh->unique, state->fd, state->flags, state->size,
+ state->off);
+
+ if (state->flags & FALLOC_FL_PUNCH_HOLE)
+ FUSE_FOP(state, fuse_fallocate_cbk, GF_FOP_DISCARD, discard,
+ state->fd, state->off, state->size, state->xdata);
+ else
+ FUSE_FOP(state, fuse_fallocate_cbk, GF_FOP_FALLOCATE, fallocate,
+ state->fd, (state->flags & FALLOC_FL_KEEP_SIZE),
+ state->off, state->size, state->xdata);
+}
+
+static void
+fuse_fallocate(xlator_t *this, fuse_in_header_t *finh, void *msg)
+{
+ struct fuse_fallocate_in *ffi = msg;
+ fuse_state_t *state = NULL;
+
+ GET_STATE(this, finh, state);
+ state->off = ffi->offset;
+ state->size = ffi->length;
+ state->flags = ffi->mode;
+ state->fd = FH_TO_FD(ffi->fh);
+
+ fuse_resolve_fd_init(state, &state->resolve, state->fd);
+ fuse_resolve_and_resume(state, fuse_fallocate_resume);
+}
+
+
static void
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 val = 0;
- int ret = 0;
- fuse_state_t *state = NULL;
- fuse_fd_ctx_t *fdctx = NULL;
- fuse_private_t *priv = NULL;
+ struct fuse_release_in *fri = msg;
+ fd_t *activefd = NULL;
+ uint64_t val = 0;
+ int ret = 0;
+ fuse_state_t *state = NULL;
+ fuse_fd_ctx_t *fdctx = NULL;
+ fuse_private_t *priv = NULL;
GET_STATE (this, finh, state);
state->fd = FH_TO_FD (fri->fh);
priv = this->private;
+ fuse_log_eh (this, "RELEASEDIR (): %"PRIu64": fd: %p, gfid: %s",
+ finh->unique, state->fd,
+ uuid_utoa (state->fd->inode->gfid));
+
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
"%"PRIu64": RELEASEDIR %p", finh->unique, state->fd);
@@ -2534,9 +2799,9 @@ fuse_releasedir (xlator_t *this, fuse_in_header_t *finh, void *msg)
if (!ret) {
fdctx = (fuse_fd_ctx_t *)(unsigned long)val;
if (fdctx) {
- new_fd = fdctx->fd;
- if (new_fd) {
- fd_unref (new_fd);
+ activefd = fdctx->activefd;
+ if (activefd) {
+ fd_unref (activefd);
}
GF_FREE (fdctx);
@@ -2577,7 +2842,7 @@ fuse_fsyncdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
GET_STATE (this, finh, state);
state->fd = fd;
- fuse_resolve_fd_init (state, &state->resolve, fd);
+ fuse_resolve_fd_init (state, &state->resolve, fd);
state->flags = fsi->fsync_flags;
fuse_resolve_and_resume (state, fuse_fsyncdir_resume);
@@ -2585,7 +2850,6 @@ fuse_fsyncdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
return;
}
-
static int
fuse_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct statvfs *buf,
@@ -2600,6 +2864,10 @@ fuse_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
priv = this->private;
finh = state->finh;
+ fuse_log_eh (this, "op_ret: %d, op_errno: %d, %"PRIu64": %s()",
+ op_ret, op_errno, frame->root->unique,
+ gf_fop_list[frame->root->op]);
+
if (op_ret == 0) {
#ifndef GF_DARWIN_HOST_OS
/* MacFUSE doesn't respect anyof these tweaks */
@@ -2639,7 +2907,6 @@ fuse_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
-
void
fuse_statfs_resume (fuse_state_t *state)
{
@@ -2668,9 +2935,9 @@ fuse_statfs (xlator_t *this, fuse_in_header_t *finh, void *msg)
GET_STATE (this, finh, state);
- fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
+ fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
- fuse_resolve_and_resume (state, fuse_statfs_resume);
+ fuse_resolve_and_resume (state, fuse_statfs_resume);
}
@@ -2682,7 +2949,7 @@ fuse_setxattr_resume (fuse_state_t *state)
"%"PRIu64": SETXATTR %s/%"PRIu64" (%s) "
"resolution failed",
state->finh->unique, uuid_utoa (state->resolve.gfid),
- state->finh->nodeid, state->name);
+ state->finh->nodeid, state->name);
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
return;
@@ -2745,21 +3012,21 @@ fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
}
if (!priv->acl) {
- if ((strcmp (name, "system.posix_acl_access") == 0) ||
- (strcmp (name, "system.posix_acl_default") == 0)) {
+ if ((strcmp (name, POSIX_ACL_ACCESS_XATTR) == 0) ||
+ (strcmp (name, POSIX_ACL_DEFAULT_XATTR) == 0)) {
send_fuse_err (this, finh, EOPNOTSUPP);
GF_FREE (finh);
return;
}
}
- if (!priv->selinux) {
- if (strncmp (name, "security.", 9) == 0) {
- send_fuse_err (this, finh, EOPNOTSUPP);
- GF_FREE (finh);
- return;
- }
- }
+ if (!priv->selinux) {
+ if (strncmp (name, "security.", 9) == 0) {
+ send_fuse_err (this, finh, EOPNOTSUPP);
+ GF_FREE (finh);
+ return;
+ }
+ }
/* Check if the command is for changing the log
level of process or specific xlator */
@@ -2788,7 +3055,7 @@ fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
GET_STATE (this, finh, state);
state->size = fsi->size;
- fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
+ fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
state->xattr = get_new_dict ();
if (!state->xattr) {
@@ -2856,10 +3123,10 @@ send_fuse_xattr (xlator_t *this, fuse_in_header_t *finh, const char *value,
* when it tries to setxattr() for selinux xattrs
*/
static int
-fuse_filter_xattr(xlator_t *this, char *key)
+fuse_filter_xattr(char *key)
{
int need_filter = 0;
- struct fuse_private *priv = this->private;
+ struct fuse_private *priv = THIS->private;
if ((priv->client_pid == GF_CLIENT_PID_GSYNCD)
&& fnmatch ("*.selinux*", key, FNM_PERIOD) == 0)
@@ -2880,11 +3147,13 @@ fuse_xattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
data_t *value_data = NULL;
int ret = -1;
int32_t len = 0;
- data_pair_t *trav = NULL;
+ int32_t len_next = 0;
state = frame->root->state;
finh = state->finh;
+ fuse_log_eh_fop(this, state, frame, op_ret, op_errno);
+
if (op_ret >= 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
"%"PRIu64": %s() %s => %d", frame->root->unique,
@@ -2909,25 +3178,21 @@ fuse_xattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
/* we need to invoke fuse_filter_xattr() twice. Once
* while counting size and then while filling buffer
*/
- trav = dict->members_list;
- while (trav) {
- if (!fuse_filter_xattr (this, trav->key))
- len += strlen (trav->key) + 1;
- trav = trav->next;
- } /* while(trav) */
+ len = dict_keys_join (NULL, 0, dict, fuse_filter_xattr);
+ if (len < 0)
+ goto out;
+
value = alloca (len + 1);
if (!value)
goto out;
- len = 0;
- trav = dict->members_list;
- while (trav) {
- if (!fuse_filter_xattr (this, trav->key)) {
- strcpy (value + len, trav->key);
- value[len + strlen (trav->key)] = '\0';
- len += strlen (trav->key) + 1;
- }
- trav = trav->next;
- } /* while(trav) */
+
+ len_next = dict_keys_join (value, len, dict,
+ fuse_filter_xattr);
+ if (len_next != len)
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "sizes not equal %d != %d",
+ len, len_next);
+
send_fuse_xattr (this, finh, value, len, state->size);
} /* if(state->name)...else */
} else {
@@ -2972,13 +3237,15 @@ out:
void
fuse_getxattr_resume (fuse_state_t *state)
{
+ char *value = NULL;
+
if (!state->loc.inode) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64": GETXATTR %s/%"PRIu64" (%s) "
- "resolution failed",
+ "resolution failed",
state->finh->unique,
- uuid_utoa (state->resolve.gfid),
- state->finh->nodeid, state->name);
+ uuid_utoa (state->resolve.gfid),
+ state->finh->nodeid, state->name);
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
@@ -2989,6 +3256,46 @@ fuse_getxattr_resume (fuse_state_t *state)
state->fd = fd_lookup (state->loc.inode, state->finh->pid);
#endif /* GF_TEST_FFOP */
+ if (state->name &&
+ (strcmp (state->name, VIRTUAL_GFID_XATTR_KEY) == 0)) {
+ /* send glusterfs gfid in binary form */
+
+ value = GF_CALLOC (16 + 1, sizeof(char),
+ gf_common_mt_char);
+ if (!value) {
+ send_fuse_err (state->this, state->finh, ENOMEM);
+ goto internal_out;
+ }
+ memcpy (value, state->loc.inode->gfid, 16);
+
+ send_fuse_xattr (THIS, state->finh, value, 16, state->size);
+ GF_FREE (value);
+ internal_out:
+ free_fuse_state (state);
+ return;
+ }
+
+ if (state->name &&
+ (strcmp (state->name, VIRTUAL_GFID_XATTR_KEY_STR) == 0)) {
+ /* transform binary gfid to canonical form */
+
+ value = GF_CALLOC (UUID_CANONICAL_FORM_LEN + 1, sizeof(char),
+ gf_common_mt_char);
+ if (!value) {
+ send_fuse_err (state->this, state->finh, ENOMEM);
+ goto internal_out1;
+ }
+ uuid_utoa_r (state->loc.inode->gfid, value);
+
+ send_fuse_xattr (THIS, state->finh, value,
+ UUID_CANONICAL_FORM_LEN, state->size);
+ GF_FREE (value);
+ internal_out1:
+ free_fuse_state (state);
+ return;
+ }
+
+
if (state->fd) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
"%"PRIu64": GETXATTR %p/%"PRIu64" (%s)", state->finh->unique,
@@ -3010,15 +3317,16 @@ fuse_getxattr_resume (fuse_state_t *state)
static void
fuse_getxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
- struct fuse_getxattr_in *fgxi = msg;
- char *name = (char *)(fgxi + 1);
-
- fuse_state_t *state = NULL;
- struct fuse_private *priv = NULL;
- int rv = 0;
- char *newkey = NULL;
+ struct fuse_getxattr_in *fgxi = msg;
+ char *name = (char *)(fgxi + 1);
+ fuse_state_t *state = NULL;
+ struct fuse_private *priv = NULL;
+ int rv = 0;
+ int op_errno = EINVAL;
+ char *newkey = NULL;
priv = this->private;
+ GET_STATE (this, finh, state);
#ifdef GF_DARWIN_HOST_OS
if (fgxi->position) {
@@ -3034,45 +3342,45 @@ fuse_getxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
"%"PRIu64": GETXATTR %s/%"PRIu64" (%s):"
"refusing positioned getxattr",
finh->unique, state->loc.path, finh->nodeid, name);
- send_fuse_err (this, finh, EINVAL);
- FREE (finh);
- return;
+ op_errno = EINVAL;
+ goto err;
}
#endif
if (!priv->acl) {
- if ((strcmp (name, "system.posix_acl_access") == 0) ||
- (strcmp (name, "system.posix_acl_default") == 0)) {
- send_fuse_err (this, finh, ENOTSUP);
- GF_FREE (finh);
- return;
+ if ((strcmp (name, POSIX_ACL_ACCESS_XATTR) == 0) ||
+ (strcmp (name, POSIX_ACL_DEFAULT_XATTR) == 0)) {
+ op_errno = ENOTSUP;
+ goto err;
}
}
- if (!priv->selinux) {
- if (strncmp (name, "security.", 9) == 0) {
- send_fuse_err (this, finh, ENODATA);
- GF_FREE (finh);
- return;
- }
- }
+ if (!priv->selinux) {
+ if (strncmp (name, "security.", 9) == 0) {
+ op_errno = ENODATA;
+ goto err;
+ }
+ }
GET_STATE (this, finh, state);
- fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
+ fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
rv = fuse_flip_xattr_ns (priv, name, &newkey);
if (rv) {
- send_fuse_err (this, finh, ENOMEM);
- free_fuse_state (state);
- goto out;
+ op_errno = ENOMEM;
+ goto err;
}
state->size = fgxi->size;
state->name = newkey;
fuse_resolve_and_resume (state, fuse_getxattr_resume);
- out:
+
+ return;
+ err:
+ send_fuse_err (this, finh, op_errno);
+ free_fuse_state (state);
return;
}
@@ -3084,7 +3392,7 @@ fuse_listxattr_resume (fuse_state_t *state)
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64": LISTXATTR %s/%"PRIu64
"resolution failed", state->finh->unique,
- uuid_utoa (state->resolve.gfid), state->finh->nodeid);
+ uuid_utoa (state->resolve.gfid), state->finh->nodeid);
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
@@ -3121,7 +3429,7 @@ fuse_listxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
GET_STATE (this, finh, state);
- fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
+ fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
state->size = fgxi->size;
@@ -3137,9 +3445,9 @@ fuse_removexattr_resume (fuse_state_t *state)
if (!state->loc.inode) {
gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
"%"PRIu64": REMOVEXATTR %s/%"PRIu64" (%s) "
- "resolution failed",
+ "resolution failed",
state->finh->unique, uuid_utoa (state->resolve.gfid),
- state->finh->nodeid, state->name);
+ state->finh->nodeid, state->name);
send_fuse_err (state->this, state->finh, ENOENT);
free_fuse_state (state);
@@ -3188,7 +3496,7 @@ fuse_removexattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
GET_STATE (this, finh, state);
- fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
+ fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
ret = fuse_flip_xattr_ns (priv, name, &newkey);
if (ret) {
@@ -3216,6 +3524,8 @@ fuse_getlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state = frame->root->state;
struct fuse_lk_out flo = {{0, }, };
+ fuse_log_eh_fop(this, state, frame, op_ret, op_errno);
+
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
"%"PRIu64": ERR => 0", frame->root->unique);
@@ -3277,7 +3587,7 @@ fuse_getlk (xlator_t *this, fuse_in_header_t *finh, void *msg)
GET_STATE (this, finh, state);
state->fd = fd;
- fuse_resolve_fd_init (state, &state->resolve, fd);
+ fuse_resolve_fd_init (state, &state->resolve, fd);
convert_fuse_file_lock (&fli->lk, &state->lk_lock,
fli->owner);
@@ -3301,6 +3611,8 @@ fuse_setlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state = frame->root->state;
op = state->finh->opcode;
+ fuse_log_eh_fop(this, state, frame, op_ret, op_errno);
+
if (op_ret == 0) {
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
"%"PRIu64": ERR => 0", frame->root->unique);
@@ -3368,7 +3680,7 @@ fuse_setlk (xlator_t *this, fuse_in_header_t *finh, void *msg)
state->finh = finh;
state->fd = fd;
- fuse_resolve_fd_init (state, &state->resolve, fd);
+ fuse_resolve_fd_init (state, &state->resolve, fd);
convert_fuse_file_lock (&fli->lk, &state->lk_lock,
fli->owner);
@@ -3455,6 +3767,10 @@ fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg)
fino.max_readahead = 1 << 17;
fino.max_write = 1 << 17;
fino.flags = FUSE_ASYNC_READ | FUSE_POSIX_LOCKS;
+#if FUSE_KERNEL_MINOR_VERSION >= 17
+ if (fini->minor >= 17)
+ fino.flags |= FUSE_FLOCK_LOCKS;
+#endif
#if FUSE_KERNEL_MINOR_VERSION >= 12
if (fini->minor >= 12) {
/* let fuse leave the umask processing to us, so that it does not
@@ -3483,8 +3799,8 @@ fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg)
}
priv->revchan_in = pfd[0];
priv->revchan_out = pfd[1];
- ret = pthread_create (&messenger, NULL, notify_kernel_loop,
- this);
+ ret = gf_thread_create (&messenger, NULL, notify_kernel_loop,
+ this);
if (ret != 0) {
gf_log ("glusterfs-fuse", GF_LOG_ERROR,
"failed to start messenger daemon (%s)",
@@ -3495,19 +3811,19 @@ fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg)
}
priv->reverse_fuse_thread_started = _gf_true;
} else {
- /*
- * FUSE minor < 12 does not implement invalidate notifications.
- * This mechanism is required for fopen-keep-cache to operate
- * correctly. Disable and warn the user.
- */
- if (priv->fopen_keep_cache) {
- gf_log("glusterfs-fuse", GF_LOG_WARNING, "FUSE version "
- "%d.%d does not support inval notifications. "
- "fopen-keep-cache disabled.", fini->major,
- fini->minor);
- priv->fopen_keep_cache = 0;
- }
- }
+ /*
+ * FUSE minor < 12 does not implement invalidate notifications.
+ * This mechanism is required for fopen-keep-cache to operate
+ * correctly. Disable and warn the user.
+ */
+ if (priv->fopen_keep_cache) {
+ gf_log("glusterfs-fuse", GF_LOG_WARNING, "FUSE version "
+ "%d.%d does not support inval notifications. "
+ "fopen-keep-cache disabled.", fini->major,
+ fini->minor);
+ priv->fopen_keep_cache = 0;
+ }
+ }
if (fini->minor >= 13) {
fino.max_background = priv->background_qlen;
@@ -3516,6 +3832,48 @@ fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg)
if (fini->minor < 9)
*priv->msg0_len_p = sizeof(*finh) + FUSE_COMPAT_WRITE_IN_SIZE;
#endif
+ if (priv->use_readdirp) {
+ if (fini->flags & FUSE_DO_READDIRPLUS)
+ fino.flags |= FUSE_DO_READDIRPLUS;
+ }
+
+ if (priv->fopen_keep_cache == 2) {
+ /* If user did not explicitly set --fopen-keep-cache[=off],
+ then check if kernel support FUSE_AUTO_INVAL_DATA and ...
+ */
+ if (fini->flags & FUSE_AUTO_INVAL_DATA) {
+ /* ... enable fopen_keep_cache mode if supported.
+ */
+ gf_log ("glusterfs-fuse", GF_LOG_DEBUG, "Detected "
+ "support for FUSE_AUTO_INVAL_DATA. Enabling "
+ "fopen_keep_cache automatically.");
+ fino.flags |= FUSE_AUTO_INVAL_DATA;
+ priv->fopen_keep_cache = 1;
+ } else {
+ gf_log ("glusterfs-fuse", GF_LOG_DEBUG, "No support "
+ "for FUSE_AUTO_INVAL_DATA. Disabling "
+ "fopen_keep_cache.");
+ /* ... else disable. */
+ priv->fopen_keep_cache = 0;
+ }
+ } else if (priv->fopen_keep_cache == 1) {
+ /* If user explicitly set --fopen-keep-cache[=on],
+ then enable FUSE_AUTO_INVAL_DATA if possible.
+ */
+ if (fini->flags & FUSE_AUTO_INVAL_DATA) {
+ gf_log ("glusterfs-fuse", GF_LOG_DEBUG, "fopen_keep_cache "
+ "is explicitly set. Enabling FUSE_AUTO_INVAL_DATA");
+ fino.flags |= FUSE_AUTO_INVAL_DATA;
+ } else {
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING, "fopen_keep_cache "
+ "is explicitly set. Support for "
+ "FUSE_AUTO_INVAL_DATA is missing");
+ }
+ }
+
+ if (fini->flags & FUSE_ASYNC_DIO)
+ fino.flags |= FUSE_ASYNC_DIO;
+
ret = send_fuse_obj (this, finh, &fino);
if (ret == 0)
gf_log ("glusterfs-fuse", GF_LOG_INFO,
@@ -3695,106 +4053,292 @@ out:
int
-fuse_migrate_fd (xlator_t *this, fd_t *fd, xlator_t *old_subvol,
- xlator_t *new_subvol)
+fuse_migrate_fd_open (xlator_t *this, fd_t *basefd, fd_t *oldfd,
+ xlator_t *old_subvol, xlator_t *new_subvol)
{
- int ret = -1;
- loc_t loc = {0, };
- char create_in_progress = 0;
- inode_t *old_inode = NULL;
- int flags = 0;
+ loc_t loc = {0, };
+ fd_t *newfd = NULL, *old_activefd = NULL;
+ fuse_fd_ctx_t *basefd_ctx = NULL;
+ fuse_fd_ctx_t *newfd_ctx = NULL;
+ int ret = 0, flags = 0;
- /* could've used pthread_cond_wait, but that requires a cond variable to
- * be mainted for each fd and that is a bit too much overhead.
- */
- do {
- LOCK (&fd->inode->lock);
- {
- if (uuid_is_null (fd->inode->gfid)) {
- create_in_progress = 1;
- } else {
- create_in_progress = 0;
- }
- }
- UNLOCK (&fd->inode->lock);
+ ret = inode_path (basefd->inode, NULL, (char **)&loc.path);
+ if (ret < 0) {
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING,
+ "cannot construct path of gfid (%s) failed"
+ "(old-subvolume:%s-%d new-subvolume:%s-%d)",
+ uuid_utoa (basefd->inode->gfid),
+ old_subvol->name, old_subvol->graph->id,
+ new_subvol->name, new_subvol->graph->id);
+ goto out;
+ }
- if (create_in_progress) {
- gf_log ("glusterfs-fuse", GF_LOG_INFO,
- "create call on fd (%p) is in progress, "
- "hence waiting", fd);
- sleep (1);
- }
+ uuid_copy (loc.gfid, basefd->inode->gfid);
- } while (create_in_progress);
+ loc.inode = inode_find (new_subvol->itable, basefd->inode->gfid);
- if (fd->inode->table->xl == old_subvol) {
- ret = syncop_fsync (old_subvol, fd, 0);
+ if (loc.inode == NULL) {
+ ret = fuse_nameless_lookup (new_subvol, basefd->inode->gfid,
+ &loc);
if (ret < 0) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "syncop_fsync failed (%s)", strerror (errno));
+ "name-less lookup of gfid (%s) failed (%s)"
+ "(old-subvolume:%s-%d new-subvolume:%s-%d)",
+ uuid_utoa (basefd->inode->gfid),
+ strerror (errno),
+ old_subvol->name, old_subvol->graph->id,
+ new_subvol->name, new_subvol->graph->id);
+ goto out;
}
+
+ }
+
+ basefd_ctx = fuse_fd_ctx_get (this, basefd);
+ GF_VALIDATE_OR_GOTO ("glusterfs-fuse", basefd_ctx, out);
+
+ newfd = fd_create (loc.inode, basefd->pid);
+ if (newfd == NULL) {
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING,
+ "cannot create new fd, hence not migrating basefd "
+ "(ptr:%p inode-gfid:%s) "
+ "(old-subvolume:%s-%d new-subvolume:%s-%d)", basefd,
+ uuid_utoa (loc.inode->gfid),
+ old_subvol->name, old_subvol->graph->id,
+ new_subvol->name, new_subvol->graph->id);
+ goto out;
+ }
+
+ newfd->flags = basefd->flags;
+ if (newfd->lk_ctx)
+ fd_lk_ctx_unref (newfd->lk_ctx);
+
+ newfd->lk_ctx = fd_lk_ctx_ref (oldfd->lk_ctx);
+
+ newfd_ctx = fuse_fd_ctx_check_n_create (this, newfd);
+ GF_VALIDATE_OR_GOTO ("glusterfs-fuse", newfd_ctx, out);
+
+ if (IA_ISDIR (basefd->inode->ia_type)) {
+ ret = syncop_opendir (new_subvol, &loc, newfd);
} else {
- gf_log ("glusterfs-fuse", GF_LOG_DEBUG, "fd (%p) was not "
- "migrated during previous graph switch", fd);
+ flags = basefd->flags & ~(O_CREAT | O_EXCL | O_TRUNC);
+ ret = syncop_open (new_subvol, &loc, flags, newfd);
}
- loc.path = "";
- loc.name = NULL;
+ if (ret < 0) {
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING,
+ "open on basefd (ptr:%p inode-gfid:%s) failed (%s)"
+ "(old-subvolume:%s-%d new-subvolume:%s-%d)", basefd,
+ uuid_utoa (basefd->inode->gfid), strerror (errno),
+ old_subvol->name, old_subvol->graph->id,
+ new_subvol->name, new_subvol->graph->id);
+ goto out;
+ }
- loc.inode = inode_find (new_subvol->itable, fd->inode->gfid);
+ fd_bind (newfd);
- if (loc.inode == NULL) {
- ret = fuse_nameless_lookup (new_subvol, fd->inode->gfid, &loc);
- if (ret < 0) {
- gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "name-less lookup of gfid (%s) failed (%s)",
- uuid_utoa (fd->inode->gfid), strerror (errno));
- goto out;
+ LOCK (&basefd->lock);
+ {
+ if (basefd_ctx->activefd != NULL) {
+ old_activefd = basefd_ctx->activefd;
}
+ basefd_ctx->activefd = newfd;
}
+ UNLOCK (&basefd->lock);
+
+ if (old_activefd != NULL) {
+ fd_unref (old_activefd);
+ }
+
+ gf_log ("glusterfs-fuse", GF_LOG_INFO,
+ "migrated basefd (%p) to newfd (%p) (inode-gfid:%s)"
+ "(old-subvolume:%s-%d new-subvolume:%s-%d)", basefd, newfd,
+ uuid_utoa (basefd->inode->gfid),
+ old_subvol->name, old_subvol->graph->id,
+ new_subvol->name, new_subvol->graph->id);
+
+ ret = 0;
+
+out:
+ loc_wipe (&loc);
+
+ return ret;
+}
+
+int
+fuse_migrate_locks (xlator_t *this, fd_t *basefd, fd_t *oldfd,
+ xlator_t *old_subvol, xlator_t *new_subvol)
+{
+ int ret = -1;
+ dict_t *lockinfo = NULL;
+ void *ptr = NULL;
+ fd_t *newfd = NULL;
+ fuse_fd_ctx_t *basefd_ctx = NULL;
+
- old_inode = fd->inode;
+ if (!oldfd->lk_ctx || fd_lk_ctx_empty (oldfd->lk_ctx))
+ return 0;
- inode_ref (loc.inode);
+ basefd_ctx = fuse_fd_ctx_get (this, basefd);
+ GF_VALIDATE_OR_GOTO ("glusterfs-fuse", basefd_ctx, out);
- LOCK (&fd->inode->lock);
+ LOCK (&basefd->lock);
{
- list_del_init (&fd->inode_list);
+ newfd = fd_ref (basefd_ctx->activefd);
}
- UNLOCK (&fd->inode->lock);
+ UNLOCK (&basefd->lock);
- LOCK (&fd->lock);
+ ret = syncop_fgetxattr (old_subvol, oldfd, &lockinfo,
+ GF_XATTR_LOCKINFO_KEY);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "getting lockinfo failed while migrating locks"
+ "(oldfd:%p newfd:%p inode-gfid:%s)"
+ "(old-subvol:%s-%d new-subvol:%s-%d)",
+ oldfd, newfd, uuid_utoa (newfd->inode->gfid),
+ old_subvol->name, old_subvol->graph->id,
+ new_subvol->name, new_subvol->graph->id);
+ goto out;
+ }
+
+ ret = dict_get_ptr (lockinfo, GF_XATTR_LOCKINFO_KEY, &ptr);
+ if (ptr == NULL) {
+ ret = 0;
+ gf_log (this->name, GF_LOG_INFO,
+ "No lockinfo present on any of the bricks "
+ "(oldfd: %p newfd:%p inode-gfid:%s) "
+ "(old-subvol:%s-%d new-subvol:%s-%d)",
+ oldfd, newfd, uuid_utoa (newfd->inode->gfid),
+ old_subvol->name, old_subvol->graph->id,
+ new_subvol->name, new_subvol->graph->id);
+
+ goto out;
+ }
+
+ ret = syncop_fsetxattr (new_subvol, newfd, lockinfo, 0);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "migrating locks failed (oldfd:%p newfd:%p "
+ "inode-gfid:%s) (old-subvol:%s-%d new-subvol:%s-%d)",
+ oldfd, newfd, uuid_utoa (newfd->inode->gfid),
+ old_subvol->name, old_subvol->graph->id,
+ new_subvol->name, new_subvol->graph->id);
+ goto out;
+ }
+
+out:
+ if (newfd)
+ fd_unref (newfd);
+
+ if (lockinfo != NULL) {
+ dict_unref (lockinfo);
+ }
+
+ return ret;
+}
+
+
+int
+fuse_migrate_fd (xlator_t *this, fd_t *basefd, xlator_t *old_subvol,
+ xlator_t *new_subvol)
+{
+ int ret = -1;
+ char create_in_progress = 0;
+ fuse_fd_ctx_t *basefd_ctx = NULL;
+ fd_t *oldfd = NULL;
+
+ basefd_ctx = fuse_fd_ctx_get (this, basefd);
+ GF_VALIDATE_OR_GOTO ("glusterfs-fuse", basefd_ctx, out);
+
+ LOCK (&basefd->lock);
{
- fd->inode = loc.inode;
+ oldfd = basefd_ctx->activefd ? basefd_ctx->activefd
+ : basefd;
+ fd_ref (oldfd);
+ }
+ UNLOCK (&basefd->lock);
+
+ LOCK (&oldfd->inode->lock);
+ {
+ if (uuid_is_null (oldfd->inode->gfid)) {
+ create_in_progress = 1;
+ } else {
+ create_in_progress = 0;
+ }
+ }
+ UNLOCK (&oldfd->inode->lock);
+
+ if (create_in_progress) {
+ gf_log ("glusterfs-fuse", GF_LOG_INFO,
+ "create call on fd (%p) is in progress "
+ "(basefd-ptr:%p basefd-inode.gfid:%s), "
+ "hence deferring migration till application does an "
+ "fd based operation on this fd"
+ "(old-subvolume:%s-%d, new-subvolume:%s-%d)",
+ oldfd, basefd, uuid_utoa (basefd->inode->gfid),
+ old_subvol->name, old_subvol->graph->id,
+ new_subvol->name, new_subvol->graph->id);
+
+ ret = 0;
+ goto out;
}
- UNLOCK (&fd->lock);
- if (IA_ISDIR (fd->inode->ia_type)) {
- ret = syncop_opendir (new_subvol, &loc, fd);
+ if (oldfd->inode->table->xl == old_subvol) {
+ ret = syncop_fsync (old_subvol, oldfd, 0);
+ if (ret < 0) {
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING,
+ "syncop_fsync failed (%s) on fd (%p)"
+ "(basefd:%p basefd-inode.gfid:%s) "
+ "(old-subvolume:%s-%d new-subvolume:%s-%d)",
+ strerror (errno), oldfd, basefd,
+ uuid_utoa (basefd->inode->gfid),
+ old_subvol->name, old_subvol->graph->id,
+ new_subvol->name, new_subvol->graph->id);
+ }
} else {
- flags = fd->flags & ~(O_CREAT | O_EXCL);
- ret = syncop_open (new_subvol, &loc, flags, fd);
+ gf_log ("glusterfs-fuse", GF_LOG_WARNING,
+ "basefd (ptr:%p inode-gfid:%s) was not "
+ "migrated during previous graph switch"
+ "(old-subvolume:%s-%d new-subvolume: %s-%d)", basefd,
+ basefd->inode->gfid,
+ old_subvol->name, old_subvol->graph->id,
+ new_subvol->name, new_subvol->graph->id);
}
+ ret = fuse_migrate_fd_open (this, basefd, oldfd, old_subvol,
+ new_subvol);
if (ret < 0) {
- gf_log ("glusterfs-fuse", GF_LOG_WARNING,
- "open on gfid (%s) failed (%s)",
- uuid_utoa (fd->inode->gfid), strerror (errno));
+ gf_log (this->name, GF_LOG_WARNING, "open corresponding to "
+ "basefd (ptr:%p inode-gfid:%s) in new graph failed "
+ "(old-subvolume:%s-%d new-subvolume:%s-%d)", basefd,
+ uuid_utoa (basefd->inode->gfid), old_subvol->name,
+ old_subvol->graph->id, new_subvol->name,
+ new_subvol->graph->id);
goto out;
}
- fd_bind (fd);
+ ret = fuse_migrate_locks (this, basefd, oldfd, old_subvol,
+ new_subvol);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "migrating locks from old-subvolume (%s-%d) to "
+ "new-subvolume (%s-%d) failed (inode-gfid:%s oldfd:%p "
+ "basefd:%p)", old_subvol->name, old_subvol->graph->id,
+ new_subvol->name, new_subvol->graph->id,
+ uuid_utoa (basefd->inode->gfid), oldfd, basefd);
- ret = 0;
+ }
out:
- if (loc.inode != NULL) {
- inode_unref (loc.inode);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_WARNING, "migration of basefd "
+ "(ptr:%p inode-gfid:%s) failed"
+ "(old-subvolume:%s-%d new-subvolume:%s-%d)", basefd,
+ oldfd ? uuid_utoa (oldfd->inode->gfid) : NULL,
+ old_subvol->name, old_subvol->graph->id,
+ new_subvol->name, new_subvol->graph->id);
}
- if (old_inode != NULL) {
- inode_unref (old_inode);
- }
+ fd_unref (oldfd);
return ret;
}
@@ -3827,13 +4371,17 @@ fuse_handle_opened_fds (xlator_t *this, xlator_t *old_subvol,
ret = fuse_migrate_fd (this, fd, old_subvol,
new_subvol);
- fdctx = fuse_fd_ctx_check_n_create (this, fd);
+ fdctx = fuse_fd_ctx_get (this, fd);
if (fdctx) {
- if (ret < 0) {
- fdctx->migration_failed = 1;
- } else {
- fdctx->migration_failed = 0;
+ LOCK (&fd->lock);
+ {
+ if (ret < 0) {
+ fdctx->migration_failed = 1;
+ } else {
+ fdctx->migration_failed = 0;
+ }
}
+ UNLOCK (&fd->lock);
}
}
@@ -3978,11 +4526,11 @@ fuse_graph_sync (xlator_t *this)
ret = pthread_cond_wait (&priv->sync_cond,
&priv->sync_mutex);
if (ret != 0) {
- gf_log (this->name, GF_LOG_DEBUG,
- "timedwait returned non zero value "
- "ret: %d errno: %d", ret, errno);
- break;
- }
+ gf_log (this->name, GF_LOG_DEBUG,
+ "timedwait returned non zero value "
+ "ret: %d errno: %d", ret, errno);
+ break;
+ }
}
}
unlock:
@@ -4133,13 +4681,20 @@ fuse_thread_proc (void *data)
"terminating upon getting %s when "
"reading /dev/fuse",
errno == ENODEV ? "ENODEV" : "EBADF");
-
+ fuse_log_eh (this, "glusterfs-fuse: terminating"
+ " upon getting %s when "
+ "reading /dev/fuse",
+ errno == ENODEV ? "ENODEV":
+ "EBADF");
break;
}
if (errno != EINTR) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"read from /dev/fuse returned -1 (%s)",
strerror (errno));
+ fuse_log_eh (this, "glusterfs-fuse: read from "
+ "/dev/fuse returned -1 (%s)",
+ strerror (errno));
}
goto cont_err;
@@ -4147,6 +4702,8 @@ fuse_thread_proc (void *data)
if (res < sizeof (finh)) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"short read on /dev/fuse");
+ fuse_log_eh (this, "glusterfs-fuse: short read on "
+ "/dev/fuse");
break;
}
@@ -4165,6 +4722,8 @@ fuse_thread_proc (void *data)
) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"inconsistent read on /dev/fuse");
+ fuse_log_eh (this, "glusterfs-fuse: inconsistent read "
+ "on /dev/fuse");
break;
}
@@ -4200,13 +4759,11 @@ fuse_thread_proc (void *data)
finh->uid == priv->uid_map_root)
finh->uid = 0;
-#ifdef GF_DARWIN_HOST_OS
if (finh->opcode >= FUSE_OP_HIGH)
/* turn down MacFUSE specific messages */
fuse_enosys (this, finh, msg);
else
-#endif
- fuse_ops[finh->opcode] (this, finh, msg);
+ fuse_ops[finh->opcode] (this, finh, msg);
iobuf_unref (iobuf);
continue;
@@ -4245,7 +4802,7 @@ fuse_itable_dump (xlator_t *this)
gf_proc_dump_add_section("xlator.mount.fuse.itable");
inode_table_dump(this->itable, "xlator.mount.fuse.itable");
- return 0;
+ return 0;
}
int32_t
@@ -4288,10 +4845,51 @@ fuse_priv_dump (xlator_t *this)
(int)private->strict_volfile_check);
gf_proc_dump_write("reverse_thread_started", "%d",
(int)private->reverse_fuse_thread_started);
+ gf_proc_dump_write("use_readdirp", "%d", private->use_readdirp);
return 0;
}
+int
+fuse_history_dump (xlator_t *this)
+{
+ int ret = -1;
+ char key_prefix[GF_DUMP_MAX_BUF_LEN] = {0,};
+
+ GF_VALIDATE_OR_GOTO ("fuse", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, this->history, out);
+
+ gf_proc_dump_build_key (key_prefix, "xlator.mount.fuse",
+ "history");
+ gf_proc_dump_add_section (key_prefix);
+ eh_dump (this->history, NULL, dump_history_fuse);
+
+ ret = 0;
+out:
+ return ret;
+}
+
+int
+dump_history_fuse (circular_buffer_t *cb, void *data)
+{
+ char *string = NULL;
+ struct tm *tm = NULL;
+ char timestr[256] = {0,};
+
+ string = (char *)cb->data;
+ tm = localtime (&cb->tv.tv_sec);
+
+ if (tm) {
+ strftime (timestr, 256, "%Y-%m-%d %H:%M:%S", tm);
+ snprintf (timestr + strlen (timestr), 256 - strlen (timestr),
+ ".%"GF_PRI_SUSECONDS, cb->tv.tv_usec);
+ gf_proc_dump_write ("TIME", "%s", timestr);
+ }
+
+ gf_proc_dump_write ("message", "%s\n", string);
+
+ return 0;
+}
int
fuse_graph_setup (xlator_t *this, glusterfs_graph_t *graph)
@@ -4376,8 +4974,8 @@ notify (xlator_t *this, int32_t event, void *data, ...)
if (!private->fuse_thread_started) {
private->fuse_thread_started = 1;
- ret = pthread_create (&private->fuse_thread, NULL,
- fuse_thread_proc, this);
+ ret = gf_thread_create (&private->fuse_thread, NULL,
+ fuse_thread_proc, this);
if (ret != 0) {
gf_log (this->name, GF_LOG_DEBUG,
"pthread_create() failed (%s)",
@@ -4425,45 +5023,52 @@ mem_acct_init (xlator_t *this)
static fuse_handler_t *fuse_std_ops[FUSE_OP_HIGH] = {
- [FUSE_INIT] = fuse_init,
- [FUSE_DESTROY] = fuse_destroy,
[FUSE_LOOKUP] = fuse_lookup,
[FUSE_FORGET] = fuse_forget,
[FUSE_GETATTR] = fuse_getattr,
[FUSE_SETATTR] = fuse_setattr,
- [FUSE_OPENDIR] = fuse_opendir,
- [FUSE_READDIR] = fuse_readdir,
- [FUSE_RELEASEDIR] = fuse_releasedir,
- [FUSE_ACCESS] = fuse_access,
[FUSE_READLINK] = fuse_readlink,
+ [FUSE_SYMLINK] = fuse_symlink,
[FUSE_MKNOD] = fuse_mknod,
[FUSE_MKDIR] = fuse_mkdir,
[FUSE_UNLINK] = fuse_unlink,
[FUSE_RMDIR] = fuse_rmdir,
- [FUSE_SYMLINK] = fuse_symlink,
[FUSE_RENAME] = fuse_rename,
[FUSE_LINK] = fuse_link,
- [FUSE_CREATE] = fuse_create,
[FUSE_OPEN] = fuse_open,
[FUSE_READ] = fuse_readv,
[FUSE_WRITE] = fuse_write,
- [FUSE_FLUSH] = fuse_flush,
+ [FUSE_STATFS] = fuse_statfs,
[FUSE_RELEASE] = fuse_release,
[FUSE_FSYNC] = fuse_fsync,
- [FUSE_FSYNCDIR] = fuse_fsyncdir,
- [FUSE_STATFS] = fuse_statfs,
[FUSE_SETXATTR] = fuse_setxattr,
[FUSE_GETXATTR] = fuse_getxattr,
[FUSE_LISTXATTR] = fuse_listxattr,
[FUSE_REMOVEXATTR] = fuse_removexattr,
+ [FUSE_FLUSH] = fuse_flush,
+ [FUSE_INIT] = fuse_init,
+ [FUSE_OPENDIR] = fuse_opendir,
+ [FUSE_READDIR] = fuse_readdir,
+ [FUSE_RELEASEDIR] = fuse_releasedir,
+ [FUSE_FSYNCDIR] = fuse_fsyncdir,
[FUSE_GETLK] = fuse_getlk,
[FUSE_SETLK] = fuse_setlk,
[FUSE_SETLKW] = fuse_setlk,
+ [FUSE_ACCESS] = fuse_access,
+ [FUSE_CREATE] = fuse_create,
+ /* [FUSE_INTERRUPT] */
+ /* [FUSE_BMAP] */
+ [FUSE_DESTROY] = fuse_destroy,
+ /* [FUSE_IOCTL] */
+ /* [FUSE_POLL] */
+ /* [FUSE_NOTIFY_REPLY] */
+ [FUSE_BATCH_FORGET]= fuse_batch_forget,
+ [FUSE_FALLOCATE] = fuse_fallocate,
+ [FUSE_READDIRPLUS] = fuse_readdirp,
};
-static fuse_handler_t *fuse_dump_ops[FUSE_OP_HIGH] = {
-};
+static fuse_handler_t *fuse_dump_ops[FUSE_OP_HIGH];
static void
@@ -4491,7 +5096,7 @@ fuse_dumper (xlator_t *this, fuse_in_header_t *finh, void *msg)
"failed to dump fuse message (R): %s",
strerror (errno));
- return priv->fuse_ops0[finh->opcode] (this, finh, msg);
+ priv->fuse_ops0[finh->opcode] (this, finh, msg);
}
@@ -4510,7 +5115,10 @@ init (xlator_t *this_xl)
int fsname_allocated = 0;
glusterfs_ctx_t *ctx = NULL;
gf_boolean_t sync_to_mount = _gf_false;
+ gf_boolean_t fopen_keep_cache = _gf_false;
+ unsigned long mntflags = 0;
char *mnt_args = NULL;
+ eh_t *event = NULL;
if (this_xl == NULL)
return -1;
@@ -4589,21 +5197,21 @@ init (xlator_t *this_xl)
goto cleanup_exit;
}
- GF_OPTION_INIT ("attribute-timeout", priv->attribute_timeout, double,
- cleanup_exit);
+ GF_OPTION_INIT ("attribute-timeout", priv->attribute_timeout, double,
+ cleanup_exit);
- GF_OPTION_INIT ("entry-timeout", priv->entry_timeout, double,
- cleanup_exit);
+ GF_OPTION_INIT ("entry-timeout", priv->entry_timeout, double,
+ cleanup_exit);
- GF_OPTION_INIT ("negative-timeout", priv->negative_timeout, double,
- cleanup_exit);
+ GF_OPTION_INIT ("negative-timeout", priv->negative_timeout, double,
+ cleanup_exit);
- GF_OPTION_INIT ("client-pid", priv->client_pid, int32, cleanup_exit);
+ GF_OPTION_INIT ("client-pid", priv->client_pid, int32, cleanup_exit);
/* have to check & register the presence of client-pid manually */
priv->client_pid_set = !!dict_get (this_xl->options, "client-pid");
- GF_OPTION_INIT ("uid-map-root", priv->uid_map_root, uint32,
- cleanup_exit);
+ GF_OPTION_INIT ("uid-map-root", priv->uid_map_root, uint32,
+ cleanup_exit);
priv->direct_io_mode = 2;
ret = dict_get_str (options, ZR_DIRECT_IO_OPT, &value_string);
@@ -4612,17 +5220,21 @@ init (xlator_t *this_xl)
GF_ASSERT (ret == 0);
}
- GF_OPTION_INIT (ZR_STRICT_VOLFILE_CHECK, priv->strict_volfile_check,
- bool, cleanup_exit);
+ GF_OPTION_INIT (ZR_STRICT_VOLFILE_CHECK, priv->strict_volfile_check,
+ bool, cleanup_exit);
- GF_OPTION_INIT ("acl", priv->acl, bool, cleanup_exit);
+ GF_OPTION_INIT ("acl", priv->acl, bool, cleanup_exit);
if (priv->uid_map_root)
priv->acl = 1;
- GF_OPTION_INIT ("selinux", priv->selinux, bool, cleanup_exit);
+ GF_OPTION_INIT ("selinux", priv->selinux, bool, cleanup_exit);
+
+ GF_OPTION_INIT ("read-only", priv->read_only, bool, cleanup_exit);
- GF_OPTION_INIT ("read-only", priv->read_only, bool, cleanup_exit);
+ GF_OPTION_INIT ("enable-ino32", priv->enable_ino32, bool, cleanup_exit);
+
+ GF_OPTION_INIT ("use-readdirp", priv->use_readdirp, bool, cleanup_exit);
priv->fuse_dump_fd = -1;
ret = dict_get_str (options, "dump-fuse", &value_string);
@@ -4649,22 +5261,28 @@ init (xlator_t *this_xl)
GF_ASSERT (ret == 0);
}
- GF_OPTION_INIT("fopen-keep-cache", priv->fopen_keep_cache, bool,
- cleanup_exit);
+ priv->fopen_keep_cache = 2;
+ if (dict_get (options, "fopen-keep-cache")) {
+ GF_OPTION_INIT("fopen-keep-cache", fopen_keep_cache, bool,
+ cleanup_exit);
+ priv->fopen_keep_cache = fopen_keep_cache;
+ }
- GF_OPTION_INIT("gid-timeout", priv->gid_cache_timeout, int32,
- cleanup_exit);
+ GF_OPTION_INIT("gid-timeout", priv->gid_cache_timeout, int32,
+ cleanup_exit);
- if (gid_cache_init(&priv->gid_cache, priv->gid_cache_timeout) < 0) {
- gf_log("glusterfs-fuse", GF_LOG_ERROR, "Failed to initialize "
- "group cache.");
- goto cleanup_exit;
- }
+ GF_OPTION_INIT ("fuse-mountopts", priv->fuse_mountopts, str, cleanup_exit);
+
+ if (gid_cache_init(&priv->gid_cache, priv->gid_cache_timeout) < 0) {
+ gf_log("glusterfs-fuse", GF_LOG_ERROR, "Failed to initialize "
+ "group cache.");
+ goto cleanup_exit;
+ }
/* default values seemed to work fine during testing */
- GF_OPTION_INIT ("background-qlen", priv->background_qlen, int32,
+ GF_OPTION_INIT ("background-qlen", priv->background_qlen, int32,
cleanup_exit);
- GF_OPTION_INIT ("congestion-threshold", priv->congestion_threshold,
+ GF_OPTION_INIT ("congestion-threshold", priv->congestion_threshold,
int32, cleanup_exit);
/* user has set only background-qlen, not congestion-threshold,
@@ -4716,9 +5334,12 @@ init (xlator_t *this_xl)
goto cleanup_exit;
}
- gf_asprintf (&mnt_args, "%s%sallow_other,max_read=131072",
- priv->read_only ? "ro," : "",
- priv->acl ? "" : "default_permissions,");
+ if (priv->read_only)
+ mntflags |= MS_RDONLY;
+ gf_asprintf (&mnt_args, "%s%s%sallow_other,max_read=131072",
+ priv->acl ? "" : "default_permissions,",
+ priv->fuse_mountopts ? priv->fuse_mountopts : "",
+ priv->fuse_mountopts ? "," : "");
if (!mnt_args)
goto cleanup_exit;
@@ -4728,12 +5349,21 @@ init (xlator_t *this_xl)
goto cleanup_exit;
}
- priv->fd = gf_fuse_mount (priv->mount_point, fsname, mnt_args,
+ priv->fd = gf_fuse_mount (priv->mount_point, fsname, mntflags, mnt_args,
sync_to_mount ? &ctx->mnt_pid : NULL,
priv->status_pipe[1]);
if (priv->fd == -1)
goto cleanup_exit;
+ event = eh_new (FUSE_EVENT_HISTORY_SIZE, _gf_false, NULL);
+ if (!event) {
+ gf_log (this_xl->name, GF_LOG_ERROR,
+ "could not create a new event history");
+ goto cleanup_exit;
+ }
+
+ this_xl->history = event;
+
pthread_mutex_init (&priv->fuse_dump_mutex, NULL);
pthread_cond_init (&priv->sync_cond, NULL);
pthread_mutex_init (&priv->sync_mutex, NULL);
@@ -4803,17 +5433,18 @@ fini (xlator_t *this_xl)
kill (getpid (), SIGTERM);
}
-struct xlator_fops fops = {
-};
+struct xlator_fops fops;
struct xlator_cbks cbks = {
- .invalidate = fuse_invalidate,
+ .invalidate = fuse_invalidate,
+ .forget = fuse_forget_cbk,
};
struct xlator_dumpops dumpops = {
.priv = fuse_priv_dump,
.inode = fuse_itable_dump,
+ .history = fuse_history_dump,
};
struct volume_options options[] = {
@@ -4828,19 +5459,19 @@ struct volume_options options[] = {
},
{ .key = {ZR_ATTR_TIMEOUT_OPT},
.type = GF_OPTION_TYPE_DOUBLE,
- .default_value = "1.0"
+ .default_value = "1.0"
},
{ .key = {ZR_ENTRY_TIMEOUT_OPT},
.type = GF_OPTION_TYPE_DOUBLE,
- .default_value = "1.0"
+ .default_value = "1.0"
},
{ .key = {ZR_NEGATIVE_TIMEOUT_OPT},
.type = GF_OPTION_TYPE_DOUBLE,
- .default_value = "0.0"
+ .default_value = "0.0"
},
{ .key = {ZR_STRICT_VOLFILE_CHECK},
.type = GF_OPTION_TYPE_BOOL,
- .default_value = "false"
+ .default_value = "false"
},
{ .key = {"client-pid"},
.type = GF_OPTION_TYPE_INT
@@ -4854,22 +5485,26 @@ struct volume_options options[] = {
{ .key = {"read-only"},
.type = GF_OPTION_TYPE_BOOL
},
- { .key = {"fopen-keep-cache"},
- .type = GF_OPTION_TYPE_BOOL,
- .default_value = "false"
- },
- { .key = {"gid-timeout"},
- .type = GF_OPTION_TYPE_INT,
- .default_value = "0"
- },
- { .key = {"acl"},
- .type = GF_OPTION_TYPE_BOOL,
- .default_value = "false"
- },
- { .key = {"selinux"},
- .type = GF_OPTION_TYPE_BOOL,
- .default_value = "false"
- },
+ { .key = {"fopen-keep-cache"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "false"
+ },
+ { .key = {"gid-timeout"},
+ .type = GF_OPTION_TYPE_INT,
+ .default_value = "2"
+ },
+ { .key = {"acl"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "false"
+ },
+ { .key = {"selinux"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "false"
+ },
+ { .key = {"enable-ino32"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "false"
+ },
{ .key = {"background-qlen"},
.type = GF_OPTION_TYPE_INT,
.default_value = "64",
@@ -4882,5 +5517,12 @@ struct volume_options options[] = {
.min = 12,
.max = (64 * GF_UNIT_KB),
},
+ { .key = {"fuse-mountopts"},
+ .type = GF_OPTION_TYPE_STR
+ },
+ { .key = {"use-readdirp"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "yes"
+ },
{ .key = {NULL} },
};
diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h
index 63ec5d2ef..34794b6ea 100644
--- a/xlators/mount/fuse/src/fuse-bridge.h
+++ b/xlators/mount/fuse/src/fuse-bridge.h
@@ -1,13 +1,12 @@
/*
- Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
- This file is part of GlusterFS.
+ Copyright (c) 2006-2012 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
- This file is licensed to you under your choice of the GNU Lesser
- General Public License, version 3 or any later version (LGPLv3 or
- later), or the GNU General Public License, version 2 (GPLv2), in all
- cases as published by the Free Software Foundation.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
-
#ifndef _GF_FUSE_BRIDGE_H_
#define _GF_FUSE_BRIDGE_H_
@@ -49,7 +48,7 @@
#include "gidcache.h"
#if defined(GF_LINUX_HOST_OS) || defined(__NetBSD__)
-#define FUSE_OP_HIGH (FUSE_POLL + 1)
+#define FUSE_OP_HIGH (FUSE_READDIRPLUS + 1)
#endif
#ifdef GF_DARWIN_HOST_OS
#define FUSE_OP_HIGH (FUSE_DESTROY + 1)
@@ -102,10 +101,12 @@ struct fuse_private {
gf_boolean_t acl;
gf_boolean_t selinux;
gf_boolean_t read_only;
- gf_boolean_t fopen_keep_cache;
+ int32_t fopen_keep_cache;
int32_t gid_cache_timeout;
+ gf_boolean_t enable_ino32;
fdtable_t *fdtable;
gid_cache_t gid_cache;
+ char *fuse_mountopts;
/* For fuse-reverse-validation */
int revchan_in;
@@ -118,6 +119,9 @@ struct fuse_private {
/* for fuse queue length and congestion threshold */
int background_qlen;
int congestion_threshold;
+
+ /* for using fuse-kernel readdirp*/
+ gf_boolean_t use_readdirp;
};
typedef struct fuse_private fuse_private_t;
@@ -133,6 +137,7 @@ typedef struct fuse_graph_switch_args fuse_graph_switch_args_t;
sizeof (struct fuse_notify_inval_entry_out) + \
NAME_MAX + 1))
+#define FUSE_EVENT_HISTORY_SIZE 1024
#define _FH_TO_FD(fh) ((fd_t *)(uintptr_t)(fh))
@@ -140,9 +145,10 @@ typedef struct fuse_graph_switch_args fuse_graph_switch_args_t;
#define FUSE_FOP(state, ret, op_num, fop, args ...) \
do { \
- call_frame_t *frame = NULL; \
- xlator_t *xl = NULL; \
- int32_t op_ret = 0, op_errno = 0; \
+ call_frame_t *frame = NULL; \
+ xlator_t *xl = NULL; \
+ int32_t op_ret = 0, op_errno = 0; \
+ fuse_resolve_t *resolve = NULL; \
\
frame = get_call_frame_for_req (state); \
if (!frame) { \
@@ -169,14 +175,20 @@ typedef struct fuse_graph_switch_args fuse_graph_switch_args_t;
frame->root->op = op_num; \
frame->op = op_num; \
\
+ if ( state->resolve_now ) { \
+ resolve = state->resolve_now; \
+ } else { \
+ resolve = &(state->resolve); \
+ } \
+ \
xl = state->active_subvol; \
if (!xl) { \
gf_log_callingfn ("glusterfs-fuse", GF_LOG_ERROR, \
"xl is NULL"); \
op_errno = ENOENT; \
op_ret = -1; \
- } else if (state->resolve.op_ret < 0) { \
- op_errno = state->resolve.op_errno; \
+ } else if (resolve->op_ret < 0) { \
+ op_errno = resolve->op_errno; \
op_ret = -1; \
if (op_num == GF_FOP_LOOKUP) { \
gf_log ("glusterfs-fuse", \
@@ -185,7 +197,7 @@ typedef struct fuse_graph_switch_args fuse_graph_switch_args_t;
"%"PRIu64": %s() %s => -1 (%s)", \
frame->root->unique, \
gf_fop_list[frame->root->op], \
- state->resolve.resolve_loc.path, \
+ resolve->resolve_loc.path, \
strerror (op_errno)); \
} else { \
gf_log ("glusterfs-fuse", \
@@ -194,7 +206,7 @@ typedef struct fuse_graph_switch_args fuse_graph_switch_args_t;
"migration of %s failed (%s)", \
frame->root->unique, \
gf_fop_list[frame->root->op], \
- state->resolve.resolve_loc.path, \
+ resolve->resolve_loc.path, \
strerror (op_errno)); \
} \
} else if (state->resolve2.op_ret < 0) { \
@@ -215,6 +227,14 @@ typedef struct fuse_graph_switch_args fuse_graph_switch_args_t;
free_fuse_state (state); \
STACK_DESTROY (frame->root); \
} else { \
+ if (state->this->history) \
+ gf_log_eh ("%"PRIu64", %s, path: (%s), gfid: " \
+ "(%s)", frame->root->unique, \
+ gf_fop_list[frame->root->op], \
+ state->loc.path, \
+ (state->fd == NULL)? \
+ uuid_utoa (state->loc.gfid): \
+ uuid_utoa (state->fd->inode->gfid));\
STACK_WIND (frame, ret, xl, xl->fops->fop, args); \
} \
\
@@ -290,6 +310,12 @@ typedef struct fuse_graph_switch_args fuse_graph_switch_args_t;
free_fuse_state (state); \
STACK_DESTROY (frame->root); \
} else { \
+ if (xl->history) \
+ gf_log_eh ("%"PRIu64", %s, path: (%s), gfid: " \
+ "(%s)", frame->root->unique, \
+ gf_fop_list[frame->root->op], \
+ state->loc.path, \
+ uuid_utoa (state->loc.gfid)); \
STACK_WIND_COOKIE (frame, ret, cky, xl, xl->fops->fop, \
args); \
} \
@@ -316,7 +342,80 @@ typedef struct fuse_graph_switch_args fuse_graph_switch_args_t;
} \
} while (0)
+#define FUSE_ENTRY_CREATE(this, priv, finh, state, fci, op) \
+ do { \
+ if (priv->proto_minor >= 12) \
+ state->mode &= ~fci->umask; \
+ if (priv->proto_minor >= 12 && priv->acl) { \
+ state->xdata = dict_new (); \
+ if (!state->xdata) { \
+ gf_log ("glusterfs-fuse", \
+ GF_LOG_WARNING, \
+ "%s failed to allocate " \
+ "a param dictionary", op); \
+ send_fuse_err (this, finh, ENOMEM); \
+ free_fuse_state (state); \
+ return; \
+ } \
+ state->umask = fci->umask; \
+ \
+/* TODO: remove this after 3.4.0 release. keeping it for the \
+ sake of backward compatibility with old (3.3.[01]) \
+ releases till then. */ \
+ ret = dict_set_int16 (state->xdata, "umask", \
+ fci->umask); \
+ if (ret < 0) { \
+ gf_log ("glusterfs-fuse", \
+ GF_LOG_WARNING, \
+ "%s Failed adding umask"\
+ " to request", op); \
+ dict_destroy (state->xdata); \
+ send_fuse_err (this, finh, ENOMEM); \
+ free_fuse_state (state); \
+ return; \
+ } \
+ ret = dict_set_int16 (state->xdata, "mode", \
+ fci->mode); \
+ if (ret < 0) { \
+ gf_log ("glusterfs-fuse", \
+ GF_LOG_WARNING, \
+ "%s Failed adding mode " \
+ "to request", op); \
+ dict_destroy (state->xdata); \
+ send_fuse_err (this, finh, ENOMEM); \
+ free_fuse_state (state); \
+ return; \
+ } \
+ } \
+ } while (0)
+#define fuse_log_eh_fop(this, state, frame, op_ret, op_errno) \
+ do { \
+ if (this->history) { \
+ if (state->fd) \
+ gf_log_eh ("op_ret: %d, op_errno: %d, " \
+ "%"PRIu64", %s () => %p, gfid: %s", \
+ op_ret, op_errno, \
+ frame->root->unique, \
+ gf_fop_list[frame->root->op], \
+ state->fd, \
+ uuid_utoa (state->fd->inode->gfid)); \
+ else \
+ gf_log_eh ("op_ret: %d, op_errno: %d, " \
+ "%"PRIu64", %s () => %s, gfid: %s", \
+ op_ret, op_errno, \
+ frame->root->unique, \
+ gf_fop_list[frame->root->op], \
+ state->loc.path, \
+ uuid_utoa (state->loc.gfid)); \
+ } \
+ } while(0)
+
+#define fuse_log_eh(this, args...) \
+ do { \
+ if (this->history) \
+ gf_log_eh(args); \
+ } while (0)
static inline xlator_t *
fuse_active_subvol (xlator_t *fuse)
@@ -399,10 +498,10 @@ typedef struct {
int32_t fd_no;
} fuse_state_t;
-typedef struct fuse_fd_ctx {
+typedef struct {
uint32_t open_flags;
char migration_failed;
- fd_t *fd;
+ fd_t *activefd;
} fuse_fd_ctx_t;
typedef void (*fuse_resume_fn_t) (fuse_state_t *state);
@@ -413,7 +512,10 @@ fuse_loc_fill (loc_t *loc, fuse_state_t *state, ino_t ino,
call_frame_t *get_call_frame_for_req (fuse_state_t *state);
fuse_state_t *get_fuse_state (xlator_t *this, fuse_in_header_t *finh);
void free_fuse_state (fuse_state_t *state);
-void gf_fuse_stat2attr (struct iatt *st, struct fuse_attr *fa);
+void gf_fuse_stat2attr (struct iatt *st, struct fuse_attr *fa,
+ gf_boolean_t enable_ino32);
+void gf_fuse_fill_dirent (gf_dirent_t *entry, struct fuse_dirent *fde,
+ gf_boolean_t enable_ino32);
uint64_t inode_to_fuse_nodeid (inode_t *inode);
xlator_t *fuse_active_subvol (xlator_t *fuse);
inode_t *fuse_ino_to_inode (uint64_t ino, xlator_t *fuse);
@@ -431,4 +533,5 @@ int fuse_resolve_entry_init (fuse_state_t *state, fuse_resolve_t *resolve,
int fuse_resolve_fd_init (fuse_state_t *state, fuse_resolve_t *resolve,
fd_t *fd);
int fuse_ignore_xattr_set (fuse_private_t *priv, char *key);
+int dump_history_fuse (circular_buffer_t *cb, void *data);
#endif /* _GF_FUSE_BRIDGE_H_ */
diff --git a/xlators/mount/fuse/src/fuse-helpers.c b/xlators/mount/fuse/src/fuse-helpers.c
index d97cb1615..4d478b919 100644
--- a/xlators/mount/fuse/src/fuse-helpers.c
+++ b/xlators/mount/fuse/src/fuse-helpers.c
@@ -1,12 +1,15 @@
/*
- Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
- This file is part of GlusterFS.
+ Copyright (c) 2010-2012 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
- This file is licensed to you under your choice of the GNU Lesser
- General Public License, version 3 or any later version (LGPLv3 or
- later), or the GNU General Public License, version 2 (GPLv2), in all
- cases as published by the Free Software Foundation.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
+#ifdef __NetBSD__
+#define _KMEMUSER
+#endif
#include "fuse-bridge.h"
#if defined(GF_SOLARIS_HOST_OS)
@@ -15,9 +18,6 @@
#include <sys/sysctl.h>
#endif
-#ifndef GF_REQUEST_MAXGROUPS
-#define GF_REQUEST_MAXGROUPS 16
-#endif /* GF_REQUEST_MAXGROUPS */
static void
fuse_resolve_wipe (fuse_resolve_t *resolve)
@@ -139,6 +139,7 @@ get_fuse_state (xlator_t *this, fuse_in_header_t *finh)
}
+#define FUSE_MAX_AUX_GROUPS 32 /* We can get only up to 32 aux groups from /proc */
void
frame_fill_groups (call_frame_t *frame)
{
@@ -161,6 +162,9 @@ frame_fill_groups (call_frame_t *frame)
if (!fp)
goto out;
+ if (call_stack_alloc_groups (frame->root, FUSE_MAX_AUX_GROUPS) != 0)
+ goto out;
+
while ((ptr = fgets (line, sizeof line, fp))) {
if (strncmp (ptr, "Groups:", 7) != 0)
continue;
@@ -177,7 +181,7 @@ frame_fill_groups (call_frame_t *frame)
if (!endptr || *endptr)
break;
frame->root->groups[idx++] = id;
- if (idx == GF_MAX_AUX_GROUPS)
+ if (idx == FUSE_MAX_AUX_GROUPS)
break;
}
@@ -193,6 +197,7 @@ out:
prcred_t *prcred = (prcred_t *) scratch;
FILE *fp = NULL;
int ret = 0;
+ int ngrps;
ret = snprintf (filename, sizeof filename,
"/proc/%d/cred", frame->root->pid);
@@ -201,8 +206,11 @@ out:
fp = fopen (filename, "r");
if (fp != NULL) {
if (fgets (scratch, sizeof scratch, fp) != NULL) {
- frame->root->ngrps = MIN(prcred->pr_ngroups,
- GF_REQUEST_MAXGROUPS);
+ ngrps = MIN(prcred->pr_ngroups,
+ GF_MAX_AUX_GROUPS);
+ if (call_stack_alloc_groups (frame->root,
+ ngrps) != 0)
+ return;
}
fclose (fp);
}
@@ -227,7 +235,9 @@ out:
if (sysctl(name, namelen, &kp, &kplen, NULL, 0) != 0)
return;
- ngroups = MIN(kp.kp_eproc.e_ucred.cr_ngroups, GF_REQUEST_MAXGROUPS);
+ ngroups = MIN(kp.kp_eproc.e_ucred.cr_ngroups, GF_MAX_AUX_GROUPS);
+ if (call_stack_alloc_groups (frame->root, ngroups) != 0)
+ return;
for (i = 0; i < ngroups; i++)
frame->root->groups[i] = kp.kp_eproc.e_ucred.cr_groups[i];
frame->root->ngrps = ngroups;
@@ -246,6 +256,11 @@ static void get_groups(fuse_private_t *priv, call_frame_t *frame)
const gid_list_t *gl;
gid_list_t agl;
+ if (-1 == priv->gid_cache_timeout) {
+ frame->root->ngrps = 0;
+ return;
+ }
+
if (!priv->gid_cache_timeout) {
frame_fill_groups(frame);
return;
@@ -253,6 +268,8 @@ static void get_groups(fuse_private_t *priv, call_frame_t *frame)
gl = gid_cache_lookup(&priv->gid_cache, frame->root->pid);
if (gl) {
+ if (call_stack_alloc_groups (frame->root, gl->gl_count) != 0)
+ return;
frame->root->ngrps = gl->gl_count;
for (i = 0; i < gl->gl_count; i++)
frame->root->groups[i] = gl->gl_list[i];
@@ -335,7 +352,9 @@ fuse_ino_to_inode (uint64_t ino, xlator_t *fuse)
uint64_t
inode_to_fuse_nodeid (inode_t *inode)
{
- if (!inode || __is_root_gfid (inode->gfid))
+ if (!inode)
+ return 0;
+ if (__is_root_gfid (inode->gfid))
return 1;
return (unsigned long) inode;
@@ -430,36 +449,56 @@ fail:
return ret;
}
+/* Use the same logic as the Linux NFS-client */
+#define GF_FUSE_SQUASH_INO(ino) ((uint32_t) ino) ^ (ino >> 32)
/* courtesy of folly */
void
-gf_fuse_stat2attr (struct iatt *st, struct fuse_attr *fa)
+gf_fuse_stat2attr (struct iatt *st, struct fuse_attr *fa, gf_boolean_t enable_ino32)
{
- fa->ino = st->ia_ino;
- fa->size = st->ia_size;
- fa->blocks = st->ia_blocks;
- fa->atime = st->ia_atime;
- fa->mtime = st->ia_mtime;
- fa->ctime = st->ia_ctime;
- fa->atimensec = st->ia_atime_nsec;
- fa->mtimensec = st->ia_mtime_nsec;
- fa->ctimensec = st->ia_ctime_nsec;
- fa->mode = st_mode_from_ia (st->ia_prot, st->ia_type);
- fa->nlink = st->ia_nlink;
- fa->uid = st->ia_uid;
- fa->gid = st->ia_gid;
- fa->rdev = makedev (ia_major (st->ia_rdev),
- ia_minor (st->ia_rdev));
+ if (enable_ino32)
+ fa->ino = GF_FUSE_SQUASH_INO(st->ia_ino);
+ else
+ fa->ino = st->ia_ino;
+
+ fa->size = st->ia_size;
+ fa->blocks = st->ia_blocks;
+ fa->atime = st->ia_atime;
+ fa->mtime = st->ia_mtime;
+ fa->ctime = st->ia_ctime;
+ fa->atimensec = st->ia_atime_nsec;
+ fa->mtimensec = st->ia_mtime_nsec;
+ fa->ctimensec = st->ia_ctime_nsec;
+ fa->mode = st_mode_from_ia (st->ia_prot, st->ia_type);
+ fa->nlink = st->ia_nlink;
+ fa->uid = st->ia_uid;
+ fa->gid = st->ia_gid;
+ fa->rdev = makedev (ia_major (st->ia_rdev),
+ ia_minor (st->ia_rdev));
#if FUSE_KERNEL_MINOR_VERSION >= 9
- fa->blksize = st->ia_blksize;
+ fa->blksize = st->ia_blksize;
#endif
#ifdef GF_DARWIN_HOST_OS
- fa->crtime = (uint64_t)-1;
- fa->crtimensec = (uint32_t)-1;
- fa->flags = 0;
+ fa->crtime = (uint64_t)-1;
+ fa->crtimensec = (uint32_t)-1;
+ fa->flags = 0;
#endif
}
+void
+gf_fuse_fill_dirent (gf_dirent_t *entry, struct fuse_dirent *fde, gf_boolean_t enable_ino32)
+{
+ if (enable_ino32)
+ fde->ino = GF_FUSE_SQUASH_INO(entry->d_ino);
+ else
+ fde->ino = entry->d_ino;
+
+ fde->off = entry->d_off;
+ fde->type = entry->d_type;
+ fde->namelen = strlen (entry->d_name);
+ strncpy (fde->name, entry->d_name, fde->namelen);
+}
+
static int
fuse_do_flip_xattr_ns (char *okey, const char *nns, char **nkey)
{
diff --git a/xlators/mount/fuse/src/fuse-mem-types.h b/xlators/mount/fuse/src/fuse-mem-types.h
index cdea9b256..28b4dfbdd 100644
--- a/xlators/mount/fuse/src/fuse-mem-types.h
+++ b/xlators/mount/fuse/src/fuse-mem-types.h
@@ -1,14 +1,13 @@
/*
- Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
- This file is part of GlusterFS.
+ Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
- This file is licensed to you under your choice of the GNU Lesser
- General Public License, version 3 or any later version (LGPLv3 or
- later), or the GNU General Public License, version 2 (GPLv2), in all
- cases as published by the Free Software Foundation.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
-
#ifndef __FUSE_MEM_TYPES_H__
#define __FUSE_MEM_TYPES_H__
diff --git a/xlators/mount/fuse/src/fuse-resolve.c b/xlators/mount/fuse/src/fuse-resolve.c
index 7bc662302..8565ce0e4 100644
--- a/xlators/mount/fuse/src/fuse-resolve.c
+++ b/xlators/mount/fuse/src/fuse-resolve.c
@@ -1,13 +1,12 @@
/*
- Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
- This file is part of GlusterFS.
+ Copyright (c) 2010-2012 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
- This file is licensed to you under your choice of the GNU Lesser
- General Public License, version 3 or any later version (LGPLv3 or
- later), or the GNU General Public License, version 2 (GPLv2), in all
- cases as published by the Free Software Foundation.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
-
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
@@ -27,6 +26,8 @@ int fuse_migrate_fd (xlator_t *this, fd_t *fd, xlator_t *old_subvol,
fuse_fd_ctx_t *
fuse_fd_ctx_get (xlator_t *this, fd_t *fd);
+gf_boolean_t fuse_inode_needs_lookup (inode_t *inode, xlator_t *this);
+
static int
fuse_resolve_loc_touchup (fuse_state_t *state)
{
@@ -202,7 +203,11 @@ fuse_resolve_gfid (fuse_state_t *state)
uuid_copy (resolve_loc->gfid, resolve->gfid);
}
- resolve_loc->inode = inode_new (state->itable);
+ /* inode may already exist in case we are looking up an inode which was
+ linked through readdirplus */
+ resolve_loc->inode = inode_find (state->itable, resolve_loc->gfid);
+ if (!resolve_loc->inode)
+ resolve_loc->inode = inode_new (state->itable);
ret = loc_path (resolve_loc, NULL);
if (ret <= 0) {
@@ -240,8 +245,12 @@ fuse_resolve_parent_simple (fuse_state_t *state)
parent = resolve->parhint;
if (parent->table == state->itable) {
+ if (fuse_inode_needs_lookup (parent, THIS))
+ return 1;
+
/* no graph switches since */
loc->parent = inode_ref (parent);
+ uuid_copy (loc->pargfid, parent->gfid);
loc->inode = inode_grep (state->itable, parent, loc->name);
/* nodeid for root is 1 and we blindly take the latest graph's
@@ -265,6 +274,10 @@ fuse_resolve_parent_simple (fuse_state_t *state)
/* non decisive result - parent missing */
return 1;
}
+ if (fuse_inode_needs_lookup (parent, THIS)) {
+ inode_unref (parent);
+ return 1;
+ }
loc->parent = parent;
uuid_copy (loc->pargfid, resolve->pargfid);
@@ -314,15 +327,18 @@ fuse_resolve_inode_simple (fuse_state_t *state)
loc = state->loc_now;
inode = resolve->hint;
- if (inode->table == state->itable) {
+ if (inode->table == state->itable)
inode_ref (inode);
- goto found;
+ else
+ inode = inode_find (state->itable, resolve->gfid);
+
+ if (inode) {
+ if (!fuse_inode_needs_lookup (inode, THIS))
+ goto found;
+ /* inode was linked through readdirplus */
+ inode_unref (inode);
}
- inode = inode_find (state->itable, resolve->gfid);
- if (inode)
- goto found;
-
return 1;
found:
loc->inode = inode;
@@ -351,31 +367,49 @@ fuse_resolve_inode (fuse_state_t *state)
int
fuse_migrate_fd_task (void *data)
{
- int ret = -1;
- fuse_fd_ctx_t *fdctx = NULL;
- fuse_state_t *state = NULL;
+ int ret = -1;
+ fuse_state_t *state = NULL;
+ fd_t *basefd = NULL, *oldfd = NULL;
+ fuse_fd_ctx_t *basefd_ctx = NULL;
+ xlator_t *old_subvol = NULL;
state = data;
if (state == NULL) {
goto out;
}
- ret = fuse_migrate_fd (state->this, state->fd,
- state->fd->inode->table->xl,
+ basefd = state->fd;
+
+ basefd_ctx = fuse_fd_ctx_get (state->this, basefd);
+
+ LOCK (&basefd->lock);
+ {
+ oldfd = basefd_ctx->activefd ? basefd_ctx->activefd : basefd;
+ fd_ref (oldfd);
+ }
+ UNLOCK (&basefd->lock);
+
+ old_subvol = oldfd->inode->table->xl;
+
+ ret = fuse_migrate_fd (state->this, basefd, old_subvol,
state->active_subvol);
- fdctx = fuse_fd_ctx_check_n_create (state->this, state->fd);
- if (fdctx != NULL) {
+ LOCK (&basefd->lock);
+ {
if (ret < 0) {
- fdctx->migration_failed = 1;
+ basefd_ctx->migration_failed = 1;
} else {
- fdctx->migration_failed = 0;
+ basefd_ctx->migration_failed = 0;
}
}
+ UNLOCK (&basefd->lock);
ret = 0;
out:
+ if (oldfd)
+ fd_unref (oldfd);
+
return ret;
}
@@ -396,22 +430,55 @@ fuse_migrate_fd_error (xlator_t *this, fd_t *fd)
return error;
}
+#define FUSE_FD_GET_ACTIVE_FD(activefd, basefd) \
+ do { \
+ LOCK (&basefd->lock); \
+ { \
+ activefd = basefd_ctx->activefd ? \
+ basefd_ctx->activefd : basefd; \
+ if (activefd != basefd) { \
+ fd_ref (activefd); \
+ } \
+ } \
+ UNLOCK (&basefd->lock); \
+ \
+ if (activefd == basefd) { \
+ fd_ref (activefd); \
+ } \
+ } while (0);
+
static int
fuse_resolve_fd (fuse_state_t *state)
{
- fuse_resolve_t *resolve = NULL;
- fd_t *fd = NULL;
- xlator_t *active_subvol = NULL;
- int ret = 0;
- char fd_migration_error = 0;
+ fuse_resolve_t *resolve = NULL;
+ fd_t *basefd = NULL, *activefd = NULL;
+ xlator_t *active_subvol = NULL, *this = NULL;
+ int ret = 0;
+ char fd_migration_error = 0;
+ fuse_fd_ctx_t *basefd_ctx = NULL;
resolve = state->resolve_now;
- fd = resolve->fd;
- active_subvol = fd->inode->table->xl;
+ this = state->this;
+
+ basefd = resolve->fd;
+ basefd_ctx = fuse_fd_ctx_get (this, basefd);
+ if (basefd_ctx == NULL) {
+ gf_log (state->this->name, GF_LOG_WARNING,
+ "fdctx is NULL for basefd (ptr:%p inode-gfid:%s), "
+ "resolver erroring out with errno EINVAL",
+ basefd, uuid_utoa (basefd->inode->gfid));
+ resolve->op_ret = -1;
+ resolve->op_errno = EINVAL;
+ goto resolve_continue;
+ }
+
+ FUSE_FD_GET_ACTIVE_FD (activefd, basefd);
- fd_migration_error = fuse_migrate_fd_error (state->this, fd);
+ active_subvol = activefd->inode->table->xl;
+
+ fd_migration_error = fuse_migrate_fd_error (state->this, basefd);
if (fd_migration_error) {
resolve->op_ret = -1;
resolve->op_errno = EBADF;
@@ -419,35 +486,78 @@ fuse_resolve_fd (fuse_state_t *state)
ret = synctask_new (state->this->ctx->env, fuse_migrate_fd_task,
NULL, NULL, state);
- fd_migration_error = fuse_migrate_fd_error (state->this, fd);
+ fd_migration_error = fuse_migrate_fd_error (state->this,
+ basefd);
+ fd_unref (activefd);
+
+ FUSE_FD_GET_ACTIVE_FD (activefd, basefd);
+ active_subvol = activefd->inode->table->xl;
if ((ret == -1) || fd_migration_error
- || (state->active_subvol != fd->inode->table->xl)) {
+ || (state->active_subvol != active_subvol)) {
if (ret == -1) {
gf_log (state->this->name, GF_LOG_WARNING,
- "starting sync-task to migrate fd (%p)"
- " failed", fd);
+ "starting sync-task to migrate "
+ "basefd (ptr:%p inode-gfid:%s) failed "
+ "(old-subvolume:%s-%d "
+ "new-subvolume:%s-%d)",
+ basefd,
+ uuid_utoa (basefd->inode->gfid),
+ active_subvol->name,
+ active_subvol->graph->id,
+ state->active_subvol->name,
+ state->active_subvol->graph->id);
} else {
gf_log (state->this->name, GF_LOG_WARNING,
- "fd migration of fd (%p) failed", fd);
+ "fd migration of basefd "
+ "(ptr:%p inode-gfid:%s) failed "
+ "(old-subvolume:%s-%d "
+ "new-subvolume:%s-%d)",
+ basefd,
+ uuid_utoa (basefd->inode->gfid),
+ active_subvol->name,
+ active_subvol->graph->id,
+ state->active_subvol->name,
+ state->active_subvol->graph->id);
}
resolve->op_ret = -1;
resolve->op_errno = EBADF;
} else {
gf_log (state->this->name, GF_LOG_DEBUG,
- "fd (%p) migrated successfully in resolver",
- fd);
+ "basefd (ptr:%p inode-gfid:%s) migrated "
+ "successfully in resolver "
+ "(old-subvolume:%s-%d new-subvolume:%s-%d)",
+ basefd, uuid_utoa (basefd->inode->gfid),
+ active_subvol->name, active_subvol->graph->id,
+ state->active_subvol->name,
+ state->active_subvol->graph->id);
}
}
if ((resolve->op_ret == -1) && (resolve->op_errno == EBADF)) {
- gf_log ("fuse-resolve", GF_LOG_WARNING, "migration of fd (%p) "
- "did not complete, failing fop with EBADF", fd);
+ gf_log ("fuse-resolve", GF_LOG_WARNING,
+ "migration of basefd (ptr:%p inode-gfid:%s) "
+ "did not complete, failing fop with EBADF "
+ "(old-subvolume:%s-%d new-subvolume:%s-%d)", basefd,
+ uuid_utoa (basefd->inode->gfid),
+ active_subvol->name, active_subvol->graph->id,
+ state->active_subvol->name,
+ state->active_subvol->graph->id);
+ }
+
+ if (activefd != basefd) {
+ state->fd = fd_ref (activefd);
+ fd_unref (basefd);
}
/* state->active_subvol = active_subvol; */
+resolve_continue:
+ if (activefd != NULL) {
+ fd_unref (activefd);
+ }
+
fuse_resolve_continue (state);
return 0;