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/fuse-bridge.c243
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.h23
-rw-r--r--xlators/mount/fuse/src/fuse-helpers.c27
-rw-r--r--xlators/mount/fuse/src/fuse-resolve.c30
4 files changed, 240 insertions, 83 deletions
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
index ce33009d8..6a5587c2d 100644
--- a/xlators/mount/fuse/src/fuse-bridge.c
+++ b/xlators/mount/fuse/src/fuse-bridge.c
@@ -12,6 +12,7 @@
#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 */
@@ -52,6 +53,46 @@ fuse_invalidate(xlator_t *this, inode_t *inode)
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)
{
@@ -372,7 +413,7 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
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);
@@ -464,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;
@@ -523,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);
@@ -532,15 +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);
@@ -551,16 +611,29 @@ 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);
+ do_forget(this, finh->unique, finh->nodeid, ffi->nlookup);
+
+ GF_FREE (finh);
+}
- fuse_log_eh (this, "%"PRIu64": FORGET %"PRIu64"/%"PRIu64" gfid: (%s)",
- finh->unique, finh->nodeid, ffi->nlookup,
- uuid_utoa (fuse_inode->gfid));
+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;
- inode_forget (fuse_inode, ffi->nlookup);
- inode_unref (fuse_inode);
+ gf_log("glusterfs-fuse", GF_LOG_TRACE,
+ "%"PRIu64": BATCH_FORGET %"PRIu64"/%"PRIu32,
+ finh->unique, finh->nodeid, fbfi->count);
- GF_FREE (finh);
+ 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
@@ -581,7 +654,7 @@ fuse_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
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);
@@ -636,7 +709,7 @@ fuse_attr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
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);
@@ -921,7 +994,7 @@ fuse_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
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);
@@ -1319,7 +1392,7 @@ 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);
send_fuse_err (state->this, state->finh, ENOENT);
@@ -1389,7 +1462,7 @@ 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);
send_fuse_err (state->this, state->finh, ENOENT);
@@ -1451,7 +1524,7 @@ 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",
+ "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);
@@ -1487,7 +1560,7 @@ 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",
+ "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);
@@ -1523,7 +1596,7 @@ 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);
send_fuse_err (state->this, state->finh, ENOENT);
@@ -1596,7 +1669,7 @@ fuse_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
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);
@@ -1771,7 +1844,7 @@ 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);
@@ -2030,7 +2103,7 @@ fuse_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
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);
@@ -2116,7 +2189,7 @@ fuse_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
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);
@@ -2158,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,
@@ -2496,7 +2569,7 @@ 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,
@@ -2601,6 +2674,8 @@ fuse_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
feo->nodeid = inode_to_fuse_nodeid (linked_inode);
+ fuse_inode_set_need_lookup (linked_inode, this);
+
inode_unref (linked_inode);
feo->entry_valid =
@@ -2627,7 +2702,7 @@ void
fuse_readdirp_resume (fuse_state_t *state)
{
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
- "%"PRIu64": READDIRP (%p, size=%zu, offset=%"PRId64")",
+ "%"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,
@@ -2937,8 +3012,8 @@ 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;
@@ -3242,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) {
@@ -3266,26 +3342,23 @@ 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;
+ op_errno = ENODATA;
+ goto err;
}
}
@@ -3295,16 +3368,19 @@ fuse_getxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
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;
}
@@ -3691,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
@@ -3719,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)",
@@ -3757,6 +3837,40 @@ fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg)
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;
@@ -3994,6 +4108,7 @@ fuse_migrate_fd_open (xlator_t *this, fd_t *basefd, fd_t *oldfd,
goto out;
}
+ newfd->flags = basefd->flags;
if (newfd->lk_ctx)
fd_lk_ctx_unref (newfd->lk_ctx);
@@ -4859,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)",
@@ -4947,7 +5062,7 @@ static fuse_handler_t *fuse_std_ops[FUSE_OP_HIGH] = {
/* [FUSE_IOCTL] */
/* [FUSE_POLL] */
/* [FUSE_NOTIFY_REPLY] */
- /* [FUSE_BATCH_FORGET] */
+ [FUSE_BATCH_FORGET]= fuse_batch_forget,
[FUSE_FALLOCATE] = fuse_fallocate,
[FUSE_READDIRPLUS] = fuse_readdirp,
};
@@ -5000,6 +5115,7 @@ 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;
@@ -5145,8 +5261,12 @@ 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);
@@ -5235,7 +5355,7 @@ init (xlator_t *this_xl)
if (priv->fd == -1)
goto cleanup_exit;
- event = eh_new (FUSE_EVENT_HISTORY_SIZE, _gf_false);
+ 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");
@@ -5317,6 +5437,7 @@ struct xlator_fops fops;
struct xlator_cbks cbks = {
.invalidate = fuse_invalidate,
+ .forget = fuse_forget_cbk,
};
@@ -5401,7 +5522,7 @@ struct volume_options options[] = {
},
{ .key = {"use-readdirp"},
.type = GF_OPTION_TYPE_BOOL,
- .default_value = "no"
+ .default_value = "yes"
},
{ .key = {NULL} },
};
diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h
index 2626638dc..34794b6ea 100644
--- a/xlators/mount/fuse/src/fuse-bridge.h
+++ b/xlators/mount/fuse/src/fuse-bridge.h
@@ -101,7 +101,7 @@ 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;
@@ -145,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) { \
@@ -174,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", \
@@ -190,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", \
@@ -199,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) { \
diff --git a/xlators/mount/fuse/src/fuse-helpers.c b/xlators/mount/fuse/src/fuse-helpers.c
index d4dcc2e61..4d478b919 100644
--- a/xlators/mount/fuse/src/fuse-helpers.c
+++ b/xlators/mount/fuse/src/fuse-helpers.c
@@ -7,6 +7,10 @@
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)
#include <sys/procfs.h>
@@ -14,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)
@@ -138,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)
{
@@ -160,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;
@@ -176,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;
}
@@ -192,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);
@@ -200,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);
}
@@ -226,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;
@@ -257,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];
diff --git a/xlators/mount/fuse/src/fuse-resolve.c b/xlators/mount/fuse/src/fuse-resolve.c
index 88ce32ab9..8565ce0e4 100644
--- a/xlators/mount/fuse/src/fuse-resolve.c
+++ b/xlators/mount/fuse/src/fuse-resolve.c
@@ -26,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)
{
@@ -201,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) {
@@ -239,6 +245,9 @@ 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);
@@ -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;