diff options
author | Ravishankar N <ravishankar@redhat.com> | 2017-09-20 12:16:06 +0530 |
---|---|---|
committer | Pranith Kumar Karampuri <pkarampu@redhat.com> | 2017-10-09 06:23:08 +0000 |
commit | 20fa80057eb430fd72b4fa31b9b65598b8ec1265 (patch) | |
tree | 3e1dd8c0cb7a394ebcdc7004ccaddb935c67e4d6 /xlators/cluster/afr/src/afr-self-heal-entry.c | |
parent | 938addeb7ec634e431c2c8c0a768a2a9ed056c0d (diff) |
afr: heal gfid as a part of entry heal
Problem:
If a brick crashes after an entry (file or dir) is created but before
gfid is assigned, the good bricks will have pending entry heal xattrs
but the heal won't complete because afr_selfheal_recreate_entry() tries
to create the entry again and it fails with EEXIST.
Fix:
We could have fixed posx_mknod/mkdir etc to assign the gfid if the file
already exists but the right thing to do seems to be to trigger a lookup
on the bad brick and let it heal the gfid instead of winding an
mknod/mkdir in the first place.
Change-Id: I82f76665a7541f1893ef8d847b78af6466aff1ff
BUG: 1493415
Signed-off-by: Ravishankar N <ravishankar@redhat.com>
Diffstat (limited to 'xlators/cluster/afr/src/afr-self-heal-entry.c')
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-entry.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heal-entry.c b/xlators/cluster/afr/src/afr-self-heal-entry.c index afa3f9044e1..647dd71911b 100644 --- a/xlators/cluster/afr/src/afr-self-heal-entry.c +++ b/xlators/cluster/afr/src/afr-self-heal-entry.c @@ -64,7 +64,6 @@ afr_selfheal_entry_delete (xlator_t *this, inode_t *dir, const char *name, return ret; } - int afr_selfheal_recreate_entry (call_frame_t *frame, int dst, int source, unsigned char *sources, inode_t *dir, @@ -164,7 +163,6 @@ out: return ret; } - static int __afr_selfheal_heal_dirent (call_frame_t *frame, xlator_t *this, fd_t *fd, char *name, inode_t *inode, int source, @@ -187,6 +185,14 @@ __afr_selfheal_heal_dirent (call_frame_t *frame, xlator_t *this, fd_t *fd, (replies[source].op_errno != ENOENT)) return -replies[source].op_errno; + if (replies[source].op_ret == 0) { + ret = afr_lookup_and_heal_gfid (this, fd->inode, name, + inode, replies, source, + &replies[source].poststat.ia_gfid); + if (ret) + return ret; + } + for (i = 0; i < priv->child_count; i++) { if (!healed_sinks[i]) continue; @@ -223,8 +229,12 @@ afr_selfheal_detect_gfid_and_type_mismatch (xlator_t *this, int i = 0; int ret = -1; afr_private_t *priv = NULL; + void *gfid = NULL; + ia_type_t ia_type = IA_INVAL; priv = this->private; + gfid = &replies[src_idx].poststat.ia_gfid; + ia_type = replies[src_idx].poststat.ia_type; for (i = 0; i < priv->child_count; i++) { if (i == src_idx) @@ -236,8 +246,8 @@ afr_selfheal_detect_gfid_and_type_mismatch (xlator_t *this, if (replies[i].op_ret != 0) continue; - if (gf_uuid_compare (replies[src_idx].poststat.ia_gfid, - replies[i].poststat.ia_gfid)) { + if (gf_uuid_compare (gfid, replies[i].poststat.ia_gfid) && + (ia_type == replies[i].poststat.ia_type)) { ret = afr_gfid_split_brain_source (this, replies, inode, pargfid, bname, src_idx, i, @@ -251,8 +261,7 @@ afr_selfheal_detect_gfid_and_type_mismatch (xlator_t *this, return ret; } - if ((replies[src_idx].poststat.ia_type) != - (replies[i].poststat.ia_type)) { + if (ia_type != replies[i].poststat.ia_type) { gf_msg (this->name, GF_LOG_ERROR, 0, AFR_MSG_SPLIT_BRAIN, "Type mismatch detected " "for <gfid:%s>/%s>, %s on %s and %s on %s. " @@ -310,6 +319,12 @@ __afr_selfheal_merge_dirent (call_frame_t *frame, xlator_t *this, fd_t *fd, } } + ret = afr_lookup_and_heal_gfid (this, fd->inode, name, inode, replies, + source, + &replies[source].poststat.ia_gfid); + if (ret) + return ret; + /* In case of type mismatch / unable to resolve gfid mismatch on the * entry, return -1.*/ ret = afr_selfheal_detect_gfid_and_type_mismatch (this, replies, inode, @@ -542,9 +557,19 @@ afr_selfheal_entry_dirent (call_frame_t *frame, xlator_t *this, struct afr_reply *replies = NULL; struct afr_reply *par_replies = NULL; afr_private_t *priv = NULL; + dict_t *xattr = NULL; priv = this->private; + xattr = dict_new (); + if (!xattr) + return -ENOMEM; + ret = dict_set_int32 (xattr, GF_GFIDLESS_LOOKUP, 1); + if (ret) { + dict_unref (xattr); + return -1; + } + sources = alloca0 (priv->child_count); sinks = alloca0 (priv->child_count); healed_sinks = alloca0 (priv->child_count); @@ -576,7 +601,7 @@ afr_selfheal_entry_dirent (call_frame_t *frame, xlator_t *this, inode = afr_selfheal_unlocked_lookup_on (frame, fd->inode, name, replies, locked_on, - NULL); + xattr); if (!inode) { ret = -ENOMEM; goto unlock; @@ -608,6 +633,8 @@ unlock: afr_replies_wipe (replies, priv->child_count); if (par_replies) afr_replies_wipe (par_replies, priv->child_count); + if (xattr) + dict_unref (xattr); return ret; } |