summaryrefslogtreecommitdiffstats
path: root/xlators/mount/fuse/src/fuse-bridge.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/mount/fuse/src/fuse-bridge.c')
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.c481
1 files changed, 420 insertions, 61 deletions
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
index 25545b783..6a5587c2d 100644
--- a/xlators/mount/fuse/src/fuse-bridge.c
+++ b/xlators/mount/fuse/src/fuse-bridge.c
@@ -11,6 +11,8 @@
#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 */
@@ -51,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)
{
@@ -371,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);
@@ -463,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;
@@ -522,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);
@@ -531,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);
@@ -550,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);
+}
+
+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;
- fuse_log_eh (this, "%"PRIu64": FORGET %"PRIu64"/%"PRIu64" gfid: (%s)",
- finh->unique, finh->nodeid, ffi->nlookup,
- uuid_utoa (fuse_inode->gfid));
+ gf_log("glusterfs-fuse", GF_LOG_TRACE,
+ "%"PRIu64": BATCH_FORGET %"PRIu64"/%"PRIu32,
+ finh->unique, finh->nodeid, fbfi->count);
- inode_forget (fuse_inode, ffi->nlookup);
- inode_unref (fuse_inode);
+ 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);
+ GF_FREE(finh);
}
static int
@@ -580,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);
@@ -635,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);
@@ -920,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);
@@ -1318,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);
@@ -1388,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);
@@ -1450,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);
@@ -1486,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);
@@ -1522,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);
@@ -1595,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);
@@ -1770,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);
@@ -2029,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);
@@ -2115,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);
@@ -2157,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,
@@ -2457,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,
@@ -2490,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,
@@ -2516,6 +2595,182 @@ fuse_readdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
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)
{
@@ -2757,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;
@@ -2982,6 +3237,8 @@ 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) "
@@ -2999,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,
@@ -3020,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) {
@@ -3044,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;
}
}
@@ -3073,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;
}
@@ -3469,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
@@ -3497,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)",
@@ -3530,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,
@@ -3764,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);
@@ -4500,6 +4845,7 @@ 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;
}
@@ -4628,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)",
@@ -4716,8 +5062,9 @@ 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,
};
@@ -4768,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;
@@ -4886,6 +5234,8 @@ init (xlator_t *this_xl)
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) {
@@ -4911,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);
@@ -5001,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");
@@ -5083,6 +5437,7 @@ struct xlator_fops fops;
struct xlator_cbks cbks = {
.invalidate = fuse_invalidate,
+ .forget = fuse_forget_cbk,
};
@@ -5136,7 +5491,7 @@ struct volume_options options[] = {
},
{ .key = {"gid-timeout"},
.type = GF_OPTION_TYPE_INT,
- .default_value = "0"
+ .default_value = "2"
},
{ .key = {"acl"},
.type = GF_OPTION_TYPE_BOOL,
@@ -5165,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} },
};