diff options
author | Ravishankar N <ravishankar@redhat.com> | 2018-09-28 17:00:00 +0530 |
---|---|---|
committer | Pranith Kumar Karampuri <pkarampu@redhat.com> | 2018-12-03 06:44:19 +0000 |
commit | 4d58730c0cd6ab5db39aec8a15276f7bd3371b04 (patch) | |
tree | 9991e615677cc9d9db0b13cebf97442fe42e02fd /xlators/cluster/afr/src/afr-self-heal-name.c | |
parent | 4364093869f59ed2af3f7d10d5a72df490eac9a9 (diff) |
afr: assign gfid during name heal when no 'source' is present.
Problem:
If parent dir is in split-brain or has dirty xattrs set, and the file
has gfid missing on one of the bricks, then name heal won't assign the
gfid.
Fix:
Use the brick we select the gfid from as the 'source'.
Note: Problem was found while trying to debug a split-brain issue on
Cynthia Zhou's setup.
updates: bz#1637249
Change-Id: Id088d4f0fb017aa35122de426654194e581ed742
Reported-by: Cynthia Zhou <cynthia.zhou@nokia-sbell.com>
Signed-off-by: Ravishankar N <ravishankar@redhat.com>
Diffstat (limited to 'xlators/cluster/afr/src/afr-self-heal-name.c')
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-name.c | 47 |
1 files changed, 8 insertions, 39 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heal-name.c b/xlators/cluster/afr/src/afr-self-heal-name.c index 39aacee6ecf..aa20ad1b835 100644 --- a/xlators/cluster/afr/src/afr-self-heal-name.c +++ b/xlators/cluster/afr/src/afr-self-heal-name.c @@ -18,7 +18,8 @@ __afr_selfheal_assign_gfid(xlator_t *this, inode_t *parent, uuid_t pargfid, const char *bname, inode_t *inode, struct afr_reply *replies, void *gfid, unsigned char *locked_on, int source, - unsigned char *sources, gf_boolean_t is_gfid_absent) + unsigned char *sources, gf_boolean_t is_gfid_absent, + int *gfid_idx) { int ret = 0; int up_count = 0; @@ -46,8 +47,8 @@ __afr_selfheal_assign_gfid(xlator_t *this, inode_t *parent, uuid_t pargfid, } } - afr_lookup_and_heal_gfid(this, parent, bname, inode, replies, source, - sources, gfid); + ret = afr_lookup_and_heal_gfid(this, parent, bname, inode, replies, source, + sources, gfid, gfid_idx); out: return ret; @@ -146,35 +147,6 @@ __afr_selfheal_name_expunge(xlator_t *this, inode_t *parent, uuid_t pargfid, return ret; } -/* This function is to be called after ensuring that there is no gfid mismatch - * for the inode across multiple sources - */ -static int -afr_selfheal_gfid_idx_get(xlator_t *this, struct afr_reply *replies, - unsigned char *sources) -{ - int i = 0; - int gfid_idx = -1; - afr_private_t *priv = NULL; - - priv = this->private; - - for (i = 0; i < priv->child_count; i++) { - if (!replies[i].valid || replies[i].op_ret != 0) - continue; - - if (!sources[i]) - continue; - - if (gf_uuid_is_null(replies[i].poststat.ia_gfid)) - continue; - - gfid_idx = i; - break; - } - return gfid_idx; -} - static gf_boolean_t afr_selfheal_name_need_heal_check(xlator_t *this, struct afr_reply *replies) { @@ -400,21 +372,18 @@ __afr_selfheal_name_do(call_frame_t *frame, xlator_t *this, inode_t *parent, gfid = gfid_req; } else { gfid = &replies[gfid_idx].poststat.ia_gfid; + if (source == -1) + /* Either entry split-brain or dirty xattrs are present on parent.*/ + source = gfid_idx; } is_gfid_absent = (gfid_idx == -1) ? _gf_true : _gf_false; ret = __afr_selfheal_assign_gfid(this, parent, pargfid, bname, inode, replies, gfid, locked_on, source, sources, - is_gfid_absent); + is_gfid_absent, &gfid_idx); if (ret) return ret; - if (gfid_idx == -1) { - gfid_idx = afr_selfheal_gfid_idx_get(this, replies, sources); - if (gfid_idx == -1) - return -1; - } - ret = __afr_selfheal_name_impunge(frame, this, parent, pargfid, bname, inode, replies, gfid_idx); if (ret == -EIO) |