summaryrefslogtreecommitdiffstats
path: root/xlators/mount
diff options
context:
space:
mode:
authorMohammed Rafi KC <rkavunga@redhat.com>2015-10-05 21:36:14 +0530
committerDan Lambright <dlambrig@redhat.com>2015-10-08 09:13:35 -0700
commit0ca5e92cffa5575984e87485ee4128eb8a72a02a (patch)
tree95988660f9433fc41be473bdddb9f676603a554b /xlators/mount
parent565300b1f3c67ff69fd878f50e9a0a09b85e7bae (diff)
fuse: resolve complete path after a graph switch
If a graph switch has happended as part of a attach-tier, then there is a chance to hash fops to newly added brick before fix-layout. This causes on going i/o to fail. This patch will resolve a path, for graph switch by sending recursive lookup to the parent directories. Those lookups will help to heal the directory. backport of> >Change-Id: Ia2bb4b43a21e5cc6875ba1205628744c3f0ce4e5 >BUG: 1263549 >Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com> >Reviewed-on: http://review.gluster.org/12184 >Tested-by: NetBSD Build System <jenkins@build.gluster.org> >Tested-by: Dan Lambright <dlambrig@redhat.com> >Reviewed-by: Dan Lambright <dlambrig@redhat.com> (cherry picked from commit d0edb6d555d687f76837515207b9408be0bdd55e) Change-Id: Ie92cecd5e77178d227ef21242cd0e1af0fe9ee72 BUG: 1259081 Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com> Reviewed-on: http://review.gluster.org/12319 Tested-by: NetBSD Build System <jenkins@build.gluster.org> Reviewed-by: Dan Lambright <dlambrig@redhat.com> Tested-by: Dan Lambright <dlambrig@redhat.com>
Diffstat (limited to 'xlators/mount')
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.c49
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.h7
-rw-r--r--xlators/mount/fuse/src/fuse-resolve.c113
3 files changed, 153 insertions, 16 deletions
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
index 12d1104d14a..041997151c6 100644
--- a/xlators/mount/fuse/src/fuse-bridge.c
+++ b/xlators/mount/fuse/src/fuse-bridge.c
@@ -4150,18 +4150,21 @@ fuse_first_lookup (xlator_t *this)
int
-fuse_nameless_lookup (xlator_t *xl, uuid_t gfid, loc_t *loc)
+fuse_nameless_lookup (xlator_t *xl, uuid_t gfid, loc_t *loc,
+ gf_boolean_t resolve_path)
{
int ret = -1;
dict_t *xattr_req = NULL;
struct iatt iatt = {0, };
inode_t *linked_inode = NULL;
+ inode_t *inode = NULL;
+ char *path = NULL;
+ dict_t *xattr_ret = NULL;
if ((loc == NULL) || (xl == NULL)) {
ret = -EINVAL;
goto out;
}
-
if (loc->inode == NULL) {
loc->inode = inode_new (xl->itable);
if (loc->inode == NULL) {
@@ -4171,6 +4174,9 @@ fuse_nameless_lookup (xlator_t *xl, uuid_t gfid, loc_t *loc)
}
gf_uuid_copy (loc->gfid, gfid);
+ if (gf_uuid_is_null (loc->gfid)) {
+ goto out;
+ }
xattr_req = dict_new ();
if (xattr_req == NULL) {
@@ -4178,20 +4184,42 @@ fuse_nameless_lookup (xlator_t *xl, uuid_t gfid, loc_t *loc)
goto out;
}
- ret = syncop_lookup (xl, loc, &iatt, NULL, xattr_req, NULL);
+ if (resolve_path) {
+ /*
+ * setting virtual xattr glusterfs.ancestry.path to get
+ * the path of the parent directory.
+ */
+ ret = dict_set_int32 (xattr_req, GET_ANCESTRY_PATH_KEY, 42);
+ if (ret)
+ goto out;
+ }
+
+ ret = syncop_lookup (xl, loc, &iatt, NULL, xattr_req, &xattr_ret);
if (ret < 0)
goto out;
- linked_inode = inode_link (loc->inode, NULL, NULL, &iatt);
- inode_unref (loc->inode);
- loc->inode = linked_inode;
-
+ if (resolve_path) {
+ ret = dict_get_str (xattr_ret, GET_ANCESTRY_PATH_KEY, &path);
+ }
+ if (path) {
+ inode = loc->inode;
+ loc->inode = fuse_resolve_path (xl, path);
+ inode_unref (inode);
+ } else {
+ linked_inode = inode_link (loc->inode, NULL, NULL, &iatt);
+ inode_unref (loc->inode);
+ loc->inode = linked_inode;
+ }
ret = 0;
out:
if (xattr_req != NULL) {
dict_unref (xattr_req);
}
+ if (xattr_ret) {
+ dict_unref (xattr_ret);
+ }
+
return ret;
}
@@ -4222,8 +4250,13 @@ fuse_migrate_fd_open (xlator_t *this, fd_t *basefd, fd_t *oldfd,
loc.inode = inode_find (new_subvol->itable, basefd->inode->gfid);
if (loc.inode == NULL) {
+
+ /* setting the get_resolve_path to send lookup
+ * on parent directories
+ * */
+
ret = fuse_nameless_lookup (new_subvol, basefd->inode->gfid,
- &loc);
+ &loc, _gf_true);
if (ret < 0) {
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"name-less lookup of gfid (%s) failed (%s)"
diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h
index bc5ea2cd4d3..01a7a971dd0 100644
--- a/xlators/mount/fuse/src/fuse-bridge.h
+++ b/xlators/mount/fuse/src/fuse-bridge.h
@@ -406,6 +406,9 @@ int fuse_flip_xattr_ns (struct fuse_private *priv, char *okey, char **nkey);
fuse_fd_ctx_t * __fuse_fd_ctx_check_n_create (xlator_t *this, fd_t *fd);
fuse_fd_ctx_t * fuse_fd_ctx_check_n_create (xlator_t *this, fd_t *fd);
+inode_t*
+fuse_resolve_path (xlator_t *this, char *path);
+
int fuse_resolve_and_resume (fuse_state_t *state, fuse_resume_fn_t fn);
int fuse_resolve_inode_init (fuse_state_t *state, fuse_resolve_t *resolve,
ino_t ino);
@@ -413,6 +416,10 @@ int fuse_resolve_entry_init (fuse_state_t *state, fuse_resolve_t *resolve,
ino_t par, char *name);
int fuse_resolve_fd_init (fuse_state_t *state, fuse_resolve_t *resolve,
fd_t *fd);
+int
+fuse_nameless_lookup (xlator_t *xl, uuid_t gfid, loc_t *loc,
+ gf_boolean_t resolve_path);
+
int fuse_ignore_xattr_set (fuse_private_t *priv, char *key);
void fuse_fop_resume (fuse_state_t *state);
int dump_history_fuse (circular_buffer_t *cb, void *data);
diff --git a/xlators/mount/fuse/src/fuse-resolve.c b/xlators/mount/fuse/src/fuse-resolve.c
index a670f4f6dac..474dace5c04 100644
--- a/xlators/mount/fuse/src/fuse-resolve.c
+++ b/xlators/mount/fuse/src/fuse-resolve.c
@@ -82,16 +82,36 @@ out:
int
-fuse_resolve_entry (fuse_state_t *state)
+fuse_resolve_entry (fuse_state_t *state, gf_boolean_t resolve_path)
{
- fuse_resolve_t *resolve = NULL;
- loc_t *resolve_loc = NULL;
+ fuse_resolve_t *resolve = NULL;
+ loc_t *resolve_loc = NULL;
+ loc_t tmp_loc = {0, };
+ uuid_t gfid = {0, };
+ inode_t *parent = NULL;
resolve = state->resolve_now;
resolve_loc = &resolve->resolve_loc;
- resolve_loc->parent = inode_ref (state->loc_now->parent);
+ parent = resolve->parhint ? resolve->parhint : resolve->hint;
+
gf_uuid_copy (resolve_loc->pargfid, state->loc_now->pargfid);
+
+ if (parent && parent->table != state->itable && resolve_path) {
+ /* graph switch happened */
+ if (!gf_uuid_is_null (resolve->pargfid)) {
+ gf_uuid_copy (gfid, resolve->pargfid);
+ } else if (!gf_uuid_is_null (resolve->gfid)) {
+ gf_uuid_copy (gfid, resolve->gfid);
+ }
+
+ /* sending lookup on parent directories */
+ fuse_nameless_lookup (state->active_subvol,
+ gfid,
+ &tmp_loc, _gf_true);
+ }
+
+ resolve_loc->parent = inode_ref (state->loc_now->parent);
resolve_loc->name = resolve->bname;
resolve_loc->inode = inode_new (state->itable);
@@ -113,7 +133,7 @@ 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 *loc_now = NULL;
+ loc_t *loc_now = NULL;
state = frame->root->state;
resolve = state->resolve_now;
@@ -160,7 +180,7 @@ fuse_resolve_gfid_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
loc_now->parent = link_inode;
gf_uuid_copy (loc_now->pargfid, link_inode->gfid);
- fuse_resolve_entry (state);
+ fuse_resolve_entry (state, _gf_false);
return 0;
out:
@@ -168,6 +188,73 @@ out:
return 0;
}
+inode_t*
+fuse_resolve_path (xlator_t *this, char *path)
+{
+ int ret = -1;
+ dict_t *xattr_req = NULL;
+ struct iatt iatt = {0, };
+ inode_t *linked_inode = NULL;
+ loc_t loc = {0, };
+ char *bname = NULL;
+ char *save_ptr = NULL;
+ uuid_t gfid = {0, };
+ char *tmp_path = NULL;
+
+
+ tmp_path = gf_strdup (path);
+
+ memset (gfid, 0, 16);
+ gfid[15] = 1;
+
+ gf_uuid_copy (loc.pargfid, gfid);
+ loc.parent = inode_ref (this->itable->root);
+
+ xattr_req = dict_new ();
+ if (xattr_req == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ bname = strtok_r (tmp_path, "/", &save_ptr);
+
+ /* sending a lookup on parent directory,
+ * Eg: if path is like /a/b/c/d/e/f/g/
+ * then we will send a lookup on a first and then b,c,d,etc
+ */
+
+ while (bname) {
+ loc.inode = inode_grep (this->itable, loc.parent, bname);
+ if (loc.inode == NULL) {
+ loc.inode = inode_new (this->itable);
+ if (loc.inode == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+
+ loc.name = bname;
+ ret = loc_path (&loc, bname);
+
+ ret = syncop_lookup (this, &loc, &iatt, NULL, xattr_req, NULL);
+ if (ret)
+ goto out;
+
+ linked_inode = inode_link (loc.inode, loc.parent, bname, &iatt);
+ if (!linked_inode)
+ goto out;
+
+ loc_wipe (&loc);
+ gf_uuid_copy (loc.pargfid, linked_inode->gfid);
+ loc.inode = NULL;
+ loc.parent = linked_inode;
+
+ bname = strtok_r (NULL, "/", &save_ptr);
+ }
+ return linked_inode;
+out:
+ return NULL;
+}
int
fuse_resolve_gfid (fuse_state_t *state)
@@ -175,10 +262,13 @@ fuse_resolve_gfid (fuse_state_t *state)
fuse_resolve_t *resolve = NULL;
loc_t *resolve_loc = NULL;
int ret = 0;
+ loc_t tmp_loc = {0, };
+ inode_t *inode = NULL;
resolve = state->resolve_now;
resolve_loc = &resolve->resolve_loc;
+
if (!gf_uuid_is_null (resolve->pargfid)) {
gf_uuid_copy (resolve_loc->gfid, resolve->pargfid);
} else if (!gf_uuid_is_null (resolve->gfid)) {
@@ -190,14 +280,21 @@ fuse_resolve_gfid (fuse_state_t *state)
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);
+ ret = loc_path (resolve_loc, NULL);
if (ret <= 0) {
gf_log (THIS->name, GF_LOG_WARNING,
"failed to get the path for inode %s",
uuid_utoa (resolve->gfid));
}
+ inode = resolve->parhint ? resolve->parhint : resolve->hint;
+ if (inode && inode->table != state->itable) {
+ /* sending lookup on parent directories */
+ fuse_nameless_lookup (state->active_subvol, resolve_loc->gfid,
+ &tmp_loc, _gf_true);
+ }
+
FUSE_FOP (state, fuse_resolve_gfid_cbk, GF_FOP_LOOKUP,
lookup, resolve_loc, NULL);
@@ -288,7 +385,7 @@ fuse_resolve_parent (fuse_state_t *state)
}
if (ret < 0) {
- fuse_resolve_entry (state);
+ fuse_resolve_entry (state, _gf_true);
return 0;
}