17b94a
From 708c17a8a69b2657f384affaedfcf4ba0a123893 Mon Sep 17 00:00:00 2001
17b94a
From: karthik-us <ksubrahm@redhat.com>
17b94a
Date: Wed, 23 Dec 2020 14:45:07 +0530
17b94a
Subject: [PATCH 513/517] afr: mark pending xattrs as a part of metadata heal
17b94a
17b94a
...if pending xattrs are zero for all children.
17b94a
17b94a
Problem:
17b94a
If there are no pending xattrs and a metadata heal needs to be
17b94a
performed, it can be possible that we end up with xattrs inadvertendly
17b94a
deleted from all bricks, as explained in the  BZ.
17b94a
17b94a
Fix:
17b94a
After picking one among the sources as the good copy, mark pending xattrs on
17b94a
all sources to blame the sinks. Now even if this metadata heal fails midway,
17b94a
a subsequent heal will still choose one of the valid sources that it
17b94a
picked previously.
17b94a
17b94a
Upstream patch details:
17b94a
> Fixes: #1067
17b94a
> Change-Id: If1b050b70b0ad911e162c04db4d89b263e2b8d7b
17b94a
> Signed-off-by: Ravishankar N <ravishankar@redhat.com>
17b94a
Upstream patch: https://review.gluster.org/#/c/glusterfs/+/21922/
17b94a
17b94a
BUG: 1640148
17b94a
Change-Id: If1b050b70b0ad911e162c04db4d89b263e2b8d7b
17b94a
Signed-off-by: karthik-us <ksubrahm@redhat.com>
17b94a
Reviewed-on: https://code.engineering.redhat.com/gerrit/222073
17b94a
Tested-by: RHGS Build Bot <nigelb@redhat.com>
17b94a
Reviewed-by: Ravishankar Narayanankutty <ravishankar@redhat.com>
17b94a
---
17b94a
 tests/bugs/replicate/mdata-heal-no-xattrs.t      | 59 ++++++++++++++++++++++
17b94a
 xlators/cluster/afr/src/afr-self-heal-metadata.c | 62 +++++++++++++++++++++++-
17b94a
 2 files changed, 120 insertions(+), 1 deletion(-)
17b94a
 create mode 100644 tests/bugs/replicate/mdata-heal-no-xattrs.t
17b94a
17b94a
diff --git a/tests/bugs/replicate/mdata-heal-no-xattrs.t b/tests/bugs/replicate/mdata-heal-no-xattrs.t
17b94a
new file mode 100644
17b94a
index 0000000..d3b0c50
17b94a
--- /dev/null
17b94a
+++ b/tests/bugs/replicate/mdata-heal-no-xattrs.t
17b94a
@@ -0,0 +1,59 @@
17b94a
+#!/bin/bash
17b94a
+
17b94a
+. $(dirname $0)/../../include.rc
17b94a
+. $(dirname $0)/../../volume.rc
17b94a
+cleanup;
17b94a
+
17b94a
+TEST glusterd
17b94a
+TEST pidof glusterd
17b94a
+TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2};
17b94a
+TEST $CLI volume set $V0 cluster.self-heal-daemon off
17b94a
+TEST $CLI volume start $V0
17b94a
+
17b94a
+TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0
17b94a
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0
17b94a
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1
17b94a
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2
17b94a
+echo "Data">$M0/FILE
17b94a
+ret=$?
17b94a
+TEST [ $ret -eq 0 ]
17b94a
+
17b94a
+# Change permission on brick-0: simulates the case where there is metadata
17b94a
+# mismatch but no pending xattrs. This brick will become the source for heal.
17b94a
+TEST chmod +x $B0/$V0"0"/FILE
17b94a
+
17b94a
+# Add gfid to xattrop
17b94a
+xattrop_b0=$(afr_get_index_path $B0/$V0"0")
17b94a
+base_entry_b0=`ls $xattrop_b0`
17b94a
+gfid_str_FILE=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/$V0"0"/FILE))
17b94a
+TEST ln $xattrop_b0/$base_entry_b0 $xattrop_b0/$gfid_str_FILE
17b94a
+EXPECT_WITHIN $HEAL_TIMEOUT "^1$" get_pending_heal_count $V0
17b94a
+
17b94a
+TEST $CLI volume set $V0 cluster.self-heal-daemon on
17b94a
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0
17b94a
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1
17b94a
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 2
17b94a
+TEST $CLI volume heal $V0
17b94a
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0
17b94a
+
17b94a
+# Brick-0 should contain xattrs blaming other 2 bricks.
17b94a
+# The values will be zero because heal is over.
17b94a
+EXPECT "000000000000000000000000" get_hex_xattr trusted.afr.$V0-client-1 $B0/${V0}0/FILE
17b94a
+EXPECT "000000000000000000000000" get_hex_xattr trusted.afr.$V0-client-2 $B0/${V0}0/FILE
17b94a
+TEST ! getfattr -n trusted.afr.$V0-client-0 $B0/${V0}0/FILE
17b94a
+
17b94a
+# Brick-1 and Brick-2 must not contain any afr xattrs.
17b94a
+TEST ! getfattr -n trusted.afr.$V0-client-0 $B0/${V0}1/FILE
17b94a
+TEST ! getfattr -n trusted.afr.$V0-client-1 $B0/${V0}1/FILE
17b94a
+TEST ! getfattr -n trusted.afr.$V0-client-2 $B0/${V0}1/FILE
17b94a
+TEST ! getfattr -n trusted.afr.$V0-client-0 $B0/${V0}2/FILE
17b94a
+TEST ! getfattr -n trusted.afr.$V0-client-1 $B0/${V0}2/FILE
17b94a
+TEST ! getfattr -n trusted.afr.$V0-client-2 $B0/${V0}2/FILE
17b94a
+
17b94a
+# check permission bits.
17b94a
+EXPECT '755' stat -c %a $B0/${V0}0/FILE
17b94a
+EXPECT '755' stat -c %a $B0/${V0}1/FILE
17b94a
+EXPECT '755' stat -c %a $B0/${V0}2/FILE
17b94a
+
17b94a
+EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
17b94a
+cleanup;
17b94a
diff --git a/xlators/cluster/afr/src/afr-self-heal-metadata.c b/xlators/cluster/afr/src/afr-self-heal-metadata.c
17b94a
index f4e31b6..03f43ba 100644
17b94a
--- a/xlators/cluster/afr/src/afr-self-heal-metadata.c
17b94a
+++ b/xlators/cluster/afr/src/afr-self-heal-metadata.c
17b94a
@@ -190,6 +190,59 @@ out:
17b94a
     return ret;
