cb8e9e
From b7b17674507090e9b161a64c3d5a6f77224fa608 Mon Sep 17 00:00:00 2001
cb8e9e
From: Anuradha Talur <atalur@redhat.com>
cb8e9e
Date: Fri, 3 Jul 2015 11:35:46 +0530
cb8e9e
Subject: [PATCH 203/212] cluster/afr : expunge first, impunge next in entry selfheal
cb8e9e
cb8e9e
        Backport of: http://review.gluster.org/11544/
cb8e9e
cb8e9e
When entry self-heals are performed, the files/directories
cb8e9e
that are to be expunged should be removed first and then
cb8e9e
impunge should be done.
cb8e9e
cb8e9e
Consider the following scenario :
cb8e9e
A volume with 2 bricks : b0 and b1.
cb8e9e
1) With following hierarchy on both bricks:
cb8e9e
olddir
cb8e9e
|__ oldfile
cb8e9e
cb8e9e
2) Bring down b1 and do 'mv olddir newdir'.
cb8e9e
cb8e9e
3) Bring up b1 and self-heal.
cb8e9e
cb8e9e
4) Without patch, during self-heal the events occur in
cb8e9e
following order,
cb8e9e
        a) Creation of newdir on the sink brick. Notice that
cb8e9e
gfid of olddir and newdir are same. As a result of which
cb8e9e
gfid-link file in .glusterfs directory still points to olddir
cb8e9e
and not to newdir.
cb8e9e
cb8e9e
        b) Deletion of olddir on the sink brick. As a part of
cb8e9e
this deletion, the gfid link file is also deleted. Now, there
cb8e9e
is no link file pointing to newdir.
cb8e9e
cb8e9e
5) Files under newdir will not get listed as part of readdir.
cb8e9e
cb8e9e
To tackle this kind of scenario, an expunge should be done first
cb8e9e
and impunge later; which is the purpose of this patch.
cb8e9e
cb8e9e
Change-Id: Idc8546f652adf11a13784ff989077cf79986bbd5
cb8e9e
BUG: 1231732
cb8e9e
Reviewed-on: http://review.gluster.org/11498
cb8e9e
Reviewed-by: Ravishankar N <ravishankar@redhat.com>
cb8e9e
Tested-by: Gluster Build System <jenkins@build.gluster.com>
cb8e9e
Reviewed-by: Krutika Dhananjay <kdhananj@redhat.com>
cb8e9e
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
cb8e9e
Signed-off-by: Anuradha Talur <atalur@redhat.com>
cb8e9e
Reviewed-on: https://code.engineering.redhat.com/gerrit/52357
cb8e9e
Reviewed-by: Ravishankar Narayanankutty <ravishankar@redhat.com>
cb8e9e
Tested-by: Ravishankar Narayanankutty <ravishankar@redhat.com>
cb8e9e
---
cb8e9e
 tests/bugs/replicate/bug-1130892.t            |    2 +
cb8e9e
 tests/bugs/replicate/bug-1238508-self-heal.t  |   51 +++++++++++++++++++++++++
cb8e9e
 xlators/cluster/afr/src/afr-self-heal-entry.c |    7 ++-
cb8e9e
 3 files changed, 58 insertions(+), 2 deletions(-)
cb8e9e
 create mode 100644 tests/bugs/replicate/bug-1238508-self-heal.t
cb8e9e
cb8e9e
diff --git a/tests/bugs/replicate/bug-1130892.t b/tests/bugs/replicate/bug-1130892.t
cb8e9e
index 945ee49..7442ab8 100644
cb8e9e
--- a/tests/bugs/replicate/bug-1130892.t
cb8e9e
+++ b/tests/bugs/replicate/bug-1130892.t
cb8e9e
@@ -54,6 +54,8 @@ EXPECT "00000000" afr_get_specific_changelog_xattr $B0/${V0}-0/one trusted.afr.$
cb8e9e
 TEST gluster volume set $V0 self-heal-daemon on
cb8e9e
 
cb8e9e
 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
cb8e9e
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0
cb8e9e
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1
cb8e9e
 TEST $CLI volume heal $V0
cb8e9e
 EXPECT_WITHIN $HEAL_TIMEOUT "Y" is_dir_heal_done $B0/${V0}-0 $B0/${V0}-1 one
cb8e9e
 EXPECT_WITHIN $HEAL_TIMEOUT "Y" is_dir_heal_done $B0/${V0}-0 $B0/${V0}-1 one/two
