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