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.c1170
1 files changed, 1064 insertions, 106 deletions
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
index 0291859c0..85ecce958 100644
--- a/xlators/mount/fuse/src/fuse-bridge.c
+++ b/xlators/mount/fuse/src/fuse-bridge.c
@@ -9,9 +9,13 @@
*/
#include <sys/wait.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <dirent.h>
#include "fuse-bridge.h"
#include "mount-gluster-compat.h"
#include "glusterfs.h"
+#include "byte-order.h"
#ifdef __NetBSD__
#undef open /* in perfuse.h, pulled from mount-gluster-compat.h */
@@ -24,6 +28,14 @@ void fini (xlator_t *this_xl);
static void fuse_invalidate_inode(xlator_t *this, uint64_t fuse_ino);
+static inline void
+fuse_lookup_gfid_dir (xlator_t *this, fuse_state_t *state, char *name,
+ gf_lookup_namespace_t ns);
+
+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);
/*
* Send an invalidate notification up to fuse to purge the file from local
* page cache.
@@ -43,10 +55,16 @@ fuse_invalidate(xlator_t *this, inode_t *inode)
if (!priv->fopen_keep_cache)
return 0;
- nodeid = inode_to_fuse_nodeid(inode);
+ /* shouldn't matter what namespace we use here, since if it
+ * is auxiliary gfid mount, we are going to invalidate both inodes
+ * corresponding to gfid and path namespaces.
+ */
+ nodeid = inode_to_fuse_nodeid(this, inode, GF_FUSE_PATH_NAMESPACE);
+
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;
@@ -214,10 +232,14 @@ fuse_invalidate_entry (xlator_t *this, uint64_t fuse_ino)
list_for_each_entry (dentry, &inode->dentry_list, inode_list) {
nlen = strlen (dentry->name);
fouh->len = sizeof (*fouh) + sizeof (*fnieo) + nlen + 1;
- fnieo->parent = inode_to_fuse_nodeid (dentry->parent);
+
+ /* entries in GF_FUSE_GFID_NAMESPACE are never linked */
+ fnieo->parent = inode_to_fuse_nodeid (this, dentry->parent,
+ GF_FUSE_PATH_NAMESPACE);
fnieo->namelen = nlen;
- strcpy (inval_buf + sizeof (*fouh) + sizeof (*fnieo), dentry->name);
+ strcpy (inval_buf + sizeof (*fouh) + sizeof (*fnieo),
+ dentry->name);
rv = write (priv->revchan_out, inval_buf, fouh->len);
if (rv != fouh->len) {
@@ -245,6 +267,43 @@ fuse_invalidate_entry (xlator_t *this, uint64_t fuse_ino)
inode_unref (inode);
}
+static int32_t
+fuse_write_invalidate_request (xlator_t *this, struct fuse_out_header *fouh,
+ struct fuse_notify_inval_inode_out *fniio,
+ uint64_t fuse_ino, inode_t *inode)
+{
+ int32_t rv = -1;
+ fuse_private_t *priv = NULL;
+
+ if (!this || !fouh || !fniio || !fuse_ino || !inode)
+ goto out;
+
+ priv = this->private;
+
+ /* inval the entire mapping until we learn how to be more granular */
+ fniio->ino = fuse_ino;
+
+ rv = write(priv->revchan_out, fouh, 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);
+ }
+
+out:
+ return rv;
+}
+
/*
* Send an inval inode notification to fuse. This causes an invalidation of the
* entire page cache mapping on the inode.
@@ -252,12 +311,14 @@ 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};
- inode_t *inode = NULL;
+ 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;
+ gf_fuse_nodeid_t *nodeid = NULL;
+ uint64_t value = 0;
fouh = (struct fuse_out_header *) inval_buf;
fniio = (struct fuse_notify_inval_inode_out *) (fouh + 1);
@@ -272,31 +333,46 @@ fuse_invalidate_inode(xlator_t *this, uint64_t fuse_ino)
fouh->len = sizeof(struct fuse_out_header) +
sizeof(struct fuse_notify_inval_inode_out);
- /* inval the entire mapping until we learn how to be more granular */
- fniio->ino = fuse_ino;
fniio->off = 0;
fniio->len = -1;
inode = fuse_ino_to_inode (fuse_ino, this);
- rv = write(priv->revchan_out, inval_buf, fouh->len);
- if (rv != fouh->len) {
- gf_log("glusterfs-fuse", GF_LOG_ERROR, "kernel notification "
- "daemon defunct");
- close(priv->fd);
- }
+ if (priv->aux_gfid_mount) {
+ inode_ctx_get (inode, this, &value);
+ nodeid = (void *)value;
+ if (nodeid == NULL) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "nodeid is NULL on an auxiliary mount");
+ goto out;
+ }
- gf_log("glusterfs-fuse", GF_LOG_TRACE, "INVALIDATE inode: %lu", fuse_ino);
+ rv = fuse_write_invalidate_request (this, fouh, fniio,
+ (uint64_t) &nodeid->inode_path_ns,
+ inode);
+ if (rv < 0) {
+ goto out;
+ }
- if (inode) {
- fuse_log_eh (this, "Invalidated inode %lu (gfid: %s)",
- fuse_ino, uuid_utoa (inode->gfid));
+ rv = fuse_write_invalidate_request (this, fouh, fniio,
+ (uint64_t) &nodeid->inode_gfid_ns,
+ inode);
+ if (rv < 0) {
+ goto out;
+ }
} else {
- fuse_log_eh (this, "Invalidated inode %lu ", fuse_ino);
+ rv = fuse_write_invalidate_request (this, fouh, fniio,
+ fuse_ino, inode);
+ if (rv < 0) {
+ goto out;
+ }
}
+out:
if (inode)
inode_unref (inode);
+
+ return;
}
int
@@ -340,10 +416,12 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
struct fuse_entry_out feo = {0, };
fuse_private_t *priv = NULL;
inode_t *linked_inode = NULL;
+ gf_lookup_namespace_t ns = 0;
priv = this->private;
state = frame->root->state;
finh = state->finh;
+ ns = (gf_lookup_namespace_t) cookie;
if (op_ret == 0) {
if (__is_root_gfid (state->loc.inode->gfid))
@@ -386,15 +464,20 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
gf_fop_list[frame->root->op], state->loc.path);
}
- linked_inode = inode_link (inode, state->loc.parent,
- state->loc.name, buf);
+ if (ns == GF_FUSE_GFID_NAMESPACE) {
+ linked_inode = inode_link (inode, NULL, NULL, buf);
+ } else {
+ linked_inode = inode_link (inode, state->loc.parent,
+ state->loc.name, buf);
- if (linked_inode != inode) {
+ if (linked_inode != inode) {
+ }
}
+
inode_lookup (linked_inode);
- feo.nodeid = inode_to_fuse_nodeid (linked_inode);
+ feo.nodeid = inode_to_fuse_nodeid (this, linked_inode, ns);
inode_unref (linked_inode);
@@ -456,11 +539,9 @@ fuse_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
struct iatt *postparent)
{
fuse_state_t *state = NULL;
- call_frame_t *prev = NULL;
inode_table_t *itable = NULL;
state = frame->root->state;
- prev = cookie;
if (op_ret == -1 && state->is_revalidate == 1) {
itable = state->itable;
@@ -479,7 +560,8 @@ fuse_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
fuse_gfid_set (state);
STACK_WIND (frame, fuse_lookup_cbk,
- prev->this, prev->this->fops->lookup,
+ state->active_subvol,
+ state->active_subvol->fops->lookup,
&state->loc, state->xdata);
return 0;
}
@@ -527,27 +609,344 @@ fuse_lookup_resume (fuse_state_t *state)
lookup, &state->loc, state->xdata);
}
+static inline int
+fuse_handle_gfiddir_rename_op (fuse_state_t *state, void *msg)
+{
+ struct fuse_rename_in *fri = msg;
+ char *oldname = (char *)(fri + 1);
+ char *newname = oldname + strlen (oldname) + 1;
+ uuid_t aux_gfid = {0, };
+ inode_t *src_parent = NULL, *dst_parent = NULL;
+ int ret = -1;
+
+ aux_gfid[15] = 0xd;
+
+ src_parent = fuse_ino_to_inode (state->finh->nodeid, state->this);
+ dst_parent = fuse_ino_to_inode (fri->newdir, state->this);
+
+ if ((uuid_compare (aux_gfid, src_parent->gfid) == 0)
+ || (uuid_compare (aux_gfid, dst_parent->gfid) == 0)) {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "RENAME %"PRIu64" rename into or from virtual "
+ "gfid-directory is not allowed.",
+ state->finh->unique);
+
+ send_fuse_err (state->this, state->finh, ENOTSUP);
+ free_fuse_state (state);
+ ret = 0;
+ }
+
+ if ((__is_root_gfid (src_parent->gfid)
+ && (strncmp (oldname, GF_GFID_DIR, strlen (GF_GFID_DIR) == 0)))
+ || (__is_root_gfid (dst_parent->gfid)
+ && (strncmp (newname, GF_GFID_DIR,
+ strlen (GF_GFID_DIR))) == 0)) {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "RENAME %"PRIu64" renaming virtual "
+ "gfid-directory is not allowed.",
+ state->finh->unique);
+
+ send_fuse_err (state->this, state->finh, ENOTSUP);
+ free_fuse_state (state);
+ ret = 0;
+ }
+
+ inode_unref (src_parent);
+ inode_unref (dst_parent);
+
+ return ret;
+}
+
+static inline int
+fuse_handle_gfiddir_inode_op (fuse_state_t *state, glusterfs_fop_t fop)
+{
+ uuid_t aux_gfid = {0, };
+ int ret = -1;
+ inode_t *inode = NULL;
+
+ aux_gfid[15] = 0xd;
+
+ inode = fuse_ino_to_inode (state->finh->nodeid, state->this);
+
+ if (uuid_compare (aux_gfid, inode->gfid) == 0) {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "%s %"PRIu64" %s on virtual "
+ "gfid-directory is not allowed.",
+ gf_fop_list[fop], state->finh->unique,
+ gf_fop_list[fop]);
+
+ send_fuse_err (state->this, state->finh, ENOTSUP);
+ free_fuse_state (state);
+ ret = 0;
+ }
+
+ inode_unref (inode);
+
+ return ret;
+}
+
+static inline int
+fuse_handle_gfiddir_rmdir_op (fuse_state_t *state, char *name)
+{
+ int ret = -1;
+ inode_t *parent = NULL;
+
+ parent = fuse_ino_to_inode (state->finh->nodeid, state->this);
+
+ if (__is_root_gfid (parent->gfid) && (strncmp (name, GF_GFID_DIR,
+ strlen (GF_GFID_DIR)
+ == 0))) {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "RMDIR %"PRIu64" removing virtual "
+ "gfid-directory is not allowed.",
+ state->finh->unique);
+
+ send_fuse_err (state->this, state->finh, ENOTSUP);
+ free_fuse_state (state);
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static inline int
+fuse_handle_gfiddir_entry_op (fuse_state_t *state, glusterfs_fop_t fop)
+{
+ uuid_t aux_gfid = {0, };
+ int ret = -1;
+ inode_t *parent = NULL;
+
+ aux_gfid[15] = 0xd;
+
+ parent = fuse_ino_to_inode (state->finh->nodeid, state->this);
+
+ if (uuid_compare (aux_gfid, parent->gfid) == 0) {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "%s %"PRIu64" operation not allowed in virtual "
+ "gfid-directory.", gf_fop_list [fop],
+ state->finh->unique);
+
+ send_fuse_err (state->this, state->finh, ENOTSUP);
+ free_fuse_state (state);
+ ret = 0;
+ }
+
+ inode_unref (parent);
+ return ret;
+}
+
+static inline int
+fuse_handle_gfiddir_op (xlator_t *this, fuse_state_t *state, void *msg,
+ glusterfs_fop_t fop)
+{
+ int ret = -1;
+
+ switch (fop) {
+ case GF_FOP_SETATTR:
+ case GF_FOP_ACCESS:
+ case GF_FOP_OPENDIR:
+ case GF_FOP_SETXATTR:
+ case GF_FOP_GETXATTR:
+ case GF_FOP_REMOVEXATTR:
+ ret = fuse_handle_gfiddir_inode_op (state, fop);
+ break;
+
+ case GF_FOP_RMDIR:
+ ret = fuse_handle_gfiddir_rmdir_op (state, msg);
+ break;
+
+ case GF_FOP_RENAME:
+ ret = fuse_handle_gfiddir_rename_op (state, msg);
+ break;
+
+ case GF_FOP_LINK:
+ ret = fuse_handle_gfiddir_entry_op (state, fop);
+
+ case GF_FOP_UNLINK:
+ ret = fuse_handle_gfiddir_entry_op (state, fop);
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static inline int
+fuse_lookup_aux_gfid (xlator_t *this, fuse_state_t *state, inode_t *parent,
+ char *name)
+{
+ int ret = -1, op_errno = EINVAL;
+ call_frame_t *frame = NULL;
+ uuid_t aux_gfid = {0, };
+
+ aux_gfid[15] = 0xd;
+
+ ret = uuid_parse (name, state->gfid);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "parsing application provided gfid (%s) failed", name);
+ op_errno = EINVAL;
+ goto err;
+ }
+
+ fuse_gfid_set (state);
+
+ if (uuid_compare (aux_gfid, state->gfid) == 0) {
+ fuse_lookup_gfid_dir (this, state, NULL,
+ GF_FUSE_GFID_NAMESPACE);
+ goto out;
+ }
+
+ state->loc.inode = inode_find (state->itable, state->gfid);
+ if (state->loc.inode == NULL) {
+ state->loc.inode = inode_new (state->itable);
+ if (state->loc.inode == NULL) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+ } else {
+ state->is_revalidate = 1;
+ }
+
+ uuid_copy (state->loc.gfid, state->gfid);
+ FUSE_FOP_COOKIE (state, this, fuse_lookup_cbk,
+ (void *)GF_FUSE_GFID_NAMESPACE,
+ GF_FOP_LOOKUP, lookup, &state->loc, state->xdata);
+
+out:
+ return 0;
+
+err:
+ frame = get_call_frame_for_req (state);
+ frame->root->state = state;
+ fuse_entry_cbk (frame, (void *)GF_FUSE_GFID_NAMESPACE, this, -1,
+ op_errno, NULL, NULL, NULL);
+ return 0;
+}
+
+
+static inline void
+fuse_lookup_gfid_dir (xlator_t *this, fuse_state_t *state, char *name,
+ gf_lookup_namespace_t ns)
+{
+ call_frame_t *frame = NULL;
+ fuse_private_t *priv = NULL;
+ int32_t op_errno = EINVAL, op_ret = -1;
+
+ priv = this->private;
+
+ frame = get_call_frame_for_req (state);
+ if (frame == NULL) {
+ op_errno = ENOMEM;
+ goto out;
+ }
+
+ frame->root->state = state;
+
+ /* virtual stat entry */
+ priv->gfiddir_stbuf.ia_gfid[15] = GF_AUX_GFID;
+ priv->gfiddir_stbuf.ia_ino = 13;
+ priv->gfiddir_stbuf.ia_type = IA_IFDIR;
+ priv->gfiddir_stbuf.ia_nlink = 2;
+
+ state->loc.inode = inode_find (state->itable,
+ priv->gfiddir_stbuf.ia_gfid);
+
+ if (state->loc.inode == NULL) {
+ /* need to build 'state->loc' ourselves */
+ state->loc.inode = inode_new (state->itable);
+ if (state->loc.inode == NULL) {
+ op_errno = ENOMEM;
+ goto out;
+ }
+ }
+
+ op_ret = op_errno = 0;
+out:
+ switch (state->finh->opcode) {
+ case FUSE_LOOKUP:
+ fuse_entry_cbk (frame, (void *)ns, this, op_ret, op_errno,
+ state->loc.inode, &priv->gfiddir_stbuf, NULL);
+ break;
+
+ case FUSE_GETATTR:
+ fuse_attr_cbk (frame, NULL, this, op_ret, op_errno,
+ &priv->gfiddir_stbuf, NULL);
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+
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;
+ fuse_private_t *priv = NULL;
+ inode_t *parent = NULL;
+ uuid_t aux_gfid = {0,};
+ priv = this->private;
GET_STATE (this, finh, state);
+ if (!priv->aux_gfid_mount) {
+ goto normal_mount;
+ }
+
+ if ((finh->nodeid == 1) && (strcmp (GF_GFID_DIR, name) == 0)) {
+ fuse_lookup_gfid_dir (this, state, name,
+ GF_FUSE_PATH_NAMESPACE);
+ return;
+ }
+
+ aux_gfid[15] = GF_AUX_GFID;
+
+ parent = fuse_ino_to_inode (finh->nodeid, state->this);
+
+ if (uuid_compare (aux_gfid, parent->gfid) == 0) {
+ fuse_lookup_aux_gfid (this, state, parent, name);
+ inode_unref (parent);
+ return;
+ }
+
+ inode_unref (parent);
+
+normal_mount:
(void) fuse_resolve_entry_init (state, &state->resolve,
finh->nodeid, name);
fuse_resolve_and_resume (state, fuse_lookup_resume);
+
+ return;
+}
+
+int32_t
+fuse_xlator_forget (xlator_t *this, inode_t *inode)
+{
+ gf_fuse_nodeid_t *nodeid = NULL;
+ uint64_t value = 0;
+
+ inode_ctx_del (inode, this, &value);
+ nodeid = (void *)value;
+
+ if (nodeid != NULL) {
+ mem_put (nodeid);
+ }
+
+ return 0;
}
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;
+ inode_t *fuse_inode = NULL;
if (finh->nodeid == 1) {
GF_FREE (finh);
@@ -648,6 +1047,10 @@ fuse_attr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state->loc.path ? state->loc.path : "ERR",
buf->ia_ino);
+ if (__is_root_gfid (buf->ia_gfid)) {
+ priv->root_stbuf = *buf;
+ }
+
buf->ia_blksize = this->ctx->page_size;
gf_fuse_stat2attr (buf, &fao.attr, priv->enable_ino32);
@@ -732,9 +1135,13 @@ fuse_getattr_resume (fuse_state_t *state)
static void
fuse_getattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
- fuse_state_t *state;
- int32_t ret = -1;
+ fuse_state_t *state = NULL;
+ int32_t ret = -1;
+ fuse_private_t *priv = NULL;
+ uuid_t aux_gfid = {0, };
+ inode_t *inode = NULL;
+ priv = this->private;
GET_STATE (this, finh, state);
if (finh->nodeid == 1) {
@@ -757,6 +1164,21 @@ fuse_getattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
return;
}
+ if (priv->aux_gfid_mount) {
+ aux_gfid[15] = GF_AUX_GFID;
+
+ inode = fuse_ino_to_inode (finh->nodeid, state->this);
+
+ if (uuid_compare (aux_gfid, inode->gfid) == 0) {
+ fuse_lookup_gfid_dir (this, state, NULL,
+ GF_FUSE_PATH_NAMESPACE);
+ inode_unref (inode);
+ return;
+ }
+
+ inode_unref (inode);
+ }
+
fuse_resolve_inode_init (state, &state->resolve, state->finh->nodeid);
fuse_resolve_and_resume (state, fuse_getattr_resume);
@@ -1055,12 +1477,13 @@ fuse_setattr_resume (fuse_state_t *state)
static void
fuse_setattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
- struct fuse_setattr_in *fsi = msg;
-
- fuse_private_t *priv = NULL;
- fuse_state_t *state = NULL;
+ struct fuse_setattr_in *fsi = msg;
+ fuse_private_t *priv = NULL;
+ fuse_state_t *state = NULL;
+ int ret = 0;
GET_STATE (this, finh, state);
+ priv = this->private;
if (fsi->valid & FATTR_FH &&
!(fsi->valid & (FATTR_ATIME|FATTR_MTIME))) {
@@ -1069,6 +1492,13 @@ fuse_setattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
state->fd = FH_TO_FD (fsi->fh);
fuse_resolve_fd_init (state, &state->resolve, state->fd);
} else {
+ if (priv->aux_gfid_mount) {
+ ret = fuse_handle_gfiddir_op (this, state, msg,
+ GF_FOP_SETATTR);
+ if (ret == 0)
+ return;
+ }
+
fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
}
@@ -1234,11 +1664,21 @@ fuse_access_resume (fuse_state_t *state)
static void
fuse_access (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
- struct fuse_access_in *fai = msg;
- fuse_state_t *state = NULL;
+ struct fuse_access_in *fai = msg;
+ fuse_state_t *state = NULL;
+ fuse_private_t *priv = NULL;
+ int ret = 0;
GET_STATE (this, finh, state);
+ priv = this->private;
+
+ if (priv->aux_gfid_mount) {
+ ret = fuse_handle_gfiddir_op (this, state, msg, GF_FOP_ACCESS);
+ if (ret == 0)
+ return;
+ }
+
fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
state->mask = fai->mask;
@@ -1324,6 +1764,11 @@ fuse_readlink (xlator_t *this, fuse_in_header_t *finh, void *msg)
void
fuse_mknod_resume (fuse_state_t *state)
{
+ fuse_private_t *priv = NULL;
+ int ret = 0;
+
+ priv = state->this->private;
+
if (!state->loc.parent) {
gf_log ("glusterfs-fuse", GF_LOG_ERROR,
"MKNOD %"PRId64"/%s (%s/%s) resolution failed",
@@ -1340,11 +1785,31 @@ fuse_mknod_resume (fuse_state_t *state)
}
if (state->loc.inode) {
- gf_log (state->this->name, GF_LOG_DEBUG, "inode already present");
+ gf_log (state->this->name, GF_LOG_DEBUG,
+ "inode already present");
inode_unref (state->loc.inode);
state->loc.inode = NULL;
}
+ if (state->xdata == NULL) {
+ state->xdata = dict_new ();
+ }
+
+ if (priv->aux_gfid_mount) {
+ ret = dict_set_str (state->xdata, GLUSTERFS_INTERNAL_FOP_KEY,
+ "gfid-mount");
+
+ if (ret < 0) {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "MKNOD %"PRId64"/%s (%s/%s) setting a key to "
+ "overload mknod to act as link(2) when target "
+ "already exists failed",
+ state->finh->nodeid, state->resolve.bname,
+ uuid_utoa (state->resolve.gfid),
+ state->resolve.bname);
+ }
+ }
+
state->loc.inode = inode_new (state->loc.parent->table);
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
@@ -1359,12 +1824,11 @@ fuse_mknod_resume (fuse_state_t *state)
static void
fuse_mknod (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
- struct fuse_mknod_in *fmi = msg;
- char *name = (char *)(fmi + 1);
-
- fuse_state_t *state = NULL;
- fuse_private_t *priv = NULL;
- int32_t ret = -1;
+ struct fuse_mknod_in *fmi = msg;
+ char *name = (char *)(fmi + 1);
+ fuse_state_t *state = NULL;
+ fuse_private_t *priv = NULL;
+ int32_t ret = -1;
priv = this->private;
#if FUSE_KERNEL_MINOR_VERSION >= 12
@@ -1477,10 +1941,19 @@ fuse_unlink_resume (fuse_state_t *state)
static void
fuse_unlink (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;
+ fuse_private_t *priv = NULL;
+ int ret = -1;
GET_STATE (this, finh, state);
+ priv = this->private;
+
+ if (priv->aux_gfid_mount) {
+ ret = fuse_handle_gfiddir_op (this, state, msg, GF_FOP_UNLINK);
+ if (ret == 0)
+ return;
+ }
fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
@@ -1513,11 +1986,21 @@ fuse_rmdir_resume (fuse_state_t *state)
static void
fuse_rmdir (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;
+ fuse_private_t *priv = NULL;
+ int ret = 0;
GET_STATE (this, finh, state);
+ priv = this->private;
+
+ if (priv->aux_gfid_mount) {
+ ret = fuse_handle_gfiddir_op (this, state, msg, GF_FOP_RMDIR);
+ if (ret == 0)
+ return;
+ }
+
fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, name);
fuse_resolve_and_resume (state, fuse_rmdir_resume);
@@ -1544,7 +2027,8 @@ fuse_symlink_resume (fuse_state_t *state)
}
if (state->loc.inode) {
- gf_log (state->this->name, GF_LOG_DEBUG, "inode already present");
+ gf_log (state->this->name, GF_LOG_DEBUG,
+ "inode already present");
inode_unref (state->loc.inode);
state->loc.inode = NULL;
}
@@ -1556,7 +2040,8 @@ fuse_symlink_resume (fuse_state_t *state)
state->loc.path, state->name);
FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_SYMLINK,
- symlink, state->name, &state->loc, state->umask, state->xdata);
+ symlink, state->name, &state->loc, state->umask,
+ state->xdata);
}
static void
@@ -1683,12 +2168,21 @@ fuse_rename_resume (fuse_state_t *state)
static void
fuse_rename (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
- struct fuse_rename_in *fri = msg;
- char *oldname = (char *)(fri + 1);
- char *newname = oldname + strlen (oldname) + 1;
- fuse_state_t *state = NULL;
+ struct fuse_rename_in *fri = msg;
+ char *oldname = (char *)(fri + 1);
+ char *newname = oldname + strlen (oldname) + 1;
+ fuse_state_t *state = NULL;
+ fuse_private_t *priv = NULL;
+ int ret = -1;
GET_STATE (this, finh, state);
+ priv = this->private;
+
+ if (priv->aux_gfid_mount) {
+ ret = fuse_handle_gfiddir_op (this, state, msg, GF_FOP_RENAME);
+ if (ret == 0)
+ return;
+ }
fuse_resolve_entry_init (state, &state->resolve, finh->nodeid, oldname);
@@ -1732,11 +2226,20 @@ fuse_link_resume (fuse_state_t *state)
static void
fuse_link (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
- struct fuse_link_in *fli = msg;
- char *name = (char *)(fli + 1);
- fuse_state_t *state = NULL;
+ struct fuse_link_in *fli = msg;
+ char *name = (char *)(fli + 1);
+ fuse_state_t *state = NULL;
+ fuse_private_t *priv = NULL;
+ int ret = -1;
GET_STATE (this, finh, state);
+ priv = this->private;
+
+ if (priv->aux_gfid_mount) {
+ ret = fuse_handle_gfiddir_op (this, state, msg, GF_FOP_LINK);
+ if (ret == 0)
+ return;
+ }
fuse_resolve_inode_init (state, &state->resolve2, fli->oldnodeid);
@@ -1801,7 +2304,8 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
inode_unref (linked_inode);
- feo.nodeid = inode_to_fuse_nodeid (linked_inode);
+ feo.nodeid = inode_to_fuse_nodeid (this, linked_inode,
+ GF_FUSE_PATH_NAMESPACE);
feo.entry_valid = calc_timeout_sec (priv->entry_timeout);
feo.entry_valid_nsec = calc_timeout_nsec (priv->entry_timeout);
@@ -1907,9 +2411,8 @@ fuse_create_resume (fuse_state_t *state)
"%"PRIu64": CREATE %s", state->finh->unique,
state->loc.path);
- FUSE_FOP (state, fuse_create_cbk, GF_FOP_CREATE,
- create, &state->loc, state->flags, state->mode,
- state->umask, fd, state->xdata);
+ FUSE_FOP (state, fuse_create_cbk, GF_FOP_CREATE, create, &state->loc,
+ state->flags, state->mode, state->umask, fd, state->xdata);
}
@@ -2382,6 +2885,11 @@ fuse_opendir_resume (fuse_state_t *state)
static void
fuse_opendir (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
+ fuse_private_t *priv = NULL;
+ int ret = -1;
+
+ priv = this->private;
+
/*
struct fuse_open_in *foi = msg;
*/
@@ -2390,6 +2898,12 @@ fuse_opendir (xlator_t *this, fuse_in_header_t *finh, void *msg)
GET_STATE (this, finh, state);
+ if (priv->aux_gfid_mount) {
+ ret = fuse_handle_gfiddir_op (this, state, msg, GF_FOP_OPENDIR);
+ if (ret == 0)
+ return;
+ }
+
fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
fuse_resolve_and_resume (state, fuse_opendir_resume);
@@ -2535,14 +3049,14 @@ 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;
+ 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;
@@ -2597,16 +3111,23 @@ fuse_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
continue;
entry->d_stat.ia_blksize = this->ctx->page_size;
- gf_fuse_stat2attr (&entry->d_stat, &feo->attr, priv->enable_ino32);
+ 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);
+ 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);
+ /* we fail opendir on /.gfid and hence there won't
+ * be readdir in that directory.
+ */
+ feo->nodeid = inode_to_fuse_nodeid (this, linked_inode,
+ GF_FUSE_PATH_NAMESPACE);
inode_unref (linked_inode);
@@ -2859,7 +3380,6 @@ fuse_statfs_resume (fuse_state_t *state)
statfs, &state->loc, state->xdata);
}
-
static void
fuse_statfs (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
@@ -2872,10 +3392,363 @@ fuse_statfs (xlator_t *this, fuse_in_header_t *finh, void *msg)
fuse_resolve_and_resume (state, fuse_statfs_resume);
}
+void
+fuse_auxgfid_heal_args_free (fuse_auxgfid_heal_args_t *args)
+{
+ if (args == NULL)
+ goto out;
+
+ GF_FREE (args->bname);
+
+ mem_put (args);
+out:
+ return;
+}
+
+fuse_auxgfid_heal_args_t *
+fuse_auxgfid_heal_parse_args (xlator_t *this, data_t *data)
+{
+ fuse_auxgfid_heal_args_t *args = NULL;
+ fuse_private_t *priv = NULL;
+ void *blob = NULL;
+ int len = 0, blob_len;
+
+ blob = data->data;
+ blob_len = data->len;
+
+ priv = this->private;
+
+ /* bname should at least contain a character */
+ if (blob_len < (sizeof (args->gfid) + 2))
+ goto err;
+
+ args = mem_get0 (priv->auxgfid_heal_args_pool);
+ if (args == NULL)
+ goto err;
+
+ memcpy (args->gfid, blob, sizeof (args->gfid));
+ blob += sizeof (args->gfid);
+ blob_len -= sizeof (args->gfid);
+
+ len = strnlen (blob, blob_len);
+ if (len == blob_len)
+ goto err;
+
+ args->bname = GF_CALLOC (1, len + 1, gf_common_mt_char);
+ if (args->bname == NULL)
+ goto err;
+
+ memcpy (args->bname, blob, len);
+ blob_len -= (len + 1);
+
+ if (blob_len)
+ goto err;
+
+ return args;
+
+err:
+ if (args)
+ fuse_auxgfid_heal_args_free (args);
+
+ return NULL;
+}
+
+static int
+fuse_auxgfid_newentry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno,
+ inode_t *inode, struct iatt *buf,
+ struct iatt *preparent, struct iatt *postparent,
+ dict_t *xdata)
+{
+ /* don't worry about inode linking and other stuff. They'll happen on
+ * the next lookup.
+ */
+ fuse_err_cbk (frame, cookie, this, op_ret, op_errno, xdata);
+
+ return 0;
+}
+
+static int
+fuse_auxgfid_heal_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno,
+ inode_t *inode, struct iatt *stat, dict_t *dict,
+ struct iatt *postparent)
+{
+ /* don't worry about inode linking and other stuff. They'll happen on
+ * the next lookup.
+ */
+ fuse_err_cbk (frame, cookie, this, op_ret, op_errno, NULL);
+ return 0;
+}
+
+void
+fuse_auxgfid_newfile_args_free (fuse_auxgfid_newfile_args_t *args)
+{
+ if (args == NULL)
+ goto out;
+
+ if (args->bname)
+ GF_FREE (args->bname);
+
+ if (S_ISLNK (args->st_mode) && args->args.symlink.linkpath) {
+ GF_FREE (args->args.symlink.linkpath);
+ args->args.symlink.linkpath = NULL;
+ }
+
+ mem_put (args);
+out:
+ return;
+}
+
+fuse_auxgfid_newfile_args_t *
+fuse_auxgfid_newfile_parse_args (xlator_t *this, data_t *data)
+{
+ fuse_auxgfid_newfile_args_t *args = NULL;
+ fuse_private_t *priv = NULL;
+ int len = 0, blob_len = 0;
+ int min_len = 0;
+ void *blob = NULL;
+
+ priv = this->private;
+
+ blob = data->data;
+ blob_len = data->len;
+
+ min_len = sizeof (args->uid) + sizeof (args->gid) + sizeof (args->gfid)
+ + sizeof (args->st_mode) + 2 + 2;
+ if (blob_len < min_len)
+ goto err;
+
+
+ args = mem_get0 (priv->auxgfid_newfile_args_pool);
+ if (args == NULL)
+ goto err;
+
+ args->uid = ntoh32 (*(uint32_t *)blob);
+ blob += sizeof (uint32_t);
+ blob_len -= sizeof (uint32_t);
+
+ args->gid = ntoh32 (*(uint32_t *)blob);
+ blob += sizeof (uint32_t);
+ blob_len -= sizeof (uint32_t);
+
+ memcpy (args->gfid, blob, sizeof (args->gfid));
+ blob += sizeof (args->gfid);
+ blob_len -= sizeof (args->gfid);
+
+ args->st_mode = ntoh32 (*(uint32_t *)blob);
+ blob += sizeof (uint32_t);
+ blob_len -= sizeof (uint32_t);
+
+ len = strnlen (blob, blob_len);
+ if (len == blob_len)
+ goto err;
+
+ args->bname = GF_CALLOC (1, (len + 1), gf_common_mt_char);
+ if (args->bname == NULL)
+ goto err;
+
+ memcpy (args->bname, blob, (len + 1));
+ blob += (len + 1);
+ blob_len -= (len + 1);
+
+ if (S_ISDIR (args->st_mode)) {
+ if (blob_len < sizeof (uint32_t))
+ goto err;
+ args->args.mkdir.mode = ntoh32 (*(uint32_t *)blob);
+ blob += sizeof (uint32_t);
+ blob_len -= sizeof (uint32_t);
+
+ if (blob_len < sizeof (uint32_t))
+ goto err;
+ args->args.mkdir.umask = ntoh32 (*(uint32_t *)blob);
+ blob += sizeof (uint32_t);
+ blob_len -= sizeof (uint32_t);
+ if (blob_len < 0)
+ goto err;
+
+ } else if (S_ISLNK (args->st_mode)) {
+ len = strnlen (blob, blob_len);
+ if (len == blob_len)
+ goto err;
+
+ args->args.symlink.linkpath = GF_CALLOC (1, len + 1,
+ gf_common_mt_char);
+ if (args->args.symlink.linkpath == NULL)
+ goto err;
+
+ memcpy (args->args.symlink.linkpath, blob, (len + 1));
+ blob += (len + 1);
+ blob_len -= (len + 1);
+ } else {
+ if (blob_len < sizeof (uint32_t))
+ goto err;
+ args->args.mknod.mode = ntoh32 (*(uint32_t *)blob);
+ blob += sizeof (uint32_t);
+ blob_len -= sizeof (uint32_t);
+
+ if (blob_len < sizeof (uint32_t))
+ goto err;
+ args->args.mknod.rdev = ntoh32 (*(uint32_t *)blob);
+ blob += sizeof (uint32_t);
+ blob_len -= sizeof (uint32_t);
+
+ if (blob_len < sizeof (uint32_t))
+ goto err;
+ args->args.mknod.umask = ntoh32 (*(uint32_t *)blob);
+ blob += sizeof (uint32_t);
+ blob_len -= sizeof (uint32_t);
+ }
+
+ if (blob_len)
+ goto err;
+
+ return args;
+
+err:
+ if (args)
+ fuse_auxgfid_newfile_args_free (args);
+
+ return NULL;
+}
+
+int
+fuse_auxgfid_loc_fill (fuse_state_t *state, char *gfid, char *bname)
+{
+ inode_t *parent = NULL;
+ int ret = -1;
+
+ parent = inode_ref (state->loc.inode);
+ loc_wipe (&state->loc);
+ state->loc.parent = parent;
+ state->loc.inode = inode_grep (parent->table, parent, bname);
+ if (state->loc.inode == NULL) {
+ state->loc.inode = inode_new (parent->table);
+ if (state->loc.inode == NULL)
+ goto out;
+ }
+
+ loc_path (&state->loc, bname);
+ state->loc.name = basename (state->loc.path);
+
+ if (state->xdata == NULL)
+ state->xdata = dict_new ();
+
+ uuid_parse (gfid, state->gfid);
+ uuid_copy (state->loc.gfid, state->gfid);
+
+ ret = dict_set_static_bin (state->xdata, "gfid-req", state->gfid, 16);
+ if (ret < 0) {
+ gf_log (state->this->name, GF_LOG_WARNING,
+ "SETXATTR %"PRId64"/%s (%s/%s) setting gfid in xdata "
+ "failed. Hence, file created will not have the gfid "
+ "provided (%s)", state->finh->nodeid,
+ bname, uuid_utoa (state->loc.parent->gfid),
+ bname, uuid_utoa (state->gfid));
+ ret = -1;
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+int
+fuse_auxgfid_heal (fuse_state_t *state, data_t *data)
+{
+ fuse_auxgfid_heal_args_t *args = NULL;
+ int ret = -1;
+
+ args = fuse_auxgfid_heal_parse_args (state->this, data);
+
+ gf_log ("glusterfs-fuse", GF_LOG_TRACE,
+ "%"PRIu64": LOOKUP %s", state->finh->unique,
+ state->loc.path);
+
+ ret = fuse_auxgfid_loc_fill (state, args->gfid, args->bname);
+ if (ret < 0) {
+ goto err;
+ }
+
+ FUSE_FOP (state, fuse_auxgfid_heal_cbk, GF_FOP_LOOKUP,
+ lookup, &state->loc, state->xdata);
+
+ fuse_auxgfid_heal_args_free (args);
+
+ return 0;
+
+err:
+ fuse_auxgfid_heal_args_free (args);
+ send_fuse_err (state->this, state->finh, ENOMEM);
+ free_fuse_state (state);
+ return 0;
+}
+
+int
+fuse_auxgfid_newentry (fuse_state_t *state, data_t *data)
+{
+ int ret = 0;
+ fuse_auxgfid_newfile_args_t *args = NULL;
+
+ args = fuse_auxgfid_newfile_parse_args (state->this, data);
+ if (args == NULL) {
+ goto err;
+ }
+
+ state->finh->uid = args->uid;
+ state->finh->gid = args->gid;
+
+ ret = fuse_auxgfid_loc_fill (state, args->gfid, args->bname);
+ if (ret < 0) {
+ goto err;
+ }
+
+ if (S_ISDIR (args->st_mode)) {
+ FUSE_FOP (state, fuse_auxgfid_newentry_cbk,
+ GF_FOP_MKDIR, mkdir, &state->loc,
+ args->args.mkdir.mode, args->args.mkdir.umask,
+ state->xdata);
+ } else if (S_ISLNK (args->st_mode)) {
+ FUSE_FOP (state, fuse_auxgfid_newentry_cbk,
+ GF_FOP_SYMLINK, symlink, args->args.symlink.linkpath,
+ &state->loc, 0, state->xdata);
+ } else {
+ if (S_ISREG (args->st_mode)) {
+ ret = dict_set_uint32 (state->xdata,
+ GLUSTERFS_CREATE_MODE_KEY,
+ args->args.mknod.mode);
+ if (ret < 0) {
+ // failure
+ }
+ args->args.mknod.mode = IA_IFREG;
+ }
+
+ FUSE_FOP (state, fuse_auxgfid_newentry_cbk, GF_FOP_MKNOD,
+ mknod, &state->loc, args->args.mknod.mode,
+ args->args.mknod.rdev, args->args.mknod.umask,
+ state->xdata);
+ }
+
+ fuse_auxgfid_newfile_args_free (args);
+ return 0;
+
+err:
+ fuse_auxgfid_newfile_args_free (args);
+ send_fuse_err (state->this, state->finh, ENOMEM);
+ free_fuse_state (state);
+ return 0;
+}
void
fuse_setxattr_resume (fuse_state_t *state)
{
+ fuse_private_t *priv = NULL;
+ data_t *data = NULL;
+
+ priv = state->this->private;
+
if (!state->loc.inode) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64": SETXATTR %s/%"PRIu64" (%s) "
@@ -2887,6 +3760,20 @@ fuse_setxattr_resume (fuse_state_t *state)
return;
}
+ if (priv->aux_gfid_mount) {
+ data = dict_get (state->xattr, GF_FUSE_AUX_GFID_NEWFILE);
+ if (data != NULL) {
+ fuse_auxgfid_newentry (state, data);
+ return;
+ }
+
+ data = dict_get (state->xattr, GF_FUSE_AUX_GFID_HEAL);
+ if (data != NULL) {
+ fuse_auxgfid_heal (state, data);
+ return;
+ }
+ }
+
#ifdef GF_TEST_FFOP
state->fd = fd_lookup (state->loc.inode, state->finh->pid);
#endif /* GF_TEST_FFOP */
@@ -2914,17 +3801,17 @@ fuse_setxattr_resume (fuse_state_t *state)
static void
fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
- struct fuse_setxattr_in *fsi = msg;
- char *name = (char *)(fsi + 1);
- char *value = name + strlen (name) + 1;
- struct fuse_private *priv = NULL;
-
- fuse_state_t *state = NULL;
- char *dict_value = NULL;
- int32_t ret = -1;
- char *newkey = NULL;
+ struct fuse_setxattr_in *fsi = msg;
+ char *name = (char *)(fsi + 1);
+ char *value = name + strlen (name) + 1;
+ struct fuse_private *priv = NULL;
+ fuse_state_t *state = NULL;
+ char *dict_value = NULL;
+ int32_t ret = -1;
+ char *newkey = NULL;
priv = this->private;
+ GET_STATE (this, finh, state);
#ifdef GF_DARWIN_HOST_OS
if (fsi->position) {
@@ -2938,6 +3825,13 @@ fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
}
#endif
+ if (priv->aux_gfid_mount) {
+ ret = fuse_handle_gfiddir_op (this, state, msg,
+ GF_FOP_SETXATTR);
+ if (ret == 0)
+ return;
+ }
+
if (fuse_ignore_xattr_set (priv, name)) {
(void) send_fuse_err (this, finh, 0);
return;
@@ -2984,7 +3878,6 @@ fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
return;
}
- GET_STATE (this, finh, state);
state->size = fsi->size;
fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
@@ -3249,15 +4142,15 @@ 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;
+ char *newkey = NULL;
priv = this->private;
+ GET_STATE (this, finh, state);
#ifdef GF_DARWIN_HOST_OS
if (fgxi->position) {
@@ -3279,6 +4172,12 @@ fuse_getxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
}
#endif
+ if (priv->aux_gfid_mount) {
+ rv = fuse_handle_gfiddir_op (this, state, msg, GF_FOP_GETXATTR);
+ if (rv == 0)
+ return;
+ }
+
if (!priv->acl) {
if ((strcmp (name, "system.posix_acl_access") == 0) ||
(strcmp (name, "system.posix_acl_default") == 0)) {
@@ -3296,8 +4195,6 @@ fuse_getxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
}
}
- GET_STATE (this, finh, state);
-
fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
rv = fuse_flip_xattr_ns (priv, name, &newkey);
@@ -3355,11 +4252,22 @@ fuse_listxattr_resume (fuse_state_t *state)
static void
fuse_listxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
- struct fuse_getxattr_in *fgxi = msg;
- fuse_state_t *state = NULL;
+ struct fuse_getxattr_in *fgxi = msg;
+ fuse_state_t *state = NULL;
+ fuse_private_t *priv = NULL;
+ int ret = -1;
GET_STATE (this, finh, state);
+ priv = this->private;
+
+ if (priv->aux_gfid_mount) {
+ ret = fuse_handle_gfiddir_op (this, state, msg,
+ GF_FOP_GETXATTR);
+ if (ret == 0)
+ return;
+ }
+
fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
state->size = fgxi->size;
@@ -3410,12 +4318,11 @@ fuse_removexattr_resume (fuse_state_t *state)
static void
fuse_removexattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
{
- char *name = msg;
-
- fuse_state_t *state = NULL;
- fuse_private_t *priv = NULL;
- int32_t ret = -1;
- char *newkey = NULL;
+ char *name = msg;
+ fuse_state_t *state = NULL;
+ fuse_private_t *priv = NULL;
+ int32_t ret = -1;
+ char *newkey = NULL;
if (!strcmp (GFID_XATTR_KEY, name)) {
send_fuse_err (this, finh, EPERM);
@@ -3427,6 +4334,13 @@ fuse_removexattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
GET_STATE (this, finh, state);
+ if (priv->aux_gfid_mount) {
+ ret = fuse_handle_gfiddir_op (this, state, msg,
+ GF_FOP_REMOVEXATTR);
+ if (ret == 0)
+ return;
+ }
+
fuse_resolve_inode_init (state, &state->resolve, finh->nodeid);
ret = fuse_flip_xattr_ns (priv, name, &newkey);
@@ -5121,6 +6035,31 @@ init (xlator_t *this_xl)
GF_OPTION_INIT ("selinux", priv->selinux, bool, cleanup_exit);
+
+#ifdef GF_LINUX_HOST_OS
+ GF_OPTION_INIT ("auxiliary-gfid-mount", priv->aux_gfid_mount, bool,
+ cleanup_exit);
+#endif
+
+ if (priv->aux_gfid_mount) {
+ priv->fuse_nodeid_pool = mem_pool_new (gf_fuse_nodeid_t, 2048);
+ if (priv->fuse_nodeid_pool == NULL) {
+ goto cleanup_exit;
+ }
+
+ priv->auxgfid_newfile_args_pool
+ = mem_pool_new (fuse_auxgfid_newfile_args_t, 2048);
+ if (priv->auxgfid_newfile_args_pool == NULL) {
+ goto cleanup_exit;
+ }
+
+ priv->auxgfid_heal_args_pool
+ = mem_pool_new (fuse_auxgfid_heal_args_t, 2048);
+ if (priv->auxgfid_heal_args_pool == NULL) {
+ goto cleanup_exit;
+ }
+ }
+
GF_OPTION_INIT ("read-only", priv->read_only, bool, cleanup_exit);
GF_OPTION_INIT ("enable-ino32", priv->enable_ino32, bool, cleanup_exit);
@@ -5284,6 +6223,16 @@ cleanup_exit:
close (priv->fd);
if (priv->fuse_dump_fd != -1)
close (priv->fuse_dump_fd);
+
+ if (priv->fuse_nodeid_pool != NULL)
+ mem_pool_destroy (priv->fuse_nodeid_pool);
+
+ if (priv->auxgfid_newfile_args_pool != NULL)
+ mem_pool_destroy (priv->auxgfid_newfile_args_pool);
+
+ if (priv->auxgfid_heal_args_pool != NULL)
+ mem_pool_destroy (priv->auxgfid_heal_args_pool);
+
GF_FREE (priv);
}
GF_FREE (mnt_args);
@@ -5324,6 +6273,7 @@ struct xlator_fops fops;
struct xlator_cbks cbks = {
.invalidate = fuse_invalidate,
+ .forget = fuse_xlator_forget,
};
@@ -5410,5 +6360,13 @@ struct volume_options options[] = {
.type = GF_OPTION_TYPE_BOOL,
.default_value = "no"
},
+#ifdef GF_LINUX_HOST_OS
+ { .key = {"auxiliary-gfid-mount"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
+ .description = "an option which makes the mount point allow "
+ "access to gfid directly",
+ },
+#endif
{ .key = {NULL} },
};