e3c68b
From d5ce2300f77c25b38a076d4dd6a5521e82c56172 Mon Sep 17 00:00:00 2001
e3c68b
From: Kotresh HR <khiremat@redhat.com>
e3c68b
Date: Mon, 29 Jul 2019 18:30:42 +0530
e3c68b
Subject: [PATCH 295/297] ctime/rebalance: Heal ctime xattr on directory during
e3c68b
 rebalance
e3c68b
e3c68b
After add-brick and rebalance, the ctime xattr is not present
e3c68b
on rebalanced directories on new brick. This patch fixes the
e3c68b
same.
e3c68b
e3c68b
Note that ctime still doesn't support consistent time across
e3c68b
distribute sub-volume.
e3c68b
e3c68b
This patch also fixes the in-memory inconsistency of time attributes
e3c68b
when metadata is self healed.
e3c68b
e3c68b
Backport of:
e3c68b
 > Patch: https://review.gluster.org/23127/
e3c68b
 > Change-Id: Ia20506f1839021bf61d4753191e7dc34b31bb2df
e3c68b
 > fixes: bz#1734026
e3c68b
 > Signed-off-by: Kotresh HR <khiremat@redhat.com>
e3c68b
e3c68b
Change-Id: Ia20506f1839021bf61d4753191e7dc34b31bb2df
e3c68b
BUG: 1728673
e3c68b
Signed-off-by: Kotresh HR <khiremat@redhat.com>
e3c68b
Reviewed-on: https://code.engineering.redhat.com/gerrit/181105
e3c68b
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e3c68b
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
e3c68b
---
e3c68b
 tests/basic/afr/split-brain-healing-ctime.t        | 253 +++++++++++++++++++++
e3c68b
 tests/basic/afr/split-brain-healing.t              |   1 +
e3c68b
 tests/basic/ctime/ctime-ec-heal.t                  |  71 ++++++
e3c68b
 tests/basic/ctime/ctime-ec-rebalance.t             |  44 ++++
e3c68b
 tests/basic/ctime/ctime-rep-heal.t                 |  71 ++++++
e3c68b
 tests/basic/ctime/ctime-rep-rebalance.t            |  42 ++++
e3c68b
 .../bug-1734370-entry-heal-restore-time.t          |  84 +++++++
e3c68b
 tests/volume.rc                                    |  15 +-
e3c68b
 xlators/cluster/afr/src/afr-self-heal-common.c     |   3 +-
e3c68b
 xlators/cluster/afr/src/afr-self-heal-entry.c      |   2 +
e3c68b
 xlators/cluster/dht/src/dht-common.c               |   1 +
e3c68b
 xlators/cluster/ec/src/ec-heal.c                   |   7 +-
e3c68b
 xlators/storage/posix/src/posix-entry-ops.c        |   8 +-
e3c68b
 xlators/storage/posix/src/posix-helpers.c          |  31 ++-
e3c68b
 xlators/storage/posix/src/posix-inode-fd-ops.c     |  57 ++---
e3c68b
 xlators/storage/posix/src/posix-metadata.c         |  65 +++++-
e3c68b
 xlators/storage/posix/src/posix-metadata.h         |   7 +
e3c68b
 xlators/storage/posix/src/posix.h                  |   5 +-
e3c68b
 18 files changed, 714 insertions(+), 53 deletions(-)
e3c68b
 create mode 100644 tests/basic/afr/split-brain-healing-ctime.t
e3c68b
 create mode 100644 tests/basic/ctime/ctime-ec-heal.t
e3c68b
 create mode 100644 tests/basic/ctime/ctime-ec-rebalance.t
e3c68b
 create mode 100644 tests/basic/ctime/ctime-rep-heal.t
e3c68b
 create mode 100644 tests/basic/ctime/ctime-rep-rebalance.t
e3c68b
 create mode 100644 tests/bugs/replicate/bug-1734370-entry-heal-restore-time.t