cb8e9e
diff --git a/tests/bugs/replicate/bug-1238508-self-heal.t b/tests/bugs/replicate/bug-1238508-self-heal.t
cb8e9e
new file mode 100644
cb8e9e
index 0000000..24fb07d
cb8e9e
--- /dev/null
cb8e9e
+++ b/tests/bugs/replicate/bug-1238508-self-heal.t
cb8e9e
@@ -0,0 +1,51 @@
cb8e9e
+#!/bin/bash
cb8e9e
+. $(dirname $0)/../../include.rc
cb8e9e
+. $(dirname $0)/../../volume.rc
cb8e9e
+cleanup;
cb8e9e
+
cb8e9e
+TEST glusterd
cb8e9e
+TEST pidof glusterd
cb8e9e
+TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1}
cb8e9e
+TEST $CLI volume start $V0
cb8e9e
+
cb8e9e
+# Disable self-heal-daemon
cb8e9e
+TEST $CLI volume set $V0 cluster.self-heal-daemon off
cb8e9e
+
cb8e9e
+TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0;
cb8e9e
+
cb8e9e
+TEST mkdir $M0/olddir;
cb8e9e
+TEST `echo "some-data" > $M0/olddir/oldfile`
cb8e9e
+
cb8e9e
+TEST kill_brick $V0 $H0 $B0/${V0}1
cb8e9e
+TEST mv $M0/olddir/oldfile $M0/olddir/newfile;
cb8e9e
+TEST mv $M0/olddir $M0/newdir;
cb8e9e
+
cb8e9e
+TEST $CLI volume start $V0 force
cb8e9e
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0
cb8e9e
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1
cb8e9e
+
cb8e9e
+TEST $CLI volume set $V0 cluster.self-heal-daemon on
cb8e9e
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
cb8e9e
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0
cb8e9e
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1
cb8e9e
+
cb8e9e
+TEST $CLI volume heal $V0
cb8e9e
+EXPECT_WITHIN $HEAL_TIMEOUT "0" get_pending_heal_count $V0
cb8e9e
+
cb8e9e
+# Test if the files are present on both the bricks
cb8e9e
+EXPECT "newdir" ls $B0/${V0}0/
cb8e9e
+EXPECT "newdir" ls $B0/${V0}1/
cb8e9e
+EXPECT "newfile" ls $B0/${V0}0/newdir/
cb8e9e
+EXPECT "newfile" ls $B0/${V0}1/newdir/
cb8e9e
+
cb8e9e
+# Test if gfid-link files in .glusterfs also provide correct info
cb8e9e
+brick0gfid=$(gf_get_gfid_backend_file_path $B0/${V0}0 newdir)
cb8e9e
+brick1gfid=$(gf_get_gfid_backend_file_path $B0/${V0}1 newdir)
cb8e9e
+EXPECT "newfile" ls $brick0gfid
cb8e9e
+EXPECT "newfile" ls $brick1gfid
cb8e9e
+
cb8e9e
+# Test if the files are accessible from the mount
cb8e9e
+EXPECT "newdir" ls $M0/
cb8e9e
+EXPECT "newfile" ls $M0/newdir
cb8e9e
+
cb8e9e
+cleanup;
cb8e9e
diff --git a/xlators/cluster/afr/src/afr-self-heal-entry.c b/xlators/cluster/afr/src/afr-self-heal-entry.c
cb8e9e
index 13a280f..f192931 100644
cb8e9e
--- a/xlators/cluster/afr/src/afr-self-heal-entry.c
cb8e9e
+++ b/xlators/cluster/afr/src/afr-self-heal-entry.c
cb8e9e
@@ -589,17 +589,20 @@ afr_selfheal_entry_do (call_frame_t *frame, xlator_t *this, fd_t *fd,
cb8e9e
 		uuid_utoa (fd->inode->gfid));
cb8e9e
 
cb8e9e
 	for (i = 0; i < priv->child_count; i++) {
cb8e9e
-		if (i != source && !healed_sinks[i])
cb8e9e
+		if (!healed_sinks[i])
cb8e9e
 			continue;
cb8e9e
 		ret = afr_selfheal_entry_do_subvol (frame, this, fd, i);
cb8e9e
                 if (ret == -1) {
cb8e9e
                         /* gfid or type mismatch. */
cb8e9e
                         mismatch = _gf_true;
cb8e9e
-                        continue;
cb8e9e
+                        ret = 0;
cb8e9e
                 }
cb8e9e
 		if (ret)
cb8e9e
 			break;
cb8e9e
 	}
cb8e9e
+        if (!ret && source != -1)
cb8e9e
+		ret = afr_selfheal_entry_do_subvol (frame, this, fd, source);
cb8e9e
+
cb8e9e
         if (mismatch == _gf_true)
cb8e9e
                 /* undo pending will be skipped */
cb8e9e
                 ret = -1;
cb8e9e
-- 
cb8e9e
1.7.1
cb8e9e