diff options
author | Ravishankar N <ravishankar@redhat.com> | 2018-06-14 12:59:06 +0530 |
---|---|---|
committer | Pranith Kumar Karampuri <pkarampu@redhat.com> | 2018-06-19 06:05:20 +0000 |
commit | eb472d82a083883335bc494b87ea175ac43471ff (patch) | |
tree | d115e0bd34d0f2ef4a1bca67ccc9046523156d88 /xlators/cluster | |
parent | 0f13eed0c1fa74cefed486538b02e0c8a8708456 (diff) |
afr: heal gfids when file is not present on all bricks
commit 20fa80057eb430fd72b4fa31b9b65598b8ec1265 introduced a regression
wherein if a file is present in only 1 brick of replica *and* doesn't
have a gfid associated with it, it doesn't get healed upon the next
lookup from the client. Fix it.
Change-Id: I7d1111dcb45b1b8b8340a7d02558f05df70aa599
fixes: bz#1591193
Signed-off-by: Ravishankar N <ravishankar@redhat.com>
Diffstat (limited to 'xlators/cluster')
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-common.c | 39 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-data.c | 8 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-entry.c | 4 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-name.c | 6 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heal.h | 6 |
5 files changed, 51 insertions, 12 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c index dc380c6d280..3cb69beabff 100644 --- a/xlators/cluster/afr/src/afr-self-heal-common.c +++ b/xlators/cluster/afr/src/afr-self-heal-common.c @@ -22,7 +22,7 @@ afr_heal_synctask (xlator_t *this, afr_local_t *local); int afr_lookup_and_heal_gfid (xlator_t *this, inode_t *parent, const char *name, inode_t *inode, struct afr_reply *replies, - int source, void *gfid) + int source, unsigned char *sources, void *gfid) { afr_private_t *priv = NULL; call_frame_t *frame = NULL; @@ -37,6 +37,23 @@ afr_lookup_and_heal_gfid (xlator_t *this, inode_t *parent, const char *name, priv = this->private; wind_on = alloca0 (priv->child_count); ia_type = replies[source].poststat.ia_type; + if ((ia_type == IA_INVAL) && + (AFR_COUNT(sources, priv->child_count) == priv->child_count)) { + /* If a file is present on some bricks of the replica but parent + * dir does not have pending xattrs, all bricks are sources and + * the 'source' we selected earlier might be one where the file + * is not actually present. Hence check if file is present in + * any of the sources.*/ + for (i = 0; i < priv->child_count; i++) { + if (i == source) + continue; + if (sources[i] && replies[i].valid && + replies[i].op_ret == 0) { + ia_type = replies[i].poststat.ia_type; + break; + } + } + } /* gfid heal on those subvolumes that do not have gfid associated * with the inode and update those replies. @@ -1256,6 +1273,21 @@ afr_mark_split_brain_source_sinks_by_policy (call_frame_t *frame, return fav_child; } +gf_boolean_t +afr_is_file_empty_on_all_children (afr_private_t *priv, + struct afr_reply *replies) +{ + int i = 0; + + for (i = 0; i < priv->child_count; i++) { + if ((!replies[i].valid) || (replies[i].op_ret != 0) || + (replies[i].poststat.ia_size != 0)) + return _gf_false; + } + + return _gf_true; +} + int afr_mark_source_sinks_if_file_empty (xlator_t *this, unsigned char *sources, unsigned char *sinks, @@ -1274,11 +1306,8 @@ afr_mark_source_sinks_if_file_empty (xlator_t *this, unsigned char *sources, return -1; if (type == AFR_DATA_TRANSACTION) { - for (i = 0; i < priv->child_count; i++) { - if (replies[i].poststat.ia_size != 0) + if (!afr_is_file_empty_on_all_children(priv, replies)) return -1; - } - goto mark; } diff --git a/xlators/cluster/afr/src/afr-self-heal-data.c b/xlators/cluster/afr/src/afr-self-heal-data.c index 40dee7a7d6c..c83ef0b7e30 100644 --- a/xlators/cluster/afr/src/afr-self-heal-data.c +++ b/xlators/cluster/afr/src/afr-self-heal-data.c @@ -683,6 +683,7 @@ __afr_selfheal_data (call_frame_t *frame, xlator_t *this, fd_t *fd, int source = -1; gf_boolean_t did_sh = _gf_true; gf_boolean_t is_arbiter_the_only_sink = _gf_false; + gf_boolean_t empty_file = _gf_false; priv = this->private; @@ -723,6 +724,11 @@ __afr_selfheal_data (call_frame_t *frame, xlator_t *this, fd_t *fd, source = ret; if (AFR_IS_ARBITER_BRICK(priv, source)) { + empty_file = afr_is_file_empty_on_all_children (priv, + locked_replies); + if (empty_file) + goto restore_time; + did_sh = _gf_false; goto unlock; } @@ -759,7 +765,7 @@ restore_time: afr_selfheal_restore_time (frame, this, fd->inode, source, healed_sinks, locked_replies); - if (!is_arbiter_the_only_sink) { + if (!is_arbiter_the_only_sink || !empty_file) { ret = afr_selfheal_inodelk (frame, this, fd->inode, this->name, 0, 0, data_lock); if (ret < priv->child_count) { diff --git a/xlators/cluster/afr/src/afr-self-heal-entry.c b/xlators/cluster/afr/src/afr-self-heal-entry.c index b601040504e..e6022cc939b 100644 --- a/xlators/cluster/afr/src/afr-self-heal-entry.c +++ b/xlators/cluster/afr/src/afr-self-heal-entry.c @@ -187,7 +187,7 @@ __afr_selfheal_heal_dirent (call_frame_t *frame, xlator_t *this, fd_t *fd, if (replies[source].op_ret == 0) { ret = afr_lookup_and_heal_gfid (this, fd->inode, name, - inode, replies, source, + inode, replies, source, sources, &replies[source].poststat.ia_gfid); if (ret) return ret; @@ -320,7 +320,7 @@ __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, + source, sources, &replies[source].poststat.ia_gfid); if (ret) return ret; diff --git a/xlators/cluster/afr/src/afr-self-heal-name.c b/xlators/cluster/afr/src/afr-self-heal-name.c index 556d14baf82..bcd0e60c947 100644 --- a/xlators/cluster/afr/src/afr-self-heal-name.c +++ b/xlators/cluster/afr/src/afr-self-heal-name.c @@ -19,7 +19,7 @@ __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, - gf_boolean_t is_gfid_absent) + unsigned char *sources, gf_boolean_t is_gfid_absent) { int ret = 0; int up_count = 0; @@ -48,7 +48,7 @@ __afr_selfheal_assign_gfid (xlator_t *this, inode_t *parent, uuid_t pargfid, } afr_lookup_and_heal_gfid (this, parent, bname, inode, replies, source, - gfid); + sources, gfid); out: return ret; @@ -426,7 +426,7 @@ __afr_selfheal_name_do (call_frame_t *frame, xlator_t *this, inode_t *parent, 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, - is_gfid_absent); + sources, is_gfid_absent); if (ret) return ret; diff --git a/xlators/cluster/afr/src/afr-self-heal.h b/xlators/cluster/afr/src/afr-self-heal.h index cd67d2a3192..9836e2fbc03 100644 --- a/xlators/cluster/afr/src/afr-self-heal.h +++ b/xlators/cluster/afr/src/afr-self-heal.h @@ -113,7 +113,7 @@ afr_selfheal_entry (call_frame_t *frame, xlator_t *this, inode_t *inode); int afr_lookup_and_heal_gfid (xlator_t *this, inode_t *parent, const char *name, inode_t *inode, struct afr_reply *replies, int source, - void *gfid); + unsigned char *sources, void *gfid); int afr_selfheal_inodelk (call_frame_t *frame, xlator_t *this, inode_t *inode, @@ -353,4 +353,8 @@ afr_mark_source_sinks_if_file_empty (xlator_t *this, unsigned char *sources, struct afr_reply *replies, afr_transaction_type type); +gf_boolean_t +afr_is_file_empty_on_all_children (afr_private_t *priv, + struct afr_reply *replies); + #endif /* !_AFR_SELFHEAL_H */ |