e3c68b
e3c68b
diff --git a/tests/basic/afr/split-brain-healing-ctime.t b/tests/basic/afr/split-brain-healing-ctime.t
e3c68b
new file mode 100644
e3c68b
index 0000000..1ca18e3
e3c68b
--- /dev/null
e3c68b
+++ b/tests/basic/afr/split-brain-healing-ctime.t
e3c68b
@@ -0,0 +1,253 @@
e3c68b
+#!/bin/bash
e3c68b
+
e3c68b
+#Test the split-brain resolution CLI commands.
e3c68b
+. $(dirname $0)/../../include.rc
e3c68b
+. $(dirname $0)/../../volume.rc
e3c68b
+
e3c68b
+function get_replicate_subvol_number {
e3c68b
+        local filename=$1
e3c68b
+        #get_backend_paths
e3c68b
+        if [ -f $B0/${V0}1/$filename ]
e3c68b
+        then
e3c68b
+                echo 0
e3c68b
+        elif [ -f $B0/${V0}3/$filename ]
e3c68b
+        then    echo 1
e3c68b
+        else
e3c68b
+                echo -1
e3c68b
+        fi
e3c68b
+}
e3c68b
+
e3c68b
+cleanup;
e3c68b
+
e3c68b
+AREQUAL_PATH=$(dirname $0)/../../utils
e3c68b
+GET_MDATA_PATH=$(dirname $0)/../../utils
e3c68b
+CFLAGS=""
e3c68b
+test "`uname -s`" != "Linux" && {
e3c68b
+    CFLAGS="$CFLAGS -lintl";
e3c68b
+}
e3c68b
+build_tester $AREQUAL_PATH/arequal-checksum.c $CFLAGS
e3c68b
+build_tester $GET_MDATA_PATH/get-mdata-xattr.c
e3c68b
+
e3c68b
+TEST glusterd
e3c68b
+TEST pidof glusterd
e3c68b
+TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{1,2,3,4}
e3c68b
+TEST $CLI volume set $V0 cluster.self-heal-daemon off
e3c68b
+TEST $CLI volume set $V0 cluster.data-self-heal off
e3c68b
+TEST $CLI volume set $V0 cluster.metadata-self-heal off
e3c68b
+TEST $CLI volume set $V0 cluster.entry-self-heal off
e3c68b
+TEST $CLI volume set $V0 ctime on
e3c68b
+TEST $CLI volume start $V0
e3c68b
+TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0
e3c68b
+
e3c68b
+cd $M0
e3c68b
+for i in {1..10}
e3c68b
+do
e3c68b
+        echo "Initial content">>file$i
e3c68b
+done
e3c68b
+
e3c68b
+replica_0_files_list=(`ls $B0/${V0}1|grep -v '^\.'`)
e3c68b
+replica_1_files_list=(`ls $B0/${V0}3|grep -v '^\.'`)
e3c68b
+
e3c68b
+############ Create data split-brain in the files. ###########################
e3c68b
+TEST kill_brick $V0 $H0 $B0/${V0}1
e3c68b
+for file in ${!replica_0_files_list[*]}
e3c68b
+do
e3c68b
+        echo "B1 is down">>${replica_0_files_list[$file]}
e3c68b
+done
e3c68b
+TEST kill_brick $V0 $H0 $B0/${V0}3
e3c68b
+for file in ${!replica_1_files_list[*]}
e3c68b
+do
e3c68b
+        echo "B3 is down">>${replica_1_files_list[$file]}
e3c68b
+done
e3c68b
+
e3c68b
+SMALLER_FILE_SIZE=$(stat -c %s file1)
e3c68b
+
e3c68b
+TEST $CLI volume start $V0 force
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2
e3c68b
+
e3c68b
+TEST kill_brick $V0 $H0 $B0/${V0}2
e3c68b
+for file in ${!replica_0_files_list[*]}
e3c68b
+do
e3c68b
+        echo "B2 is down">>${replica_0_files_list[$file]}
e3c68b
+        echo "appending more content to make it the bigger file">>${replica_0_files_list[$file]}
e3c68b
+done
e3c68b
+TEST kill_brick $V0 $H0 $B0/${V0}4
e3c68b
+for file in ${!replica_1_files_list[*]}
e3c68b
+do
e3c68b
+        echo "B4 is down">>${replica_1_files_list[$file]}
e3c68b
+        echo "appending more content to make it the bigger file">>${replica_1_files_list[$file]}
e3c68b
+done
e3c68b
+
e3c68b
+BIGGER_FILE_SIZE=$(stat -c %s file1)
e3c68b
+TEST $CLI volume start $V0 force
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 3
e3c68b
+
e3c68b
+
e3c68b
+############### Acessing the files should now give EIO. ###############################
e3c68b
+TEST ! cat file1
e3c68b
+TEST ! cat file2
e3c68b
+TEST ! cat file3
e3c68b
+TEST ! cat file4
e3c68b
+TEST ! cat file5
e3c68b
+TEST ! cat file6
e3c68b
+TEST ! cat file7
e3c68b
+TEST ! cat file8
e3c68b
+TEST ! cat file9
e3c68b
+TEST ! cat file10
e3c68b
+###################
e3c68b
+TEST $CLI volume set $V0 cluster.self-heal-daemon on
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
e3c68b
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0
e3c68b
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1
e3c68b
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 2
e3c68b
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 3
e3c68b
+
e3c68b
+################ Heal file1 using the bigger-file option  ##############
e3c68b
+$CLI volume heal $V0 split-brain bigger-file /file1
e3c68b
+EXPECT "0" echo $?
e3c68b
+EXPECT $BIGGER_FILE_SIZE stat -c %s file1
e3c68b
+
e3c68b
+################ Heal file2 using the bigger-file option and its gfid ##############
e3c68b
+subvolume=$(get_replicate_subvol_number file2)
e3c68b
+if [ $subvolume == 0 ]
e3c68b
+then
e3c68b
+        GFID=$(gf_get_gfid_xattr $B0/${V0}1/file2)
e3c68b
+elif [ $subvolume == 1 ]
e3c68b
+then
e3c68b
+        GFID=$(gf_get_gfid_xattr $B0/${V0}3/file2)
e3c68b
+fi
e3c68b
+GFIDSTR="gfid:$(gf_gfid_xattr_to_str $GFID)"
e3c68b
+$CLI volume heal $V0 split-brain bigger-file $GFIDSTR
e3c68b
+EXPECT "0" echo $?
e3c68b
+
e3c68b
+################ Heal file3 using the source-brick option  ##############
e3c68b
+################ Use the brick having smaller file size as source #######
e3c68b
+subvolume=$(get_replicate_subvol_number file3)
e3c68b
+if [ $subvolume == 0 ]
e3c68b
+then
e3c68b
+        $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}2 /file3
e3c68b
+elif [ $subvolume == 1 ]
e3c68b
+then
e3c68b
+        $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}4 /file3
e3c68b
+fi
e3c68b
+EXPECT "0" echo $?
e3c68b
+EXPECT $SMALLER_FILE_SIZE stat -c %s file3
e3c68b
+
e3c68b
+################ Heal file4 using the source-brick option and it's gfid ##############
e3c68b
+################ Use the brick having smaller file size as source #######
e3c68b
+subvolume=$(get_replicate_subvol_number file4)
e3c68b
+if [ $subvolume == 0 ]
e3c68b
+then
e3c68b
+        GFID=$(gf_get_gfid_xattr $B0/${V0}1/file4)
e3c68b
+        GFIDSTR="gfid:$(gf_gfid_xattr_to_str $GFID)"
e3c68b
+        $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}2 $GFIDSTR
e3c68b
+elif [ $subvolume == 1 ]
e3c68b
+then
e3c68b
+        GFID=$(gf_get_gfid_xattr $B0/${V0}3/file4)
e3c68b
+        GFIDSTR="gfid:$(gf_gfid_xattr_to_str $GFID)"
e3c68b
+        $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}4 $GFIDSTR
e3c68b
+fi
e3c68b
+EXPECT "0" echo $?
e3c68b
+EXPECT $SMALLER_FILE_SIZE stat -c %s file4
e3c68b
+
e3c68b
+# With ctime enabled, the ctime xattr ("trusted.glusterfs.mdata") gets healed
e3c68b
+# as part of metadata heal. So mtime would be same, hence it can't be healed
e3c68b
+# using 'latest-mtime' policy, use 'source-brick' option instead.
e3c68b
+################ Heal file5 using the source-brick option  ##############
e3c68b
+subvolume=$(get_replicate_subvol_number file5)
e3c68b
+if [ $subvolume == 0 ]
e3c68b
+then
e3c68b
+        $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}1 /file5
e3c68b
+elif [ $subvolume == 1 ]
e3c68b
+then
e3c68b
+        $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}3 /file5
e3c68b
+fi
e3c68b
+EXPECT "0" echo $?
e3c68b
+
e3c68b
+if [ $subvolume == 0 ]
e3c68b
+then
e3c68b
+        mtime1_after_heal=$(get_mtime $B0/${V0}1/file5)
e3c68b
+        mtime2_after_heal=$(get_mtime $B0/${V0}2/file5)
e3c68b
+elif [ $subvolume == 1 ]
e3c68b
+then
e3c68b
+        mtime1_after_heal=$(get_mtime $B0/${V0}3/file5)
e3c68b
+        mtime2_after_heal=$(get_mtime $B0/${V0}4/file5)
e3c68b
+fi
e3c68b
+
e3c68b
+#TODO: To below comparisons on full sub-second resolution
e3c68b
+
e3c68b
+TEST [ $mtime1_after_heal -eq $mtime2_after_heal ]
e3c68b
+
e3c68b
+mtime_mount_after_heal=$(stat -c %Y file5)
e3c68b
+
e3c68b
+TEST [ $mtime1_after_heal -eq $mtime_mount_after_heal ]
e3c68b
+
e3c68b
+################ Heal file6 using the source-brick option and its gfid  ##############
e3c68b
+subvolume=$(get_replicate_subvol_number file6)
e3c68b
+if [ $subvolume == 0 ]
e3c68b
+then
e3c68b
+        GFID=$(gf_get_gfid_xattr $B0/${V0}1/file6)
e3c68b
+        GFIDSTR="gfid:$(gf_gfid_xattr_to_str $GFID)"
e3c68b
+        $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}1 $GFIDSTR
e3c68b
+elif [ $subvolume == 1 ]
e3c68b
+then
e3c68b
+        GFID=$(gf_get_gfid_xattr $B0/${V0}3/file6)
e3c68b
+        GFIDSTR="gfid:$(gf_gfid_xattr_to_str $GFID)"
e3c68b
+        $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}3 $GFIDSTR
e3c68b
+fi
e3c68b
+EXPECT "0" echo $?
e3c68b
+
e3c68b
+if [ $subvolume == 0 ]
e3c68b
+then
e3c68b
+        mtime1_after_heal=$(get_mtime $B0/${V0}1/file6)
e3c68b
+        mtime2_after_heal=$(get_mtime $B0/${V0}2/file6)
e3c68b
+elif [ $subvolume == 1 ]
e3c68b
+then
e3c68b
+        mtime1_after_heal=$(get_mtime $B0/${V0}3/file6)
e3c68b
+        mtime2_after_heal=$(get_mtime $B0/${V0}4/file6)
e3c68b
+fi
e3c68b
+
e3c68b
+#TODO: To below comparisons on full sub-second resolution
e3c68b
+
e3c68b
+TEST [ $mtime1_after_heal -eq $mtime2_after_heal ]
e3c68b
+
e3c68b
+mtime_mount_after_heal=$(stat -c %Y file6)
e3c68b
+
e3c68b
+TEST [ $mtime1_after_heal -eq $mtime_mount_after_heal ]
e3c68b
+
e3c68b
+################ Heal remaining SB'ed files of replica_0 using B1 as source ##############
e3c68b
+$CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}1
e3c68b
+EXPECT "0" echo $?
e3c68b
+
e3c68b
+################ Heal remaining SB'ed files of replica_1 using B3 as source ##############
e3c68b
+$CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}3
e3c68b
+EXPECT "0" echo $?
e3c68b
+
e3c68b
+############### Reading the files should now succeed. ###############################
e3c68b
+TEST  cat file1
e3c68b
+TEST  cat file2
e3c68b
+TEST  cat file3
e3c68b
+TEST  cat file4
e3c68b
+TEST  cat file5
e3c68b
+TEST  cat file6
e3c68b
+TEST  cat file7
e3c68b
+TEST  cat file8
e3c68b
+TEST  cat file9
e3c68b
+TEST  cat file10
e3c68b
+
e3c68b
+################ File contents on the bricks must be same. ################################
e3c68b
+TEST diff <(arequal-checksum -p $B0/$V01 -i .glusterfs) <(arequal-checksum -p $B0/$V02 -i .glusterfs)
e3c68b
+TEST diff <(arequal-checksum -p $B0/$V03 -i .glusterfs) <(arequal-checksum -p $B0/$V04 -i .glusterfs)
e3c68b
+
e3c68b
+############### Trying to heal files not in SB should fail. ###############################
e3c68b
+$CLI volume heal $V0 split-brain bigger-file /file1
e3c68b
+EXPECT "1" echo $?
e3c68b
+$CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}4 /file3
e3c68b
+EXPECT "1" echo $?
e3c68b
+
e3c68b
+cd -
e3c68b
+TEST rm $AREQUAL_PATH/arequal-checksum
e3c68b
+TEST rm $GET_MDATA_PATH/get-mdata-xattr
e3c68b
+cleanup
e3c68b
diff --git a/tests/basic/afr/split-brain-healing.t b/tests/basic/afr/split-brain-healing.t
e3c68b
index 78553e6..315e815 100644
e3c68b
--- a/tests/basic/afr/split-brain-healing.t
e3c68b
+++ b/tests/basic/afr/split-brain-healing.t
e3c68b
@@ -35,6 +35,7 @@ TEST $CLI volume set $V0 cluster.self-heal-daemon off
e3c68b
 TEST $CLI volume set $V0 cluster.data-self-heal off
