diff options
Diffstat (limited to 'xlators/mount/fuse/src')
| -rw-r--r-- | xlators/mount/fuse/src/Makefile.am | 2 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 1422 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.h | 117 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-helpers.c | 31 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-resolve.c | 31 |
5 files changed, 1101 insertions, 502 deletions
diff --git a/xlators/mount/fuse/src/Makefile.am b/xlators/mount/fuse/src/Makefile.am index 4e9287067..653121d18 100644 --- a/xlators/mount/fuse/src/Makefile.am +++ b/xlators/mount/fuse/src/Makefile.am @@ -24,7 +24,7 @@ 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 +fuse_la_LDFLAGS = -module -avoid-version fuse_la_LIBADD = @GF_FUSE_LDADD@ AM_CPPFLAGS = $(GF_CPPFLAGS) \ diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index e46283793..6a5587c2d 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -10,6 +10,13 @@ #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; @@ -25,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) { @@ -93,7 +142,6 @@ out: return fd_ctx; } - fuse_fd_ctx_t * fuse_fd_ctx_get (xlator_t *this, fd_t *fd) { @@ -112,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. @@ -191,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); @@ -225,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); } /* @@ -235,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); - gf_log("glusterfs-fuse", GF_LOG_TRACE, "INVALIDATE inode: %lu", fuse_ino); + /* 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); + + 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 @@ -274,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, @@ -298,24 +387,33 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this, finh = state->finh; 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; - } + 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); @@ -364,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 = @@ -372,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); @@ -380,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, @@ -392,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, @@ -408,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; @@ -467,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); @@ -476,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); @@ -496,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, @@ -519,9 +650,11 @@ 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); @@ -557,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) @@ -571,9 +703,13 @@ 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); @@ -594,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", @@ -611,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, @@ -630,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, @@ -693,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) { @@ -735,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) @@ -750,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; @@ -770,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 } @@ -822,7 +957,6 @@ out: return 0; } - static void fuse_do_truncate (fuse_state_t *state, size_t size) { @@ -837,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, @@ -854,9 +987,14 @@ 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); @@ -901,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) { @@ -928,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 \ @@ -941,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; @@ -997,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 @@ -1045,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) @@ -1053,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, @@ -1077,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, @@ -1086,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) @@ -1100,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, @@ -1112,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); @@ -1138,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) { @@ -1146,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; @@ -1161,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) { @@ -1179,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, @@ -1191,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'; @@ -1213,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) { @@ -1234,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) { @@ -1242,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; @@ -1271,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); @@ -1285,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) { @@ -1306,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); @@ -1355,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; @@ -1377,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); @@ -1390,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) { @@ -1405,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); @@ -1453,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; @@ -1475,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) { @@ -1484,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); @@ -1496,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; @@ -1512,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) { @@ -1521,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; @@ -1550,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); @@ -1563,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) { @@ -1575,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); @@ -1584,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, @@ -1598,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); @@ -1640,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); @@ -1654,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); @@ -1677,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) { @@ -1688,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) { @@ -1713,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", @@ -1728,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) { @@ -1738,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, @@ -1768,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; @@ -1777,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); @@ -1844,7 +1911,6 @@ out: return 0; } - void fuse_create_resume (fuse_state_t *state) { @@ -1856,7 +1922,7 @@ fuse_create_resume (fuse_state_t *state) 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; @@ -1913,7 +1979,6 @@ fuse_create_resume (fuse_state_t *state) } - static void fuse_create (xlator_t *this, fuse_in_header_t *finh, void *msg) { @@ -1938,56 +2003,20 @@ 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) { @@ -2039,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) { @@ -2048,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; @@ -2057,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, @@ -2072,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); @@ -2127,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; @@ -2144,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, @@ -2157,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); @@ -2201,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, @@ -2239,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; @@ -2256,7 +2286,6 @@ fuse_write (xlator_t *this, fuse_in_header_t *finh, void *msg) return; } - void fuse_flush_resume (fuse_state_t *state) { @@ -2264,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) { @@ -2277,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; @@ -2289,7 +2317,6 @@ 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) { @@ -2308,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); @@ -2335,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) { @@ -2361,14 +2389,13 @@ 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) { @@ -2418,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) { @@ -2435,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) { @@ -2469,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, @@ -2487,6 +2511,8 @@ fuse_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, 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, "%"PRIu64": READDIR => -1 (%s)", frame->root->unique, @@ -2505,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, @@ -2534,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) { @@ -2561,12 +2590,187 @@ 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) { @@ -2583,6 +2787,10 @@ fuse_releasedir (xlator_t *this, fuse_in_header_t *finh, void *msg) 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); @@ -2634,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); @@ -2642,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, @@ -2657,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 */ @@ -2696,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) { @@ -2725,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); } @@ -2739,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; @@ -2802,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 */ @@ -2845,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) { @@ -2913,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) @@ -2937,10 +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; + 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, @@ -2965,32 +3178,20 @@ 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 */ - int _get_total_len (dict_t *d, char *k, data_t *v, - void *tmp) - { - if (!fuse_filter_xattr (this, k)) - len += strlen (k) + 1; - return 0; - } - dict_foreach (dict, _get_total_len, NULL); + 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; - - int _set_listxattr_keys (dict_t *d, char *k, data_t *v, - void *tmp) - { - if (!fuse_filter_xattr (this, k)) { - strcpy (value + len, k); - value[len + strlen (k)] = '\0'; - len += strlen (k) + 1; - } - return 0; - } - dict_foreach (dict, _set_listxattr_keys, NULL); + 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 */ @@ -3036,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); @@ -3053,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, @@ -3074,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) { @@ -3098,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; } @@ -3148,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); @@ -3185,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; @@ -3201,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); @@ -3252,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) { @@ -3280,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); @@ -3341,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); @@ -3365,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); @@ -3432,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); @@ -3519,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 @@ -3547,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)", @@ -3559,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; @@ -3580,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, @@ -3814,6 +4108,10 @@ 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); + newfd->lk_ctx = fd_lk_ctx_ref (oldfd->lk_ctx); newfd_ctx = fuse_fd_ctx_check_n_create (this, newfd); @@ -3852,20 +4150,93 @@ fuse_migrate_fd_open (xlator_t *this, fd_t *basefd, fd_t *oldfd, fd_unref (old_activefd); } - gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "migrated basefd (%p) to newfd (%p) " + 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, - old_subvol->name, old_subvol->graph->id, + uuid_utoa (basefd->inode->gfid), + old_subvol->name, old_subvol->graph->id, new_subvol->name, new_subvol->graph->id); - newfd = NULL; 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; + + + if (!oldfd->lk_ctx || fd_lk_ctx_empty (oldfd->lk_ctx)) + return 0; + + basefd_ctx = fuse_fd_ctx_get (this, basefd); + GF_VALIDATE_OR_GOTO ("glusterfs-fuse", basefd_ctx, out); + + LOCK (&basefd->lock); + { + newfd = fd_ref (basefd_ctx->activefd); + } + UNLOCK (&basefd->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, @@ -3873,7 +4244,7 @@ fuse_migrate_fd (xlator_t *this, fd_t *basefd, xlator_t *old_subvol, { int ret = -1; char create_in_progress = 0; - fuse_fd_ctx_t *basefd_ctx = NULL; + fuse_fd_ctx_t *basefd_ctx = NULL; fd_t *oldfd = NULL; basefd_ctx = fuse_fd_ctx_get (this, basefd); @@ -3936,6 +4307,27 @@ fuse_migrate_fd (xlator_t *this, fd_t *basefd, xlator_t *old_subvol, ret = fuse_migrate_fd_open (this, basefd, oldfd, old_subvol, new_subvol); + if (ret < 0) { + 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; + } + + 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); + + } out: if (ret < 0) { gf_log (this->name, GF_LOG_WARNING, "migration of basefd " @@ -4134,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: @@ -4289,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; @@ -4303,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; } @@ -4321,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; } @@ -4399,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 @@ -4442,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) @@ -4530,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)", @@ -4618,13 +5062,13 @@ static fuse_handler_t *fuse_std_ops[FUSE_OP_HIGH] = { /* [FUSE_IOCTL] */ /* [FUSE_POLL] */ /* [FUSE_NOTIFY_REPLY] */ - /* [FUSE_BATCH_FORGET] */ - /* [FUSE_FALLOCATE] */ + [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 @@ -4652,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); } @@ -4671,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; @@ -4750,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); @@ -4773,20 +5220,22 @@ 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); if (ret == 0) { @@ -4812,24 +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); - GF_OPTION_INIT ("fuse-mountopts", priv->fuse_mountopts, str, 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; - } + 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, @@ -4881,8 +5334,9 @@ init (xlator_t *this_xl) goto cleanup_exit; } - gf_asprintf (&mnt_args, "%s%s%s%sallow_other,max_read=131072", - priv->read_only ? "ro," : "", + 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 ? "," : ""); @@ -4895,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); @@ -4970,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[] = { @@ -4995,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 @@ -5021,26 +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 = {"enable-ino32"}, - .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", @@ -5056,5 +5520,9 @@ struct volume_options options[] = { { .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 fdfe08b2c..34794b6ea 100644 --- a/xlators/mount/fuse/src/fuse-bridge.h +++ b/xlators/mount/fuse/src/fuse-bridge.h @@ -48,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) @@ -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; @@ -119,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; @@ -134,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)) @@ -141,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) { \ @@ -170,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", \ @@ -186,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", \ @@ -195,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) { \ @@ -216,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); \ } \ \ @@ -291,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); \ } \ @@ -317,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) @@ -435,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 e72669a9e..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]; @@ -339,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; diff --git a/xlators/mount/fuse/src/fuse-resolve.c b/xlators/mount/fuse/src/fuse-resolve.c index e7e580fe8..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,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 @@ -264,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); @@ -313,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; |
