17b94a
From aab8a587360214432c4a2ab59134411f1d38c509 Mon Sep 17 00:00:00 2001
17b94a
From: karthik-us <ksubrahm@redhat.com>
17b94a
Date: Wed, 9 Dec 2020 10:46:31 +0530
17b94a
Subject: [PATCH 515/517] cluster/afr: Heal directory rename without
17b94a
 rmdir/mkdir
17b94a
17b94a
Problem1:
17b94a
When a directory is renamed while a brick
17b94a
is down entry-heal always did an rm -rf on that directory on
17b94a
the sink on old location and did mkdir and created the directory
17b94a
hierarchy again in the new location. This is inefficient.
17b94a
17b94a
Problem2:
17b94a
Renamedir heal order may lead to a scenario where directory in
17b94a
the new location could be created before deleting it from old
17b94a
location leading to 2 directories with same gfid in posix.
17b94a
17b94a
Fix:
17b94a
As part of heal, if oldlocation is healed first and is not present in
17b94a
source-brick always rename it into a hidden directory inside the
17b94a
sink-brick so that when heal is triggered in new-location shd can
17b94a
rename it from this hidden directory to the new-location.
17b94a
17b94a
If new-location heal is triggered first and it detects that the
17b94a
directory already exists in the brick, then it should skip healing the
17b94a
directory until it appears in the hidden directory.
17b94a
17b94a
Credits: Ravi for rename-data-loss.t script
17b94a
17b94a
Upstream patch details:
17b94a
> Fixes: #1211
17b94a
> Change-Id: I0cba2006f35cd03d314d18211ce0bd530e254843
17b94a
> Signed-off-by: Pranith Kumar K <pkarampu@redhat.com>
17b94a
Upstream patch: https://review.gluster.org/#/c/glusterfs/+/24373/
17b94a
17b94a
BUG: 1640148
17b94a
Change-Id: I0cba2006f35cd03d314d18211ce0bd530e254843
17b94a
Signed-off-by: karthik-us <ksubrahm@redhat.com>
17b94a
Reviewed-on: https://code.engineering.redhat.com/gerrit/220660
17b94a
Tested-by: RHGS Build Bot <nigelb@redhat.com>
17b94a
Reviewed-by: Ravishankar Narayanankutty <ravishankar@redhat.com>
17b94a
---
17b94a
 tests/afr.rc                                    |  16 +
17b94a
 tests/basic/afr/afr-anon-inode-no-quorum.t      |  63 ++++
17b94a
 tests/basic/afr/afr-anon-inode.t                | 114 ++++++
17b94a
 tests/basic/afr/entry-self-heal-anon-dir-off.t  | 464 ++++++++++++++++++++++++
17b94a
 tests/basic/afr/rename-data-loss.t              |  72 ++++
17b94a
 tests/bugs/replicate/bug-1744548-heal-timeout.t |   6 +-
17b94a
 tests/features/trash.t                          |  74 ++--
17b94a
 xlators/cluster/afr/src/afr-common.c            |  46 ++-
17b94a
 xlators/cluster/afr/src/afr-dir-read.c          |  12 +-
17b94a
 xlators/cluster/afr/src/afr-self-heal-common.c  | 182 ++++++++++
17b94a
 xlators/cluster/afr/src/afr-self-heal-entry.c   | 206 +++++++++--
17b94a
 xlators/cluster/afr/src/afr-self-heal-name.c    |  33 +-
17b94a
 xlators/cluster/afr/src/afr-self-heal.h         |   5 +
17b94a
 xlators/cluster/afr/src/afr-self-heald.c        | 178 ++++++++-
17b94a
 xlators/cluster/afr/src/afr-self-heald.h        |   2 +-
17b94a
 xlators/cluster/afr/src/afr.c                   |  40 +-
17b94a
 xlators/cluster/afr/src/afr.h                   |  11 +
17b94a
 xlators/mgmt/glusterd/src/glusterd-volgen.c     |  39 ++
17b94a
 xlators/mgmt/glusterd/src/glusterd-volume-set.c |   6 +
17b94a
 19 files changed, 1442 insertions(+), 127 deletions(-)
17b94a
 create mode 100644 tests/basic/afr/afr-anon-inode-no-quorum.t
17b94a
 create mode 100644 tests/basic/afr/afr-anon-inode.t
17b94a
 create mode 100644 tests/basic/afr/entry-self-heal-anon-dir-off.t
17b94a
 create mode 100644 tests/basic/afr/rename-data-loss.t
17b94a
17b94a
diff --git a/tests/afr.rc b/tests/afr.rc
17b94a
index 35f352d..2417899 100644
17b94a
--- a/tests/afr.rc
17b94a
+++ b/tests/afr.rc
17b94a
@@ -105,3 +105,19 @@ function get_quorum_type()
17b94a
         local repl_id="$3"
17b94a
         cat $m/.meta/graphs/active/$v-replicate-$repl_id/private|grep quorum-type|awk '{print $3}'
17b94a
 }