17b94a
 }
17b94a
 
17b94a
+static int
17b94a
+__afr_selfheal_metadata_mark_pending_xattrs(call_frame_t *frame, xlator_t *this,
17b94a
+                                            inode_t *inode,
17b94a
+                                            struct afr_reply *replies,
17b94a
+                                            unsigned char *sources)
17b94a
+{
17b94a
+    int ret = 0;
17b94a
+    int i = 0;
17b94a
+    int m_idx = 0;
17b94a
+    afr_private_t *priv = NULL;
17b94a
+    int raw[AFR_NUM_CHANGE_LOGS] = {0};
17b94a
+    dict_t *xattr = NULL;
17b94a
+
17b94a
+    priv = this->private;
17b94a
+    m_idx = afr_index_for_transaction_type(AFR_METADATA_TRANSACTION);
17b94a
+    raw[m_idx] = 1;
17b94a
+
17b94a
+    xattr = dict_new();
17b94a
+    if (!xattr)
17b94a
+        return -ENOMEM;
17b94a
+
17b94a
+    for (i = 0; i < priv->child_count; i++) {
17b94a
+        if (sources[i])
17b94a
+            continue;
17b94a
+        ret = dict_set_static_bin(xattr, priv->pending_key[i], raw,
17b94a
+                                  sizeof(int) * AFR_NUM_CHANGE_LOGS);
17b94a
+        if (ret) {
17b94a
+            ret = -1;
17b94a
+            goto out;
17b94a
+        }
17b94a
+    }
17b94a
+
17b94a
+    for (i = 0; i < priv->child_count; i++) {
17b94a
+        if (!sources[i])
17b94a
+            continue;
17b94a
+        ret = afr_selfheal_post_op(frame, this, inode, i, xattr, NULL);
17b94a
+        if (ret < 0) {
17b94a
+            gf_msg(this->name, GF_LOG_INFO, -ret, AFR_MSG_SELF_HEAL_INFO,
17b94a
+                   "Failed to set pending metadata xattr on child %d for %s", i,
17b94a
+                   uuid_utoa(inode->gfid));
17b94a
+            goto out;
17b94a
+        }
17b94a
+    }
17b94a
+
17b94a
+    afr_replies_wipe(replies, priv->child_count);
17b94a
+    ret = afr_selfheal_unlocked_discover(frame, inode, inode->gfid, replies);
17b94a
+
17b94a
+out:
17b94a
+    if (xattr)
17b94a
+        dict_unref(xattr);
17b94a
+    return ret;
17b94a
+}
17b94a
+
17b94a
 /*
17b94a
  * Look for mismatching uid/gid or mode or user xattrs even if
17b94a
  * AFR xattrs don't say so, and pick one arbitrarily as winner. */
17b94a
@@ -210,6 +263,7 @@ __afr_selfheal_metadata_finalize_source(call_frame_t *frame, xlator_t *this,
17b94a
     };
17b94a
     int source = -1;
17b94a
     int sources_count = 0;
17b94a
+    int ret = 0;
17b94a
 
17b94a
     priv = this->private;
17b94a
 
17b94a
@@ -300,7 +354,13 @@ __afr_selfheal_metadata_finalize_source(call_frame_t *frame, xlator_t *this,
17b94a
             healed_sinks[i] = 1;
17b94a
         }
17b94a
     }
17b94a
-
17b94a
+    if ((sources_count == priv->child_count) && (source > -1) &&
17b94a
+        (AFR_COUNT(healed_sinks, priv->child_count) != 0)) {
17b94a
+        ret = __afr_selfheal_metadata_mark_pending_xattrs(frame, this, inode,
17b94a
+                                                          replies, sources);
17b94a
+        if (ret < 0)
17b94a
+            return ret;
17b94a
+    }
17b94a
 out:
17b94a
     afr_mark_active_sinks(this, sources, locked_on, healed_sinks);
17b94a
     return source;
17b94a
-- 
17b94a
1.8.3.1
17b94a