e3c68b
 TEST $CLI volume set $V0 cluster.metadata-self-heal off
e3c68b
 TEST $CLI volume set $V0 cluster.entry-self-heal off
e3c68b
+TEST $CLI volume set $V0 ctime off
e3c68b
 TEST $CLI volume start $V0
e3c68b
 TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0
e3c68b
 
e3c68b
diff --git a/tests/basic/ctime/ctime-ec-heal.t b/tests/basic/ctime/ctime-ec-heal.t
e3c68b
new file mode 100644
e3c68b
index 0000000..1cb4516
e3c68b
--- /dev/null
e3c68b
+++ b/tests/basic/ctime/ctime-ec-heal.t
e3c68b
@@ -0,0 +1,71 @@
e3c68b
+#!/bin/bash
e3c68b
+#
e3c68b
+# This will test self healing of ctime xattr 'trusted.glusterfs.mdata'
e3c68b
+#
e3c68b
+###
e3c68b
+
e3c68b
+. $(dirname $0)/../../include.rc
e3c68b
+. $(dirname $0)/../../volume.rc
e3c68b
+. $(dirname $0)/../../afr.rc
e3c68b
+
e3c68b
+cleanup
e3c68b
+
e3c68b
+#cleate and start volume
e3c68b
+TEST glusterd
e3c68b
+TEST pidof glusterd
e3c68b
+TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{1..3}
e3c68b
+TEST $CLI volume set $V0 ctime on
e3c68b
+TEST $CLI volume start $V0
e3c68b
+
e3c68b
+#Mount the volume
e3c68b
+TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0;
e3c68b
+
e3c68b
+# Create files
e3c68b
+mkdir $M0/dir1
e3c68b
+echo "Initial content" > $M0/file1
e3c68b
+
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/file1
e3c68b
+
e3c68b
+# Kill brick
e3c68b
+TEST kill_brick $V0 $H0 $B0/${V0}3
e3c68b
+
e3c68b
+echo "B3 is down" >> $M0/file1
e3c68b
+echo "Change dir1 time attributes" > $M0/dir1/dir1_file1
e3c68b
+echo "Entry heal file" > $M0/entry_heal_file1
e3c68b
+mkdir $M0/entry_heal_dir1
e3c68b
+
e3c68b
+# Check xattr
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_uniq_count $B0/${V0}{1..3}/dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_uniq_count $B0/${V0}{1..3}/file1
e3c68b
+
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_count $B0/${V0}{1..3}/dir1/dir1_file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1/dir1_file1
e3c68b
+
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_count $B0/${V0}{1..3}/entry_heal_file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_count $B0/${V0}{1..3}/entry_heal_dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_dir1
e3c68b
+
e3c68b
+TEST $CLI volume start $V0 force
e3c68b
+$CLI volume heal $V0
e3c68b
+
e3c68b
+# Check xattr
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/file1
e3c68b
+
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1/dir1_file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1/dir1_file1
e3c68b
+
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/entry_heal_file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/entry_heal_dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_dir1
e3c68b
+
e3c68b
+cleanup;
e3c68b
diff --git a/tests/basic/ctime/ctime-ec-rebalance.t b/tests/basic/ctime/ctime-ec-rebalance.t
e3c68b
new file mode 100644
e3c68b
index 0000000..caccdc1
e3c68b
--- /dev/null
e3c68b
+++ b/tests/basic/ctime/ctime-ec-rebalance.t
e3c68b
@@ -0,0 +1,44 @@
e3c68b
+#!/bin/bash
e3c68b
+#
e3c68b
+# This will test healing of ctime xattr 'trusted.glusterfs.mdata' after add-brick and rebalance
e3c68b
+#
e3c68b
+###
e3c68b
+
e3c68b
+. $(dirname $0)/../../include.rc
e3c68b
+. $(dirname $0)/../../volume.rc
e3c68b
+. $(dirname $0)/../../fallocate.rc
e3c68b
+
e3c68b
+cleanup
e3c68b
+
e3c68b
+#cleate and start volume
e3c68b
+TEST glusterd
e3c68b
+TEST pidof glusterd
e3c68b
+TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0..5}
e3c68b
+TEST $CLI volume set $V0 ctime on
e3c68b
+TEST $CLI volume start $V0
e3c68b
+
e3c68b
+#Mount the volume
e3c68b
+TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0;
e3c68b
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0
e3c68b
+
e3c68b
+# Create files
e3c68b
+mkdir $M0/dir1
e3c68b
+echo "test data" > $M0/dir1/file1
e3c68b
+
e3c68b
+# Add brick
e3c68b
+TEST $CLI volume add-brick $V0 $H0:$B0/${V0}{6..8}
e3c68b
+
e3c68b
+#Trigger rebalance
e3c68b
+TEST $CLI volume rebalance $V0 start force
e3c68b
+EXPECT_WITHIN $REBALANCE_TIMEOUT "completed" rebalance_status_field $V0
e3c68b
+
e3c68b
+#Verify ctime xattr heal on directory
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}6/dir1"
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}7/dir1"
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}8/dir1"
e3c68b
+
e3c68b
+b6_mdata=$(get_mdata "$B0/${V0}6/dir1")
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "${b6_mdata}" get_mdata $B0/${V0}7/dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "${b6_mdata}" get_mdata $B0/${V0}8/dir1
e3c68b
+
e3c68b
+cleanup;
e3c68b
diff --git a/tests/basic/ctime/ctime-rep-heal.t b/tests/basic/ctime/ctime-rep-heal.t
e3c68b
new file mode 100644
e3c68b
index 0000000..ba8b08a
e3c68b
--- /dev/null
e3c68b
+++ b/tests/basic/ctime/ctime-rep-heal.t
e3c68b
@@ -0,0 +1,71 @@
e3c68b
+#!/bin/bash
e3c68b
+#
e3c68b
+# This will test self healing of ctime xattr 'trusted.glusterfs.mdata'
e3c68b
+#
e3c68b
+###
e3c68b
+
e3c68b
+. $(dirname $0)/../../include.rc
e3c68b
+. $(dirname $0)/../../volume.rc
e3c68b
+. $(dirname $0)/../../afr.rc
e3c68b
+
e3c68b
+cleanup
e3c68b
+
e3c68b
+#cleate and start volume
e3c68b
+TEST glusterd
e3c68b
+TEST pidof glusterd
e3c68b
+TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{1..3}
e3c68b
+TEST $CLI volume set $V0 ctime on
e3c68b
+TEST $CLI volume start $V0
e3c68b
+
e3c68b
+#Mount the volume
e3c68b
+TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0;
e3c68b
+
e3c68b
+# Create files
e3c68b
+mkdir $M0/dir1
e3c68b
+echo "Initial content" > $M0/file1
e3c68b
+
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/file1
e3c68b
+
e3c68b
+# Kill brick
e3c68b
+TEST kill_brick $V0 $H0 $B0/${V0}3
e3c68b
+
e3c68b
+echo "B3 is down" >> $M0/file1
e3c68b
+echo "Change dir1 time attributes" > $M0/dir1/dir1_file1
e3c68b
+echo "Entry heal file" > $M0/entry_heal_file1
e3c68b
+mkdir $M0/entry_heal_dir1
e3c68b
+
e3c68b
+# Check xattr
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_uniq_count $B0/${V0}{1..3}/dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_uniq_count $B0/${V0}{1..3}/file1
e3c68b
+
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_count $B0/${V0}{1..3}/dir1/dir1_file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1/dir1_file1
e3c68b
+
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_count $B0/${V0}{1..3}/entry_heal_file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_count $B0/${V0}{1..3}/entry_heal_dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_dir1
e3c68b
+
e3c68b
+TEST $CLI volume start $V0 force
e3c68b
+$CLI volume heal $V0
e3c68b
+
e3c68b
+# Check xattr
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/file1
e3c68b
+
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1/dir1_file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1/dir1_file1
e3c68b
+
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/entry_heal_file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_file1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/entry_heal_dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_dir1
e3c68b
+
e3c68b
+cleanup;
e3c68b
diff --git a/tests/basic/ctime/ctime-rep-rebalance.t b/tests/basic/ctime/ctime-rep-rebalance.t
e3c68b
new file mode 100644
e3c68b
index 0000000..dd9743e
e3c68b
--- /dev/null
e3c68b
+++ b/tests/basic/ctime/ctime-rep-rebalance.t
e3c68b
@@ -0,0 +1,42 @@
e3c68b
+#!/bin/bash
e3c68b
+#
e3c68b
+# This will test healing of ctime xattr 'trusted.glusterfs.mdata' after add-brick and rebalance
e3c68b
+#
e3c68b
+###
e3c68b
+
e3c68b
+. $(dirname $0)/../../include.rc
e3c68b
+. $(dirname $0)/../../volume.rc
e3c68b
+. $(dirname $0)/../../afr.rc
e3c68b
+
e3c68b
+cleanup
e3c68b
+
e3c68b
+#cleate and start volume
e3c68b
+TEST glusterd
e3c68b
+TEST pidof glusterd
e3c68b
+TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0..5}
e3c68b
+TEST $CLI volume set $V0 ctime on
e3c68b
+TEST $CLI volume start $V0
e3c68b
+
e3c68b
+#Mount the volume
e3c68b
+TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0;
e3c68b
+
e3c68b
+# Create files
e3c68b
+mkdir $M0/dir1
e3c68b
+
e3c68b
+# Add brick
e3c68b
+TEST $CLI volume add-brick $V0 $H0:$B0/${V0}{6..8}
e3c68b
+
e3c68b
+#Trigger rebalance
e3c68b
+TEST $CLI volume rebalance $V0 start force
e3c68b
+EXPECT_WITHIN $REBALANCE_TIMEOUT "completed" rebalance_status_field $V0
e3c68b
+
e3c68b
+#Verify ctime xattr heal on directory
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}6/dir1"
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}7/dir1"
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}8/dir1"
e3c68b
+
e3c68b
+b6_mdata=$(get_mdata "$B0/${V0}6/dir1")
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "${b6_mdata}" get_mdata $B0/${V0}7/dir1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "${b6_mdata}" get_mdata $B0/${V0}8/dir1
e3c68b
+
e3c68b
+cleanup;
e3c68b
diff --git a/tests/bugs/replicate/bug-1734370-entry-heal-restore-time.t b/tests/bugs/replicate/bug-1734370-entry-heal-restore-time.t
e3c68b
new file mode 100644
e3c68b
index 0000000..298d6ed
e3c68b
--- /dev/null
e3c68b
+++ b/tests/bugs/replicate/bug-1734370-entry-heal-restore-time.t
e3c68b
@@ -0,0 +1,84 @@
e3c68b
+#!/bin/bash
e3c68b
+
e3c68b
+. $(dirname $0)/../../include.rc
e3c68b
+. $(dirname $0)/../../volume.rc
e3c68b
+. $(dirname $0)/../../afr.rc
e3c68b
+
e3c68b
+cleanup;
e3c68b
+
e3c68b
+function time_stamps_match {
e3c68b
+        path=$1
e3c68b
+        mtime_source_b0=$(get_mtime $B0/${V0}0/$path)
e3c68b
+        atime_source_b0=$(get_atime $B0/${V0}0/$path)
e3c68b
+        mtime_source_b2=$(get_mtime $B0/${V0}2/$path)
e3c68b
+        atime_source_b2=$(get_atime $B0/${V0}2/$path)
e3c68b
+        mtime_sink_b1=$(get_mtime $B0/${V0}1/$path)
e3c68b
+        atime_sink_b1=$(get_atime $B0/${V0}1/$path)
e3c68b
+
e3c68b
+        #The same brick must be the source of heal for both atime and mtime.
e3c68b
+        if [[ ( $mtime_source_b0 -eq $mtime_sink_b1 && $atime_source_b0 -eq $atime_sink_b1 ) || \
e3c68b
+              ( $mtime_source_b2 -eq $mtime_sink_b1 && $atime_source_b2 -eq $atime_sink_b1 ) ]]
e3c68b
+        then
e3c68b
+            echo "Y"
e3c68b
+        else
e3c68b
+            echo "N"
e3c68b
+        fi
e3c68b
+
e3c68b
+}
e3c68b
+
e3c68b
+# Test that the parent dir's timestamps are restored during entry-heal.
e3c68b
+GET_MDATA_PATH=$(dirname $0)/../../utils
e3c68b
+build_tester $GET_MDATA_PATH/get-mdata-xattr.c
e3c68b
+
e3c68b
+TEST glusterd;
e3c68b
+TEST pidof glusterd;
e3c68b
+TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2};
e3c68b
+TEST $CLI volume set $V0 ctime on
e3c68b
+TEST $CLI volume start $V0;
e3c68b
+
e3c68b
+TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 --attribute-timeout=0 --entry-timeout=0 $M0
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2
e3c68b
+
e3c68b
+###############################################################################
e3c68b
+TEST mkdir $M0/DIR
e3c68b
+TEST kill_brick $V0 $H0 $B0/${V0}1
e3c68b
+TEST touch $M0/DIR/FILE
e3c68b
+
e3c68b
+TEST $CLI volume start $V0 force
e3c68b
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
e3c68b
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0
e3c68b
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1
e3c68b
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 2
e3c68b
+TEST $CLI volume heal $V0
e3c68b
+EXPECT_WITHIN $HEAL_TIMEOUT "0" get_pending_heal_count $V0
e3c68b
+
e3c68b
+EXPECT "Y" time_stamps_match DIR
e3c68b
+ctime_source1=$(get_ctime $B0/${V0}0/$path)
e3c68b
+ctime_source2=$(get_ctime $B0/${V0}2/$path)
e3c68b
+ctime_sink=$(get_ctime $B0/${V0}1/$path)
e3c68b
+TEST [ $ctime_source1 -eq $ctime_sink ]
e3c68b
+TEST [ $ctime_source2 -eq $ctime_sink ]
e3c68b
+
e3c68b
+###############################################################################
e3c68b
+# Repeat the test with ctime feature disabled.
e3c68b
+TEST $CLI volume set $V0 features.ctime off
e3c68b
+TEST mkdir $M0/DIR2
e3c68b
+TEST kill_brick $V0 $H0 $B0/${V0}1
e3c68b
+TEST touch $M0/DIR2/FILE
e3c68b
+
e3c68b
+TEST $CLI volume start $V0 force
e3c68b
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
e3c68b
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0
e3c68b
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1
e3c68b
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 2
e3c68b
+TEST $CLI volume heal $V0
e3c68b
+EXPECT_WITHIN $HEAL_TIMEOUT "0" get_pending_heal_count $V0
e3c68b
+
e3c68b
+EXPECT "Y" time_stamps_match DIR2
e3c68b
+
e3c68b
+TEST rm $GET_MDATA_PATH/get-mdata-xattr
e3c68b
+cleanup;
e3c68b
diff --git a/tests/volume.rc b/tests/volume.rc
e3c68b
index 76a8fd4..9a002d9 100644
e3c68b
--- a/tests/volume.rc
e3c68b
+++ b/tests/volume.rc
e3c68b
@@ -371,6 +371,19 @@ function get_gfid2path {
e3c68b
         getfattr -h --only-values -n glusterfs.gfidtopath $path 2>/dev/null
e3c68b
 }
