diff options
Diffstat (limited to 'xlators/mount/fuse/src')
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 243 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.h | 23 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-helpers.c | 27 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-resolve.c | 30 |
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; |
