summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
authorRavishankar N <ravishankar@redhat.com>2018-06-14 12:59:06 +0530
committerPranith Kumar Karampuri <pkarampu@redhat.com>2018-06-19 06:05:20 +0000
commiteb472d82a083883335bc494b87ea175ac43471ff (patch)
treed115e0bd34d0f2ef4a1bca67ccc9046523156d88 /xlators
parent0f13eed0c1fa74cefed486538b02e0c8a8708456 (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')
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-common.c39
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-data.c8
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-entry.c4
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-name.c6
-rw-r--r--xlators/cluster/afr/src/afr-self-heal.h6
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 */