e3c68b
 
e3c68b
+function get_mdata {
e3c68b
+        local path=$1
e3c68b
+        getfattr -h -e hex -n trusted.glusterfs.mdata $path 2>/dev/null | grep "trusted.glusterfs.mdata" | cut -f2 -d'='
e3c68b
+}
e3c68b
+
e3c68b
+function get_mdata_count {
e3c68b
+    getfattr -d -m . -e hex $@ 2>/dev/null | grep mdata | wc -l
e3c68b
+}
e3c68b
+
e3c68b
+function get_mdata_uniq_count {
e3c68b
+    getfattr -d -m . -e hex $@ 2>/dev/null | grep mdata | uniq | wc -l
e3c68b
+}
e3c68b
+
e3c68b
 function get_xattr_key {
e3c68b
         local key=$1
e3c68b
         local path=$2
e3c68b
@@ -925,7 +938,7 @@ function get_ctime {
e3c68b
     local time=$(get-mdata-xattr -c $1)
e3c68b
     if [ $time == "-1" ];
e3c68b
     then
e3c68b
-        echo $(stat -c %Z $2)
e3c68b
+        echo $(stat -c %Z $1)
e3c68b
     else
e3c68b
         echo $time
e3c68b
     fi
e3c68b
diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c
e3c68b
index b38085a..81ef38a 100644
e3c68b
--- a/xlators/cluster/afr/src/afr-self-heal-common.c
e3c68b
+++ b/xlators/cluster/afr/src/afr-self-heal-common.c
e3c68b
@@ -513,7 +513,8 @@ afr_selfheal_restore_time(call_frame_t *frame, xlator_t *this, inode_t *inode,
e3c68b
 
e3c68b
     AFR_ONLIST(healed_sinks, frame, afr_sh_generic_fop_cbk, setattr, &loc,
e3c68b
                &replies[source].poststat,
e3c68b
-               (GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME), NULL);
e3c68b
+               (GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME | GF_SET_ATTR_CTIME),
e3c68b
+               NULL);
e3c68b
 
e3c68b
     loc_wipe(&loc;;
e3c68b
 
e3c68b
diff --git a/xlators/cluster/afr/src/afr-self-heal-entry.c b/xlators/cluster/afr/src/afr-self-heal-entry.c
e3c68b
index e07b521..35b600f 100644
e3c68b
--- a/xlators/cluster/afr/src/afr-self-heal-entry.c
e3c68b
+++ b/xlators/cluster/afr/src/afr-self-heal-entry.c
e3c68b
@@ -1032,6 +1032,8 @@ unlock:
e3c68b
             goto postop_unlock;
e3c68b
         }
e3c68b
 
e3c68b
+        afr_selfheal_restore_time(frame, this, fd->inode, source, healed_sinks,
e3c68b
+                                  locked_replies);
e3c68b
         ret = afr_selfheal_undo_pending(
e3c68b
             frame, this, fd->inode, sources, sinks, healed_sinks, undid_pending,
e3c68b
             AFR_ENTRY_TRANSACTION, locked_replies, postop_lock);
e3c68b
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
e3c68b
index 219b072..99cccd6 100644
e3c68b
--- a/xlators/cluster/dht/src/dht-common.c
e3c68b
+++ b/xlators/cluster/dht/src/dht-common.c
e3c68b
@@ -115,6 +115,7 @@ char *xattrs_to_heal[] = {"user.",
e3c68b
                           QUOTA_LIMIT_KEY,
e3c68b
                           QUOTA_LIMIT_OBJECTS_KEY,
e3c68b
                           GF_SELINUX_XATTR_KEY,
e3c68b
+                          GF_XATTR_MDATA_KEY,
e3c68b
                           NULL};
e3c68b
 
e3c68b
 char *dht_dbg_vxattrs[] = {DHT_DBG_HASHED_SUBVOL_PATTERN, NULL};
e3c68b
diff --git a/xlators/cluster/ec/src/ec-heal.c b/xlators/cluster/ec/src/ec-heal.c
e3c68b
index 0f0f398..06a7016 100644
e3c68b
--- a/xlators/cluster/ec/src/ec-heal.c
e3c68b
+++ b/xlators/cluster/ec/src/ec-heal.c
e3c68b
@@ -2301,9 +2301,10 @@ ec_restore_time_and_adjust_versions(call_frame_t *frame, ec_t *ec, fd_t *fd,
e3c68b
 
e3c68b
         loc.inode = inode_ref(fd->inode);
e3c68b
         gf_uuid_copy(loc.gfid, fd->inode->gfid);
e3c68b
-        ret = cluster_setattr(ec->xl_list, healed_sinks, ec->nodes, replies,
e3c68b
-                              output, frame, ec->xl, &loc, &source_buf,
e3c68b
-                              GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME, NULL);
e3c68b
+        ret = cluster_setattr(
e3c68b
+            ec->xl_list, healed_sinks, ec->nodes, replies, output, frame,
e3c68b
+            ec->xl, &loc, &source_buf,
e3c68b
+            GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME | GF_SET_ATTR_CTIME, NULL);
e3c68b
         EC_INTERSECT(healed_sinks, healed_sinks, output, ec->nodes);
e3c68b
         if (EC_COUNT(healed_sinks, ec->nodes) == 0) {
e3c68b
             ret = -ENOTCONN;
e3c68b
diff --git a/xlators/storage/posix/src/posix-entry-ops.c b/xlators/storage/posix/src/posix-entry-ops.c
e3c68b
index 34ee2b8..283b305 100644
e3c68b
--- a/xlators/storage/posix/src/posix-entry-ops.c
e3c68b
+++ b/xlators/storage/posix/src/posix-entry-ops.c
e3c68b
@@ -500,7 +500,7 @@ post_op:
e3c68b
         posix_set_gfid2path_xattr(this, real_path, loc->pargfid, loc->name);
e3c68b
     }
e3c68b
 
e3c68b
-    op_ret = posix_entry_create_xattr_set(this, real_path, xdata);
e3c68b
+    op_ret = posix_entry_create_xattr_set(this, loc, real_path, xdata);
e3c68b
     if (op_ret) {
e3c68b
         if (errno != EEXIST)
e3c68b
             gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED,
e3c68b
@@ -828,7 +828,7 @@ posix_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode,
e3c68b
                "setting ACLs on %s failed ", real_path);
e3c68b
     }
e3c68b
 
e3c68b
-    op_ret = posix_entry_create_xattr_set(this, real_path, xdata);
e3c68b
+    op_ret = posix_entry_create_xattr_set(this, loc, real_path, xdata);
e3c68b
     if (op_ret) {
e3c68b
         gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED,
e3c68b
                "setting xattrs on %s failed", real_path);
e3c68b
@@ -1529,7 +1529,7 @@ posix_symlink(call_frame_t *frame, xlator_t *this, const char *linkname,
e3c68b
     }
e3c68b
 
e3c68b
 ignore:
e3c68b
-    op_ret = posix_entry_create_xattr_set(this, real_path, xdata);
e3c68b
+    op_ret = posix_entry_create_xattr_set(this, loc, real_path, xdata);
e3c68b
     if (op_ret) {
e3c68b
         gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED,
e3c68b
                "setting xattrs on %s failed ", real_path);
e3c68b
@@ -2167,7 +2167,7 @@ posix_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
e3c68b
         posix_set_gfid2path_xattr(this, real_path, loc->pargfid, loc->name);
e3c68b
     }
e3c68b
 ignore:
e3c68b
-    op_ret = posix_entry_create_xattr_set(this, real_path, xdata);
e3c68b
+    op_ret = posix_entry_create_xattr_set(this, loc, real_path, xdata);
e3c68b
     if (op_ret) {
e3c68b
         gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED,
e3c68b
                "setting xattrs on %s failed ", real_path);
e3c68b
diff --git a/xlators/storage/posix/src/posix-helpers.c b/xlators/storage/posix/src/posix-helpers.c
e3c68b
index d143d4c..6a1a35c 100644
e3c68b
--- a/xlators/storage/posix/src/posix-helpers.c
e3c68b
+++ b/xlators/storage/posix/src/posix-helpers.c
e3c68b
@@ -1188,11 +1188,15 @@ posix_dump_buffer(xlator_t *this, const char *real_path, const char *key,
e3c68b
 #endif
e3c68b
 
e3c68b
 int
e3c68b
-posix_handle_pair(xlator_t *this, const char *real_path, char *key,
e3c68b
+posix_handle_pair(xlator_t *this, loc_t *loc, const char *real_path, char *key,
e3c68b
                   data_t *value, int flags, struct iatt *stbuf)
e3c68b
 {
e3c68b
     int sys_ret = -1;
e3c68b
     int ret = 0;
e3c68b
+    int op_errno = 0;
e3c68b
+    struct mdata_iatt mdata_iatt = {
e3c68b
+        0,
e3c68b
+    };
e3c68b
 #ifdef GF_DARWIN_HOST_OS
e3c68b
     const int error_code = EINVAL;
e3c68b
 #else
e3c68b
@@ -1216,6 +1220,23 @@ posix_handle_pair(xlator_t *this, const char *real_path, char *key,
e3c68b
         /* ignore this key value pair */
e3c68b
         ret = 0;
e3c68b
         goto out;
e3c68b
+    } else if (!strncmp(key, GF_XATTR_MDATA_KEY, strlen(key))) {
e3c68b
+        /* This is either by rebalance or self heal. Create the xattr if it's
e3c68b
+         * not present. Compare and update the larger value if the xattr is
e3c68b
+         * already present.
e3c68b
+         */
e3c68b
+        if (loc == NULL) {
e3c68b
+            ret = -EINVAL;
e3c68b
+            goto out;
e3c68b
+        }
e3c68b
+        posix_mdata_iatt_from_disk(&mdata_iatt,
e3c68b
+                                   (posix_mdata_disk_t *)value->data);
e3c68b
+        ret = posix_set_mdata_xattr_legacy_files(this, loc->inode, real_path,
e3c68b
+                                                 &mdata_iatt, &op_errno);
e3c68b
+        if (ret != 0) {
e3c68b
+            ret = -op_errno;
e3c68b
+        }
e3c68b
+        goto out;
e3c68b
     } else {
e3c68b
         sys_ret = sys_lsetxattr(real_path, key, value->data, value->len, flags);
e3c68b
 #ifdef GF_DARWIN_HOST_OS
e3c68b
@@ -1810,8 +1831,8 @@ _handle_entry_create_keyvalue_pair(dict_t *d, char *k, data_t *v, void *tmp)
e3c68b
         return 0;
e3c68b
     }
e3c68b
 
e3c68b
-    ret = posix_handle_pair(filler->this, filler->real_path, k, v, XATTR_CREATE,
e3c68b
-                            filler->stbuf);
e3c68b
+    ret = posix_handle_pair(filler->this, filler->loc, filler->real_path, k, v,
e3c68b
+                            XATTR_CREATE, filler->stbuf);
e3c68b
     if (ret < 0) {
e3c68b
         errno = -ret;
e3c68b
         return -1;
e3c68b
@@ -1820,7 +1841,8 @@ _handle_entry_create_keyvalue_pair(dict_t *d, char *k, data_t *v, void *tmp)
e3c68b
 }
e3c68b
 
e3c68b
 int
e3c68b
-posix_entry_create_xattr_set(xlator_t *this, const char *path, dict_t *dict)
e3c68b
+posix_entry_create_xattr_set(xlator_t *this, loc_t *loc, const char *path,
e3c68b
+                             dict_t *dict)
e3c68b
 {
e3c68b
     int ret = -1;
e3c68b
 
e3c68b
@@ -1834,6 +1856,7 @@ posix_entry_create_xattr_set(xlator_t *this, const char *path, dict_t *dict)
e3c68b
     filler.this = this;
e3c68b
     filler.real_path = path;
e3c68b
     filler.stbuf = NULL;
e3c68b
+    filler.loc = loc;
e3c68b
 
e3c68b
     ret = dict_foreach(dict, _handle_entry_create_keyvalue_pair, &filler);
e3c68b
 
e3c68b
diff --git a/xlators/storage/posix/src/posix-inode-fd-ops.c b/xlators/storage/posix/src/posix-inode-fd-ops.c
e3c68b
index e0ea85b..a2a518f 100644
e3c68b
--- a/xlators/storage/posix/src/posix-inode-fd-ops.c
e3c68b
+++ b/xlators/storage/posix/src/posix-inode-fd-ops.c
e3c68b
@@ -429,22 +429,9 @@ posix_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc,
e3c68b
                                     &frame->root->ctime, stbuf, valid);
e3c68b
     }
e3c68b
 
e3c68b
-    if (valid & GF_SET_ATTR_CTIME && !priv->ctime) {
e3c68b
-        /*
e3c68b
-         * If ctime is not enabled, we have no means to associate an
e3c68b
-         * arbitrary ctime with the file, so as a fallback, we ignore
e3c68b
-         * the ctime payload and update the file ctime to current time
e3c68b
-         * (which is possible directly with the POSIX API).
e3c68b
-         */
e3c68b
-        op_ret = PATH_SET_TIMESPEC_OR_TIMEVAL(real_path, NULL);
e3c68b
-        if (op_ret == -1) {
e3c68b
-            op_errno = errno;
e3c68b
-            gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_UTIMES_FAILED,
e3c68b
-                   "setattr (utimes) on %s "
e3c68b
-                   "failed",
e3c68b
-                   real_path);
e3c68b
-            goto out;
e3c68b
-        }
e3c68b
+    if ((valid & GF_SET_ATTR_CTIME) && priv->ctime) {
e3c68b
+        posix_update_ctime_in_mdata(this, real_path, -1, loc->inode,
e3c68b
+                                    &frame->root->ctime, stbuf, valid);
e3c68b
     }
e3c68b
 
e3c68b
     if (!valid) {
e3c68b
@@ -469,14 +456,6 @@ posix_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc,
e3c68b
         goto out;
e3c68b
     }
e3c68b
 
e3c68b
-    if (valid & GF_SET_ATTR_CTIME && priv->ctime) {
e3c68b
-        /*
e3c68b
-         * If we got ctime payload, we override
e3c68b
-         * the ctime of statpost with that.
e3c68b
-         */
e3c68b
-        statpost.ia_ctime = stbuf->ia_ctime;
e3c68b
-        statpost.ia_ctime_nsec = stbuf->ia_ctime_nsec;
e3c68b
-    }
e3c68b
     posix_set_ctime(frame, this, real_path, -1, loc->inode, &statpost);
e3c68b
 
e3c68b
     if (xdata)
e3c68b
@@ -592,6 +571,7 @@ posix_fsetattr(call_frame_t *frame, xlator_t *this, fd_t *fd,
e3c68b
     struct iatt statpost = {
e3c68b
         0,
e3c68b
     };
e3c68b
+    struct posix_private *priv = NULL;
e3c68b
     struct posix_fd *pfd = NULL;
e3c68b
     dict_t *xattr_rsp = NULL;
e3c68b
     int32_t ret = -1;
e3c68b
@@ -604,6 +584,9 @@ posix_fsetattr(call_frame_t *frame, xlator_t *this, fd_t *fd,
e3c68b
     VALIDATE_OR_GOTO(this, out);
e3c68b
     VALIDATE_OR_GOTO(fd, out);
e3c68b
 
e3c68b
+    priv = this->private;
e3c68b
+    VALIDATE_OR_GOTO(priv, out);
e3c68b
+
e3c68b
     ret = posix_fd_ctx_get(fd, this, &pfd, &op_errno);
e3c68b
     if (ret < 0) {
e3c68b
         gf_msg_debug(this->name, 0, "pfd is NULL from fd=%p", fd);
e3c68b
@@ -656,6 +639,11 @@ posix_fsetattr(call_frame_t *frame, xlator_t *this, fd_t *fd,
e3c68b
                                     &frame->root->ctime, stbuf, valid);
e3c68b
     }
e3c68b
 
e3c68b
+    if ((valid & GF_SET_ATTR_CTIME) && priv->ctime) {
e3c68b
+        posix_update_ctime_in_mdata(this, NULL, pfd->fd, fd->inode,
e3c68b
+                                    &frame->root->ctime, stbuf, valid);
e3c68b
+    }
e3c68b
+
e3c68b
     if (!valid) {
e3c68b
         op_ret = sys_fchown(pfd->fd, -1, -1);
e3c68b
         if (op_ret == -1) {
e3c68b
@@ -2578,7 +2566,7 @@ _handle_setxattr_keyvalue_pair(dict_t *d, char *k, data_t *v, void *tmp)
e3c68b
 
e3c68b
     filler = tmp;
e3c68b
 
e3c68b
-    return posix_handle_pair(filler->this, filler->real_path, k, v,
e3c68b
+    return posix_handle_pair(filler->this, filler->loc, filler->real_path, k, v,
e3c68b
                              filler->flags, filler->stbuf);
e3c68b
 }
e3c68b
 
e3c68b
@@ -2641,27 +2629,27 @@ posix_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict,
e3c68b
     priv = this->private;
e3c68b
     DISK_SPACE_CHECK_AND_GOTO(frame, priv, xdata, op_ret, op_errno, out);
e3c68b
 
e3c68b
+    MAKE_INODE_HANDLE(real_path, this, loc, NULL);
e3c68b
+    if (!real_path) {
e3c68b
+        op_ret = -1;
e3c68b
+        op_errno = ESTALE;
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
     ret = dict_get_mdata(dict, CTIME_MDATA_XDATA_KEY, &mdata_iatt);
e3c68b
     if (ret == 0) {
e3c68b
         /* This is initiated by lookup when ctime feature is enabled to create
e3c68b
          * "trusted.glusterfs.mdata" xattr if not present. These are the files
e3c68b
          * which were created when ctime feature is disabled.
e3c68b
          */
e3c68b
-        ret = posix_set_mdata_xattr_legacy_files(this, loc->inode, &mdata_iatt,
e3c68b
-                                                 &op_errno);
e3c68b
+        ret = posix_set_mdata_xattr_legacy_files(this, loc->inode, real_path,
e3c68b
+                                                 &mdata_iatt, &op_errno);
e3c68b
         if (ret != 0) {
e3c68b
             op_ret = -1;
e3c68b
         }
e3c68b
         goto out;
e3c68b
     }
e3c68b
 
e3c68b
-    MAKE_INODE_HANDLE(real_path, this, loc, NULL);
e3c68b
-    if (!real_path) {
e3c68b
-        op_ret = -1;
e3c68b
-        op_errno = ESTALE;
e3c68b
-        goto out;
e3c68b
-    }
e3c68b
-
e3c68b
     posix_pstat(this, loc->inode, loc->gfid, real_path, &preop, _gf_false);
e3c68b
 
e3c68b
     op_ret = -1;
e3c68b
@@ -2796,6 +2784,7 @@ posix_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict,
e3c68b
     filler.real_path = real_path;
e3c68b
     filler.this = this;
e3c68b
     filler.stbuf = &preo;;
e3c68b
+    filler.loc = loc;
e3c68b
 
e3c68b
 #ifdef GF_DARWIN_HOST_OS
e3c68b
     filler.flags = map_xattr_flags(flags);
e3c68b
diff --git a/xlators/storage/posix/src/posix-metadata.c b/xlators/storage/posix/src/posix-metadata.c
e3c68b
index 532daa2..9efaf99 100644
e3c68b
--- a/xlators/storage/posix/src/posix-metadata.c
e3c68b
+++ b/xlators/storage/posix/src/posix-metadata.c
e3c68b
@@ -56,6 +56,19 @@ posix_mdata_from_disk(posix_mdata_t *out, posix_mdata_disk_t *in)
e3c68b
     out->atime.tv_nsec = be64toh(in->atime.tv_nsec);
e3c68b
 }
e3c68b
 
e3c68b
+void
e3c68b
+posix_mdata_iatt_from_disk(struct mdata_iatt *out, posix_mdata_disk_t *in)
e3c68b
+{
e3c68b
+    out->ia_ctime = be64toh(in->ctime.tv_sec);
e3c68b
+    out->ia_ctime_nsec = be64toh(in->ctime.tv_nsec);
e3c68b
+
e3c68b
+    out->ia_mtime = be64toh(in->mtime.tv_sec);
e3c68b
+    out->ia_mtime_nsec = be64toh(in->mtime.tv_nsec);
e3c68b
+
e3c68b
+    out->ia_atime = be64toh(in->atime.tv_sec);
e3c68b
+    out->ia_atime_nsec = be64toh(in->atime.tv_nsec);
e3c68b
+}
e3c68b
+
e3c68b
 /* posix_fetch_mdata_xattr fetches the posix_mdata_t from disk */
e3c68b
 static int
e3c68b
 posix_fetch_mdata_xattr(xlator_t *this, const char *real_path_arg, int _fd,
e3c68b
@@ -341,6 +354,7 @@ posix_compare_timespec(struct timespec *first, struct timespec *second)
e3c68b
 
e3c68b
 int
e3c68b
 posix_set_mdata_xattr_legacy_files(xlator_t *this, inode_t *inode,
e3c68b
+                                   const char *realpath,
e3c68b
                                    struct mdata_iatt *mdata_iatt, int *op_errno)
e3c68b
 {
e3c68b
     posix_mdata_t *mdata = NULL;
e3c68b
@@ -369,8 +383,8 @@ posix_set_mdata_xattr_legacy_files(xlator_t *this, inode_t *inode,
e3c68b
                 goto unlock;
e3c68b
             }
e3c68b
 
e3c68b
-            ret = posix_fetch_mdata_xattr(this, NULL, -1, inode, (void *)mdata,
e3c68b
-                                          op_errno);
e3c68b
+            ret = posix_fetch_mdata_xattr(this, realpath, -1, inode,
e3c68b
+                                          (void *)mdata, op_errno);
e3c68b
             if (ret == 0) {
e3c68b
                 /* Got mdata from disk. This is a race, another client
e3c68b
                  * has healed the xattr during lookup. So set it in inode
e3c68b
@@ -412,7 +426,7 @@ posix_set_mdata_xattr_legacy_files(xlator_t *this, inode_t *inode,
e3c68b
             }
e3c68b
         }
e3c68b
 
e3c68b
-        ret = posix_store_mdata_xattr(this, NULL, -1, inode, mdata);
e3c68b
+        ret = posix_store_mdata_xattr(this, realpath, -1, inode, mdata);
e3c68b
         if (ret) {
e3c68b
             gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_STOREMDATA_FAILED,
e3c68b
                    "gfid: %s key:%s ", uuid_utoa(inode->gfid),
e3c68b
@@ -445,7 +459,8 @@ posix_set_mdata_xattr(xlator_t *this, const char *real_path, int fd,
e3c68b
     GF_VALIDATE_OR_GOTO(this->name, inode, out);
e3c68b
     GF_VALIDATE_OR_GOTO(this->name, time, out);
e3c68b
 
e3c68b
-    if (update_utime && (!u_atime || !u_mtime)) {
e3c68b
+    if (update_utime && (flag->ctime && !time) && (flag->atime && !u_atime) &&
e3c68b
+        (flag->mtime && !u_mtime)) {
e3c68b
         goto out;
e3c68b
     }
e3c68b
 
e3c68b
@@ -652,6 +667,48 @@ posix_update_utime_in_mdata(xlator_t *this, const char *real_path, int fd,
e3c68b
     return;
e3c68b
 }
e3c68b
 
e3c68b
+/* posix_update_ctime_in_mdata updates the posix_mdata_t when ctime needs
e3c68b
+ * to be modified
e3c68b
+ */
e3c68b
+void
e3c68b
+posix_update_ctime_in_mdata(xlator_t *this, const char *real_path, int fd,
e3c68b
+                            inode_t *inode, struct timespec *ctime,
e3c68b
+                            struct iatt *stbuf, int valid)
e3c68b
+{
e3c68b
+    int32_t ret = 0;
e3c68b
+#if defined(HAVE_UTIMENSAT)
e3c68b
+    struct timespec tv_ctime = {
e3c68b
+        0,
e3c68b
+    };
e3c68b
+#else
e3c68b
+    struct timeval tv_ctime = {
e3c68b
+        0,
e3c68b
+    };
e3c68b
+#endif
e3c68b
+    posix_mdata_flag_t flag = {
e3c68b
+        0,
e3c68b
+    };
e3c68b
+
e3c68b
+    struct posix_private *priv = NULL;
e3c68b
+    priv = this->private;
e3c68b
+
e3c68b
+    if (inode && priv->ctime) {
e3c68b
+        tv_ctime.tv_sec = stbuf->ia_ctime;
e3c68b
+        SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv_ctime, stbuf->ia_ctime_nsec);
e3c68b
+        flag.ctime = 1;
e3c68b
+
e3c68b
+        ret = posix_set_mdata_xattr(this, real_path, -1, inode, &tv_ctime, NULL,
e3c68b
+                                    NULL, NULL, &flag, _gf_true);
e3c68b
+        if (ret) {
e3c68b
+            gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED,
e3c68b
+                   "posix set mdata atime failed on file:"
e3c68b
+                   " %s gfid:%s",
e3c68b
+                   real_path, uuid_utoa(inode->gfid));
e3c68b
+        }
e3c68b
+    }
e3c68b
+    return;
e3c68b
+}
e3c68b
+
e3c68b
 static void
e3c68b
 posix_get_mdata_flag(uint64_t flags, posix_mdata_flag_t *flag)
e3c68b
 {
e3c68b
diff --git a/xlators/storage/posix/src/posix-metadata.h b/xlators/storage/posix/src/posix-metadata.h
e3c68b
index c176699..63e8771 100644
e3c68b
--- a/xlators/storage/posix/src/posix-metadata.h
e3c68b
+++ b/xlators/storage/posix/src/posix-metadata.h
e3c68b
@@ -43,6 +43,10 @@ posix_update_utime_in_mdata(xlator_t *this, const char *real_path, int fd,
e3c68b
                             inode_t *inode, struct timespec *ctime,
e3c68b
                             struct iatt *stbuf, int valid);
e3c68b
 void
e3c68b
+posix_update_ctime_in_mdata(xlator_t *this, const char *real_path, int fd,
e3c68b
+                            inode_t *inode, struct timespec *ctime,
e3c68b
+                            struct iatt *stbuf, int valid);
e3c68b
+void
e3c68b
 posix_set_ctime(call_frame_t *frame, xlator_t *this, const char *real_path,
e3c68b
                 int fd, inode_t *inode, struct iatt *stbuf);
e3c68b
 void
e3c68b
@@ -56,7 +60,10 @@ posix_set_ctime_cfr(call_frame_t *frame, xlator_t *this,
e3c68b
                     int fd_out, inode_t *inode_out, struct iatt *stbuf_out);
e3c68b
 int
e3c68b
 posix_set_mdata_xattr_legacy_files(xlator_t *this, inode_t *inode,
e3c68b
+                                   const char *realpath,
e3c68b
                                    struct mdata_iatt *mdata_iatt,
e3c68b
                                    int *op_errno);
e3c68b
+void
e3c68b
+posix_mdata_iatt_from_disk(struct mdata_iatt *out, posix_mdata_disk_t *in);
e3c68b
 
e3c68b
 #endif /* _POSIX_METADATA_H */
e3c68b
diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h
e3c68b
index 64288a7..dd51062 100644
e3c68b
--- a/xlators/storage/posix/src/posix.h
e3c68b
+++ b/xlators/storage/posix/src/posix.h
e3c68b
@@ -339,7 +339,7 @@ dict_t *
e3c68b
 posix_xattr_fill(xlator_t *this, const char *path, loc_t *loc, fd_t *fd,
e3c68b
                  int fdnum, dict_t *xattr, struct iatt *buf);
e3c68b
 int
e3c68b
-posix_handle_pair(xlator_t *this, const char *real_path, char *key,
e3c68b
+posix_handle_pair(xlator_t *this, loc_t *loc, const char *real_path, char *key,
e3c68b
                   data_t *value, int flags, struct iatt *stbuf);
e3c68b
 int
e3c68b
 posix_fhandle_pair(call_frame_t *frame, xlator_t *this, int fd, char *key,
e3c68b
@@ -352,7 +352,8 @@ int
e3c68b
 posix_gfid_heal(xlator_t *this, const char *path, loc_t *loc,
e3c68b
                 dict_t *xattr_req);
e3c68b
 int
e3c68b
-posix_entry_create_xattr_set(xlator_t *this, const char *path, dict_t *dict);
e3c68b
+posix_entry_create_xattr_set(xlator_t *this, loc_t *loc, const char *path,
e3c68b
+                             dict_t *dict);
e3c68b
 
e3c68b
 int
e3c68b
 posix_fd_ctx_get(fd_t *fd, xlator_t *this, struct posix_fd **pfd,
e3c68b
-- 
e3c68b
1.8.3.1
e3c68b