17b94a
+
17b94a
+function afr_private_key_value()
17b94a
+{
17b94a
+        local v=$1
17b94a
+        local m=$2
17b94a
+        local replica_id=$3
17b94a
+        local key=$4
17b94a
+#xargs at the end will strip leading spaces
17b94a
+        grep -E "^${key} = " $m/.meta/graphs/active/${v}-replicate-${replica_id}/private | cut -f2 -d'=' | xargs
17b94a
+}
17b94a
+
17b94a
+function afr_anon_entry_count()
17b94a
+{
17b94a
+    local b=$1
17b94a
+    ls $b/.glusterfs-anonymous-inode* | wc -l
17b94a
+}
17b94a
diff --git a/tests/basic/afr/afr-anon-inode-no-quorum.t b/tests/basic/afr/afr-anon-inode-no-quorum.t
17b94a
new file mode 100644
17b94a
index 0000000..896ba0c
17b94a
--- /dev/null
17b94a
+++ b/tests/basic/afr/afr-anon-inode-no-quorum.t
17b94a
@@ -0,0 +1,63 @@
17b94a
+#!/bin/bash
17b94a
+
17b94a
+#Test that anon-inode entry is not cleaned up as long as there exists at least
17b94a
+#one valid entry
17b94a
+. $(dirname $0)/../../include.rc
17b94a
+. $(dirname $0)/../../volume.rc
17b94a
+. $(dirname $0)/../../afr.rc
17b94a
+
17b94a
+cleanup;
17b94a
+
17b94a
+TEST glusterd
17b94a
+TEST pidof glusterd
17b94a
+TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1}
17b94a
+TEST $CLI volume heal $V0 disable
17b94a
+TEST $CLI volume set $V0 performance.write-behind off
17b94a
+TEST $CLI volume set $V0 performance.read-ahead off
17b94a
+TEST $CLI volume set $V0 performance.readdir-ahead off
17b94a
+TEST $CLI volume set $V0 performance.open-behind off
17b94a
+TEST $CLI volume set $V0 performance.stat-prefetch off
17b94a
+TEST $CLI volume set $V0 performance.io-cache off
17b94a
+TEST $CLI volume set $V0 performance.quick-read off
17b94a
+TEST $CLI volume set $V0 cluster.entry-self-heal off
17b94a
+TEST $CLI volume start $V0
17b94a
+
17b94a
+TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0
17b94a
+
17b94a
+TEST touch $M0/a $M0/b
17b94a
+
17b94a
+gfid_a=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/a))
17b94a
+gfid_b=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/b))
17b94a
+TEST kill_brick $V0 $H0 $B0/${V0}0
17b94a
+TEST mv $M0/a $M0/a-new
17b94a
+TEST mv $M0/b $M0/b-new
17b94a
+
17b94a
+TEST $CLI volume start $V0 force
17b94a
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0
17b94a
+TEST ! ls $M0/a
17b94a
+TEST ! ls $M0/b
17b94a
+anon_inode_name=$(ls -a $B0/${V0}0 | grep glusterfs-anonymous-inode)
17b94a
+TEST stat $B0/${V0}0/$anon_inode_name/$gfid_a
17b94a
+TEST stat $B0/${V0}0/$anon_inode_name/$gfid_b
17b94a
+#Make sure index heal doesn't happen after enabling heal
17b94a
+TEST setfattr -x trusted.afr.$V0-client-0 $B0/${V0}1
17b94a
+TEST rm -f $B0/${V0}1/.glusterfs/indices/xattrop/*
17b94a
+TEST $CLI volume heal $V0 enable
17b94a
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
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
+TEST $CLI volume heal $V0
17b94a
+#Allow time for a scan
17b94a
+sleep 5
17b94a
+TEST stat $B0/${V0}0/$anon_inode_name/$gfid_a
17b94a
+TEST stat $B0/${V0}0/$anon_inode_name/$gfid_b
17b94a
+inum_b=$(STAT_INO $B0/${V0}0/$anon_inode_name/$gfid_b)
17b94a
+TEST rm -f $M0/a-new
17b94a
+TEST stat $M0/b-new
17b94a
+
17b94a
+TEST $CLI volume heal $V0
17b94a
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_anon_entry_count $B0/${V0}0
17b94a
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_anon_entry_count $B0/${V0}1
17b94a
+EXPECT "$inum_b" STAT_INO $B0/${V0}0/b-new
17b94a
+
17b94a
+cleanup
17b94a
diff --git a/tests/basic/afr/afr-anon-inode.t b/tests/basic/afr/afr-anon-inode.t
17b94a
new file mode 100644
17b94a
index 0000000..f4cf37a
17b94a
--- /dev/null
17b94a
+++ b/tests/basic/afr/afr-anon-inode.t
17b94a
@@ -0,0 +1,114 @@
17b94a
+#!/bin/bash
17b94a
+#Tests that afr-anon-inode test cases work fine as expected
17b94a
+#These are cases where in entry-heal/name-heal we dont know entry for an inode
17b94a
+#so these inodes are kept in a special directory
17b94a
+
17b94a
+. $(dirname $0)/../../include.rc
17b94a
+. $(dirname $0)/../../volume.rc
17b94a
+. $(dirname $0)/../../afr.rc
17b94a
+
17b94a
+cleanup;
17b94a
+
17b94a
+TEST glusterd
17b94a
+TEST pidof glusterd
17b94a
+TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0..2}
17b94a
+TEST $CLI volume set $V0 performance.quick-read off
17b94a
+TEST $CLI volume set $V0 performance.io-cache off
17b94a
+TEST $CLI volume set $V0 performance.write-behind off
17b94a
+TEST $CLI volume set $V0 performance.stat-prefetch off
17b94a
+TEST $CLI volume set $V0 performance.read-ahead off
17b94a
+TEST $CLI volume set $V0 performance.open-behind off
17b94a
+TEST $CLI volume start $V0
17b94a
+TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0;
17b94a
+EXPECT "^1$" afr_private_key_value $V0 $M0 0 "use-anonymous-inode"
17b94a
+TEST $CLI volume set $V0 cluster.use-anonymous-inode no
17b94a
+EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "^0$" afr_private_key_value $V0 $M0 0 "use-anonymous-inode"
17b94a
+TEST $CLI volume set $V0 cluster.use-anonymous-inode yes
17b94a
+EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "^1$" afr_private_key_value $V0 $M0 0 "use-anonymous-inode"
17b94a
+TEST mkdir -p $M0/d1/b $M0/d2/a
17b94a
+TEST kill_brick $V0 $H0 $B0/${V0}0
17b94a
+TEST mv $M0/d2/a $M0/d1
17b94a
+TEST mv $M0/d1/b $M0/d2
17b94a
+TEST $CLI volume start $V0 force
17b94a
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0
17b94a
+anon_inode_name=$(ls -a $B0/${V0}0 | grep glusterfs-anonymous-inode)
17b94a
+TEST [[ -d $B0/${V0}1/$anon_inode_name ]]
17b94a
+TEST [[ -d $B0/${V0}2/$anon_inode_name ]]
17b94a
+anon_gfid=$(gf_get_gfid_xattr $B0/${V0}0/$anon_inode_name)
17b94a
+EXPECT "$anon_gfid" gf_get_gfid_xattr $B0/${V0}1/$anon_inode_name
17b94a
+EXPECT "$anon_gfid" gf_get_gfid_xattr $B0/${V0}2/$anon_inode_name
17b94a
+
17b94a
+TEST ! ls $M0/$anon_inode_name
17b94a
+EXPECT "^4$" echo $(ls -a $M0 | wc -l)
17b94a
+
17b94a
+#Test purging code path by shd
17b94a
+TEST $CLI volume heal $V0 disable
17b94a
+TEST mkdir $M0/l0 $M0/l1 $M0/l2
17b94a
+TEST touch $M0/del-file $M0/del-file-nolink $M0/l0/file
17b94a
+TEST ln $M0/del-file $M0/del-file-link
17b94a
+TEST ln $M0/l0/file $M0/l1/file-link1
17b94a
+TEST ln $M0/l0/file $M0/l2/file-link2
17b94a
+TEST mkdir -p $M0/del-recursive-dir/d1
17b94a
+
17b94a
+TEST kill_brick $V0 $H0 $B0/${V0}0
17b94a
+TEST rm -f $M0/del-file $M0/del-file-nolink
17b94a
+TEST rm -rf $M0/del-recursive-dir
17b94a
+TEST mv $M0/d1/a $M0/d2
17b94a
+TEST mv $M0/l0/file $M0/l0/renamed-file
17b94a
+TEST $CLI volume start $V0 force
17b94a
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "^1$" afr_child_up_status $V0 0
17b94a
+
17b94a
+nolink_gfid=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/del-file-nolink))
17b94a
+link_gfid=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/del-file))
17b94a
+dir_gfid=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/del-recursive-dir))
17b94a
+rename_dir_gfid=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/d1/a))
17b94a
+rename_file_gfid=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/l0/file))
17b94a
+TEST ! stat $M0/del-file
17b94a
+TEST stat $B0/${V0}0/$anon_inode_name/$link_gfid
17b94a
+TEST ! stat $M0/del-file-nolink
17b94a
+TEST ! stat $B0/${V0}0/$anon_inode_name/$nolink_gfid
17b94a
+TEST ! stat $M0/del-recursive-dir
17b94a
+TEST stat $B0/${V0}0/$anon_inode_name/$dir_gfid
17b94a
+TEST ! stat $M0/d1/a
17b94a
+TEST stat $B0/${V0}0/$anon_inode_name/$rename_dir_gfid
17b94a
+TEST ! stat $M0/l0/file
17b94a
+TEST stat $B0/${V0}0/$anon_inode_name/$rename_file_gfid
17b94a
+
17b94a
+TEST kill_brick $V0 $H0 $B0/${V0}1
17b94a
+TEST mv $M0/l1/file-link1 $M0/l1/renamed-file-link1
17b94a
+TEST $CLI volume start $V0 force
17b94a
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "^1$" afr_child_up_status $V0 1
17b94a
+TEST ! stat $M0/l1/file-link1
17b94a
+TEST stat $B0/${V0}1/$anon_inode_name/$rename_file_gfid
17b94a
+
17b94a
+TEST kill_brick $V0 $H0 $B0/${V0}2
17b94a
+TEST mv $M0/l2/file-link2 $M0/l2/renamed-file-link2
17b94a
+TEST $CLI volume start $V0 force
17b94a
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "^1$" afr_child_up_status $V0 2
17b94a
+TEST ! stat $M0/l2/file-link2
17b94a
+TEST stat $B0/${V0}2/$anon_inode_name/$rename_file_gfid
17b94a
+
17b94a
+#Simulate only anon-inodes present in all bricks
17b94a
+TEST rm -f $M0/l0/renamed-file $M0/l1/renamed-file-link1 $M0/l2/renamed-file-link2
17b94a
+
17b94a
+#Test that shd doesn't cleanup anon-inodes when some bricks are down
17b94a
+TEST kill_brick $V0 $H0 $B0/${V0}1
17b94a
+TEST $CLI volume heal $V0 enable
17b94a
+$CLI volume heal $V0
17b94a
+sleep 5 #Allow time for completion of one scan
17b94a
+TEST stat $B0/${V0}0/$anon_inode_name/$link_gfid
17b94a
+TEST stat $B0/${V0}0/$anon_inode_name/$rename_dir_gfid
17b94a
+TEST stat $B0/${V0}0/$anon_inode_name/$dir_gfid
17b94a
+rename_dir_inum=$(STAT_INO $B0/${V0}0/$anon_inode_name/$rename_dir_gfid)
17b94a
+
17b94a
+TEST $CLI volume start $V0 force
17b94a
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "^1$" afr_child_up_status $V0 1
17b94a
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0
17b94a
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_anon_entry_count $B0/${V0}0
17b94a
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_anon_entry_count $B0/${V0}1
17b94a
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_anon_entry_count $B0/${V0}2
17b94a
+
17b94a
+#Test that rename indeed happened instead of rmdir/mkdir
17b94a
+renamed_dir_inum=$(STAT_INO $B0/${V0}0/d2/a)
17b94a
+EXPECT "$rename_dir_inum" echo $renamed_dir_inum
17b94a
+cleanup;
17b94a
diff --git a/tests/basic/afr/entry-self-heal-anon-dir-off.t b/tests/basic/afr/entry-self-heal-anon-dir-off.t
17b94a
new file mode 100644
17b94a
index 0000000..0803a08
17b94a
--- /dev/null
17b94a
+++ b/tests/basic/afr/entry-self-heal-anon-dir-off.t
17b94a
@@ -0,0 +1,464 @@
17b94a
+#!/bin/bash
17b94a
+
17b94a
+#This file checks if missing entry self-heal and entry self-heal are working
17b94a
+#as expected.
17b94a
+. $(dirname $0)/../../include.rc
17b94a
+. $(dirname $0)/../../volume.rc
17b94a
+. $(dirname $0)/../../afr.rc
17b94a
+
17b94a
+cleanup;
17b94a
+
17b94a
+function get_file_type {
17b94a
+        stat -c "%a:%F:%g:%t:%T:%u" $1
17b94a
+}
17b94a
+
17b94a
+function diff_dirs {
17b94a
+        diff <(ls $1 | sort) <(ls $2 | sort)
17b94a
+}
17b94a
+
17b94a
+function heal_status {
17b94a
+        local f1_path="${1}/${3}"
17b94a
+        local f2_path="${2}/${3}"
17b94a
+        local insync=""
17b94a
+        diff_dirs $f1_path $f2_path
17b94a
+        if [ $? -eq 0 ];
17b94a
+        then
17b94a
+                insync="Y"
17b94a
+        else
17b94a
+                insync="N"
17b94a
+        fi
17b94a
+        local xattr11=$(get_hex_xattr trusted.afr.$V0-client-0 $f1_path)
17b94a
+        local xattr12=$(get_hex_xattr trusted.afr.$V0-client-1 $f1_path)
17b94a
+        local xattr21=$(get_hex_xattr trusted.afr.$V0-client-0 $f2_path)
17b94a
+        local xattr22=$(get_hex_xattr trusted.afr.$V0-client-1 $f2_path)
17b94a
+        local dirty1=$(get_hex_xattr trusted.afr.dirty $f1_path)
17b94a
+        local dirty2=$(get_hex_xattr trusted.afr.dirty $f2_path)
17b94a
+        if [ -z $xattr11 ]; then xattr11="000000000000000000000000"; fi
17b94a
+        if [ -z $xattr12 ]; then xattr12="000000000000000000000000"; fi
17b94a
+        if [ -z $xattr21 ]; then xattr21="000000000000000000000000"; fi
17b94a
+        if [ -z $xattr22 ]; then xattr22="000000000000000000000000"; fi
17b94a
+        if [ -z $dirty1 ]; then dirty1="000000000000000000000000"; fi
17b94a
+        if [ -z $dirty2 ]; then dirty2="000000000000000000000000"; fi
17b94a
+        echo ${insync}${xattr11}${xattr12}${xattr21}${xattr22}${dirty1}${dirty2}
17b94a
+}
17b94a
+
17b94a
+function is_heal_done {
17b94a
+        local zero_xattr="000000000000000000000000"
17b94a
+        if [ "$(heal_status $@)" == "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" ];
17b94a
+        then
17b94a
+                echo "Y"
17b94a
+        else
17b94a
+                echo "N"
17b94a
+        fi
17b94a
+}
17b94a
+
17b94a
+function print_pending_heals {
17b94a
+        local result=":"
17b94a
+        for i in "$@";
17b94a
+        do
17b94a
+                if [ "N" == $(is_heal_done $B0/${V0}0 $B0/${V0}1 $i) ];
17b94a
+                then
17b94a
+                        result="$result:$i"
17b94a
+                fi
17b94a
+        done
17b94a
+#To prevent any match for EXPECT_WITHIN, print a char non-existent in file-names
17b94a
+        if [ $result == ":" ]; then result="~"; fi
17b94a
+        echo $result
17b94a
+}
17b94a
+
17b94a
+zero_xattr="000000000000000000000000"
17b94a
+TEST glusterd
17b94a
+TEST pidof glusterd
17b94a
+TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1}
17b94a
+TEST $CLI volume heal $V0 disable
17b94a
+TEST $CLI volume set $V0 cluster.use-anonymous-inode off
17b94a
+TEST $CLI volume set $V0 performance.write-behind off
17b94a
+TEST $CLI volume set $V0 performance.read-ahead off
17b94a
+TEST $CLI volume set $V0 performance.readdir-ahead off
17b94a
+TEST $CLI volume set $V0 performance.open-behind off
17b94a
+TEST $CLI volume set $V0 performance.stat-prefetch off
17b94a
+TEST $CLI volume set $V0 performance.io-cache off
17b94a
+TEST $CLI volume set $V0 performance.quick-read off
17b94a
+TEST $CLI volume set $V0 cluster.data-self-heal on
17b94a
+TEST $CLI volume set $V0 cluster.metadata-self-heal on
17b94a
+TEST $CLI volume set $V0 cluster.entry-self-heal on
17b94a
+TEST $CLI volume start $V0
17b94a
+
17b94a
+TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 --use-readdirp=no $M0
17b94a
+cd $M0
17b94a
+#_me_ is dir on which missing entry self-heal happens, _heal is where dir self-heal happens
17b94a
+#spb is split-brain, fool is all fool
17b94a
+
17b94a
+#source_self_accusing means there exists source and a sink which self-accuses.
17b94a
+#This simulates failures where fops failed on the bricks without it going down.
17b94a
+#Something like EACCESS/EDQUOT etc
17b94a
+
17b94a
+TEST mkdir spb_heal spb spb_me_heal spb_me fool_heal fool_me v1_fool_heal v1_fool_me source_creations_heal source_deletions_heal source_creations_me source_deletions_me v1_dirty_me v1_dirty_heal source_self_accusing
17b94a
+TEST mkfifo source_deletions_heal/fifo
17b94a
+TEST mknod  source_deletions_heal/block b 4 5
17b94a
+TEST mknod  source_deletions_heal/char c 1 5
17b94a
+TEST touch  source_deletions_heal/file
17b94a
+TEST ln -s  source_deletions_heal/file source_deletions_heal/slink
17b94a
+TEST mkdir  source_deletions_heal/dir1
17b94a
+TEST mkdir  source_deletions_heal/dir1/dir2
17b94a
+
17b94a
+TEST mkfifo source_deletions_me/fifo
17b94a
+TEST mknod  source_deletions_me/block b 4 5
17b94a
+TEST mknod  source_deletions_me/char c 1 5
17b94a
+TEST touch  source_deletions_me/file
17b94a
+TEST ln -s  source_deletions_me/file source_deletions_me/slink
17b94a
+TEST mkdir  source_deletions_me/dir1
17b94a
+TEST mkdir  source_deletions_me/dir1/dir2
17b94a
+
17b94a
+TEST mkfifo source_self_accusing/fifo
17b94a
+TEST mknod  source_self_accusing/block b 4 5
17b94a
+TEST mknod  source_self_accusing/char c 1 5
17b94a
+TEST touch  source_self_accusing/file
17b94a
+TEST ln -s  source_self_accusing/file source_self_accusing/slink
17b94a
+TEST mkdir  source_self_accusing/dir1
17b94a
+TEST mkdir  source_self_accusing/dir1/dir2
17b94a
+
17b94a
+TEST kill_brick $V0 $H0 $B0/${V0}0
17b94a
+
17b94a
+TEST touch spb_heal/0 spb/0 spb_me_heal/0 spb_me/0 fool_heal/0 fool_me/0 v1_fool_heal/0 v1_fool_me/0 v1_dirty_heal/0 v1_dirty_me/0
17b94a
+TEST rm -rf source_deletions_heal/fifo source_deletions_heal/block source_deletions_heal/char source_deletions_heal/file source_deletions_heal/slink source_deletions_heal/dir1
17b94a
+TEST rm -rf source_deletions_me/fifo source_deletions_me/block source_deletions_me/char source_deletions_me/file source_deletions_me/slink source_deletions_me/dir1
17b94a
+TEST rm -rf source_self_accusing/fifo source_self_accusing/block source_self_accusing/char source_self_accusing/file source_self_accusing/slink source_self_accusing/dir1
17b94a
+
17b94a
+#Test that the files are deleted
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_heal/fifo
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_heal/block
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_heal/char
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_heal/file
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_heal/slink
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_heal/dir1
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_me/fifo
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_me/block
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_me/char
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_me/file
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_me/slink
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_me/dir1
17b94a
+TEST ! stat $B0/${V0}1/source_self_accusing/fifo
17b94a
+TEST ! stat $B0/${V0}1/source_self_accusing/block
17b94a
+TEST ! stat $B0/${V0}1/source_self_accusing/char
17b94a
+TEST ! stat $B0/${V0}1/source_self_accusing/file
17b94a
+TEST ! stat $B0/${V0}1/source_self_accusing/slink
17b94a
+TEST ! stat $B0/${V0}1/source_self_accusing/dir1
17b94a
+
17b94a
+
17b94a
+TEST mkfifo source_creations_heal/fifo
17b94a
+TEST mknod  source_creations_heal/block b 4 5
17b94a
+TEST mknod  source_creations_heal/char c 1 5
17b94a
+TEST touch  source_creations_heal/file
17b94a
+TEST ln -s  source_creations_heal/file source_creations_heal/slink
17b94a
+TEST mkdir  source_creations_heal/dir1
17b94a
+TEST mkdir  source_creations_heal/dir1/dir2
17b94a
+
17b94a
+TEST mkfifo source_creations_me/fifo
17b94a
+TEST mknod  source_creations_me/block b 4 5
17b94a
+TEST mknod  source_creations_me/char c 1 5
17b94a
+TEST touch  source_creations_me/file
17b94a
+TEST ln -s  source_creations_me/file source_creations_me/slink
17b94a
+TEST mkdir  source_creations_me/dir1
17b94a
+TEST mkdir  source_creations_me/dir1/dir2
17b94a
+
17b94a
+$CLI volume stop $V0
17b94a
+
17b94a
+#simulate fool fool scenario for fool_* dirs
17b94a
+setfattr -x trusted.afr.$V0-client-0 $B0/${V0}1/{fool_heal,fool_me}
17b94a
+setfattr -n trusted.afr.dirty -v 0x000000000000000000000001 $B0/${V0}1/{fool_heal,fool_me}
17b94a
+setfattr -n trusted.afr.$V0-client-1 -v 0x000000000000000000000001 $B0/${V0}1/{v1_fool_heal,v1_fool_me}
17b94a
+
17b94a
+#Simulate v1-dirty(self-accusing but no pending ops on others) scenario for v1-dirty
17b94a
+setfattr -x trusted.afr.$V0-client-0 $B0/${V0}1/v1_dirty_{heal,me}
17b94a
+setfattr -n trusted.afr.$V0-client-1 -v 0x000000000000000000000001 $B0/${V0}1/v1_dirty_{heal,me}
17b94a
+
17b94a
+$CLI volume start $V0 force
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
+TEST kill_brick $V0 $H0 $B0/${V0}1
17b94a
+
17b94a
+TEST touch spb_heal/1 spb/0 spb_me_heal/1 spb_me/0 fool_heal/1 fool_me/1 v1_fool_heal/1 v1_fool_me/1
17b94a
+
17b94a
+$CLI volume stop $V0
17b94a
+
17b94a
+#simulate fool fool scenario for fool_* dirs
17b94a
+setfattr -x trusted.afr.$V0-client-1 $B0/${V0}0/{fool_heal,fool_me}
17b94a
+setfattr -n trusted.afr.dirty -v 0x000000000000000000000001 $B0/${V0}1/{fool_heal,fool_me}
17b94a
+setfattr -n trusted.afr.$V0-client-0 -v 0x000000000000000000000001 $B0/${V0}1/{v1_fool_heal,v1_fool_me}
17b94a
+
17b94a
+#simulate self-accusing for source_self_accusing
17b94a
+TEST setfattr -n trusted.afr.$V0-client-0 -v 0x000000000000000000000006 $B0/${V0}0/source_self_accusing
17b94a
+
17b94a
+$CLI volume start $V0 force
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 0
17b94a
+
17b94a
+# Check if conservative merges happened correctly on _me_ dirs
17b94a
+TEST stat spb_me_heal/1
17b94a
+TEST stat $B0/${V0}0/spb_me_heal/1
17b94a
+TEST stat $B0/${V0}1/spb_me_heal/1
17b94a
+
17b94a
+TEST stat spb_me_heal/0
17b94a
+TEST stat $B0/${V0}0/spb_me_heal/0
17b94a
+TEST stat $B0/${V0}1/spb_me_heal/0
17b94a
+
17b94a
+TEST stat fool_me/1
17b94a
+TEST stat $B0/${V0}0/fool_me/1
17b94a
+TEST stat $B0/${V0}1/fool_me/1
17b94a
+
17b94a
+TEST stat fool_me/0
17b94a
+TEST stat $B0/${V0}0/fool_me/0
17b94a
+TEST stat $B0/${V0}1/fool_me/0
17b94a
+
17b94a
+TEST stat v1_fool_me/0
17b94a
+TEST stat $B0/${V0}0/v1_fool_me/0
17b94a
+TEST stat $B0/${V0}1/v1_fool_me/0
17b94a
+
17b94a
+TEST stat v1_fool_me/1
17b94a
+TEST stat $B0/${V0}0/v1_fool_me/1
17b94a
+TEST stat $B0/${V0}1/v1_fool_me/1
17b94a
+
17b94a
+TEST stat v1_dirty_me/0
17b94a
+TEST stat $B0/${V0}0/v1_dirty_me/0
17b94a
+TEST stat $B0/${V0}1/v1_dirty_me/0
17b94a
+
17b94a
+#Check if files that have gfid-mismatches in _me_ are giving EIO
17b94a
+TEST ! stat spb_me/0
17b94a
+
17b94a
+#Check if stale files are deleted on access
17b94a
+TEST ! stat source_deletions_me/fifo
17b94a
+TEST ! stat $B0/${V0}0/source_deletions_me/fifo
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_me/fifo
17b94a
+TEST ! stat source_deletions_me/block
17b94a
+TEST ! stat $B0/${V0}0/source_deletions_me/block
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_me/block
17b94a
+TEST ! stat source_deletions_me/char
17b94a
+TEST ! stat $B0/${V0}0/source_deletions_me/char
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_me/char
17b94a
+TEST ! stat source_deletions_me/file
17b94a
+TEST ! stat $B0/${V0}0/source_deletions_me/file
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_me/file
17b94a
+TEST ! stat source_deletions_me/file
17b94a
+TEST ! stat $B0/${V0}0/source_deletions_me/file
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_me/file
17b94a
+TEST ! stat source_deletions_me/dir1/dir2
17b94a
+TEST ! stat $B0/${V0}0/source_deletions_me/dir1/dir2
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_me/dir1/dir2
17b94a
+TEST ! stat source_deletions_me/dir1
17b94a
+TEST ! stat $B0/${V0}0/source_deletions_me/dir1
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_me/dir1
17b94a
+
17b94a
+#Test if the files created as part of access are healed correctly
17b94a
+r=$(get_file_type source_creations_me/fifo)
17b94a
+EXPECT "$r" get_file_type $B0/${V0}0/source_creations_me/fifo
17b94a
+EXPECT "$r" get_file_type $B0/${V0}1/source_creations_me/fifo
17b94a
+TEST [ -p source_creations_me/fifo ]
17b94a
+
17b94a
+r=$(get_file_type source_creations_me/block)
17b94a
+EXPECT "$r" get_file_type $B0/${V0}0/source_creations_me/block
17b94a
+EXPECT "$r" get_file_type $B0/${V0}1/source_creations_me/block
17b94a
+EXPECT "^4 5$" stat -c "%t %T" $B0/${V0}1/source_creations_me/block
17b94a
+EXPECT "^4 5$" stat -c "%t %T" $B0/${V0}0/source_creations_me/block
17b94a
+TEST [ -b source_creations_me/block ]
17b94a
+
17b94a
+r=$(get_file_type source_creations_me/char)
17b94a
+EXPECT "$r" get_file_type $B0/${V0}0/source_creations_me/char
17b94a
+EXPECT "$r" get_file_type $B0/${V0}1/source_creations_me/char
17b94a
+EXPECT "^1 5$" stat -c "%t %T" $B0/${V0}1/source_creations_me/char
17b94a
+EXPECT "^1 5$" stat -c "%t %T" $B0/${V0}0/source_creations_me/char
17b94a
+TEST [ -c source_creations_me/char ]
17b94a
+
17b94a
+r=$(get_file_type source_creations_me/file)
17b94a
+EXPECT "$r" get_file_type $B0/${V0}0/source_creations_me/file
17b94a
+EXPECT "$r" get_file_type $B0/${V0}1/source_creations_me/file
17b94a
+TEST [ -f source_creations_me/file ]
17b94a
+
17b94a
+r=$(get_file_type source_creations_me/slink)
17b94a
+EXPECT "$r" get_file_type $B0/${V0}0/source_creations_me/slink
17b94a
+EXPECT "$r" get_file_type $B0/${V0}1/source_creations_me/slink
17b94a
+TEST [ -h source_creations_me/slink ]
17b94a
+
17b94a
+r=$(get_file_type source_creations_me/dir1/dir2)
17b94a
+EXPECT "$r" get_file_type $B0/${V0}0/source_creations_me/dir1/dir2
17b94a
+EXPECT "$r" get_file_type $B0/${V0}1/source_creations_me/dir1/dir2
17b94a
+TEST [ -d source_creations_me/dir1/dir2 ]
17b94a
+
17b94a
+r=$(get_file_type source_creations_me/dir1)
17b94a
+EXPECT "$r" get_file_type $B0/${V0}0/source_creations_me/dir1
17b94a
+EXPECT "$r" get_file_type $B0/${V0}1/source_creations_me/dir1
17b94a
+TEST [ -d source_creations_me/dir1 ]
17b94a
+
17b94a
+#Trigger heal and check _heal dirs are healed properly
17b94a
+#Trigger change in event generation number. That way inodes would get refreshed during lookup
17b94a
+TEST kill_brick $V0 $H0 $B0/${V0}1
17b94a
+$CLI volume start $V0 force
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 0
17b94a
+
17b94a
+TEST stat spb_heal
17b94a
+TEST stat spb_me_heal
17b94a
+TEST stat fool_heal
17b94a
+TEST stat fool_me
17b94a
+TEST stat v1_fool_heal
17b94a
+TEST stat v1_fool_me
17b94a
+TEST stat source_deletions_heal
17b94a
+TEST stat source_deletions_me
17b94a
+TEST stat source_self_accusing
17b94a
+TEST stat source_creations_heal
17b94a
+TEST stat source_creations_me
17b94a
+TEST stat v1_dirty_heal
17b94a
+TEST stat v1_dirty_me
17b94a
+TEST $CLI volume stop $V0
17b94a
+TEST rm -rf $B0/${V0}{0,1}/.glusterfs/indices/xattrop/*
17b94a
+
17b94a
+$CLI volume start $V0
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 0
17b94a
+
17b94a
+#Create base entry in indices/xattrop
17b94a
+echo "Data" > $M0/FILE
17b94a
+rm -f $M0/FILE
17b94a
+EXPECT "1" count_index_entries $B0/${V0}0
17b94a
+EXPECT "1" count_index_entries $B0/${V0}1
17b94a
+
17b94a
+TEST $CLI volume stop $V0;
17b94a
+
17b94a
+#Create entries for fool_heal and fool_me to ensure they are fully healed and dirty xattrs erased, before triggering index heal
17b94a
+create_brick_xattrop_entry $B0/${V0}0 fool_heal fool_me source_creations_heal/dir1
17b94a
+
17b94a
+$CLI volume start $V0
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 0
17b94a
+
17b94a
+$CLI volume heal $V0 enable
17b94a
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
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
+
17b94a
+TEST $CLI volume heal $V0;
17b94a
+EXPECT_WITHIN $HEAL_TIMEOUT "~" print_pending_heals spb_heal spb_me_heal fool_heal fool_me v1_fool_heal v1_fool_me source_deletions_heal source_deletions_me source_creations_heal source_creations_me v1_dirty_heal v1_dirty_me source_self_accusing
17b94a
+
17b94a
+EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 spb_heal
17b94a
+EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 spb_me_heal
17b94a
+EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 fool_heal
17b94a
+EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 fool_me
17b94a
+EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 v1_fool_heal
17b94a
+EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 v1_fool_me
17b94a
+EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 source_deletions_heal
17b94a
+EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 source_deletions_me
17b94a
+EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 source_self_accusing
17b94a
+EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 source_creations_heal
17b94a
+EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 source_creations_me
17b94a
+EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 v1_dirty_heal
17b94a
+EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 v1_dirty_me
17b94a
+
17b94a
+#Don't access the files/dirs from mount point as that may cause self-heals
17b94a
+# Check if conservative merges happened correctly on heal dirs
17b94a
+TEST stat $B0/${V0}0/spb_heal/1
17b94a
+TEST stat $B0/${V0}1/spb_heal/1
17b94a
+
17b94a
+TEST stat $B0/${V0}0/spb_heal/0
17b94a
+TEST stat $B0/${V0}1/spb_heal/0
17b94a
+
17b94a
+TEST stat $B0/${V0}0/fool_heal/1
17b94a
+TEST stat $B0/${V0}1/fool_heal/1
17b94a
+
17b94a
+TEST stat $B0/${V0}0/fool_heal/0
17b94a
+TEST stat $B0/${V0}1/fool_heal/0
17b94a
+
17b94a
+TEST stat $B0/${V0}0/v1_fool_heal/0
17b94a
+TEST stat $B0/${V0}1/v1_fool_heal/0
17b94a
+
17b94a
+TEST stat $B0/${V0}0/v1_fool_heal/1
17b94a
+TEST stat $B0/${V0}1/v1_fool_heal/1
17b94a
+
17b94a
+TEST stat $B0/${V0}0/v1_dirty_heal/0
17b94a
+TEST stat $B0/${V0}1/v1_dirty_heal/0
17b94a
+
17b94a
+#Check if files that have gfid-mismatches in spb are giving EIO
17b94a
+TEST ! stat spb/0
17b94a
+
17b94a
+#Check if stale files are deleted on access
17b94a
+TEST ! stat $B0/${V0}0/source_deletions_heal/fifo
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_heal/fifo
17b94a
+TEST ! stat $B0/${V0}0/source_deletions_heal/block
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_heal/block
17b94a
+TEST ! stat $B0/${V0}0/source_deletions_heal/char
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_heal/char
17b94a
+TEST ! stat $B0/${V0}0/source_deletions_heal/file
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_heal/file
17b94a
+TEST ! stat $B0/${V0}0/source_deletions_heal/file
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_heal/file
17b94a
+TEST ! stat $B0/${V0}0/source_deletions_heal/dir1/dir2
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_heal/dir1/dir2
17b94a
+TEST ! stat $B0/${V0}0/source_deletions_heal/dir1
17b94a
+TEST ! stat $B0/${V0}1/source_deletions_heal/dir1
17b94a
+
17b94a
+#Check if stale files are deleted on access
17b94a
+TEST ! stat $B0/${V0}0/source_self_accusing/fifo
17b94a
+TEST ! stat $B0/${V0}1/source_self_accusing/fifo
17b94a
+TEST ! stat $B0/${V0}0/source_self_accusing/block
17b94a
+TEST ! stat $B0/${V0}1/source_self_accusing/block
17b94a
+TEST ! stat $B0/${V0}0/source_self_accusing/char
17b94a
+TEST ! stat $B0/${V0}1/source_self_accusing/char
17b94a
+TEST ! stat $B0/${V0}0/source_self_accusing/file
17b94a
+TEST ! stat $B0/${V0}1/source_self_accusing/file
17b94a
+TEST ! stat $B0/${V0}0/source_self_accusing/file
17b94a
+TEST ! stat $B0/${V0}1/source_self_accusing/file
17b94a
+TEST ! stat $B0/${V0}0/source_self_accusing/dir1/dir2
17b94a
+TEST ! stat $B0/${V0}1/source_self_accusing/dir1/dir2
17b94a
+TEST ! stat $B0/${V0}0/source_self_accusing/dir1
17b94a
+TEST ! stat $B0/${V0}1/source_self_accusing/dir1
17b94a
+
17b94a
+#Test if the files created as part of full self-heal correctly
17b94a
+r=$(get_file_type $B0/${V0}0/source_creations_heal/fifo)
17b94a
+EXPECT "$r" get_file_type $B0/${V0}1/source_creations_heal/fifo
17b94a
+TEST [ -p $B0/${V0}0/source_creations_heal/fifo ]
17b94a
+EXPECT "^4 5$" stat -c "%t %T" $B0/${V0}1/source_creations_heal/block
17b94a
+EXPECT "^4 5$" stat -c "%t %T" $B0/${V0}0/source_creations_heal/block
17b94a
+
17b94a
+r=$(get_file_type $B0/${V0}0/source_creations_heal/block)
17b94a
+EXPECT "$r" get_file_type $B0/${V0}1/source_creations_heal/block
17b94a
+
17b94a
+r=$(get_file_type $B0/${V0}0/source_creations_heal/char)
17b94a
+EXPECT "$r" get_file_type $B0/${V0}1/source_creations_heal/char
17b94a
+EXPECT "^1 5$" stat -c "%t %T" $B0/${V0}1/source_creations_heal/char
17b94a
+EXPECT "^1 5$" stat -c "%t %T" $B0/${V0}0/source_creations_heal/char
17b94a
+
17b94a
+r=$(get_file_type $B0/${V0}0/source_creations_heal/file)
17b94a
+EXPECT "$r" get_file_type $B0/${V0}1/source_creations_heal/file
17b94a
+TEST [ -f $B0/${V0}0/source_creations_heal/file ]
17b94a
+
17b94a
+r=$(get_file_type source_creations_heal/file $B0/${V0}0/slink)
17b94a
+EXPECT "$r" get_file_type $B0/${V0}1/source_creations_heal/file slink
17b94a
+TEST [ -h $B0/${V0}0/source_creations_heal/slink ]
17b94a
+
17b94a
+r=$(get_file_type $B0/${V0}0/source_creations_heal/dir1/dir2)
17b94a
+EXPECT "$r" get_file_type $B0/${V0}1/source_creations_heal/dir1/dir2
17b94a
+TEST [ -d $B0/${V0}0/source_creations_heal/dir1/dir2 ]
17b94a
+
17b94a
+r=$(get_file_type $B0/${V0}0/source_creations_heal/dir1)
17b94a
+EXPECT "$r" get_file_type $B0/${V0}1/source_creations_heal/dir1
17b94a
+TEST [ -d $B0/${V0}0/source_creations_heal/dir1 ]
17b94a
+
17b94a
+cd -
17b94a
+
17b94a
+#Anonymous directory shouldn't be created
17b94a
+TEST mkdir $M0/rename-dir
17b94a
+before_rename=$(STAT_INO $B0/${V0}1/rename-dir)
17b94a
+TEST kill_brick $V0 $H0 $B0/${V0}1
17b94a
+TEST mv $M0/rename-dir $M0/new-name
17b94a
+TEST $CLI volume start $V0 force
17b94a
+#Since features.ctime is not enabled by default in downstream, the below test
17b94a
+#will fail. If ctime feature is enabled, there will be trusted.glusterfs.mdata
17b94a
+#xattr set which will differ for the parent in the gfid split-brain scenario
17b94a
+#and when lookup is triggered, the gfid gets added to indices/xattrop leading
17b94a
+#the below test to pass in upstream. Hence commenting it here.
17b94a
+#'spb' is in split-brain so pending-heal-count will be 2
17b94a
+#EXPECT_WITHIN $HEAL_TIMEOUT "^2$" get_pending_heal_count $V0
17b94a
+after_rename=$(STAT_INO $B0/${V0}1/new-name)
17b94a
+EXPECT "0" echo $(ls -a $B0/${V0}0/ | grep anonymous-inode | wc -l)
17b94a
+EXPECT "0" echo $(ls -a $B0/${V0}1/ | grep anonymous-inode | wc -l)
17b94a
+EXPECT_NOT "$before_rename" echo $after_rename
17b94a
+cleanup
17b94a
diff --git a/tests/basic/afr/rename-data-loss.t b/tests/basic/afr/rename-data-loss.t
17b94a
new file mode 100644
17b94a
index 0000000..256ee2a
17b94a
--- /dev/null
17b94a
+++ b/tests/basic/afr/rename-data-loss.t
17b94a
@@ -0,0 +1,72 @@
17b94a
+#!/bin/bash
17b94a
+#Self-heal tests
17b94a
+. $(dirname $0)/../../include.rc
17b94a
+. $(dirname $0)/../../volume.rc
17b94a
+. $(dirname $0)/../../afr.rc
17b94a
+
17b94a
+cleanup;
17b94a
+
17b94a
+TEST glusterd
17b94a
+TEST pidof glusterd
17b94a
+TEST $CLI volume create $V0 replica 2 $H0:$B0/brick{0,1}
17b94a
+TEST $CLI volume set $V0 write-behind off
17b94a
+TEST $CLI volume set $V0 self-heal-daemon off
17b94a
+TEST $CLI volume set $V0 data-self-heal off
17b94a
+TEST $CLI volume set $V0 metadata-self-heal off
17b94a
+TEST $CLI volume set $V0 entry-self-heal off
17b94a
+TEST $CLI volume start $V0
17b94a
+EXPECT 'Started' volinfo_field $V0 'Status'
17b94a
+TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0;
17b94a
+
17b94a
+cd $M0
17b94a
+TEST `echo "line1" >> file1`
17b94a
+TEST mkdir dir1
17b94a
+TEST mkdir dir2
17b94a
+TEST mkdir -p dir1/dira/dirb
17b94a
+TEST `echo "line1">>dir1/dira/dirb/file1`
17b94a
+TEST mkdir delete_me
17b94a
+TEST `echo "line1" >> delete_me/file1`
17b94a
+
17b94a
+#brick0 has witnessed the second write while brick1 is down.
17b94a
+TEST kill_brick $V0 $H0 $B0/brick1
17b94a
+TEST `echo "line2" >> file1`
17b94a
+TEST `echo "line2" >> dir1/dira/dirb/file1`
17b94a
+TEST `echo "line2" >> delete_me/file1`
17b94a
+
17b94a
+#Toggle the bricks that are up/down.
17b94a
+TEST $CLI volume start $V0 force
17b94a
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1
17b94a
+TEST kill_brick $V0 $H0 $B0/brick0
17b94a
+
17b94a
+#Rename when the 'source' brick0 for data-selfheals is down.
17b94a
+mv file1 file2
17b94a
+mv dir1/dira dir2
17b94a
+
17b94a
+#Delete a dir when brick0 is down.
17b94a
+rm -rf delete_me
17b94a
+cd -
17b94a
+
17b94a
+#Bring everything up and trigger heal
17b94a
+TEST $CLI volume set $V0 self-heal-daemon on
17b94a
+TEST $CLI volume start $V0 force
17b94a
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0
17b94a
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
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
+TEST $CLI volume heal $V0
17b94a
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0
17b94a
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_anon_entry_count $B0/brick0
17b94a
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_anon_entry_count $B0/brick1
17b94a
+
17b94a
+#Remount to avoid reading from caches
17b94a
+EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
17b94a
+TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0;
17b94a
+EXPECT "line2" tail -1 $M0/file2
17b94a
+EXPECT "line2" tail -1 $M0/dir2/dira/dirb/file1
17b94a
+TEST ! stat $M0/delete_me/file1
17b94a
+TEST ! stat $M0/delete_me
17b94a
+
17b94a
+anon_inode_name=$(ls -a $B0/brick0 | grep glusterfs-anonymous-inode)
17b94a
+TEST [[ -d $B0/brick0/$anon_inode_name ]]
17b94a
+TEST [[ -d $B0/brick1/$anon_inode_name ]]
17b94a
+cleanup
17b94a
diff --git a/tests/bugs/replicate/bug-1744548-heal-timeout.t b/tests/bugs/replicate/bug-1744548-heal-timeout.t
17b94a
index c208112..0115350 100644
17b94a
--- a/tests/bugs/replicate/bug-1744548-heal-timeout.t
17b94a
+++ b/tests/bugs/replicate/bug-1744548-heal-timeout.t
17b94a
@@ -25,14 +25,14 @@ TEST ! $CLI volume heal $V0
17b94a
 TEST $CLI volume profile $V0 start
17b94a
 TEST $CLI volume profile $V0 info clear
17b94a
 TEST $CLI volume heal $V0 enable
17b94a
-# Each brick does 3 opendirs, corresponding to dirty, xattrop and entry-changes
17b94a
-EXPECT_WITHIN $HEAL_TIMEOUT "^333$" get_cumulative_opendir_count
17b94a
+# Each brick does 4 opendirs, corresponding to dirty, xattrop and entry-changes, anonymous-inode
17b94a
+EXPECT_WITHIN 4 "^444$" get_cumulative_opendir_count
17b94a
 
17b94a
 # Check that a change in heal-timeout is honoured immediately.
17b94a
 TEST $CLI volume set $V0 cluster.heal-timeout 5
17b94a
 sleep 10
17b94a
 # Two crawls must have happened.
17b94a
-EXPECT_WITHIN $HEAL_TIMEOUT "^999$" get_cumulative_opendir_count
17b94a
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "^121212$" get_cumulative_opendir_count
17b94a
 
17b94a
 # shd must not heal if it is disabled and heal-timeout is changed.
17b94a
 TEST $CLI volume heal $V0 disable
17b94a
diff --git a/tests/features/trash.t b/tests/features/trash.t
17b94a
index 472e909..da5b50b 100755
17b94a
--- a/tests/features/trash.t
17b94a
+++ b/tests/features/trash.t
17b94a
@@ -94,105 +94,105 @@ wildcard_not_exists() {
17b94a
         if [ $? -eq 0 ]; then echo "Y"; else echo "N"; fi
17b94a
 }
17b94a
 
17b94a
-# testing glusterd [1-3]
17b94a
+# testing glusterd
17b94a
 TEST glusterd
17b94a
 TEST pidof glusterd
17b94a
 TEST $CLI volume info
17b94a
 
17b94a
-# creating distributed volume [4]
17b94a
+# creating distributed volume
17b94a
 TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2}
17b94a
 
17b94a
-# checking volume status [5-7]
17b94a
+# checking volume status
17b94a
 EXPECT "$V0" volinfo_field $V0 'Volume Name'
17b94a
 EXPECT 'Created' volinfo_field $V0 'Status'
17b94a
 EXPECT '2' brick_count $V0
17b94a
 
17b94a
-# test without enabling trash translator [8]
17b94a
+# test without enabling trash translator
17b94a
 TEST start_vol $V0 $M0
17b94a
 
17b94a
-# test on enabling trash translator [9-10]
17b94a
+# test on enabling trash translator
17b94a
 TEST $CLI volume set $V0 features.trash on
17b94a
 EXPECT 'on' volinfo_field $V0 'features.trash'
17b94a
 
17b94a
-# files directly under mount point [11]
17b94a
+# files directly under mount point
17b94a
 create_files $M0/file1 $M0/file2
17b94a
 TEST file_exists $V0 file1 file2
17b94a
 
17b94a
-# perform unlink [12]
17b94a
+# perform unlink
17b94a
 TEST unlink_op file1
17b94a
 
17b94a
-# perform truncate [13]
17b94a
+# perform truncate
17b94a
 TEST truncate_op file2 4
17b94a
 
17b94a
-# create files directory hierarchy and check [14]
17b94a
+# create files directory hierarchy and check
17b94a
 mkdir -p $M0/1/2/3
17b94a
 create_files $M0/1/2/3/foo1 $M0/1/2/3/foo2
17b94a
 TEST file_exists $V0 1/2/3/foo1 1/2/3/foo2
17b94a
 
17b94a
-# perform unlink [15]
17b94a
+# perform unlink
17b94a
 TEST unlink_op 1/2/3/foo1
17b94a
 
17b94a
-# perform truncate [16]
17b94a
+# perform truncate
17b94a
 TEST truncate_op 1/2/3/foo2 4
17b94a
 
17b94a
 # create a directory for eliminate pattern
17b94a
 mkdir $M0/a
17b94a
 
17b94a
-# set the eliminate pattern [17-18]
17b94a
+# set the eliminate pattern
17b94a
 TEST $CLI volume set $V0 features.trash-eliminate-path /a
17b94a
 EXPECT '/a' volinfo_field $V0 'features.trash-eliminate-path'
17b94a
 
17b94a
-# create two files and check [19]
17b94a
+# create two files and check
17b94a
 create_files $M0/a/test1 $M0/a/test2
17b94a
 TEST file_exists $V0 a/test1 a/test2
17b94a
 
17b94a
-# remove from eliminate pattern [20]
17b94a
+# remove from eliminate pattern
17b94a
 rm -f $M0/a/test1
17b94a
 EXPECT "Y" wildcard_not_exists $M0/.trashcan/a/test1*
17b94a
 
17b94a
-# truncate from eliminate path [21-23]
17b94a
+# truncate from eliminate path
17b94a
 truncate -s 2 $M0/a/test2
17b94a
 TEST [ -e $M0/a/test2 ]
17b94a
 TEST [ `ls -l $M0/a/test2 | awk '{print $5}'` -eq 2 ]
17b94a
 EXPECT "Y" wildcard_not_exists $M0/.trashcan/a/test2*
17b94a
 
17b94a
-# set internal op on [24-25]
17b94a
+# set internal op on
17b94a
 TEST $CLI volume set $V0 features.trash-internal-op on
17b94a
 EXPECT 'on' volinfo_field $V0 'features.trash-internal-op'
17b94a
 
17b94a
-# again create two files and check [26]
17b94a
+# again create two files and check
17b94a
 create_files $M0/inop1 $M0/inop2
17b94a
 TEST file_exists $V0 inop1 inop2
17b94a
 
17b94a
-# perform unlink [27]
17b94a
+# perform unlink
17b94a
 TEST unlink_op inop1
17b94a
 
17b94a
-# perform truncate [28]
17b94a
+# perform truncate
17b94a
 TEST truncate_op inop2 4
17b94a
 
17b94a
-# remove one brick and restart the volume [28-31]
17b94a
+# remove one brick and restart the volume
17b94a
 TEST $CLI volume remove-brick $V0 $H0:$B0/${V0}2 force
17b94a
 EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
17b94a
 TEST $CLI volume stop $V0
17b94a
 TEST start_vol $V0 $M0 $M0/.trashcan
17b94a
 
17b94a
-# again create two files and check [33]
17b94a
+# again create two files and check
17b94a
 create_files $M0/rebal1 $M0/rebal2
17b94a
 TEST file_exists $V0 rebal1 rebal2
17b94a
 
17b94a
-# add one brick [34-35]
17b94a
+# add one brick
17b94a
 TEST $CLI volume add-brick $V0 $H0:$B0/${V0}3
17b94a
 TEST [ -d $B0/${V0}3 ]
17b94a
 
17b94a
 
17b94a
-# perform rebalance [36]
17b94a
+# perform rebalance
17b94a
 TEST $CLI volume rebalance $V0 start force
17b94a
 EXPECT_WITHIN $REBALANCE_TIMEOUT "0" rebalance_completed
17b94a
 
17b94a
 #Find out which file was migrated to the new brick
17b94a
 file_name=$(ls $B0/${V0}3/rebal*| xargs basename)
17b94a
 
17b94a
-# check whether rebalance was succesful [37-40]
17b94a
+# check whether rebalance was succesful
17b94a
 EXPECT "Y" wildcard_exists $B0/${V0}3/$file_name*
17b94a
 EXPECT "Y" wildcard_exists $B0/${V0}1/.trashcan/internal_op/$file_name*
17b94a
 
17b94a
@@ -201,52 +201,42 @@ EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
17b94a
 # force required in case rebalance is not over
17b94a
 TEST $CLI volume stop $V0 force
17b94a
 
17b94a
-# create a replicated volume [41]
17b94a
+# create a replicated volume
17b94a
 TEST $CLI volume create $V1 replica 2 $H0:$B0/${V1}{1,2}
17b94a
 
17b94a
-# checking volume status [42-45]
17b94a
+# checking volume status
17b94a
 EXPECT "$V1" volinfo_field $V1 'Volume Name'
17b94a
 EXPECT 'Replicate' volinfo_field $V1 'Type'
17b94a
 EXPECT 'Created' volinfo_field $V1 'Status'
17b94a
 EXPECT '2' brick_count $V1
17b94a
 
17b94a
-# enable trash with options and start the replicate volume by disabling automatic self-heal [46-50]
17b94a
+# enable trash with options and start the replicate volume by disabling automatic self-heal
17b94a
 TEST $CLI volume set $V1 features.trash on
17b94a
 TEST $CLI volume set $V1 features.trash-internal-op on
17b94a
 EXPECT 'on' volinfo_field $V1 'features.trash'
17b94a
 EXPECT 'on' volinfo_field $V1 'features.trash-internal-op'
17b94a
 TEST start_vol $V1 $M1 $M1/.trashcan
17b94a
 
17b94a
-# mount and check for trash directory [51]
17b94a
+# mount and check for trash directory
17b94a
 TEST [ -d $M1/.trashcan/internal_op ]
17b94a
 
17b94a
-# create a file and check [52]
17b94a
+# create a file and check
17b94a
 touch $M1/self
17b94a
 TEST [ -e $B0/${V1}1/self -a -e $B0/${V1}2/self ]
17b94a
 
17b94a
-# kill one brick and delete the file from mount point [53-54]
17b94a
+# kill one brick and delete the file from mount point
17b94a
 kill_brick $V1 $H0 $B0/${V1}1
17b94a
 EXPECT_WITHIN ${PROCESS_UP_TIMEOUT} "1" online_brick_count
17b94a
 rm -f $M1/self
17b94a
 EXPECT "Y" wildcard_exists $B0/${V1}2/.trashcan/self*
17b94a
 
17b94a
-# force start the volume and trigger the self-heal manually [55-57]
17b94a
-TEST $CLI volume start $V1 force
17b94a
-EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" online_brick_count
17b94a
-EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
17b94a
-# Since we created the file under root of the volume, it will be
17b94a
-# healed automatically
17b94a
-
17b94a
-# check for the removed file in trashcan [58]
17b94a
-EXPECT_WITHIN $HEAL_TIMEOUT "Y" wildcard_exists $B0/${V1}1/.trashcan/internal_op/self*
17b94a
-
17b94a
-# check renaming of trash directory through cli [59-62]
17b94a
+# check renaming of trash directory through cli
17b94a
 TEST $CLI volume set $V0 trash-dir abc
17b94a
 TEST start_vol $V0 $M0 $M0/abc
17b94a
 TEST [ -e $M0/abc -a ! -e $M0/.trashcan ]
17b94a
 EXPECT "Y" wildcard_exists $B0/${V0}1/abc/internal_op/rebal*
17b94a
 
17b94a
-# ensure that rename and delete operation on trash directory fails [63-65]
17b94a
+# ensure that rename and delete operation on trash directory fails
17b94a
 rm -rf $M0/abc/internal_op
17b94a
 TEST [ -e $M0/abc/internal_op ]
17b94a
 rm -rf $M0/abc/
17b94a
diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c
17b94a
index 90b4f14..6f2da11 100644
17b94a
--- a/xlators/cluster/afr/src/afr-common.c
17b94a
+++ b/xlators/cluster/afr/src/afr-common.c
17b94a
@@ -47,6 +47,41 @@ afr_quorum_errno(afr_private_t *priv)
17b94a
     return ENOTCONN;
17b94a
 }
17b94a
 
17b94a
+gf_boolean_t
17b94a
+afr_is_private_directory(afr_private_t *priv, uuid_t pargfid, const char *name,
17b94a
+                         pid_t pid)
17b94a
+{
17b94a
+    if (!__is_root_gfid(pargfid)) {
17b94a
+        return _gf_false;
17b94a
+    }
17b94a
+
17b94a
+    if (strcmp(name, GF_REPLICATE_TRASH_DIR) == 0) {
17b94a
+        /*For backward compatibility /.landfill is private*/
17b94a
+        return _gf_true;
17b94a
+    }
17b94a
+
17b94a
+    if (pid == GF_CLIENT_PID_GSYNCD) {
17b94a
+        /*geo-rep needs to create/sync private directory on slave because
17b94a
+         * it appears in changelog*/
17b94a
+        return _gf_false;
17b94a
+    }
17b94a
+
17b94a
+    if (pid == GF_CLIENT_PID_GLFS_HEAL || pid == GF_CLIENT_PID_SELF_HEALD) {
17b94a
+        if (strcmp(name, priv->anon_inode_name) == 0) {
17b94a
+            /* anonymous-inode dir is private*/
17b94a
+            return _gf_true;
17b94a
+        }
17b94a
+    } else {
17b94a
+        if (strncmp(name, AFR_ANON_DIR_PREFIX, strlen(AFR_ANON_DIR_PREFIX)) ==
17b94a
+            0) {
17b94a
+            /* anonymous-inode dir prefix is private for geo-rep to work*/
17b94a
+            return _gf_true;
17b94a
+        }
17b94a
+    }
17b94a
+
17b94a
+    return _gf_false;
17b94a
+}
17b94a
+
17b94a
 int
