summaryrefslogtreecommitdiffstats
path: root/xlators/mount/fuse/src/fuse-resolve.c
diff options
context:
space:
mode:
authorAnand Avati <avati@redhat.com>2012-01-30 15:03:56 +0530
committerAnand Avati <avati@gluster.com>2012-02-08 03:13:08 -0800
commit8e81cbacc53adc77bc4eabb5a26d6d13012f5f86 (patch)
tree4788e3a14fb2d276689c4423cc7542f0d72c3348 /xlators/mount/fuse/src/fuse-resolve.c
parentaec6d5d89249868dc99d8fb432d8ab120bb38ef1 (diff)
fuse: fix resolver to handle graph switches properly
perform resolution on the latest graph by caching it in state->itable and use fuse_nodeid as just a hint to the possible final resolved inode (in case it was resolved off the latest graph). GFID is the primary key for resolving inodes on the latest graph. Change-Id: I3921c6f59c9ff80e4ff076bec3bd334423fc36cc BUG: 785675 Reviewed-on: http://review.gluster.com/2703 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Amar Tumballi <amar@gluster.com> Reviewed-by: Anand Avati <avati@gluster.com>
Diffstat (limited to 'xlators/mount/fuse/src/fuse-resolve.c')
-rw-r--r--xlators/mount/fuse/src/fuse-resolve.c431
1 files changed, 183 insertions, 248 deletions
diff --git a/xlators/mount/fuse/src/fuse-resolve.c b/xlators/mount/fuse/src/fuse-resolve.c
index 755e2f429f1..1af80b93c57 100644
--- a/xlators/mount/fuse/src/fuse-resolve.c
+++ b/xlators/mount/fuse/src/fuse-resolve.c
@@ -46,8 +46,11 @@ fuse_resolve_loc_touchup (fuse_state_t *state)
if (!loc->path) {
if (loc->parent && resolve->bname) {
ret = inode_path (loc->parent, resolve->bname, &path);
+ uuid_copy (loc->pargfid, loc->parent->gfid);
+ loc->name = resolve->bname;
} else if (loc->inode) {
ret = inode_path (loc->inode, NULL, &path);
+ uuid_copy (loc->gfid, loc->inode->gfid);
}
if (ret)
gf_log (THIS->name, GF_LOG_TRACE,
@@ -60,10 +63,10 @@ fuse_resolve_loc_touchup (fuse_state_t *state)
int
-fuse_resolve_gfid_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int op_ret, int op_errno, inode_t *inode,
- struct iatt *buf, dict_t *xattr,
- struct iatt *postparent)
+fuse_resolve_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, inode_t *inode,
+ struct iatt *buf, dict_t *xattr,
+ struct iatt *postparent)
{
fuse_state_t *state = NULL;
fuse_resolve_t *resolve = NULL;
@@ -88,13 +91,7 @@ fuse_resolve_gfid_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
link_inode = inode_link (inode, resolve_loc->parent,
resolve_loc->name, buf);
- if (!link_inode)
- goto out;
-
- inode_lookup (link_inode);
-
- inode_unref (link_inode);
-
+ state->loc_now->inode = link_inode;
out:
loc_wipe (resolve_loc);
@@ -104,6 +101,30 @@ out:
int
+fuse_resolve_entry (fuse_state_t *state)
+{
+ fuse_resolve_t *resolve = NULL;
+ loc_t *resolve_loc = NULL;
+
+ resolve = state->resolve_now;
+ resolve_loc = &resolve->resolve_loc;
+
+ resolve_loc->parent = inode_ref (state->loc_now->parent);
+ uuid_copy (resolve_loc->pargfid, state->loc_now->pargfid);
+ resolve_loc->name = resolve->bname;
+ resolve_loc->inode = inode_new (state->itable);
+
+ inode_path (resolve_loc->parent, resolve_loc->name,
+ (char **) &resolve_loc->path);
+
+ FUSE_FOP (state, fuse_resolve_entry_cbk, GF_FOP_LOOKUP,
+ lookup, resolve_loc, NULL);
+
+ return 0;
+}
+
+
+int
fuse_resolve_gfid_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int op_ret, int op_errno, inode_t *inode, struct iatt *buf,
dict_t *xattr, struct iatt *postparent)
@@ -111,11 +132,11 @@ fuse_resolve_gfid_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
fuse_state_t *state = NULL;
fuse_resolve_t *resolve = NULL;
inode_t *link_inode = NULL;
- loc_t *resolve_loc = NULL;
+ loc_t *loc_now = NULL;
state = frame->root->state;
resolve = state->resolve_now;
- resolve_loc = &resolve->resolve_loc;
+ loc_now = state->loc_now;
STACK_DESTROY (frame->root);
@@ -123,36 +144,27 @@ fuse_resolve_gfid_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
gf_log (this->name, ((op_errno == ENOENT) ? GF_LOG_DEBUG :
GF_LOG_WARNING),
"%s: failed to resolve (%s)",
- uuid_utoa (resolve_loc->gfid), strerror (op_errno));
+ uuid_utoa (resolve->resolve_loc.gfid),
+ strerror (op_errno));
loc_wipe (&resolve->resolve_loc);
goto out;
}
- loc_wipe (resolve_loc);
+ loc_wipe (&resolve->resolve_loc);
link_inode = inode_link (inode, NULL, NULL, buf);
if (!link_inode)
goto out;
- inode_lookup (link_inode);
-
- if (uuid_is_null (resolve->pargfid)) {
- inode_unref (link_inode);
- goto out;
- }
-
- resolve_loc->parent = link_inode;
- uuid_copy (resolve_loc->pargfid, resolve_loc->parent->gfid);
+ if (!uuid_is_null (resolve->gfid)) {
+ loc_now->inode = link_inode;
+ goto out;
+ }
- resolve_loc->name = resolve->bname;
-
- resolve_loc->inode = inode_new (state->itable);
- inode_path (resolve_loc->parent, resolve_loc->name,
- (char **) &resolve_loc->path);
+ loc_now->parent = link_inode;
- FUSE_FOP (state, fuse_resolve_gfid_entry_cbk, GF_FOP_LOOKUP,
- lookup, &resolve->resolve_loc, NULL);
+ fuse_resolve_entry (state);
return 0;
out:
@@ -173,15 +185,14 @@ fuse_resolve_gfid (fuse_state_t *state)
if (!uuid_is_null (resolve->pargfid)) {
uuid_copy (resolve_loc->gfid, resolve->pargfid);
- resolve_loc->inode = inode_new (state->itable);
- ret = inode_path (resolve_loc->inode, NULL,
- (char **)&resolve_loc->path);
} else if (!uuid_is_null (resolve->gfid)) {
uuid_copy (resolve_loc->gfid, resolve->gfid);
- resolve_loc->inode = inode_new (state->itable);
- ret = inode_path (resolve_loc->inode, NULL,
- (char **)&resolve_loc->path);
}
+
+ resolve_loc->inode = inode_new (state->itable);
+ ret = inode_path (resolve_loc->inode, NULL,
+ (char **)&resolve_loc->path);
+
if (ret <= 0) {
gf_log (THIS->name, GF_LOG_WARNING,
"failed to get the path from inode %s",
@@ -189,122 +200,83 @@ fuse_resolve_gfid (fuse_state_t *state)
}
FUSE_FOP (state, fuse_resolve_gfid_cbk, GF_FOP_LOOKUP,
- lookup, &resolve->resolve_loc, NULL);
-
- return 0;
-}
-
-
-int
-fuse_resolve_continue (fuse_state_t *state)
-{
- fuse_resolve_t *resolve = NULL;
- int ret = 0;
-
- resolve = state->resolve_now;
-
- resolve->op_ret = 0;
- resolve->op_errno = 0;
-
- /* TODO: should we handle 'fd' here ? */
- if (!uuid_is_null (resolve->pargfid))
- ret = fuse_resolve_entry_simple (state);
- else if (!uuid_is_null (resolve->gfid))
- ret = fuse_resolve_inode_simple (state);
- if (ret)
- gf_log (THIS->name, GF_LOG_DEBUG,
- "return value of resolve_*_simple %d", ret);
-
- fuse_resolve_loc_touchup (state);
-
- fuse_resolve_all (state);
+ lookup, resolve_loc, NULL);
return 0;
}
/*
- Check if the requirements are fulfilled by entries in the inode cache itself
- Return value:
- <= 0 - simple resolution was decisive and complete (either success or failure)
- > 0 - indecisive, need to perform deep resolution
-*/
+ * Return value:
+ * 0 - resolved parent and entry (as necessary)
+ * -1 - resolved parent but not entry (though necessary)
+ * 1 - resolved neither parent nor entry
+ */
int
-fuse_resolve_entry_simple (fuse_state_t *state)
+fuse_resolve_parent_simple (fuse_state_t *state)
{
fuse_resolve_t *resolve = NULL;
- inode_t *parent = NULL;
- inode_t *inode = NULL;
- int ret = 0;
+ loc_t *loc = NULL;
+ inode_t *parent = NULL;
+ inode_t *inode = NULL;
resolve = state->resolve_now;
+ loc = state->loc_now;
- parent = inode_find (state->itable, resolve->pargfid);
- if (!parent) {
- /* simple resolution is indecisive. need to perform
- deep resolution */
- resolve->op_ret = -1;
- resolve->op_errno = ENOENT;
- ret = 1;
- goto out;
- }
-
- /* expected @parent was found from the inode cache */
- if (state->loc_now->parent) {
- inode_unref (state->loc_now->parent);
- }
-
- state->loc_now->parent = inode_ref (parent);
+ loc->name = resolve->bname;
- inode = inode_grep (state->itable, parent, resolve->bname);
- if (!inode) {
- resolve->op_ret = -1;
- resolve->op_errno = ENOENT;
- ret = 1;
- goto out;
- }
-
- ret = 0;
-
- if (state->loc_now->inode) {
- inode_unref (state->loc_now->inode);
- state->loc_now->inode = NULL;
- }
+ parent = resolve->parhint;
+ if (parent->table == state->itable) {
+ /* no graph switches since */
+ loc->parent = inode_ref (parent);
+ loc->inode = inode_grep (state->itable, parent, loc->name);
+ /* decisive result - resolution success */
+ return 0;
+ }
- state->loc_now->inode = inode_ref (inode);
- uuid_copy (state->loc_now->gfid, resolve->gfid);
-
-out:
- if (parent)
- inode_unref (parent);
-
- if (inode)
- inode_unref (inode);
-
- return ret;
+ parent = inode_find (state->itable, resolve->pargfid);
+ if (!parent) {
+ resolve->op_ret = -1;
+ resolve->op_errno = ENOENT;
+ /* non decisive result - parent missing */
+ return 1;
+ }
+
+ loc->parent = parent;
+
+ inode = inode_grep (state->itable, parent, loc->name);
+ if (inode) {
+ loc->inode = inode;
+ /* decisive result - resolution success */
+ return 0;
+ }
+
+ /* non decisive result - entry missing */
+ return -1;
}
int
-fuse_resolve_entry (fuse_state_t *state)
+fuse_resolve_parent (fuse_state_t *state)
{
int ret = 0;
loc_t *loc = NULL;
loc = state->loc_now;
- ret = fuse_resolve_entry_simple (state);
+ ret = fuse_resolve_parent_simple (state);
if (ret > 0) {
- loc_wipe (loc);
fuse_resolve_gfid (state);
return 0;
}
- if (ret == 0)
- fuse_resolve_loc_touchup (state);
+ if (ret < 0) {
+ fuse_resolve_entry (state);
+ return 0;
+ }
- fuse_resolve_all (state);
+ fuse_resolve_continue (state);
return 0;
}
@@ -314,33 +286,29 @@ int
fuse_resolve_inode_simple (fuse_state_t *state)
{
fuse_resolve_t *resolve = NULL;
- inode_t *inode = NULL;
- int ret = 0;
+ loc_t *loc = NULL;
+ inode_t *inode = NULL;
resolve = state->resolve_now;
+ loc = state->loc_now;
- inode = inode_find (state->itable, resolve->gfid);
- if (!inode) {
- resolve->op_ret = -1;
- resolve->op_errno = ENOENT;
- ret = 1;
- goto out;
- }
-
- ret = 0;
-
- if (state->loc_now->inode) {
- inode_unref (state->loc_now->inode);
- }
-
- state->loc_now->inode = inode_ref (inode);
- uuid_copy (state->loc_now->gfid, resolve->gfid);
+ inode = resolve->hint;
+ if (inode->table == state->itable) {
+ inode_ref (inode);
+ goto found;
+ }
-out:
+ inode = inode_find (state->itable, resolve->gfid);
if (inode)
- inode_unref (inode);
+ goto found;
- return ret;
+ resolve->op_ret = -1;
+ resolve->op_errno = ENOENT;
+
+ return 1;
+found:
+ loc->inode = inode;
+ return 0;
}
@@ -355,15 +323,11 @@ fuse_resolve_inode (fuse_state_t *state)
ret = fuse_resolve_inode_simple (state);
if (ret > 0) {
- loc_wipe (loc);
fuse_resolve_gfid (state);
return 0;
}
- if (ret == 0)
- fuse_resolve_loc_touchup (state);
-
- fuse_resolve_all (state);
+ fuse_resolve_continue (state);
return 0;
}
@@ -372,46 +336,87 @@ static int
fuse_resolve_fd (fuse_state_t *state)
{
fuse_resolve_t *resolve = NULL;
- fd_t *fd = NULL;
- int ret = 0;
- uint64_t tmp_fd_ctx = 0;
- char *path = NULL;
- char *name = NULL;
+ fd_t *fd = NULL;
+ xlator_t *active_subvol = NULL;
resolve = state->resolve_now;
fd = resolve->fd;
+ active_subvol = fd->inode->table->xl;
- ret = fd_ctx_get (fd, state->this, &tmp_fd_ctx);
- if (!ret) {
- state->fd = (fd_t *)(long)tmp_fd_ctx;
- fd_ref (state->fd);
- fuse_resolve_all (state);
+ state->active_subvol = active_subvol;
+
+ fuse_resolve_continue (state);
+
+ return 0;
+}
+
+
+int
+fuse_gfid_set (fuse_state_t *state)
+{
+ int ret = 0;
+
+ if (uuid_is_null (state->gfid))
+ goto out;
+
+ if (!state->dict)
+ state->dict = dict_new ();
+
+ if (!state->dict) {
+ ret = -1;
goto out;
}
- ret = inode_path (fd->inode, 0, &path);
- if (ret <= 0)
- gf_log ("", GF_LOG_WARNING,
- "failed to do inode-path on fd %d %s", ret, path);
+ ret = dict_set_static_bin (state->dict, "gfid-req",
+ state->gfid, sizeof (state->gfid));
+out:
+ return ret;
+}
- name = strrchr (path, '/');
- if (name)
- name++;
- resolve->path = path;
- resolve->bname = gf_strdup (name);
+int
+fuse_resolve_entry_init (fuse_state_t *state, fuse_resolve_t *resolve,
+ ino_t par, char *name)
+{
+ inode_t *parent = NULL;
- state->loc_now = &state->loc;
+ parent = fuse_ino_to_inode (par, state->this);
+ uuid_copy (resolve->pargfid, parent->gfid);
+ resolve->parhint = parent;
+ resolve->bname = gf_strdup (name);
-out:
- return 0;
+ return 0;
+}
+
+
+int
+fuse_resolve_inode_init (fuse_state_t *state, fuse_resolve_t *resolve,
+ ino_t ino)
+{
+ inode_t *inode = NULL;
+
+ inode = fuse_ino_to_inode (ino, state->this);
+ uuid_copy (resolve->gfid, inode->gfid);
+ resolve->hint = inode;
+
+ return 0;
+}
+
+
+int
+fuse_resolve_fd_init (fuse_state_t *state, fuse_resolve_t *resolve,
+ fd_t *fd)
+{
+ resolve->fd = fd_ref (fd);
+
+ return 0;
}
static int
fuse_resolve (fuse_state_t *state)
- {
+{
fuse_resolve_t *resolve = NULL;
resolve = state->resolve_now;
@@ -422,7 +427,7 @@ fuse_resolve (fuse_state_t *state)
} else if (!uuid_is_null (resolve->pargfid)) {
- fuse_resolve_entry (state);
+ fuse_resolve_parent (state);
} else if (!uuid_is_null (resolve->gfid)) {
@@ -445,17 +450,10 @@ fuse_resolve_done (fuse_state_t *state)
{
fuse_resume_fn_t fn = NULL;
- if (state->resolve.op_ret || state->resolve2.op_ret) {
- send_fuse_err (state->this, state->finh,
- state->resolve.op_errno);
- free_fuse_state (state);
- goto out;
- }
fn = state->resume_fn;
- if (fn)
- fn (state);
-out:
+ fn (state);
+
return 0;
}
@@ -495,87 +493,24 @@ fuse_resolve_all (fuse_state_t *state)
int
-fuse_gfid_set (fuse_state_t *state)
+fuse_resolve_continue (fuse_state_t *state)
{
- int ret = 0;
-
- if (uuid_is_null (state->gfid))
- goto out;
-
- if (!state->dict)
- state->dict = dict_new ();
+ fuse_resolve_loc_touchup (state);
- if (!state->dict) {
- ret = -1;
- goto out;
- }
+ fuse_resolve_all (state);
- ret = dict_set_static_bin (state->dict, "gfid-req",
- state->gfid, sizeof (state->gfid));
-out:
- return ret;
+ return 0;
}
int
fuse_resolve_and_resume (fuse_state_t *state, fuse_resume_fn_t fn)
{
- xlator_t *inode_xl = NULL;
- xlator_t *active_xl = NULL;
-
fuse_gfid_set (state);
state->resume_fn = fn;
- active_xl = fuse_active_subvol (state->this);
- inode_xl = fuse_state_subvol (state);
- if (!inode_xl && state->loc.parent)
- inode_xl = state->loc.parent->table->xl;
-
- /* If inode or fd is already in new graph, goto resume */
- if (inode_xl == active_xl) {
- /* Lets move to resume if there is no other inode to check */
- if (!(state->loc2.parent || state->loc2.inode))
- goto resume;
-
- inode_xl = NULL;
- /* We have to make sure both inodes we are
- working on are in same inode table */
- if (state->loc2.inode)
- inode_xl = state->loc2.inode->table->xl;
- if (!inode_xl && state->loc2.parent)
- inode_xl = state->loc2.parent->table->xl;
-
- if (inode_xl == active_xl)
- goto resume;
- }
-
-
- /* If the resolve is for 'fd' and its open with 'write' flag
- set, don't switch to new graph yet */
-
- /* TODO: fix it later */
- /* if (state->fd && ((state->fd->flags & O_RDWR) ||
- (state->fd->flags & O_WRONLY)))
- */
- if (state->fd)
- goto resume;
-
- /*
- if (state->fd) {
- state->resolve.fd = state->fd;
- state->fd = NULL; // TODO: we may need a 'fd_unref()' here, not very sure'
- }
- */
-
- /* now we have to resolve the inode to 'itable' */
- state->itable = active_xl->itable;
-
fuse_resolve_all (state);
return 0;
-resume:
- fn (state);
-
- return 0;
}