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