17b94a
 afr_fav_child_reset_sink_xattrs(void *opaque);
17b94a
 
17b94a
@@ -3301,11 +3336,10 @@ afr_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req)
17b94a
         return 0;
17b94a
     }
17b94a
 
17b94a
-    if (__is_root_gfid(loc->parent->gfid)) {
17b94a
-        if (!strcmp(loc->name, GF_REPLICATE_TRASH_DIR)) {
17b94a
-            op_errno = EPERM;
17b94a
-            goto out;
17b94a
-        }
17b94a
+    if (afr_is_private_directory(this->private, loc->parent->gfid, loc->name,
17b94a
+                                 frame->root->pid)) {
17b94a
+        op_errno = EPERM;
17b94a
+        goto out;
17b94a
     }
17b94a
 
17b94a
     local = AFR_FRAME_INIT(frame, op_errno);
17b94a
@@ -4832,6 +4866,7 @@ afr_priv_dump(xlator_t *this)
17b94a
                        priv->background_self_heal_count);
17b94a
     gf_proc_dump_write("healers", "%d", priv->healers);
17b94a
     gf_proc_dump_write("read-hash-mode", "%d", priv->hash_mode);
17b94a
+    gf_proc_dump_write("use-anonymous-inode", "%d", priv->use_anon_inode);
17b94a
     if (priv->quorum_count == AFR_QUORUM_AUTO) {
17b94a
         gf_proc_dump_write("quorum-type", "auto");
17b94a
     } else if (priv->quorum_count == 0) {
17b94a
@@ -5792,6 +5827,7 @@ afr_priv_destroy(afr_private_t *priv)
17b94a
     GF_FREE(priv->local);
17b94a
     GF_FREE(priv->pending_key);
17b94a
     GF_FREE(priv->children);
17b94a
+    GF_FREE(priv->anon_inode);
17b94a
     GF_FREE(priv->child_up);
17b94a
     GF_FREE(priv->child_latency);
17b94a
     LOCK_DESTROY(&priv->lock);
17b94a
diff --git a/xlators/cluster/afr/src/afr-dir-read.c b/xlators/cluster/afr/src/afr-dir-read.c
17b94a
index 6307b63..d64b6a9 100644
17b94a
--- a/xlators/cluster/afr/src/afr-dir-read.c
17b94a
+++ b/xlators/cluster/afr/src/afr-dir-read.c
17b94a
@@ -158,8 +158,8 @@ afr_validate_read_subvol(inode_t *inode, xlator_t *this, int par_read_subvol)
17b94a
 }
17b94a
 
17b94a
 static void
17b94a
-afr_readdir_transform_entries(gf_dirent_t *subvol_entries, int subvol,
17b94a
-                              gf_dirent_t *entries, fd_t *fd)
17b94a
+afr_readdir_transform_entries(call_frame_t *frame, gf_dirent_t *subvol_entries,
17b94a
+                              int subvol, gf_dirent_t *entries, fd_t *fd)
17b94a
 {
17b94a
     int ret = -1;
17b94a
     gf_dirent_t *entry = NULL;
17b94a
@@ -177,8 +177,8 @@ afr_readdir_transform_entries(gf_dirent_t *subvol_entries, int subvol,
17b94a
 
17b94a
     list_for_each_entry_safe(entry, tmp, &subvol_entries->list, list)
17b94a
     {
17b94a
-        if (__is_root_gfid(fd->inode->gfid) &&
17b94a
-            !strcmp(entry->d_name, GF_REPLICATE_TRASH_DIR)) {
17b94a
+        if (afr_is_private_directory(priv, fd->inode->gfid, entry->d_name,
17b94a
+                                     frame->root->pid)) {
17b94a
             continue;
17b94a
         }
17b94a
 
17b94a
@@ -222,8 +222,8 @@ afr_readdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
17b94a
     }
17b94a
 
17b94a
     if (op_ret >= 0)
17b94a
-        afr_readdir_transform_entries(subvol_entries, (long)cookie, &entries,
17b94a
-                                      local->fd);
17b94a
+        afr_readdir_transform_entries(frame, subvol_entries, (long)cookie,
17b94a
+                                      &entries, local->fd);
17b94a
 
17b94a
     AFR_STACK_UNWIND(readdir, frame, op_ret, op_errno, &entries, xdata);
17b94a
 
17b94a
diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c
17b94a
index 9b6575f..0a8a7fd 100644
17b94a
--- a/xlators/cluster/afr/src/afr-self-heal-common.c
17b94a
+++ b/xlators/cluster/afr/src/afr-self-heal-common.c
17b94a
@@ -2753,3 +2753,185 @@ afr_choose_source_by_policy(afr_private_t *priv, unsigned char *sources,
17b94a
 out:
17b94a
     return source;
17b94a
 }
17b94a
+
17b94a
+static int
17b94a
+afr_anon_inode_mkdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
17b94a
+                         int32_t op_ret, int32_t op_errno, inode_t *inode,
17b94a
+                         struct iatt *buf, struct iatt *preparent,
17b94a
+                         struct iatt *postparent, dict_t *xdata)
17b94a
+{
17b94a
+    afr_local_t *local = frame->local;
17b94a
+    int i = (long)cookie;
17b94a
+
17b94a
+    local->replies[i].valid = 1;
17b94a
+    local->replies[i].op_ret = op_ret;
17b94a
+    local->replies[i].op_errno = op_errno;
17b94a
+    if (op_ret == 0) {
17b94a
+        local->op_ret = 0;
17b94a
+        local->replies[i].poststat = *buf;
17b94a
+        local->replies[i].preparent = *preparent;
17b94a
+        local->replies[i].postparent = *postparent;
17b94a
+    }
17b94a
+    if (xdata) {
17b94a
+        local->replies[i].xdata = dict_ref(xdata);
17b94a
+    }
17b94a
+
17b94a
+    syncbarrier_wake(&local->barrier);
17b94a
+    return 0;
17b94a
+}
17b94a
+
17b94a
+int
17b94a
+afr_anon_inode_create(xlator_t *this, int child, inode_t **linked_inode)
17b94a
+{
17b94a
+    call_frame_t *frame = NULL;
17b94a
+    afr_local_t *local = NULL;
17b94a
+    afr_private_t *priv = this->private;
17b94a
+    unsigned char *mkdir_on = alloca0(priv->child_count);
17b94a
+    unsigned char *lookup_on = alloca0(priv->child_count);
17b94a
+    loc_t loc = {0};
17b94a
+    int32_t op_errno = 0;
17b94a
+    int32_t child_op_errno = 0;
17b94a
+    struct iatt iatt = {0};
17b94a
+    dict_t *xdata = NULL;
17b94a
+    uuid_t anon_inode_gfid = {0};
17b94a
+    int mkdir_count = 0;
17b94a
+    int i = 0;
17b94a
+
17b94a
+    /*Try to mkdir everywhere and return success if the dir exists on 'child'
17b94a
+     */
17b94a
+
17b94a
+    if (!priv->use_anon_inode) {
17b94a
+        op_errno = EINVAL;
17b94a
+        goto out;
17b94a
+    }
17b94a
+
17b94a
+    frame = afr_frame_create(this, &op_errno);
17b94a
+    if (op_errno) {
17b94a
+        goto out;
17b94a
+    }
17b94a
+    local = frame->local;
17b94a
+    if (!local->child_up[child]) {
17b94a
+        /*Other bricks may need mkdir so don't error out yet*/
17b94a
+        child_op_errno = ENOTCONN;
17b94a
+    }
17b94a
+    gf_uuid_parse(priv->anon_gfid_str, anon_inode_gfid);
17b94a
+    for (i = 0; i < priv->child_count; i++) {
17b94a
+        if (!local->child_up[i])
17b94a
+            continue;
17b94a
+
17b94a
+        if (priv->anon_inode[i]) {
17b94a
+            mkdir_on[i] = 0;
17b94a
+        } else {
17b94a
+            mkdir_on[i] = 1;
17b94a
+            mkdir_count++;
17b94a
+        }
17b94a
+    }
17b94a
+
17b94a
+    if (mkdir_count == 0) {
17b94a
+        *linked_inode = inode_find(this->itable, anon_inode_gfid);
17b94a
+        if (*linked_inode) {
17b94a
+            op_errno = 0;
17b94a
+            goto out;
17b94a
+        }
17b94a
+    }
17b94a
+
17b94a
+    loc.parent = inode_ref(this->itable->root);
17b94a
+    loc.name = priv->anon_inode_name;
17b94a
+    loc.inode = inode_new(this->itable);
17b94a
+    if (!loc.inode) {
17b94a
+        op_errno = ENOMEM;
17b94a
+        goto out;
17b94a
+    }
17b94a
+
17b94a
+    xdata = dict_new();
17b94a
+    if (!xdata) {
17b94a
+        op_errno = ENOMEM;
17b94a
+        goto out;
17b94a
+    }
17b94a
+
17b94a
+    op_errno = -dict_set_gfuuid(xdata, "gfid-req", anon_inode_gfid, _gf_true);
17b94a
+    if (op_errno) {
17b94a
+        goto out;
17b94a
+    }
17b94a
+
17b94a
+    if (mkdir_count == 0) {
17b94a
+        memcpy(lookup_on, local->child_up, priv->child_count);
17b94a
+        goto lookup;
17b94a
+    }
17b94a
+
17b94a
+    AFR_ONLIST(mkdir_on, frame, afr_anon_inode_mkdir_cbk, mkdir, &loc, 0755, 0,
17b94a
+               xdata);
17b94a
+
17b94a
+    for (i = 0; i < priv->child_count; i++) {
17b94a
+        if (!mkdir_on[i]) {
17b94a
+            continue;
17b94a
+        }
17b94a
+
17b94a
+        if (local->replies[i].op_ret == 0) {
17b94a
+            priv->anon_inode[i] = 1;
17b94a
+            iatt = local->replies[i].poststat;
17b94a
+        } else if (local->replies[i].op_ret < 0 &&
17b94a
+                   local->replies[i].op_errno == EEXIST) {
17b94a
+            lookup_on[i] = 1;
17b94a
+        } else if (i == child) {
17b94a
+            child_op_errno = local->replies[i].op_errno;
17b94a
+        }
17b94a
+    }
17b94a
+
17b94a
+    if (AFR_COUNT(lookup_on, priv->child_count) == 0) {
17b94a
+        goto link;
17b94a
+    }
17b94a
+
17b94a
+lookup:
17b94a
+    AFR_ONLIST(lookup_on, frame, afr_selfheal_discover_cbk, lookup, &loc,
17b94a
+               xdata);
17b94a
+    for (i = 0; i < priv->child_count; i++) {
17b94a
+        if (!lookup_on[i]) {
17b94a
+            continue;
17b94a
+        }
17b94a
+
17b94a
+        if (local->replies[i].op_ret == 0) {
17b94a
+            if (gf_uuid_compare(anon_inode_gfid,
17b94a
+                                local->replies[i].poststat.ia_gfid) == 0) {
17b94a
+                priv->anon_inode[i] = 1;
17b94a
+                iatt = local->replies[i].poststat;
17b94a
+            } else {
17b94a
+                if (i == child)
17b94a
+                    child_op_errno = EINVAL;
17b94a
+                gf_msg(this->name, GF_LOG_ERROR, 0, AFR_MSG_INVALID_DATA,
17b94a
+                       "%s has gfid: %s", priv->anon_inode_name,
17b94a
+                       uuid_utoa(local->replies[i].poststat.ia_gfid));
17b94a
+            }
17b94a
+        } else if (i == child) {
17b94a
+            child_op_errno = local->replies[i].op_errno;
17b94a
+        }
17b94a
+    }
17b94a
+link:
17b94a
+    if (!gf_uuid_is_null(iatt.ia_gfid)) {
17b94a
+        *linked_inode = inode_link(loc.inode, loc.parent, loc.name, &iatt);
17b94a
+        if (*linked_inode) {
17b94a
+            op_errno = 0;
17b94a
+            inode_lookup(*linked_inode);
17b94a
+        } else {
17b94a
+            op_errno = ENOMEM;
17b94a
+        }
17b94a
+        goto out;
17b94a
+    }
17b94a
+
17b94a
+out:
17b94a
+    if (xdata)
17b94a
+        dict_unref(xdata);
17b94a
+    loc_wipe(&loc;;
17b94a
+    /*child_op_errno takes precedence*/
17b94a
+    if (child_op_errno == 0) {
17b94a
+        child_op_errno = op_errno;
17b94a
+    }
17b94a
+
17b94a
+    if (child_op_errno && *linked_inode) {
17b94a
+        inode_unref(*linked_inode);
17b94a
+        *linked_inode = NULL;
17b94a
+    }
17b94a
+    if (frame)
17b94a
+        AFR_STACK_DESTROY(frame);
17b94a
+    return -child_op_errno;
17b94a
+}
17b94a
diff --git a/xlators/cluster/afr/src/afr-self-heal-entry.c b/xlators/cluster/afr/src/afr-self-heal-entry.c
17b94a
index 00b5b2d..20b07dd 100644
17b94a
--- a/xlators/cluster/afr/src/afr-self-heal-entry.c
17b94a
+++ b/xlators/cluster/afr/src/afr-self-heal-entry.c
17b94a
@@ -16,54 +16,170 @@
17b94a
 #include <glusterfs/syncop-utils.h>
17b94a
 #include <glusterfs/events.h>
17b94a
 
17b94a
-static int
17b94a
-afr_selfheal_entry_delete(xlator_t *this, inode_t *dir, const char *name,
17b94a
-                          inode_t *inode, int child, struct afr_reply *replies)
17b94a
+int
17b94a
+afr_selfheal_entry_anon_inode(xlator_t *this, inode_t *dir, const char *name,
17b94a
+                              inode_t *inode, int child,
17b94a
+                              struct afr_reply *replies,
17b94a
+                              gf_boolean_t *anon_inode)
17b94a
 {
17b94a
     afr_private_t *priv = NULL;
17b94a
+    afr_local_t *local = NULL;
17b94a
     xlator_t *subvol = NULL;
17b94a
     int ret = 0;
17b94a
+    int i = 0;
17b94a
+    char g[64] = {0};
17b94a
+    unsigned char *lookup_success = NULL;
17b94a
+    call_frame_t *frame = NULL;
17b94a
+    loc_t loc2 = {
17b94a
+        0,
17b94a
+    };
17b94a
     loc_t loc = {
17b94a
         0,
17b94a
     };
17b94a
-    char g[64];
17b94a
 
17b94a
     priv = this->private;
17b94a
-
17b94a
     subvol = priv->children[child];
17b94a
+    lookup_success = alloca0(priv->child_count);
17b94a
+    uuid_utoa_r(replies[child].poststat.ia_gfid, g);
17b94a
+    loc.inode = inode_new(inode->table);
17b94a
+    if (!loc.inode) {
17b94a
+        ret = -ENOMEM;
17b94a
+        goto out;
17b94a
+    }
17b94a
+
17b94a
+    if (replies[child].poststat.ia_type == IA_IFDIR) {
17b94a
+        /* This directory may have sub-directory hierarchy which may need to
17b94a
+         * be preserved for subsequent heals. So unconditionally move the
17b94a
+         * directory to anonymous-inode directory*/
17b94a
+        *anon_inode = _gf_true;
17b94a
+        goto anon_inode;
17b94a
+    }
17b94a
+
17b94a
+    frame = afr_frame_create(this, &ret;;
17b94a
+    if (!frame) {
17b94a
+        ret = -ret;
17b94a
+        goto out;
17b94a
+    }
17b94a
+    local = frame->local;
17b94a
+    gf_uuid_copy(loc.gfid, replies[child].poststat.ia_gfid);
17b94a
+    AFR_ONLIST(local->child_up, frame, afr_selfheal_discover_cbk, lookup, &loc,
17b94a
+               NULL);
17b94a
+    for (i = 0; i < priv->child_count; i++) {
17b94a
+        if (local->replies[i].op_ret == 0) {
17b94a
+            lookup_success[i] = 1;
17b94a
+        } else if (local->replies[i].op_errno != ENOENT &&
17b94a
+                   local->replies[i].op_errno != ESTALE) {
17b94a
+            ret = -local->replies[i].op_errno;
17b94a
+        }
17b94a
+    }
17b94a
+
17b94a
+    if (priv->quorum_count) {
17b94a
+        if (afr_has_quorum(lookup_success, this, NULL)) {
17b94a
+            *anon_inode = _gf_true;
17b94a
+        }
17b94a
+    } else if (AFR_COUNT(lookup_success, priv->child_count) > 1) {
17b94a
+        *anon_inode = _gf_true;
17b94a
+    } else if (ret) {
17b94a
+        goto out;
17b94a
+    }
17b94a
+
17b94a
+anon_inode:
17b94a
+    if (!*anon_inode) {
17b94a
+        ret = 0;
17b94a
+        goto out;
17b94a
+    }
17b94a
 
17b94a
     loc.parent = inode_ref(dir);
17b94a
     gf_uuid_copy(loc.pargfid, dir->gfid);
17b94a
     loc.name = name;
17b94a
-    loc.inode = inode_ref(inode);
17b94a
 
17b94a
-    if (replies[child].valid && replies[child].op_ret == 0) {
17b94a
-        switch (replies[child].poststat.ia_type) {
17b94a
-            case IA_IFDIR:
17b94a
-                gf_msg(this->name, GF_LOG_WARNING, 0,
17b94a
-                       AFR_MSG_EXPUNGING_FILE_OR_DIR,
17b94a
-                       "expunging dir %s/%s (%s) on %s", uuid_utoa(dir->gfid),
17b94a
-                       name, uuid_utoa_r(replies[child].poststat.ia_gfid, g),
17b94a
-                       subvol->name);
17b94a
-                ret = syncop_rmdir(subvol, &loc, 1, NULL, NULL);
17b94a
-                break;
17b94a
-            default:
17b94a
-                gf_msg(this->name, GF_LOG_WARNING, 0,
17b94a
-                       AFR_MSG_EXPUNGING_FILE_OR_DIR,
17b94a
-                       "expunging file %s/%s (%s) on %s", uuid_utoa(dir->gfid),
17b94a
-                       name, uuid_utoa_r(replies[child].poststat.ia_gfid, g),
17b94a
-                       subvol->name);
17b94a
-                ret = syncop_unlink(subvol, &loc, NULL, NULL);
17b94a
-                break;
17b94a
-        }
17b94a
+    ret = afr_anon_inode_create(this, child, &loc2.parent);
17b94a
+    if (ret < 0)
17b94a
+        goto out;
17b94a
+
17b94a
+    loc2.name = g;
17b94a
+    ret = syncop_rename(subvol, &loc, &loc2, NULL, NULL);
17b94a
+    if (ret < 0) {
17b94a
+        gf_msg(this->name, GF_LOG_WARNING, -ret, AFR_MSG_EXPUNGING_FILE_OR_DIR,
17b94a
+               "Rename to %s dir %s/%s (%s) on %s failed",
17b94a
+               priv->anon_inode_name, uuid_utoa(dir->gfid), name, g,
17b94a
+               subvol->name);
17b94a
+    } else {
17b94a
+        gf_msg(this->name, GF_LOG_WARNING, 0, AFR_MSG_EXPUNGING_FILE_OR_DIR,
17b94a
+               "Rename to %s dir %s/%s (%s) on %s successful",
17b94a
+               priv->anon_inode_name, uuid_utoa(dir->gfid), name, g,
17b94a
+               subvol->name);
17b94a
     }
17b94a
 
17b94a
+out:
17b94a
     loc_wipe(&loc;;
17b94a
+    loc_wipe(&loc2);
17b94a
+    if (frame) {
17b94a
+        AFR_STACK_DESTROY(frame);
17b94a
+    }
17b94a
 
17b94a
     return ret;
17b94a
 }
17b94a
 
17b94a
 int
17b94a
+afr_selfheal_entry_delete(xlator_t *this, inode_t *dir, const char *name,
17b94a
+                          inode_t *inode, int child, struct afr_reply *replies)
17b94a
+{
17b94a
+    char g[64] = {0};
17b94a
+    afr_private_t *priv = NULL;
17b94a
+    xlator_t *subvol = NULL;
17b94a
+    int ret = 0;
17b94a
+    loc_t loc = {
17b94a
+        0,
17b94a
+    };
17b94a
+    gf_boolean_t anon_inode = _gf_false;
17b94a
+
17b94a
+    priv = this->private;
17b94a
+    subvol = priv->children[child];
17b94a
+
17b94a
+    if ((!replies[child].valid) || (replies[child].op_ret < 0)) {
17b94a
+        /*Nothing to do*/
17b94a
+        ret = 0;
17b94a
+        goto out;
17b94a
+    }
17b94a
+
17b94a
+    if (priv->use_anon_inode) {
17b94a
+        ret = afr_selfheal_entry_anon_inode(this, dir, name, inode, child,
17b94a
+                                            replies, &anon_inode);
17b94a
+        if (ret < 0 || anon_inode)
17b94a
+            goto out;
17b94a
+    }
17b94a
+
17b94a
+    loc.parent = inode_ref(dir);
17b94a
+    loc.inode = inode_new(inode->table);
17b94a
+    if (!loc.inode) {
17b94a
+        ret = -ENOMEM;
17b94a
+        goto out;
17b94a
+    }
17b94a
+    loc.name = name;
17b94a
+    switch (replies[child].poststat.ia_type) {
17b94a
+        case IA_IFDIR:
17b94a
+            gf_msg(this->name, GF_LOG_WARNING, 0, AFR_MSG_EXPUNGING_FILE_OR_DIR,
17b94a
+                   "expunging dir %s/%s (%s) on %s", uuid_utoa(dir->gfid), name,
17b94a
+                   uuid_utoa_r(replies[child].poststat.ia_gfid, g),
17b94a
+                   subvol->name);
17b94a
+            ret = syncop_rmdir(subvol, &loc, 1, NULL, NULL);
17b94a
+            break;
17b94a
+        default:
17b94a
+            gf_msg(this->name, GF_LOG_WARNING, 0, AFR_MSG_EXPUNGING_FILE_OR_DIR,
17b94a
+                   "expunging file %s/%s (%s) on %s", uuid_utoa(dir->gfid),
17b94a
+                   name, uuid_utoa_r(replies[child].poststat.ia_gfid, g),
17b94a
+                   subvol->name);
17b94a
+            ret = syncop_unlink(subvol, &loc, NULL, NULL);
17b94a
+            break;
17b94a
+    }
17b94a
+
17b94a
+out:
17b94a
+    loc_wipe(&loc;;
17b94a
+    return ret;
17b94a
+}
17b94a
+
17b94a
+int
17b94a
 afr_selfheal_recreate_entry(call_frame_t *frame, int dst, int source,
17b94a
                             unsigned char *sources, inode_t *dir,
17b94a
                             const char *name, inode_t *inode,
17b94a
@@ -76,6 +192,9 @@ afr_selfheal_recreate_entry(call_frame_t *frame, int dst, int source,
17b94a
     loc_t srcloc = {
17b94a
         0,
17b94a
     };
17b94a
+    loc_t anonloc = {
17b94a
+        0,
17b94a
+    };
17b94a
     xlator_t *this = frame->this;
17b94a
     afr_private_t *priv = NULL;
17b94a
     dict_t *xdata = NULL;
17b94a
@@ -86,15 +205,18 @@ afr_selfheal_recreate_entry(call_frame_t *frame, int dst, int source,
17b94a
         0,
17b94a
     };
17b94a
     unsigned char *newentry = NULL;
17b94a
+    char iatt_uuid_str[64] = {0};
17b94a
+    char dir_uuid_str[64] = {0};
17b94a
 
17b94a
     priv = this->private;
17b94a
     iatt = &replies[source].poststat;
17b94a
+    uuid_utoa_r(iatt->ia_gfid, iatt_uuid_str);
17b94a
     if (iatt->ia_type == IA_INVAL || gf_uuid_is_null(iatt->ia_gfid)) {
17b94a
         gf_msg(this->name, GF_LOG_ERROR, 0, AFR_MSG_SELF_HEAL_FAILED,
17b94a
                "Invalid ia_type (%d) or gfid(%s). source brick=%d, "
17b94a
                "pargfid=%s, name=%s",
17b94a
-               iatt->ia_type, uuid_utoa(iatt->ia_gfid), source,
17b94a
-               uuid_utoa(dir->gfid), name);
17b94a
+               iatt->ia_type, iatt_uuid_str, source,
17b94a
+               uuid_utoa_r(dir->gfid, dir_uuid_str), name);
17b94a
         ret = -EINVAL;
17b94a
         goto out;
17b94a
     }
17b94a
@@ -119,14 +241,24 @@ afr_selfheal_recreate_entry(call_frame_t *frame, int dst, int source,
17b94a
 
17b94a
     srcloc.inode = inode_ref(inode);
17b94a
     gf_uuid_copy(srcloc.gfid, iatt->ia_gfid);
17b94a
-    if (iatt->ia_type != IA_IFDIR)
17b94a
-        ret = syncop_lookup(priv->children[dst], &srcloc, 0, 0, 0, 0);
17b94a
-    if (iatt->ia_type == IA_IFDIR || ret == -ENOENT || ret == -ESTALE) {
17b94a
+    ret = syncop_lookup(priv->children[dst], &srcloc, 0, 0, 0, 0);
17b94a
+    if (ret == -ENOENT || ret == -ESTALE) {
17b94a
         newentry[dst] = 1;
17b94a
         ret = afr_selfheal_newentry_mark(frame, this, inode, source, replies,
17b94a
                                          sources, newentry);
17b94a
         if (ret)
17b94a
             goto out;
17b94a
+    } else if (ret == 0 && iatt->ia_type == IA_IFDIR && priv->use_anon_inode) {
17b94a
+        // Try rename from hidden directory
17b94a
+        ret = afr_anon_inode_create(this, dst, &anonloc.parent);
17b94a
+        if (ret < 0)
17b94a
+            goto out;
17b94a
+        anonloc.inode = inode_ref(inode);
17b94a
+        anonloc.name = iatt_uuid_str;
17b94a
+        ret = syncop_rename(priv->children[dst], &anonloc, &loc, NULL, NULL);
17b94a
+        if (ret == -ENOENT || ret == -ESTALE)
17b94a
+            ret = -1; /*This sets 'mismatch' to true*/
17b94a
+        goto out;
17b94a
     }
17b94a
 
17b94a
     mode = st_mode_from_ia(iatt->ia_prot, iatt->ia_type);
17b94a
@@ -165,6 +297,7 @@ out:
17b94a
     GF_FREE(linkname);
17b94a
     loc_wipe(&loc;;
17b94a
     loc_wipe(&srcloc);
17b94a
+    loc_wipe(&anonloc);
17b94a
     return ret;
17b94a
 }
17b94a
 
17b94a
@@ -580,6 +713,11 @@ afr_selfheal_entry_dirent(call_frame_t *frame, xlator_t *this, fd_t *fd,
17b94a
 
17b94a
     priv = this->private;
17b94a
 
17b94a
+    if (afr_is_private_directory(priv, fd->inode->gfid, name,
17b94a
+                                 GF_CLIENT_PID_SELF_HEALD)) {
17b94a
+        return 0;
17b94a
+    }
17b94a
+
17b94a
     xattr = dict_new();
17b94a
     if (!xattr)
17b94a
         return -ENOMEM;
17b94a
@@ -628,7 +766,7 @@ afr_selfheal_entry_dirent(call_frame_t *frame, xlator_t *this, fd_t *fd,
17b94a
                                           replies);
17b94a
 
17b94a
         if ((ret == 0) && (priv->esh_granular) && parent_idx_inode) {
17b94a
-            ret = afr_shd_index_purge(subvol, parent_idx_inode, name,
17b94a
+            ret = afr_shd_entry_purge(subvol, parent_idx_inode, name,
17b94a
                                       inode->ia_type);
17b94a
             /* Why is ret force-set to 0? We do not care about
17b94a
              * index purge failing for full heal as it is quite
17b94a
@@ -758,10 +896,6 @@ afr_selfheal_entry_do_subvol(call_frame_t *frame, xlator_t *this, fd_t *fd,
17b94a
             if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
17b94a
                 continue;
17b94a
 
17b94a
-            if (__is_root_gfid(fd->inode->gfid) &&
17b94a
-                !strcmp(entry->d_name, GF_REPLICATE_TRASH_DIR))
17b94a
-                continue;
17b94a
-
17b94a
             ret = afr_selfheal_entry_dirent(iter_frame, this, fd, entry->d_name,
17b94a
                                             loc.inode, subvol,
17b94a
                                             local->need_full_crawl);
17b94a
@@ -824,7 +958,7 @@ afr_selfheal_entry_granular_dirent(xlator_t *subvol, gf_dirent_t *entry,
17b94a
         /* The name indices under the pgfid index dir are guaranteed
17b94a
          * to be regular files. Hence the hardcoding.
17b94a
          */
17b94a
-        afr_shd_index_purge(subvol, parent->inode, entry->d_name, IA_IFREG);
17b94a
+        afr_shd_entry_purge(subvol, parent->inode, entry->d_name, IA_IFREG);
17b94a
         ret = 0;
17b94a
         goto out;
17b94a
     }
17b94a
diff --git a/xlators/cluster/afr/src/afr-self-heal-name.c b/xlators/cluster/afr/src/afr-self-heal-name.c
17b94a
index dace071..51e3d8c 100644
17b94a
--- a/xlators/cluster/afr/src/afr-self-heal-name.c
17b94a
+++ b/xlators/cluster/afr/src/afr-self-heal-name.c
17b94a
@@ -98,21 +98,12 @@ __afr_selfheal_name_expunge(xlator_t *this, inode_t *parent, uuid_t pargfid,
17b94a
                             const char *bname, inode_t *inode,
17b94a
                             struct afr_reply *replies)
17b94a
 {
17b94a
-    loc_t loc = {
17b94a
-        0,
17b94a
-    };
17b94a
     int i = 0;
17b94a
     afr_private_t *priv = NULL;
17b94a
-    char g[64];
17b94a
     int ret = 0;
17b94a
 
17b94a
     priv = this->private;
17b94a
 
17b94a
-    loc.parent = inode_ref(parent);
17b94a
-    gf_uuid_copy(loc.pargfid, pargfid);
17b94a
-    loc.name = bname;
17b94a
-    loc.inode = inode_ref(inode);
17b94a
-
17b94a
     for (i = 0; i < priv->child_count; i++) {
17b94a
         if (!replies[i].valid)
17b94a
             continue;
17b94a
@@ -120,30 +111,10 @@ __afr_selfheal_name_expunge(xlator_t *this, inode_t *parent, uuid_t pargfid,
17b94a
         if (replies[i].op_ret)
17b94a
             continue;
17b94a
 
17b94a
-        switch (replies[i].poststat.ia_type) {
17b94a
-            case IA_IFDIR:
17b94a
-                gf_msg(this->name, GF_LOG_WARNING, 0,
17b94a
-                       AFR_MSG_EXPUNGING_FILE_OR_DIR,
17b94a
-                       "expunging dir %s/%s (%s) on %s", uuid_utoa(pargfid),
17b94a
-                       bname, uuid_utoa_r(replies[i].poststat.ia_gfid, g),
17b94a
-                       priv->children[i]->name);
17b94a
-
17b94a
-                ret |= syncop_rmdir(priv->children[i], &loc, 1, NULL, NULL);
17b94a
-                break;
17b94a
-            default:
17b94a
-                gf_msg(this->name, GF_LOG_WARNING, 0,
17b94a
-                       AFR_MSG_EXPUNGING_FILE_OR_DIR,
17b94a
-                       "expunging file %s/%s (%s) on %s", uuid_utoa(pargfid),
17b94a
-                       bname, uuid_utoa_r(replies[i].poststat.ia_gfid, g),
17b94a
-                       priv->children[i]->name);
17b94a
-
17b94a
-                ret |= syncop_unlink(priv->children[i], &loc, NULL, NULL);
17b94a
-                break;
17b94a
-        }
17b94a
+        ret |= afr_selfheal_entry_delete(this, parent, bname, inode, i,
17b94a
+                                         replies);
17b94a
     }
17b94a
 
17b94a
-    loc_wipe(&loc;;
17b94a
-
17b94a
     return ret;
17b94a
 }
17b94a
 
17b94a
diff --git a/xlators/cluster/afr/src/afr-self-heal.h b/xlators/cluster/afr/src/afr-self-heal.h
17b94a
index 8f6fb00..c8dc384 100644
17b94a
--- a/xlators/cluster/afr/src/afr-self-heal.h
17b94a
+++ b/xlators/cluster/afr/src/afr-self-heal.h
17b94a
@@ -370,4 +370,9 @@ gf_boolean_t
17b94a
 afr_is_file_empty_on_all_children(afr_private_t *priv,
17b94a
                                   struct afr_reply *replies);
17b94a
 
17b94a
+int
17b94a
+afr_selfheal_entry_delete(xlator_t *this, inode_t *dir, const char *name,
17b94a
+                          inode_t *inode, int child, struct afr_reply *replies);
17b94a
+int
17b94a
+afr_anon_inode_create(xlator_t *this, int child, inode_t **linked_inode);
17b94a
 #endif /* !_AFR_SELFHEAL_H */
17b94a
diff --git a/xlators/cluster/afr/src/afr-self-heald.c b/xlators/cluster/afr/src/afr-self-heald.c
17b94a
index 95ac5f2..939a135 100644
17b94a
--- a/xlators/cluster/afr/src/afr-self-heald.c
17b94a
+++ b/xlators/cluster/afr/src/afr-self-heald.c
17b94a
@@ -222,7 +222,7 @@ out:
17b94a
 }
17b94a
 
17b94a
 int
17b94a
-afr_shd_index_purge(xlator_t *subvol, inode_t *inode, char *name,
17b94a
+afr_shd_entry_purge(xlator_t *subvol, inode_t *inode, char *name,
17b94a
                     ia_type_t type)
17b94a
 {
17b94a
     int ret = 0;
17b94a
@@ -422,7 +422,7 @@ afr_shd_index_heal(xlator_t *subvol, gf_dirent_t *entry, loc_t *parent,
17b94a
     ret = afr_shd_selfheal(healer, healer->subvol, gfid);
17b94a
 
17b94a
     if (ret == -ENOENT || ret == -ESTALE)
17b94a
-        afr_shd_index_purge(subvol, parent->inode, entry->d_name, val);
17b94a
+        afr_shd_entry_purge(subvol, parent->inode, entry->d_name, val);
17b94a
 
17b94a
     if (ret == 2)
17b94a
         /* If bricks crashed in pre-op after creating indices/xattrop
17b94a
@@ -798,6 +798,176 @@ afr_bricks_available_for_heal(afr_private_t *priv)
17b94a
     return _gf_true;
17b94a
 }
17b94a
 
17b94a
+static int
17b94a
+afr_shd_anon_inode_cleaner(xlator_t *subvol, gf_dirent_t *entry, loc_t *parent,
17b94a
+                           void *data)
17b94a
+{
17b94a
+    struct subvol_healer *healer = data;
17b94a
+    afr_private_t *priv = healer->this->private;
17b94a
+    call_frame_t *frame = NULL;
17b94a
+    afr_local_t *local = NULL;
17b94a
+    int ret = 0;
17b94a
+    loc_t loc = {0};
17b94a
+    int count = 0;
17b94a
+    int i = 0;
17b94a
+    int op_errno = 0;
17b94a
+    struct iatt *iatt = NULL;
17b94a
+    gf_boolean_t multiple_links = _gf_false;
17b94a
+    unsigned char *gfid_present = alloca0(priv->child_count);
17b94a
+    unsigned char *entry_present = alloca0(priv->child_count);
17b94a
+    char *type = "file";
17b94a
+
17b94a
+    frame = afr_frame_create(healer->this, &ret;;
17b94a
+    if (!frame) {
17b94a
+        ret = -ret;
17b94a
+        goto out;
17b94a
+    }
17b94a
+    local = frame->local;
17b94a
+    if (AFR_COUNT(local->child_up, priv->child_count) != priv->child_count) {
17b94a
+        gf_msg_debug(healer->this->name, 0,
17b94a
+                     "Not all bricks are up. Skipping "
17b94a
+                     "cleanup of %s on %s",
17b94a
+                     entry->d_name, subvol->name);
17b94a
+        ret = 0;
17b94a
+        goto out;
17b94a
+    }
17b94a
+
17b94a
+    loc.inode = inode_new(parent->inode->table);
17b94a
+    if (!loc.inode) {
17b94a
+        ret = -ENOMEM;
17b94a
+        goto out;
17b94a
+    }
17b94a
+    ret = gf_uuid_parse(entry->d_name, loc.gfid);
17b94a
+    if (ret) {
17b94a
+        ret = 0;
17b94a
+        goto out;
17b94a
+    }
17b94a
+    AFR_ONLIST(local->child_up, frame, afr_selfheal_discover_cbk, lookup, &loc,
17b94a
+               NULL);
17b94a
+    for (i = 0; i < priv->child_count; i++) {
17b94a
+        if (local->replies[i].op_ret == 0) {
17b94a
+            count++;
17b94a
+            gfid_present[i] = 1;
17b94a
+            iatt = &local->replies[i].poststat;
17b94a
+            if (iatt->ia_type == IA_IFDIR) {
17b94a
+                type = "dir";
17b94a
+            }
17b94a
+
17b94a
+            if (i == healer->subvol) {
17b94a
+                if (local->replies[i].poststat.ia_nlink > 1) {
17b94a
+                    multiple_links = _gf_true;
17b94a
+                }
17b94a
+            }
17b94a
+        } else if (local->replies[i].op_errno != ENOENT &&
17b94a
+                   local->replies[i].op_errno != ESTALE) {
17b94a
+            /*We don't have complete view. Skip the entry*/
17b94a
+            gf_msg_debug(healer->this->name, local->replies[i].op_errno,
17b94a
+                         "Skipping cleanup of %s on %s", entry->d_name,
17b94a
+                         subvol->name);
17b94a
+            ret = 0;
17b94a
+            goto out;
17b94a
+        }
17b94a
+    }
17b94a
+
17b94a
+    /*Inode is deleted from subvol*/
17b94a
+    if (count == 1 || (iatt->ia_type != IA_IFDIR && multiple_links)) {
17b94a
+        gf_msg(healer->this->name, GF_LOG_WARNING, 0,
17b94a
+               AFR_MSG_EXPUNGING_FILE_OR_DIR, "expunging %s %s/%s on %s", type,
17b94a
+               priv->anon_inode_name, entry->d_name, subvol->name);
17b94a
+        ret = afr_shd_entry_purge(subvol, parent->inode, entry->d_name,
17b94a
+                                  iatt->ia_type);
17b94a
+        if (ret == -ENOENT || ret == -ESTALE)
17b94a
+            ret = 0;
17b94a
+    } else if (count > 1) {
17b94a
+        loc_wipe(&loc;;
17b94a
+        loc.parent = inode_ref(parent->inode);
17b94a
+        loc.name = entry->d_name;
17b94a
+        loc.inode = inode_new(parent->inode->table);
17b94a
+        if (!loc.inode) {
17b94a
+            ret = -ENOMEM;
17b94a
+            goto out;
17b94a
+        }
17b94a
+        AFR_ONLIST(local->child_up, frame, afr_selfheal_discover_cbk, lookup,
17b94a
+                   &loc, NULL);
17b94a
+        count = 0;
17b94a
+        for (i = 0; i < priv->child_count; i++) {
17b94a
+            if (local->replies[i].op_ret == 0) {
17b94a
+                count++;
17b94a
+                entry_present[i] = 1;
17b94a
+                iatt = &local->replies[i].poststat;
17b94a
+            } else if (local->replies[i].op_errno != ENOENT &&
17b94a
+                       local->replies[i].op_errno != ESTALE) {
17b94a
+                /*We don't have complete view. Skip the entry*/
17b94a
+                gf_msg_debug(healer->this->name, local->replies[i].op_errno,
17b94a
+                             "Skipping cleanup of %s on %s", entry->d_name,
17b94a
+                             subvol->name);
17b94a
+                ret = 0;
17b94a
+                goto out;
17b94a
+            }
17b94a
+        }
17b94a
+        for (i = 0; i < priv->child_count; i++) {
17b94a
+            if (gfid_present[i] && !entry_present[i]) {
17b94a
+                /*Entry is not anonymous on at least one subvol*/
17b94a
+                gf_msg_debug(healer->this->name, 0,
17b94a
+                             "Valid entry present on %s "
17b94a
+                             "Skipping cleanup of %s on %s",
17b94a
+                             priv->children[i]->name, entry->d_name,
17b94a
+                             subvol->name);
17b94a
+                ret = 0;
17b94a
+                goto out;
17b94a
+            }
17b94a
+        }
17b94a
+
17b94a
+        gf_msg(healer->this->name, GF_LOG_WARNING, 0,
17b94a
+               AFR_MSG_EXPUNGING_FILE_OR_DIR,
17b94a
+               "expunging %s %s/%s on all subvols", type, priv->anon_inode_name,
17b94a
+               entry->d_name);
17b94a
+        ret = 0;
17b94a
+        for (i = 0; i < priv->child_count; i++) {
17b94a
+            op_errno = -afr_shd_entry_purge(priv->children[i], loc.parent,
17b94a
+                                            entry->d_name, iatt->ia_type);
17b94a
+            if (op_errno != ENOENT && op_errno != ESTALE) {
17b94a
+                ret |= -op_errno;
17b94a
+            }
17b94a
+        }
17b94a
+    }
17b94a
+
17b94a
+out:
17b94a
+    if (frame)
17b94a
+        AFR_STACK_DESTROY(frame);
17b94a
+    loc_wipe(&loc;;
17b94a
+    return ret;
17b94a
+}
17b94a
+
17b94a
+static void
17b94a
+afr_cleanup_anon_inode_dir(struct subvol_healer *healer)
17b94a
+{
17b94a
+    int ret = 0;
17b94a
+    call_frame_t *frame = NULL;
17b94a
+    afr_private_t *priv = healer->this->private;
17b94a
+    loc_t loc = {0};
17b94a
+
17b94a
+    ret = afr_anon_inode_create(healer->this, healer->subvol, &loc.inode);
17b94a
+    if (ret)
17b94a
+        goto out;
17b94a
+
17b94a
+    frame = afr_frame_create(healer->this, &ret;;
17b94a
+    if (!frame) {
17b94a
+        ret = -ret;
17b94a
+        goto out;
17b94a
+    }
17b94a
+
17b94a
+    ret = syncop_mt_dir_scan(frame, priv->children[healer->subvol], &loc,
17b94a
+                             GF_CLIENT_PID_SELF_HEALD, healer,
17b94a
+                             afr_shd_anon_inode_cleaner, NULL,
17b94a
+                             priv->shd.max_threads, priv->shd.wait_qlength);
17b94a
+out:
17b94a
+    if (frame)
17b94a
+        AFR_STACK_DESTROY(frame);
17b94a
+    loc_wipe(&loc;;
17b94a
+    return;
17b94a
+}
17b94a
+
17b94a
 void *
17b94a
 afr_shd_index_healer(void *data)
17b94a
 {
17b94a
@@ -854,6 +1024,10 @@ afr_shd_index_healer(void *data)
17b94a
             sleep(1);
17b94a
         } while (ret > 0);
17b94a
 
17b94a
+        if (ret == 0) {
17b94a
+            afr_cleanup_anon_inode_dir(healer);
17b94a
+        }
17b94a
+
17b94a
         if (pre_crawl_xdata && !healer->crawl_event.heal_failed_count) {
17b94a
             afr_shd_ta_check_and_unset_xattrs(this, &loc, healer,
17b94a
                                               pre_crawl_xdata);
17b94a
diff --git a/xlators/cluster/afr/src/afr-self-heald.h b/xlators/cluster/afr/src/afr-self-heald.h
17b94a
index 1990539..acd567e 100644
17b94a
--- a/xlators/cluster/afr/src/afr-self-heald.h
17b94a
+++ b/xlators/cluster/afr/src/afr-self-heald.h
17b94a
@@ -70,6 +70,6 @@ afr_shd_gfid_to_path(xlator_t *this, xlator_t *subvol, uuid_t gfid,
17b94a
                      char **path_p);
17b94a
 
17b94a
 int
17b94a
-afr_shd_index_purge(xlator_t *subvol, inode_t *inode, char *name,
17b94a
+afr_shd_entry_purge(xlator_t *subvol, inode_t *inode, char *name,
17b94a
                     ia_type_t type);
17b94a
 #endif /* !_AFR_SELF_HEALD_H */
17b94a
diff --git a/xlators/cluster/afr/src/afr.c b/xlators/cluster/afr/src/afr.c
17b94a
index bfa464f..33fe4d8 100644
17b94a
--- a/xlators/cluster/afr/src/afr.c
17b94a
+++ b/xlators/cluster/afr/src/afr.c
17b94a
@@ -135,6 +135,27 @@ set_data_self_heal_algorithm(afr_private_t *priv, char *algo)
17b94a
     }
17b94a
 }
17b94a
 
17b94a
+void
17b94a
+afr_handle_anon_inode_options(afr_private_t *priv, dict_t *options)
17b94a
+{
17b94a
+    char *volfile_id_str = NULL;
17b94a
+    uuid_t anon_inode_gfid = {0};
17b94a
+
17b94a
+    /*If volume id is not present don't enable anything*/
17b94a
+    if (dict_get_str(options, "volume-id", &volfile_id_str))
17b94a
+        return;
17b94a
+    GF_ASSERT(strlen(AFR_ANON_DIR_PREFIX) + strlen(volfile_id_str) <= NAME_MAX);
17b94a
+    /*anon_inode_name is not supposed to change once assigned*/
17b94a
+    if (!priv->anon_inode_name[0]) {
17b94a
+        snprintf(priv->anon_inode_name, sizeof(priv->anon_inode_name), "%s-%s",
17b94a
+                 AFR_ANON_DIR_PREFIX, volfile_id_str);
17b94a
+        gf_uuid_parse(volfile_id_str, anon_inode_gfid);
17b94a
+        /*Flip a bit to make sure volfile-id and anon-gfid are not same*/
17b94a
+        anon_inode_gfid[0] ^= 1;
17b94a
+        uuid_utoa_r(anon_inode_gfid, priv->anon_gfid_str);
17b94a
+    }
17b94a
+}
17b94a
+
17b94a
 int
17b94a
 reconfigure(xlator_t *this, dict_t *options)
17b94a
 {
17b94a
@@ -287,6 +308,10 @@ reconfigure(xlator_t *this, dict_t *options)
17b94a
         consistent_io = _gf_false;
17b94a
     priv->consistent_io = consistent_io;
17b94a
 
17b94a
+    afr_handle_anon_inode_options(priv, options);
17b94a
+
17b94a
+    GF_OPTION_RECONF("use-anonymous-inode", priv->use_anon_inode, options, bool,
17b94a
+                     out);
17b94a
     if (priv->shd.enabled) {
17b94a
         if ((priv->shd.enabled != enabled_old) ||
17b94a
             (timeout_old != priv->shd.timeout))
17b94a
@@ -535,7 +560,9 @@ init(xlator_t *this)
17b94a
 
17b94a
     GF_OPTION_INIT("consistent-metadata", priv->consistent_metadata, bool, out);
17b94a
     GF_OPTION_INIT("consistent-io", priv->consistent_io, bool, out);
17b94a
+    afr_handle_anon_inode_options(priv, this->options);
17b94a
 
17b94a
+    GF_OPTION_INIT("use-anonymous-inode", priv->use_anon_inode, bool, out);
17b94a
     if (priv->quorum_count != 0)
17b94a
         priv->consistent_io = _gf_false;
17b94a
 
17b94a
@@ -547,13 +574,16 @@ init(xlator_t *this)
17b94a
         goto out;
17b94a
     }
17b94a
 
17b94a
+    priv->anon_inode = GF_CALLOC(sizeof(unsigned char), child_count,
17b94a
+                                 gf_afr_mt_char);
17b94a
+
17b94a
     priv->child_up = GF_CALLOC(sizeof(unsigned char), child_count,
17b94a
                                gf_afr_mt_char);
17b94a
 
17b94a
     priv->child_latency = GF_MALLOC(sizeof(*priv->child_latency) * child_count,
17b94a
                                     gf_afr_mt_child_latency_t);
17b94a
 
17b94a
-    if (!priv->child_up || !priv->child_latency) {
17b94a
+    if (!priv->child_up || !priv->child_latency || !priv->anon_inode) {
17b94a
         ret = -ENOMEM;
17b94a
         goto out;
17b94a
     }
17b94a
@@ -1218,6 +1248,14 @@ struct volume_options options[] = {
17b94a
      .tags = {"replicate"},
17b94a
      .description = "This option exists only for backward compatibility "
17b94a
                     "and configuring it doesn't have any effect"},
17b94a
+    {.key = {"use-anonymous-inode"},
17b94a
+     .type = GF_OPTION_TYPE_BOOL,
17b94a
+     .default_value = "no",
17b94a
+     .op_version = {GD_OP_VERSION_7_0},
17b94a
+     .flags = OPT_FLAG_CLIENT_OPT | OPT_FLAG_SETTABLE,
17b94a
+     .tags = {"replicate"},
17b94a
+     .description = "Setting this option heals directory renames efficiently"},
17b94a
+
17b94a
     {.key = {NULL}},
17b94a
 };
17b94a
 
17b94a
diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h
17b94a
index 3a2b26d..6a9a763 100644
17b94a
--- a/xlators/cluster/afr/src/afr.h
17b94a
+++ b/xlators/cluster/afr/src/afr.h
17b94a
@@ -40,6 +40,8 @@
17b94a
 #define AFR_TA_DOM_MODIFY "afr.ta.dom-modify"
17b94a
 
17b94a
 #define AFR_HALO_MAX_LATENCY 99999
17b94a
+#define AFR_ANON_DIR_PREFIX ".glusterfs-anonymous-inode"
17b94a
+
17b94a
 
17b94a
 #define PFLAG_PENDING (1 << 0)
17b94a
 #define PFLAG_SBRAIN (1 << 1)
17b94a
@@ -155,6 +157,7 @@ typedef struct _afr_private {
17b94a
     struct list_head ta_waitq;
17b94a
     struct list_head ta_onwireq;
17b94a
 
17b94a
+    unsigned char *anon_inode;
17b94a
     unsigned char *child_up;
17b94a
     int64_t *child_latency;
17b94a
     unsigned char *local;
17b94a
@@ -240,6 +243,11 @@ typedef struct _afr_private {
17b94a
     gf_boolean_t esh_granular;
17b94a
     gf_boolean_t consistent_io;
17b94a
     gf_boolean_t data_self_heal; /* on/off */
17b94a
+    gf_boolean_t use_anon_inode;
17b94a
+
17b94a
+    /*For anon-inode handling */
17b94a
+    char anon_inode_name[NAME_MAX + 1];
17b94a
+    char anon_gfid_str[UUID_SIZE + 1];
17b94a
 } afr_private_t;
17b94a
 
17b94a
 typedef enum {
17b94a
@@ -1341,4 +1349,7 @@ afr_selfheal_childup(xlator_t *this, afr_private_t *priv);
17b94a
 void
17b94a
 afr_fill_success_replies(afr_local_t *local, afr_private_t *priv,
17b94a
                          unsigned char *replies);
17b94a
+gf_boolean_t
17b94a
+afr_is_private_directory(afr_private_t *priv, uuid_t pargfid, const char *name,
17b94a
+                         pid_t pid);
17b94a
 #endif /* __AFR_H__ */
17b94a
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c
17b94a
index 094a71f..1920284 100644
17b94a
--- a/xlators/mgmt/glusterd/src/glusterd-volgen.c
17b94a
+++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c
17b94a
@@ -3867,6 +3867,38 @@ out:
17b94a
 }
17b94a
 
17b94a
 static int
17b94a
+set_volfile_id_option(volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
17b94a
+                      int clusters)
17b94a
+{
17b94a
+    xlator_t *xlator = NULL;
17b94a
+    int i = 0;
17b94a
+    int ret = -1;
17b94a
+    glusterd_conf_t *conf = NULL;
17b94a
+    xlator_t *this = NULL;
17b94a
+
17b94a
+    this = THIS;
17b94a
+    GF_VALIDATE_OR_GOTO("glusterd", this, out);
17b94a
+    conf = this->private;
17b94a
+    GF_VALIDATE_OR_GOTO(this->name, conf, out);
17b94a
+
17b94a
+    if (conf->op_version < GD_OP_VERSION_7_1)
17b94a
+        return 0;
17b94a
+    xlator = first_of(graph);
17b94a
+
17b94a
+    for (i = 0; i < clusters; i++) {
17b94a
+        ret = xlator_set_fixed_option(xlator, "volume-id",
17b94a
+                                      uuid_utoa(volinfo->volume_id));
17b94a
+        if (ret)
17b94a
+            goto out;
17b94a
+
17b94a
+        xlator = xlator->next;
17b94a
+    }
17b94a
+
17b94a
+out:
17b94a
+    return ret;
17b94a
+}
17b94a
+
17b94a
+static int
17b94a
 volgen_graph_build_afr_clusters(volgen_graph_t *graph,
17b94a
                                 glusterd_volinfo_t *volinfo)
17b94a
 {
17b94a
@@ -3906,6 +3938,13 @@ volgen_graph_build_afr_clusters(volgen_graph_t *graph,
17b94a
         clusters = -1;
17b94a
         goto out;
17b94a
     }
17b94a
+
17b94a
+    ret = set_volfile_id_option(graph, volinfo, clusters);
17b94a
+    if (ret) {
17b94a
+        clusters = -1;
17b94a
+        goto out;
17b94a
+    }
17b94a
+
17b94a
     if (!volinfo->arbiter_count)
17b94a
         goto out;
17b94a
 
17b94a
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
17b94a
index 62acadf..c1ca190 100644
17b94a
--- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c
17b94a
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
17b94a
@@ -3789,4 +3789,10 @@ struct volopt_map_entry glusterd_volopt_map[] = {
17b94a
      .voltype = "features/cloudsync",
17b94a
      .op_version = GD_OP_VERSION_7_0,
17b94a
      .flags = VOLOPT_FLAG_CLIENT_OPT},
17b94a
+
17b94a
+    {.key = "cluster.use-anonymous-inode",
17b94a
+     .voltype = "cluster/replicate",
17b94a
+     .op_version = GD_OP_VERSION_7_1,
17b94a
+     .value = "yes",
17b94a
+     .flags = VOLOPT_FLAG_CLIENT_OPT},
17b94a
     {.key = NULL}};
17b94a
-- 
17b94a
1.8.3.1
17b94a