diff options
Diffstat (limited to 'tests')
102 files changed, 4501 insertions, 199 deletions
diff --git a/tests/00-geo-rep/00-georep-verify-non-root-setup.t b/tests/00-geo-rep/00-georep-verify-non-root-setup.t index 27ed82732c9..a55fd3e5e6a 100644 --- a/tests/00-geo-rep/00-georep-verify-non-root-setup.t +++ b/tests/00-geo-rep/00-georep-verify-non-root-setup.t @@ -5,7 +5,7 @@ . $(dirname $0)/../geo-rep.rc . $(dirname $0)/../env.rc -SCRIPT_TIMEOUT=500 +SCRIPT_TIMEOUT=600 ### Basic Non-root geo-rep setup test with Distribute Replicate volumes @@ -144,12 +144,15 @@ TEST pidof glusterd; TEST $CLI volume create $META_VOL replica 3 $H0:$B0/${META_VOL}{1,2,3}; TEST $CLI volume start $META_VOL TEST mkdir -p $META_MNT +EXPECT_WITHIN ${PROCESS_UP_TIMEOUT} "3" brick_count ${META_VOL} TEST glusterfs -s $H0 --volfile-id $META_VOL $META_MNT ##Mount master +EXPECT_WITHIN ${PROCESS_UP_TIMEOUT} "4" brick_count $GMV0 TEST glusterfs -s $H0 --volfile-id $GMV0 $M0 ##Mount slave +EXPECT_WITHIN ${PROCESS_UP_TIMEOUT} "4" brick_count $GSV0 TEST glusterfs -s $H0 --volfile-id $GSV0 $M1 ## Check status of mount-broker @@ -189,6 +192,8 @@ TEST gluster-georep-sshkey generate TEST $GEOREP_CLI $master $slave_url create push-pem +#check for session creation +EXPECT_WITHIN $GEO_REP_TIMEOUT 4 check_status_non_root "Created" #Config gluster-command-dir TEST $GEOREP_CLI $master $slave_url config gluster-command-dir ${GLUSTER_CMD_DIR} @@ -240,21 +245,25 @@ TEST ! $GEOREP_CLI $master $slave_url config ssh-port 22a TEST $GEOREP_CLI $master $slave config ssh-port 22 #Hybrid directory rename test BZ#1763439 + TEST $GEOREP_CLI $master $slave_url config change_detector xsync -mkdir ${master_mnt}/dir1 -mkdir ${master_mnt}/dir1/dir2 -mkdir ${master_mnt}/dir1/dir3 -mkdir ${master_mnt}/hybrid_d1 +#verify master and slave mount -EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/hybrid_d1 -EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/dir1 -EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/dir1/dir2 -EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/dir1/dir3 +EXPECT_WITHIN $CHECK_MOUNT_TIMEOUT "^1$" check_mounted ${master_mnt} +EXPECT_WITHIN $CHECK_MOUNT_TIMEOUT "^1$" check_mounted ${slave_mnt} + +#Create test data for hybrid crawl +TEST mkdir ${master_mnt}/dir1 +TEST mkdir ${master_mnt}/dir1/dir2 +TEST mkdir ${master_mnt}/dir1/dir3 +TEST mkdir ${master_mnt}/hybrid_d1 mv ${master_mnt}/hybrid_d1 ${master_mnt}/hybrid_rn_d1 mv ${master_mnt}/dir1/dir2 ${master_mnt}/rn_dir2 mv ${master_mnt}/dir1/dir3 ${master_mnt}/dir1/rn_dir3 +#Verify hybrid crawl data on slave +EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/dir1 EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/hybrid_rn_d1 EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/rn_dir2 EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/dir1/rn_dir3 diff --git a/tests/00-geo-rep/00-georep-verify-setup.t b/tests/00-geo-rep/00-georep-verify-setup.t index cdfccd35db5..0d46c04102d 100644 --- a/tests/00-geo-rep/00-georep-verify-setup.t +++ b/tests/00-geo-rep/00-georep-verify-setup.t @@ -5,7 +5,8 @@ . $(dirname $0)/../geo-rep.rc . $(dirname $0)/../env.rc -SCRIPT_TIMEOUT=300 +SCRIPT_TIMEOUT=400 +GEO_REP_TIMEOUT=200 ##Cleanup and start glusterd cleanup; diff --git a/tests/00-geo-rep/georep-upgrade.t b/tests/00-geo-rep/georep-upgrade.t new file mode 100644 index 00000000000..7523068ed50 --- /dev/null +++ b/tests/00-geo-rep/georep-upgrade.t @@ -0,0 +1,79 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc + +SCRIPT_TIMEOUT=500 + +############################################################################################### +#Before upgrade +############################################################################################### +brick=/bricks/brick1 +epoch1=$(date '+%s') +sleep 1 +epoch2=$(date '+%s') +mkdir -p /bricks/brick1/.glusterfs/changelogs/htime +mkdir -p /bricks/brick1/.glusterfs/changelogs + +#multiple htime files(changelog enable/disable scenario) +TEST touch /bricks/brick1/.glusterfs/changelogs/htime/HTIME.$epoch1 +TEST touch /bricks/brick1/.glusterfs/changelogs/htime/HTIME.$epoch2 + +#changelog files +TEST touch /bricks/brick1/.glusterfs/changelogs/CHANGELOG.$epoch1 +TEST touch /bricks/brick1/.glusterfs/changelogs/CHANGELOG.$epoch2 + +htime_file1=/bricks/brick1/.glusterfs/changelogs/htime/HTIME.$epoch1 +htime_file2=/bricks/brick1/.glusterfs/changelogs/htime/HTIME.$epoch2 + +#data inside htime files before upgrade +data1=/bricks/brick1/.glusterfs/changelogs/CHANGELOG.$epoch1 +data2=/bricks/brick1/.glusterfs/changelogs/CHANGELOG.$epoch2 + +#data inside htime files after upgrade +updated_data1=/bricks/brick1/.glusterfs/changelogs/`echo $(date '+%Y/%m/%d')`/CHANGELOG.$epoch1 +updated_data2=/bricks/brick1/.glusterfs/changelogs/`echo $(date '+%Y/%m/%d')`/CHANGELOG.$epoch2 + +echo -n $data1>$htime_file1 +echo -n $data2>$htime_file2 + +echo "Before upgrade:" +EXPECT '1' echo $(grep $data1 $htime_file1 | wc -l) +EXPECT '1' echo $(grep $data2 $htime_file2 | wc -l) + +EXPECT '1' echo $(ls /bricks/brick1/.glusterfs/changelogs/CHANGELOG.$epoch1 | wc -l) +EXPECT '1' echo $(ls /bricks/brick1/.glusterfs/changelogs/htime/HTIME.$epoch1 | wc -l) +EXPECT '1' echo $(ls /bricks/brick1/.glusterfs/changelogs/CHANGELOG.$epoch2 | wc -l) +EXPECT '1' echo $(ls /bricks/brick1/.glusterfs/changelogs/htime/HTIME.$epoch2 | wc -l) +############################################################################################### +#Upgrade +############################################################################################### +### This needed to be fixed as this very vague finding a file with name in '/' +### multiple file with same name can exist +### for temp fix picking only 1st result +TEST upgrade_script=$(find / -type f -name glusterfs-georep-upgrade.py -print | head -n 1) +TEST python3 $upgrade_script $brick + +############################################################################################### +#After upgrade +############################################################################################### +echo "After upgrade:" +EXPECT '1' echo $(grep $updated_data1 $htime_file1 | wc -l) +EXPECT '1' echo $(grep $updated_data2 $htime_file2 | wc -l) + +#Check directory structure inside changelogs +TEST ! ls /bricks/brick1/.glusterfs/changelogs/CHANGELOG.$epoch1 +EXPECT '1' echo $(ls /bricks/brick1/.glusterfs/changelogs/htime/HTIME.$epoch1 | wc -l) +EXPECT '1' echo $(ls /bricks/brick1/.glusterfs/changelogs/htime/HTIME.$epoch1.bak | wc -l) +EXPECT '1' echo $(ls /bricks/brick1/.glusterfs/changelogs/`echo $(date '+%Y')` | wc -l) +EXPECT '1' echo $(ls /bricks/brick1/.glusterfs/changelogs/`echo $(date '+%Y/%m')` | wc -l) +EXPECT '2' echo $(ls /bricks/brick1/.glusterfs/changelogs/`echo $(date '+%Y/%m/%d')` | wc -l) +EXPECT '1' echo $(ls /bricks/brick1/.glusterfs/changelogs/`echo $(date '+%Y/%m/%d')`/CHANGELOG.$epoch1 | wc -l) + +TEST ! ls /bricks/brick1/.glusterfs/changelogs/CHANGELOG.$epoch2 +EXPECT '1' echo $(ls /bricks/brick1/.glusterfs/changelogs/htime/HTIME.$epoch2 | wc -l) +EXPECT '1' echo $(ls /bricks/brick1/.glusterfs/changelogs/htime/HTIME.$epoch2.bak | wc -l) +EXPECT '1' echo $(ls /bricks/brick1/.glusterfs/changelogs/`echo $(date '+%Y')` | wc -l) +EXPECT '1' echo $(ls /bricks/brick1/.glusterfs/changelogs/`echo $(date '+%Y/%m')`| wc -l) +EXPECT '1' echo $(ls /bricks/brick1/.glusterfs/changelogs/`echo $(date '+%Y/%m/%d')`/CHANGELOG.$epoch2 | wc -l) + +TEST rm -rf /bricks diff --git a/tests/basic/afr/split-brain-favorite-child-policy.t b/tests/000-flaky/basic_afr_split-brain-favorite-child-policy.t index c268c125610..77d82a4996f 100644 --- a/tests/basic/afr/split-brain-favorite-child-policy.t +++ b/tests/000-flaky/basic_afr_split-brain-favorite-child-policy.t @@ -1,8 +1,8 @@ #!/bin/bash #Test the split-brain resolution CLI commands. -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc cleanup; diff --git a/tests/basic/changelog/changelog-snapshot.t b/tests/000-flaky/basic_changelog_changelog-snapshot.t index 7742db48cdd..f6cd0b04d47 100644 --- a/tests/basic/changelog/changelog-snapshot.t +++ b/tests/000-flaky/basic_changelog_changelog-snapshot.t @@ -1,7 +1,7 @@ #!/bin/bash -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../snapshot.rc +. $(dirname $0)/../include.rc +. $(dirname $0)/../snapshot.rc cleanup; ROLLOVER_TIME=3 diff --git a/tests/basic/distribute/rebal-all-nodes-migrate.t b/tests/000-flaky/basic_distribute_rebal-all-nodes-migrate.t index acc4ffefecc..eb5d3305ac1 100644 --- a/tests/basic/distribute/rebal-all-nodes-migrate.t +++ b/tests/000-flaky/basic_distribute_rebal-all-nodes-migrate.t @@ -1,8 +1,8 @@ #!/bin/bash -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../cluster.rc -. $(dirname $0)/../../dht.rc +. $(dirname $0)/../include.rc +. $(dirname $0)/../cluster.rc +. $(dirname $0)/../dht.rc # Check if every single rebalance process migrated some files @@ -10,11 +10,9 @@ function cluster_rebal_all_nodes_migrated_files { val=0 a=$($CLI_1 volume rebalance $V0 status | grep "completed" | awk '{print $2}'); -# echo $a b=($a) for i in "${b[@]}" do -# echo "$i"; if [ "$i" -eq "0" ]; then echo "false"; val=1; diff --git a/tests/basic/ec/ec-quorum-count-partial-failure.t b/tests/000-flaky/basic_ec_ec-quorum-count-partial-failure.t index 79f5825ae10..42808ce0c0e 100755..100644 --- a/tests/basic/ec/ec-quorum-count-partial-failure.t +++ b/tests/000-flaky/basic_ec_ec-quorum-count-partial-failure.t @@ -1,7 +1,7 @@ #!/bin/bash -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc #This test checks that partial failure of fop results in main fop failure only cleanup; diff --git a/tests/basic/mount-nfs-auth.t b/tests/000-flaky/basic_mount-nfs-auth.t index 3d4a9cff00b..3d4a9cff00b 100755..100644 --- a/tests/basic/mount-nfs-auth.t +++ b/tests/000-flaky/basic_mount-nfs-auth.t diff --git a/tests/bugs/core/multiplex-limit-issue-151.t b/tests/000-flaky/bugs_core_multiplex-limit-issue-151.t index dc9013061b0..5a88f97d726 100644 --- a/tests/bugs/core/multiplex-limit-issue-151.t +++ b/tests/000-flaky/bugs_core_multiplex-limit-issue-151.t @@ -1,8 +1,8 @@ #!/bin/bash -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../traps.rc -. $(dirname $0)/../../volume.rc +. $(dirname $0)/../include.rc +. $(dirname $0)/../traps.rc +. $(dirname $0)/../volume.rc function count_up_bricks { $CLI --xml volume status all | grep '<status>1' | wc -l diff --git a/tests/bugs/distribute/bug-1117851.t b/tests/000-flaky/bugs_distribute_bug-1117851.t index 62cb6b66ab4..5980bf2fd4b 100755..100644 --- a/tests/bugs/distribute/bug-1117851.t +++ b/tests/000-flaky/bugs_distribute_bug-1117851.t @@ -2,8 +2,8 @@ SCRIPT_TIMEOUT=250 -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc create_files () { for i in {1..1000}; do diff --git a/tests/bugs/distribute/bug-1122443.t b/tests/000-flaky/bugs_distribute_bug-1122443.t index 906be7072bd..abd37082b33 100644 --- a/tests/bugs/distribute/bug-1122443.t +++ b/tests/000-flaky/bugs_distribute_bug-1122443.t @@ -1,8 +1,8 @@ #!/bin/bash -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../dht.rc +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../dht.rc make_files() { mkdir $1 && \ @@ -42,8 +42,8 @@ TEST glusterfs -s $H0 --volfile-id $V0 $M0 TEST make_files $M0/subdir # Get mtime before migration -BEFORE="$(stat -c %n:%Y $M0/subdir/* | tr '\n' ',')" - +BEFORE="$(stat -c %n:%Y $M0/subdir/* | sort | tr '\n' ',')" +echo $BEFORE # Migrate brick TEST $CLI volume add-brick $V0 $H0:$B0/${V0}1 TEST $CLI volume remove-brick $V0 $H0:$B0/${V0}0 start @@ -51,9 +51,10 @@ EXPECT_WITHIN $REBALANCE_TIMEOUT "completed" remove_brick_status_completed_field TEST $CLI volume remove-brick $V0 $H0:$B0/${V0}0 commit # Get mtime after migration -EXPECT_WITHIN 5 RECONNECTED bug_1113050_workaround $M0/subdir/* -AFTER="$(stat -c %n:%Y $M0/subdir/* | tr '\n' ',')" - +EXPECT_WITHIN 30 RECONNECTED bug_1113050_workaround $M0/subdir/symlink +sleep 3 +AFTER="$(stat -c %n:%Y $M0/subdir/* | sort | tr '\n' ',')" +echo $AFTER # Check if mtime is unchanged TEST [ "$AFTER" == "$BEFORE" ] diff --git a/tests/bugs/glusterd/bug-857330/common.rc b/tests/000-flaky/bugs_glusterd_bug-857330/common.rc index d0aa4b1a640..bd122eff18c 100644 --- a/tests/bugs/glusterd/bug-857330/common.rc +++ b/tests/000-flaky/bugs_glusterd_bug-857330/common.rc @@ -1,4 +1,4 @@ -. $(dirname $0)/../../../include.rc +. $(dirname $0)/../../include.rc UUID_REGEX='[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}' diff --git a/tests/bugs/glusterd/bug-857330/normal.t b/tests/000-flaky/bugs_glusterd_bug-857330/normal.t index ad0c8844fae..6c1cf54ec3c 100755 --- a/tests/bugs/glusterd/bug-857330/normal.t +++ b/tests/000-flaky/bugs_glusterd_bug-857330/normal.t @@ -1,7 +1,7 @@ #!/bin/bash . $(dirname $0)/common.rc -. $(dirname $0)/../../../volume.rc +. $(dirname $0)/../../volume.rc cleanup; TEST glusterd @@ -14,7 +14,7 @@ TEST $CLI volume start $V0; TEST glusterfs -s $H0 --volfile-id=$V0 $M0; -TEST $PYTHON $(dirname $0)/../../../utils/create-files.py \ +TEST $PYTHON $(dirname $0)/../../utils/create-files.py \ --multi -b 10 -d 10 -n 10 $M0; EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 diff --git a/tests/bugs/glusterd/bug-857330/xml.t b/tests/000-flaky/bugs_glusterd_bug-857330/xml.t index 8383d2a0711..11785adacdb 100755 --- a/tests/bugs/glusterd/bug-857330/xml.t +++ b/tests/000-flaky/bugs_glusterd_bug-857330/xml.t @@ -1,7 +1,7 @@ #!/bin/bash . $(dirname $0)/common.rc -. $(dirname $0)/../../../volume.rc +. $(dirname $0)/../../volume.rc cleanup; @@ -15,7 +15,7 @@ TEST $CLI volume start $V0; TEST glusterfs -s $H0 --volfile-id=$V0 $M0; -TEST $PYTHON $(dirname $0)/../../../utils/create-files.py \ +TEST $PYTHON $(dirname $0)/../../utils/create-files.py \ --multi -b 10 -d 10 -n 10 $M0; EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 diff --git a/tests/bugs/glusterd/quorum-value-check.t b/tests/000-flaky/bugs_glusterd_quorum-value-check.t index c701f08bbd5..a431b8c4fd4 100755..100644 --- a/tests/bugs/glusterd/quorum-value-check.t +++ b/tests/000-flaky/bugs_glusterd_quorum-value-check.t @@ -1,7 +1,7 @@ #!/bin/bash -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc #G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST diff --git a/tests/bugs/nfs/bug-1116503.t b/tests/000-flaky/bugs_nfs_bug-1116503.t index dd3998df150..fc50021acc7 100644 --- a/tests/bugs/nfs/bug-1116503.t +++ b/tests/000-flaky/bugs_nfs_bug-1116503.t @@ -3,9 +3,9 @@ # Verify that mounting NFS over UDP (MOUNT service only) works. # -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../nfs.rc +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../nfs.rc #G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST diff --git a/tests/features/lock-migration/lkmigration-set-option.t b/tests/000-flaky/features_lock-migration_lkmigration-set-option.t index 4340438591f..1327ef3579f 100644 --- a/tests/features/lock-migration/lkmigration-set-option.t +++ b/tests/000-flaky/features_lock-migration_lkmigration-set-option.t @@ -1,7 +1,7 @@ #!/bin/bash # Test to check -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc #Check lock-migration set option sanity cleanup; diff --git a/tests/afr.rc b/tests/afr.rc index 35f352df78f..241789903ba 100644 --- a/tests/afr.rc +++ b/tests/afr.rc @@ -105,3 +105,19 @@ function get_quorum_type() local repl_id="$3" cat $m/.meta/graphs/active/$v-replicate-$repl_id/private|grep quorum-type|awk '{print $3}' } + +function afr_private_key_value() +{ + local v=$1 + local m=$2 + local replica_id=$3 + local key=$4 +#xargs at the end will strip leading spaces + grep -E "^${key} = " $m/.meta/graphs/active/${v}-replicate-${replica_id}/private | cut -f2 -d'=' | xargs +} + +function afr_anon_entry_count() +{ + local b=$1 + ls $b/.glusterfs-anonymous-inode* | wc -l +} diff --git a/tests/basic/afr/afr-anon-inode-no-quorum.t b/tests/basic/afr/afr-anon-inode-no-quorum.t new file mode 100644 index 00000000000..896ba0c9b2c --- /dev/null +++ b/tests/basic/afr/afr-anon-inode-no-quorum.t @@ -0,0 +1,63 @@ +#!/bin/bash + +#Test that anon-inode entry is not cleaned up as long as there exists at least +#one valid entry +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../afr.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1} +TEST $CLI volume heal $V0 disable +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume set $V0 performance.read-ahead off +TEST $CLI volume set $V0 performance.readdir-ahead off +TEST $CLI volume set $V0 performance.open-behind off +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume set $V0 performance.io-cache off +TEST $CLI volume set $V0 performance.quick-read off +TEST $CLI volume set $V0 cluster.entry-self-heal off +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 + +TEST touch $M0/a $M0/b + +gfid_a=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/a)) +gfid_b=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/b)) +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST mv $M0/a $M0/a-new +TEST mv $M0/b $M0/b-new + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST ! ls $M0/a +TEST ! ls $M0/b +anon_inode_name=$(ls -a $B0/${V0}0 | grep glusterfs-anonymous-inode) +TEST stat $B0/${V0}0/$anon_inode_name/$gfid_a +TEST stat $B0/${V0}0/$anon_inode_name/$gfid_b +#Make sure index heal doesn't happen after enabling heal +TEST setfattr -x trusted.afr.$V0-client-0 $B0/${V0}1 +TEST rm -f $B0/${V0}1/.glusterfs/indices/xattrop/* +TEST $CLI volume heal $V0 enable +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 +TEST $CLI volume heal $V0 +#Allow time for a scan +sleep 5 +TEST stat $B0/${V0}0/$anon_inode_name/$gfid_a +TEST stat $B0/${V0}0/$anon_inode_name/$gfid_b +inum_b=$(STAT_INO $B0/${V0}0/$anon_inode_name/$gfid_b) +TEST rm -f $M0/a-new +TEST stat $M0/b-new + +TEST $CLI volume heal $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_anon_entry_count $B0/${V0}0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_anon_entry_count $B0/${V0}1 +EXPECT "$inum_b" STAT_INO $B0/${V0}0/b-new + +cleanup diff --git a/tests/basic/afr/afr-anon-inode.t b/tests/basic/afr/afr-anon-inode.t new file mode 100644 index 00000000000..f4cf37a2fa0 --- /dev/null +++ b/tests/basic/afr/afr-anon-inode.t @@ -0,0 +1,114 @@ +#!/bin/bash +#Tests that afr-anon-inode test cases work fine as expected +#These are cases where in entry-heal/name-heal we dont know entry for an inode +#so these inodes are kept in a special directory + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../afr.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0..2} +TEST $CLI volume set $V0 performance.quick-read off +TEST $CLI volume set $V0 performance.io-cache off +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume set $V0 performance.read-ahead off +TEST $CLI volume set $V0 performance.open-behind off +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +EXPECT "^1$" afr_private_key_value $V0 $M0 0 "use-anonymous-inode" +TEST $CLI volume set $V0 cluster.use-anonymous-inode no +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "^0$" afr_private_key_value $V0 $M0 0 "use-anonymous-inode" +TEST $CLI volume set $V0 cluster.use-anonymous-inode yes +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "^1$" afr_private_key_value $V0 $M0 0 "use-anonymous-inode" +TEST mkdir -p $M0/d1/b $M0/d2/a +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST mv $M0/d2/a $M0/d1 +TEST mv $M0/d1/b $M0/d2 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 +anon_inode_name=$(ls -a $B0/${V0}0 | grep glusterfs-anonymous-inode) +TEST [[ -d $B0/${V0}1/$anon_inode_name ]] +TEST [[ -d $B0/${V0}2/$anon_inode_name ]] +anon_gfid=$(gf_get_gfid_xattr $B0/${V0}0/$anon_inode_name) +EXPECT "$anon_gfid" gf_get_gfid_xattr $B0/${V0}1/$anon_inode_name +EXPECT "$anon_gfid" gf_get_gfid_xattr $B0/${V0}2/$anon_inode_name + +TEST ! ls $M0/$anon_inode_name +EXPECT "^4$" echo $(ls -a $M0 | wc -l) + +#Test purging code path by shd +TEST $CLI volume heal $V0 disable +TEST mkdir $M0/l0 $M0/l1 $M0/l2 +TEST touch $M0/del-file $M0/del-file-nolink $M0/l0/file +TEST ln $M0/del-file $M0/del-file-link +TEST ln $M0/l0/file $M0/l1/file-link1 +TEST ln $M0/l0/file $M0/l2/file-link2 +TEST mkdir -p $M0/del-recursive-dir/d1 + +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST rm -f $M0/del-file $M0/del-file-nolink +TEST rm -rf $M0/del-recursive-dir +TEST mv $M0/d1/a $M0/d2 +TEST mv $M0/l0/file $M0/l0/renamed-file +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "^1$" afr_child_up_status $V0 0 + +nolink_gfid=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/del-file-nolink)) +link_gfid=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/del-file)) +dir_gfid=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/del-recursive-dir)) +rename_dir_gfid=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/d1/a)) +rename_file_gfid=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/l0/file)) +TEST ! stat $M0/del-file +TEST stat $B0/${V0}0/$anon_inode_name/$link_gfid +TEST ! stat $M0/del-file-nolink +TEST ! stat $B0/${V0}0/$anon_inode_name/$nolink_gfid +TEST ! stat $M0/del-recursive-dir +TEST stat $B0/${V0}0/$anon_inode_name/$dir_gfid +TEST ! stat $M0/d1/a +TEST stat $B0/${V0}0/$anon_inode_name/$rename_dir_gfid +TEST ! stat $M0/l0/file +TEST stat $B0/${V0}0/$anon_inode_name/$rename_file_gfid + +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST mv $M0/l1/file-link1 $M0/l1/renamed-file-link1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "^1$" afr_child_up_status $V0 1 +TEST ! stat $M0/l1/file-link1 +TEST stat $B0/${V0}1/$anon_inode_name/$rename_file_gfid + +TEST kill_brick $V0 $H0 $B0/${V0}2 +TEST mv $M0/l2/file-link2 $M0/l2/renamed-file-link2 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "^1$" afr_child_up_status $V0 2 +TEST ! stat $M0/l2/file-link2 +TEST stat $B0/${V0}2/$anon_inode_name/$rename_file_gfid + +#Simulate only anon-inodes present in all bricks +TEST rm -f $M0/l0/renamed-file $M0/l1/renamed-file-link1 $M0/l2/renamed-file-link2 + +#Test that shd doesn't cleanup anon-inodes when some bricks are down +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST $CLI volume heal $V0 enable +$CLI volume heal $V0 +sleep 5 #Allow time for completion of one scan +TEST stat $B0/${V0}0/$anon_inode_name/$link_gfid +TEST stat $B0/${V0}0/$anon_inode_name/$rename_dir_gfid +TEST stat $B0/${V0}0/$anon_inode_name/$dir_gfid +rename_dir_inum=$(STAT_INO $B0/${V0}0/$anon_inode_name/$rename_dir_gfid) + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "^1$" afr_child_up_status $V0 1 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_anon_entry_count $B0/${V0}0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_anon_entry_count $B0/${V0}1 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_anon_entry_count $B0/${V0}2 + +#Test that rename indeed happened instead of rmdir/mkdir +renamed_dir_inum=$(STAT_INO $B0/${V0}0/d2/a) +EXPECT "$rename_dir_inum" echo $renamed_dir_inum +cleanup; diff --git a/tests/basic/afr/durability-off.t b/tests/basic/afr/durability-off.t index 155ffa09ef0..6e0f18b88f8 100644 --- a/tests/basic/afr/durability-off.t +++ b/tests/basic/afr/durability-off.t @@ -26,6 +26,8 @@ TEST $CLI volume heal $V0 EXPECT_WITHIN $HEAL_TIMEOUT "0" get_pending_heal_count $V0 EXPECT "^0$" echo $($CLI volume profile $V0 info | grep -w FSYNC | wc -l) +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1 #Test that fsyncs happen when durability is on TEST $CLI volume set $V0 cluster.ensure-durability on TEST $CLI volume set $V0 performance.strict-write-ordering on diff --git a/tests/basic/afr/entry-self-heal-anon-dir-off.t b/tests/basic/afr/entry-self-heal-anon-dir-off.t new file mode 100644 index 00000000000..7bb6ee14193 --- /dev/null +++ b/tests/basic/afr/entry-self-heal-anon-dir-off.t @@ -0,0 +1,459 @@ +#!/bin/bash + +#This file checks if missing entry self-heal and entry self-heal are working +#as expected. +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../afr.rc + +cleanup; + +function get_file_type { + stat -c "%a:%F:%g:%t:%T:%u" $1 +} + +function diff_dirs { + diff <(ls $1 | sort) <(ls $2 | sort) +} + +function heal_status { + local f1_path="${1}/${3}" + local f2_path="${2}/${3}" + local insync="" + diff_dirs $f1_path $f2_path + if [ $? -eq 0 ]; + then + insync="Y" + else + insync="N" + fi + local xattr11=$(get_hex_xattr trusted.afr.$V0-client-0 $f1_path) + local xattr12=$(get_hex_xattr trusted.afr.$V0-client-1 $f1_path) + local xattr21=$(get_hex_xattr trusted.afr.$V0-client-0 $f2_path) + local xattr22=$(get_hex_xattr trusted.afr.$V0-client-1 $f2_path) + local dirty1=$(get_hex_xattr trusted.afr.dirty $f1_path) + local dirty2=$(get_hex_xattr trusted.afr.dirty $f2_path) + if [ -z $xattr11 ]; then xattr11="000000000000000000000000"; fi + if [ -z $xattr12 ]; then xattr12="000000000000000000000000"; fi + if [ -z $xattr21 ]; then xattr21="000000000000000000000000"; fi + if [ -z $xattr22 ]; then xattr22="000000000000000000000000"; fi + if [ -z $dirty1 ]; then dirty1="000000000000000000000000"; fi + if [ -z $dirty2 ]; then dirty2="000000000000000000000000"; fi + echo ${insync}${xattr11}${xattr12}${xattr21}${xattr22}${dirty1}${dirty2} +} + +function is_heal_done { + local zero_xattr="000000000000000000000000" + if [ "$(heal_status $@)" == "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" ]; + then + echo "Y" + else + echo "N" + fi +} + +function print_pending_heals { + local result=":" + for i in "$@"; + do + if [ "N" == $(is_heal_done $B0/${V0}0 $B0/${V0}1 $i) ]; + then + result="$result:$i" + fi + done +#To prevent any match for EXPECT_WITHIN, print a char non-existent in file-names + if [ $result == ":" ]; then result="~"; fi + echo $result +} + +zero_xattr="000000000000000000000000" +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1} +TEST $CLI volume heal $V0 disable +TEST $CLI volume set $V0 cluster.use-anonymous-inode off +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume set $V0 performance.read-ahead off +TEST $CLI volume set $V0 performance.readdir-ahead off +TEST $CLI volume set $V0 performance.open-behind off +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume set $V0 performance.io-cache off +TEST $CLI volume set $V0 performance.quick-read off +TEST $CLI volume set $V0 cluster.data-self-heal on +TEST $CLI volume set $V0 cluster.metadata-self-heal on +TEST $CLI volume set $V0 cluster.entry-self-heal on +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 --use-readdirp=no $M0 +cd $M0 +#_me_ is dir on which missing entry self-heal happens, _heal is where dir self-heal happens +#spb is split-brain, fool is all fool + +#source_self_accusing means there exists source and a sink which self-accuses. +#This simulates failures where fops failed on the bricks without it going down. +#Something like EACCESS/EDQUOT etc + +TEST mkdir spb_heal spb spb_me_heal spb_me fool_heal fool_me v1_fool_heal v1_fool_me source_creations_heal source_deletions_heal source_creations_me source_deletions_me v1_dirty_me v1_dirty_heal source_self_accusing +TEST mkfifo source_deletions_heal/fifo +TEST mknod source_deletions_heal/block b 4 5 +TEST mknod source_deletions_heal/char c 1 5 +TEST touch source_deletions_heal/file +TEST ln -s source_deletions_heal/file source_deletions_heal/slink +TEST mkdir source_deletions_heal/dir1 +TEST mkdir source_deletions_heal/dir1/dir2 + +TEST mkfifo source_deletions_me/fifo +TEST mknod source_deletions_me/block b 4 5 +TEST mknod source_deletions_me/char c 1 5 +TEST touch source_deletions_me/file +TEST ln -s source_deletions_me/file source_deletions_me/slink +TEST mkdir source_deletions_me/dir1 +TEST mkdir source_deletions_me/dir1/dir2 + +TEST mkfifo source_self_accusing/fifo +TEST mknod source_self_accusing/block b 4 5 +TEST mknod source_self_accusing/char c 1 5 +TEST touch source_self_accusing/file +TEST ln -s source_self_accusing/file source_self_accusing/slink +TEST mkdir source_self_accusing/dir1 +TEST mkdir source_self_accusing/dir1/dir2 + +TEST kill_brick $V0 $H0 $B0/${V0}0 + +TEST touch spb_heal/0 spb/0 spb_me_heal/0 spb_me/0 fool_heal/0 fool_me/0 v1_fool_heal/0 v1_fool_me/0 v1_dirty_heal/0 v1_dirty_me/0 +TEST rm -rf source_deletions_heal/fifo source_deletions_heal/block source_deletions_heal/char source_deletions_heal/file source_deletions_heal/slink source_deletions_heal/dir1 +TEST rm -rf source_deletions_me/fifo source_deletions_me/block source_deletions_me/char source_deletions_me/file source_deletions_me/slink source_deletions_me/dir1 +TEST rm -rf source_self_accusing/fifo source_self_accusing/block source_self_accusing/char source_self_accusing/file source_self_accusing/slink source_self_accusing/dir1 + +#Test that the files are deleted +TEST ! stat $B0/${V0}1/source_deletions_heal/fifo +TEST ! stat $B0/${V0}1/source_deletions_heal/block +TEST ! stat $B0/${V0}1/source_deletions_heal/char +TEST ! stat $B0/${V0}1/source_deletions_heal/file +TEST ! stat $B0/${V0}1/source_deletions_heal/slink +TEST ! stat $B0/${V0}1/source_deletions_heal/dir1 +TEST ! stat $B0/${V0}1/source_deletions_me/fifo +TEST ! stat $B0/${V0}1/source_deletions_me/block +TEST ! stat $B0/${V0}1/source_deletions_me/char +TEST ! stat $B0/${V0}1/source_deletions_me/file +TEST ! stat $B0/${V0}1/source_deletions_me/slink +TEST ! stat $B0/${V0}1/source_deletions_me/dir1 +TEST ! stat $B0/${V0}1/source_self_accusing/fifo +TEST ! stat $B0/${V0}1/source_self_accusing/block +TEST ! stat $B0/${V0}1/source_self_accusing/char +TEST ! stat $B0/${V0}1/source_self_accusing/file +TEST ! stat $B0/${V0}1/source_self_accusing/slink +TEST ! stat $B0/${V0}1/source_self_accusing/dir1 + + +TEST mkfifo source_creations_heal/fifo +TEST mknod source_creations_heal/block b 4 5 +TEST mknod source_creations_heal/char c 1 5 +TEST touch source_creations_heal/file +TEST ln -s source_creations_heal/file source_creations_heal/slink +TEST mkdir source_creations_heal/dir1 +TEST mkdir source_creations_heal/dir1/dir2 + +TEST mkfifo source_creations_me/fifo +TEST mknod source_creations_me/block b 4 5 +TEST mknod source_creations_me/char c 1 5 +TEST touch source_creations_me/file +TEST ln -s source_creations_me/file source_creations_me/slink +TEST mkdir source_creations_me/dir1 +TEST mkdir source_creations_me/dir1/dir2 + +$CLI volume stop $V0 + +#simulate fool fool scenario for fool_* dirs +setfattr -x trusted.afr.$V0-client-0 $B0/${V0}1/{fool_heal,fool_me} +setfattr -n trusted.afr.dirty -v 0x000000000000000000000001 $B0/${V0}1/{fool_heal,fool_me} +setfattr -n trusted.afr.$V0-client-1 -v 0x000000000000000000000001 $B0/${V0}1/{v1_fool_heal,v1_fool_me} + +#Simulate v1-dirty(self-accusing but no pending ops on others) scenario for v1-dirty +setfattr -x trusted.afr.$V0-client-0 $B0/${V0}1/v1_dirty_{heal,me} +setfattr -n trusted.afr.$V0-client-1 -v 0x000000000000000000000001 $B0/${V0}1/v1_dirty_{heal,me} + +$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 1 +TEST kill_brick $V0 $H0 $B0/${V0}1 + +TEST touch spb_heal/1 spb/0 spb_me_heal/1 spb_me/0 fool_heal/1 fool_me/1 v1_fool_heal/1 v1_fool_me/1 + +$CLI volume stop $V0 + +#simulate fool fool scenario for fool_* dirs +setfattr -x trusted.afr.$V0-client-1 $B0/${V0}0/{fool_heal,fool_me} +setfattr -n trusted.afr.dirty -v 0x000000000000000000000001 $B0/${V0}1/{fool_heal,fool_me} +setfattr -n trusted.afr.$V0-client-0 -v 0x000000000000000000000001 $B0/${V0}1/{v1_fool_heal,v1_fool_me} + +#simulate self-accusing for source_self_accusing +TEST setfattr -n trusted.afr.$V0-client-0 -v 0x000000000000000000000006 $B0/${V0}0/source_self_accusing + +$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 0 + +# Check if conservative merges happened correctly on _me_ dirs +TEST stat spb_me_heal/1 +TEST stat $B0/${V0}0/spb_me_heal/1 +TEST stat $B0/${V0}1/spb_me_heal/1 + +TEST stat spb_me_heal/0 +TEST stat $B0/${V0}0/spb_me_heal/0 +TEST stat $B0/${V0}1/spb_me_heal/0 + +TEST stat fool_me/1 +TEST stat $B0/${V0}0/fool_me/1 +TEST stat $B0/${V0}1/fool_me/1 + +TEST stat fool_me/0 +TEST stat $B0/${V0}0/fool_me/0 +TEST stat $B0/${V0}1/fool_me/0 + +TEST stat v1_fool_me/0 +TEST stat $B0/${V0}0/v1_fool_me/0 +TEST stat $B0/${V0}1/v1_fool_me/0 + +TEST stat v1_fool_me/1 +TEST stat $B0/${V0}0/v1_fool_me/1 +TEST stat $B0/${V0}1/v1_fool_me/1 + +TEST stat v1_dirty_me/0 +TEST stat $B0/${V0}0/v1_dirty_me/0 +TEST stat $B0/${V0}1/v1_dirty_me/0 + +#Check if files that have gfid-mismatches in _me_ are giving EIO +TEST ! stat spb_me/0 + +#Check if stale files are deleted on access +TEST ! stat source_deletions_me/fifo +TEST ! stat $B0/${V0}0/source_deletions_me/fifo +TEST ! stat $B0/${V0}1/source_deletions_me/fifo +TEST ! stat source_deletions_me/block +TEST ! stat $B0/${V0}0/source_deletions_me/block +TEST ! stat $B0/${V0}1/source_deletions_me/block +TEST ! stat source_deletions_me/char +TEST ! stat $B0/${V0}0/source_deletions_me/char +TEST ! stat $B0/${V0}1/source_deletions_me/char +TEST ! stat source_deletions_me/file +TEST ! stat $B0/${V0}0/source_deletions_me/file +TEST ! stat $B0/${V0}1/source_deletions_me/file +TEST ! stat source_deletions_me/file +TEST ! stat $B0/${V0}0/source_deletions_me/file +TEST ! stat $B0/${V0}1/source_deletions_me/file +TEST ! stat source_deletions_me/dir1/dir2 +TEST ! stat $B0/${V0}0/source_deletions_me/dir1/dir2 +TEST ! stat $B0/${V0}1/source_deletions_me/dir1/dir2 +TEST ! stat source_deletions_me/dir1 +TEST ! stat $B0/${V0}0/source_deletions_me/dir1 +TEST ! stat $B0/${V0}1/source_deletions_me/dir1 + +#Test if the files created as part of access are healed correctly +r=$(get_file_type source_creations_me/fifo) +EXPECT "$r" get_file_type $B0/${V0}0/source_creations_me/fifo +EXPECT "$r" get_file_type $B0/${V0}1/source_creations_me/fifo +TEST [ -p source_creations_me/fifo ] + +r=$(get_file_type source_creations_me/block) +EXPECT "$r" get_file_type $B0/${V0}0/source_creations_me/block +EXPECT "$r" get_file_type $B0/${V0}1/source_creations_me/block +EXPECT "^4 5$" stat -c "%t %T" $B0/${V0}1/source_creations_me/block +EXPECT "^4 5$" stat -c "%t %T" $B0/${V0}0/source_creations_me/block +TEST [ -b source_creations_me/block ] + +r=$(get_file_type source_creations_me/char) +EXPECT "$r" get_file_type $B0/${V0}0/source_creations_me/char +EXPECT "$r" get_file_type $B0/${V0}1/source_creations_me/char +EXPECT "^1 5$" stat -c "%t %T" $B0/${V0}1/source_creations_me/char +EXPECT "^1 5$" stat -c "%t %T" $B0/${V0}0/source_creations_me/char +TEST [ -c source_creations_me/char ] + +r=$(get_file_type source_creations_me/file) +EXPECT "$r" get_file_type $B0/${V0}0/source_creations_me/file +EXPECT "$r" get_file_type $B0/${V0}1/source_creations_me/file +TEST [ -f source_creations_me/file ] + +r=$(get_file_type source_creations_me/slink) +EXPECT "$r" get_file_type $B0/${V0}0/source_creations_me/slink +EXPECT "$r" get_file_type $B0/${V0}1/source_creations_me/slink +TEST [ -h source_creations_me/slink ] + +r=$(get_file_type source_creations_me/dir1/dir2) +EXPECT "$r" get_file_type $B0/${V0}0/source_creations_me/dir1/dir2 +EXPECT "$r" get_file_type $B0/${V0}1/source_creations_me/dir1/dir2 +TEST [ -d source_creations_me/dir1/dir2 ] + +r=$(get_file_type source_creations_me/dir1) +EXPECT "$r" get_file_type $B0/${V0}0/source_creations_me/dir1 +EXPECT "$r" get_file_type $B0/${V0}1/source_creations_me/dir1 +TEST [ -d source_creations_me/dir1 ] + +#Trigger heal and check _heal dirs are healed properly +#Trigger change in event generation number. That way inodes would get refreshed during lookup +TEST kill_brick $V0 $H0 $B0/${V0}1 +$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 0 + +TEST stat spb_heal +TEST stat spb_me_heal +TEST stat fool_heal +TEST stat fool_me +TEST stat v1_fool_heal +TEST stat v1_fool_me +TEST stat source_deletions_heal +TEST stat source_deletions_me +TEST stat source_self_accusing +TEST stat source_creations_heal +TEST stat source_creations_me +TEST stat v1_dirty_heal +TEST stat v1_dirty_me +TEST $CLI volume stop $V0 +TEST rm -rf $B0/${V0}{0,1}/.glusterfs/indices/xattrop/* + +$CLI volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 + +#Create base entry in indices/xattrop +echo "Data" > $M0/FILE +rm -f $M0/FILE +EXPECT "1" count_index_entries $B0/${V0}0 +EXPECT "1" count_index_entries $B0/${V0}1 + +TEST $CLI volume stop $V0; + +#Create entries for fool_heal and fool_me to ensure they are fully healed and dirty xattrs erased, before triggering index heal +create_brick_xattrop_entry $B0/${V0}0 fool_heal fool_me source_creations_heal/dir1 + +$CLI volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 + +$CLI volume heal $V0 enable +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 + +TEST $CLI volume heal $V0; +EXPECT_WITHIN $HEAL_TIMEOUT "~" print_pending_heals spb_heal spb_me_heal fool_heal fool_me v1_fool_heal v1_fool_me source_deletions_heal source_deletions_me source_creations_heal source_creations_me v1_dirty_heal v1_dirty_me source_self_accusing + +EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 spb_heal +EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 spb_me_heal +EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 fool_heal +EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 fool_me +EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 v1_fool_heal +EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 v1_fool_me +EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 source_deletions_heal +EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 source_deletions_me +EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 source_self_accusing +EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 source_creations_heal +EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 source_creations_me +EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 v1_dirty_heal +EXPECT "Y${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}${zero_xattr}" heal_status $B0/${V0}0 $B0/${V0}1 v1_dirty_me + +#Don't access the files/dirs from mount point as that may cause self-heals +# Check if conservative merges happened correctly on heal dirs +TEST stat $B0/${V0}0/spb_heal/1 +TEST stat $B0/${V0}1/spb_heal/1 + +TEST stat $B0/${V0}0/spb_heal/0 +TEST stat $B0/${V0}1/spb_heal/0 + +TEST stat $B0/${V0}0/fool_heal/1 +TEST stat $B0/${V0}1/fool_heal/1 + +TEST stat $B0/${V0}0/fool_heal/0 +TEST stat $B0/${V0}1/fool_heal/0 + +TEST stat $B0/${V0}0/v1_fool_heal/0 +TEST stat $B0/${V0}1/v1_fool_heal/0 + +TEST stat $B0/${V0}0/v1_fool_heal/1 +TEST stat $B0/${V0}1/v1_fool_heal/1 + +TEST stat $B0/${V0}0/v1_dirty_heal/0 +TEST stat $B0/${V0}1/v1_dirty_heal/0 + +#Check if files that have gfid-mismatches in spb are giving EIO +TEST ! stat spb/0 + +#Check if stale files are deleted on access +TEST ! stat $B0/${V0}0/source_deletions_heal/fifo +TEST ! stat $B0/${V0}1/source_deletions_heal/fifo +TEST ! stat $B0/${V0}0/source_deletions_heal/block +TEST ! stat $B0/${V0}1/source_deletions_heal/block +TEST ! stat $B0/${V0}0/source_deletions_heal/char +TEST ! stat $B0/${V0}1/source_deletions_heal/char +TEST ! stat $B0/${V0}0/source_deletions_heal/file +TEST ! stat $B0/${V0}1/source_deletions_heal/file +TEST ! stat $B0/${V0}0/source_deletions_heal/file +TEST ! stat $B0/${V0}1/source_deletions_heal/file +TEST ! stat $B0/${V0}0/source_deletions_heal/dir1/dir2 +TEST ! stat $B0/${V0}1/source_deletions_heal/dir1/dir2 +TEST ! stat $B0/${V0}0/source_deletions_heal/dir1 +TEST ! stat $B0/${V0}1/source_deletions_heal/dir1 + +#Check if stale files are deleted on access +TEST ! stat $B0/${V0}0/source_self_accusing/fifo +TEST ! stat $B0/${V0}1/source_self_accusing/fifo +TEST ! stat $B0/${V0}0/source_self_accusing/block +TEST ! stat $B0/${V0}1/source_self_accusing/block +TEST ! stat $B0/${V0}0/source_self_accusing/char +TEST ! stat $B0/${V0}1/source_self_accusing/char +TEST ! stat $B0/${V0}0/source_self_accusing/file +TEST ! stat $B0/${V0}1/source_self_accusing/file +TEST ! stat $B0/${V0}0/source_self_accusing/file +TEST ! stat $B0/${V0}1/source_self_accusing/file +TEST ! stat $B0/${V0}0/source_self_accusing/dir1/dir2 +TEST ! stat $B0/${V0}1/source_self_accusing/dir1/dir2 +TEST ! stat $B0/${V0}0/source_self_accusing/dir1 +TEST ! stat $B0/${V0}1/source_self_accusing/dir1 + +#Test if the files created as part of full self-heal correctly +r=$(get_file_type $B0/${V0}0/source_creations_heal/fifo) +EXPECT "$r" get_file_type $B0/${V0}1/source_creations_heal/fifo +TEST [ -p $B0/${V0}0/source_creations_heal/fifo ] +EXPECT "^4 5$" stat -c "%t %T" $B0/${V0}1/source_creations_heal/block +EXPECT "^4 5$" stat -c "%t %T" $B0/${V0}0/source_creations_heal/block + +r=$(get_file_type $B0/${V0}0/source_creations_heal/block) +EXPECT "$r" get_file_type $B0/${V0}1/source_creations_heal/block + +r=$(get_file_type $B0/${V0}0/source_creations_heal/char) +EXPECT "$r" get_file_type $B0/${V0}1/source_creations_heal/char +EXPECT "^1 5$" stat -c "%t %T" $B0/${V0}1/source_creations_heal/char +EXPECT "^1 5$" stat -c "%t %T" $B0/${V0}0/source_creations_heal/char + +r=$(get_file_type $B0/${V0}0/source_creations_heal/file) +EXPECT "$r" get_file_type $B0/${V0}1/source_creations_heal/file +TEST [ -f $B0/${V0}0/source_creations_heal/file ] + +r=$(get_file_type source_creations_heal/file $B0/${V0}0/slink) +EXPECT "$r" get_file_type $B0/${V0}1/source_creations_heal/file slink +TEST [ -h $B0/${V0}0/source_creations_heal/slink ] + +r=$(get_file_type $B0/${V0}0/source_creations_heal/dir1/dir2) +EXPECT "$r" get_file_type $B0/${V0}1/source_creations_heal/dir1/dir2 +TEST [ -d $B0/${V0}0/source_creations_heal/dir1/dir2 ] + +r=$(get_file_type $B0/${V0}0/source_creations_heal/dir1) +EXPECT "$r" get_file_type $B0/${V0}1/source_creations_heal/dir1 +TEST [ -d $B0/${V0}0/source_creations_heal/dir1 ] + +cd - + +#Anonymous directory shouldn't be created +TEST mkdir $M0/rename-dir +before_rename=$(STAT_INO $B0/${V0}1/rename-dir) +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST mv $M0/rename-dir $M0/new-name +TEST $CLI volume start $V0 force +#'spb' is in split-brain so pending-heal-count will be 2 +EXPECT_WITHIN $HEAL_TIMEOUT "^2$" get_pending_heal_count $V0 +after_rename=$(STAT_INO $B0/${V0}1/new-name) +EXPECT "0" echo $(ls -a $B0/${V0}0/ | grep anonymous-inode | wc -l) +EXPECT "0" echo $(ls -a $B0/${V0}1/ | grep anonymous-inode | wc -l) +EXPECT_NOT "$before_rename" echo $after_rename +cleanup diff --git a/tests/basic/afr/gfid-mismatch-resolution-with-fav-child-policy.t b/tests/basic/afr/gfid-mismatch-resolution-with-fav-child-policy.t index f4aa351e461..35e295dc170 100644 --- a/tests/basic/afr/gfid-mismatch-resolution-with-fav-child-policy.t +++ b/tests/basic/afr/gfid-mismatch-resolution-with-fav-child-policy.t @@ -168,8 +168,8 @@ TEST [ "$gfid_1" != "$gfid_2" ] #We know that second brick has the bigger size file BIGGER_FILE_MD5=$(md5sum $B0/${V0}1/f3 | cut -d\ -f1) -TEST ls $M0/f3 -TEST cat $M0/f3 +TEST ls $M0 #Trigger entry heal via readdir inode refresh +TEST cat $M0/f3 #Trigger data heal via readv inode refresh EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 #gfid split-brain should be resolved @@ -215,8 +215,8 @@ TEST $CLI volume start $V0 force EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}2 EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 2 -TEST ls $M0/f4 -TEST cat $M0/f4 +TEST ls $M0 #Trigger entry heal via readdir inode refresh +TEST cat $M0/f4 #Trigger data heal via readv inode refresh EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 #gfid split-brain should be resolved @@ -227,4 +227,3 @@ HEALED_MD5=$(md5sum $B0/${V0}2/f4 | cut -d\ -f1) TEST [ "$MAJORITY_MD5" == "$HEALED_MD5" ] cleanup; -#G_TESTDEF_TEST_STATUS_NETBSD7=1501390 diff --git a/tests/basic/afr/halo.t b/tests/basic/afr/halo.t new file mode 100644 index 00000000000..3f61f5a0402 --- /dev/null +++ b/tests/basic/afr/halo.t @@ -0,0 +1,61 @@ +#!/bin/bash +#Tests that halo basic functionality works as expected + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../afr.rc + +cleanup; + +function get_up_child() +{ + if [ "1" == $(afr_private_key_value $V0 $M0 0 "child_up\[0\]") ]; + then + echo 0 + elif [ "1" == $(afr_private_key_value $V0 $M0 0 "child_up\[1\]") ] + then + echo 1 + fi +} + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1} +TEST $CLI volume set $V0 cluster.halo-enabled yes +TEST $CLI volume set $V0 cluster.halo-max-replicas 1 +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +EXPECT "^1$" afr_private_key_value $V0 $M0 0 "halo_child_up\[0\]" +EXPECT "^1$" afr_private_key_value $V0 $M0 0 "halo_child_up\[1\]" +EXPECT_NOT "^-1$" afr_private_key_value $V0 $M0 0 "child_latency\[0\]" +EXPECT_NOT "^-1$" afr_private_key_value $V0 $M0 0 "child_latency\[1\]" + +up_id=$(get_up_child) +TEST [[ ! -z "$up_id" ]] + +down_id=$((1-up_id)) + +TEST kill_brick $V0 $H0 $B0/${V0}${up_id} +#As max-replicas is configured to be 1, down_child should be up now +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^1$" afr_private_key_value $V0 $M0 0 "halo_child_up\[${down_id}\]" +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^1$" afr_private_key_value $V0 $M0 0 "child_up\[${down_id}\]" +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^0$" afr_private_key_value $V0 $M0 0 "halo_child_up\[${up_id}\]" +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^0$" afr_private_key_value $V0 $M0 0 "child_up\[${up_id}\]" +EXPECT "^-1$" afr_private_key_value $V0 $M0 0 "child_latency\[${up_id}\]" +EXPECT_NOT "^-1$" afr_private_key_value $V0 $M0 0 "child_latency\[${down_id}\]" + +#Bring the brick back up and the state should be restored +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" afr_private_key_value $V0 $M0 0 "halo_child_up\[${up_id}\]" + +up_id=$(get_up_child) +TEST [[ ! -z "$up_id" ]] +down_id=$((1-up_id)) +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^1$" afr_private_key_value $V0 $M0 0 "halo_child_up\[${down_id}\]" +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^0$" afr_private_key_value $V0 $M0 0 "child_up\[${down_id}\]" +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^1$" afr_private_key_value $V0 $M0 0 "halo_child_up\[${up_id}\]" +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^1$" afr_private_key_value $V0 $M0 0 "child_up\[${up_id}\]" +EXPECT_NOT "^-1$" afr_private_key_value $V0 $M0 0 "child_latency\[0\]" +EXPECT_NOT "^-1$" afr_private_key_value $V0 $M0 0 "child_latency\[1\]" + +cleanup; diff --git a/tests/basic/afr/rename-data-loss.t b/tests/basic/afr/rename-data-loss.t new file mode 100644 index 00000000000..256ee2aafce --- /dev/null +++ b/tests/basic/afr/rename-data-loss.t @@ -0,0 +1,72 @@ +#!/bin/bash +#Self-heal tests +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../afr.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 2 $H0:$B0/brick{0,1} +TEST $CLI volume set $V0 write-behind off +TEST $CLI volume set $V0 self-heal-daemon off +TEST $CLI volume set $V0 data-self-heal off +TEST $CLI volume set $V0 metadata-self-heal off +TEST $CLI volume set $V0 entry-self-heal off +TEST $CLI volume start $V0 +EXPECT 'Started' volinfo_field $V0 'Status' +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0; + +cd $M0 +TEST `echo "line1" >> file1` +TEST mkdir dir1 +TEST mkdir dir2 +TEST mkdir -p dir1/dira/dirb +TEST `echo "line1">>dir1/dira/dirb/file1` +TEST mkdir delete_me +TEST `echo "line1" >> delete_me/file1` + +#brick0 has witnessed the second write while brick1 is down. +TEST kill_brick $V0 $H0 $B0/brick1 +TEST `echo "line2" >> file1` +TEST `echo "line2" >> dir1/dira/dirb/file1` +TEST `echo "line2" >> delete_me/file1` + +#Toggle the bricks that are up/down. +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1 +TEST kill_brick $V0 $H0 $B0/brick0 + +#Rename when the 'source' brick0 for data-selfheals is down. +mv file1 file2 +mv dir1/dira dir2 + +#Delete a dir when brick0 is down. +rm -rf delete_me +cd - + +#Bring everything up and trigger heal +TEST $CLI volume set $V0 self-heal-daemon on +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 +TEST $CLI volume heal $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_anon_entry_count $B0/brick0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_anon_entry_count $B0/brick1 + +#Remount to avoid reading from caches +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0; +EXPECT "line2" tail -1 $M0/file2 +EXPECT "line2" tail -1 $M0/dir2/dira/dirb/file1 +TEST ! stat $M0/delete_me/file1 +TEST ! stat $M0/delete_me + +anon_inode_name=$(ls -a $B0/brick0 | grep glusterfs-anonymous-inode) +TEST [[ -d $B0/brick0/$anon_inode_name ]] +TEST [[ -d $B0/brick1/$anon_inode_name ]] +cleanup diff --git a/tests/basic/afr/split-brain-favorite-child-policy-client-side-healing.t b/tests/basic/afr/split-brain-favorite-child-policy-client-side-healing.t new file mode 100644 index 00000000000..7c249c4bcbd --- /dev/null +++ b/tests/basic/afr/split-brain-favorite-child-policy-client-side-healing.t @@ -0,0 +1,124 @@ +#!/bin/bash + +#Test the client side split-brain resolution +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +GET_MDATA_PATH=$(dirname $0)/../../utils +build_tester $GET_MDATA_PATH/get-mdata-xattr.c + +TEST glusterd +TEST pidof glusterd + +count_files () { + ls $1 | wc -l +} + +#Create replica 2 volume +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1} +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume heal $V0 disable +TEST $CLI volume set $V0 cluster.quorum-type fixed +TEST $CLI volume set $V0 cluster.quorum-count 1 +TEST $CLI volume set $V0 cluster.metadata-self-heal on +TEST $CLI volume set $V0 cluster.data-self-heal on +TEST $CLI volume set $V0 cluster.entry-self-heal on + +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1 + +TEST mkdir $M0/data +TEST touch $M0/data/file + + +############ Client side healing using favorite-child-policy = mtime ################# +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST dd if=/dev/urandom of=$M0/data/file bs=1024 count=1024 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST dd if=/dev/urandom of=$M0/data/file bs=1024 count=1024 + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 + +mtime1=$(get_mtime $B0/${V0}0/data/file) +mtime2=$(get_mtime $B0/${V0}1/data/file) +if (( $(echo "$mtime1 > $mtime2" | bc -l) )); then + LATEST_MTIME_MD5=$(md5sum $B0/${V0}0/data/file | cut -d\ -f1) +else + LATEST_MTIME_MD5=$(md5sum $B0/${V0}1/data/file | cut -d\ -f1) +fi + +#file will be in split-brain +cat $M0/data/file > /dev/null +EXPECT "1" echo $? + +TEST $CLI volume set $V0 cluster.favorite-child-policy mtime +TEST $CLI volume start $V0 force + +EXPECT_WITHIN $HEAL_TIMEOUT "^2$" afr_get_split_brain_count $V0 +cat $M0/data/file > /dev/null +EXPECT "0" echo $? +M0_MD5=$(md5sum $M0/data/file | cut -d\ -f1) +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_get_split_brain_count $V0 +TEST [ "$LATEST_MTIME_MD5" == "$M0_MD5" ] + +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +B0_MD5=$(md5sum $B0/${V0}0/data/file | cut -d\ -f1) +B1_MD5=$(md5sum $B0/${V0}1/data/file | cut -d\ -f1) +TEST [ "$LATEST_MTIME_MD5" == "$B0_MD5" ] +TEST [ "$LATEST_MTIME_MD5" == "$B1_MD5" ] + +############ Client side directory conservative merge ################# +TEST $CLI volume reset $V0 cluster.favorite-child-policy +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST touch $M0/data/test +files=$(count_files $M0/data) +EXPECT "2" echo $files +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST touch $M0/data/test1 +files=$(count_files $M0/data) +EXPECT "2" echo $files + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 + +#data dir will be in entry split-brain +ls $M0/data > /dev/null +EXPECT "2" echo $? + +TEST $CLI volume set $V0 cluster.favorite-child-policy mtime + +EXPECT_WITHIN $HEAL_TIMEOUT "^2$" afr_get_split_brain_count $V0 + + +ls $M0/data > /dev/null +EXPECT "0" echo $? + +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" afr_get_split_brain_count $V0 +#Entry Split-brain is gone, but data self-heal is pending on the files +EXPECT_WITHIN $HEAL_TIMEOUT "^2$" get_pending_heal_count $V0 + +cat $M0/data/test > /dev/null +cat $M0/data/test1 > /dev/null + +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 +files=$(count_files $M0/data) +EXPECT "3" echo $files + +TEST force_umount $M0 +TEST rm $GET_MDATA_PATH/get-mdata-xattr + +cleanup diff --git a/tests/basic/distribute/spare_file_rebalance.t b/tests/basic/distribute/spare_file_rebalance.t new file mode 100644 index 00000000000..061c02f7392 --- /dev/null +++ b/tests/basic/distribute/spare_file_rebalance.t @@ -0,0 +1,51 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../dht.rc + +# Initialize +#------------------------------------------------------------ +cleanup; + +# Start glusterd +TEST glusterd; +TEST pidof glusterd; +TEST $CLI volume info; + +# Create a volume +TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2}; + +# Verify volume creation +EXPECT "$V0" volinfo_field $V0 'Volume Name'; +EXPECT 'Created' volinfo_field $V0 'Status'; + +# Start volume and verify successful start +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; + +#------------------------------------------------------------ + +# Test case - Create sparse files on MP and verify +# file info after rebalance +#------------------------------------------------------------ + +# Create some sparse files and get their size +TEST cd $M0; +dd if=/dev/urandom of=sparse_file bs=10k count=1 seek=2M +cp --sparse=always sparse_file sparse_file_3; + +# Add a 3rd brick +TEST $CLI volume add-brick $V0 $H0:$B0/${V0}3; + +# Trigger rebalance +TEST $CLI volume rebalance $V0 start force; +EXPECT_WITHIN $REBALANCE_TIMEOUT "0" rebalance_completed; + +# Compare original and rebalanced files +TEST cd $B0/${V0}2 +TEST cmp sparse_file $B0/${V0}3/sparse_file_3 +EXPECT_WITHIN 30 ""; + +cleanup; diff --git a/tests/basic/ec/ec-quorum-count.t b/tests/basic/ec/ec-quorum-count.t index 56b5329c411..9310ebbb8f2 100644 --- a/tests/basic/ec/ec-quorum-count.t +++ b/tests/basic/ec/ec-quorum-count.t @@ -11,6 +11,8 @@ TEST $CLI volume create $V0 disperse 6 redundancy 2 $H0:$B0/${V0}{0..5} TEST $CLI volume create $V1 $H0:$B0/${V1}{0..5} TEST $CLI volume set $V0 disperse.eager-lock-timeout 5 TEST $CLI volume set $V0 performance.flush-behind off +TEST $CLI volume set $V0 disperse.background-heals 0 +TEST $CLI volume set $V0 disperse.heal-wait-qlength 0 #Should fail on non-disperse volume TEST ! $CLI volume set $V1 disperse.quorum-count 5 diff --git a/tests/basic/ec/ec-reset-brick.t b/tests/basic/ec/ec-reset-brick.t new file mode 100644 index 00000000000..f1a625df4ff --- /dev/null +++ b/tests/basic/ec/ec-reset-brick.t @@ -0,0 +1,50 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup +function num_entries { + ls -l $1 | wc -l +} + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 6 redundancy 2 $H0:$B0/${V0}{0..5} +TEST $CLI volume start $V0 +TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 + +mkdir $M0/dir +touch $M0/dir/{1..10} + +mkdir $M0/dir/dir1 +touch $M0/dir/dir1/{1..10} + +#kill brick process +TEST $CLI volume reset-brick $V0 $H0:$B0/${V0}5 start +EXPECT_WITHIN $CHILD_UP_TIMEOUT "5" ec_child_up_count $V0 0 + +#reset-brick by removing all the data and create dir again +rm -rf $B0/${V0}5 +mkdir $B0/${V0}5 + +#start brick process and heal by commiting reset-brick +TEST $CLI volume reset-brick $V0 $H0:$B0/${V0}5 $H0:$B0/${V0}5 commit force + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count_shd $V0 0 + +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count ${V0} + +EXPECT "^12$" num_entries $B0/${V0}5/dir +EXPECT "^11$" num_entries $B0/${V0}5/dir/dir1 + +ec_version=$(get_hex_xattr trusted.ec.version $B0/${V0}0) +EXPECT "$ec_version" get_hex_xattr trusted.ec.version $B0/${V0}1 +EXPECT "$ec_version" get_hex_xattr trusted.ec.version $B0/${V0}2 +EXPECT "$ec_version" get_hex_xattr trusted.ec.version $B0/${V0}3 +EXPECT "$ec_version" get_hex_xattr trusted.ec.version $B0/${V0}4 +EXPECT "$ec_version" get_hex_xattr trusted.ec.version $B0/${V0}5 + +cleanup; diff --git a/tests/basic/ec/gfapi-ec-open-truncate.c b/tests/basic/ec/gfapi-ec-open-truncate.c index 22f17f436b6..fb16807003a 100644 --- a/tests/basic/ec/gfapi-ec-open-truncate.c +++ b/tests/basic/ec/gfapi-ec-open-truncate.c @@ -150,7 +150,8 @@ main(int argc, char *argv[]) for (i = 0; i < 20; i++) { ret = system( "[ $(for i in $(pgrep glusterfsd); do ls -l /proc/$i/fd | grep " - "\"[.]glusterfs\" | grep -v health_check; done | wc -l) == 3 ]"); + "\"[.]glusterfs\" | grep -v \".glusterfs/[0-9a-f][0-9a-f]\" | grep " + "-v health_check; done | wc -l) == 3 ]"); if (WIFEXITED(ret) && WEXITSTATUS(ret)) { printf("Ret value of system: %d\n, ifexited: %d, exitstatus: %d", ret, WIFEXITED(ret), WEXITSTATUS(ret)); diff --git a/tests/basic/fencing/afr-lock-heal-advanced.t b/tests/basic/fencing/afr-lock-heal-advanced.t index 8a7a208db29..8a5b5989b5e 100644 --- a/tests/basic/fencing/afr-lock-heal-advanced.t +++ b/tests/basic/fencing/afr-lock-heal-advanced.t @@ -4,6 +4,7 @@ . $(dirname $0)/../../volume.rc cleanup; +PROCESS_UP_TIMEOUT=90 function is_gfapi_program_alive() { @@ -19,9 +20,14 @@ function is_gfapi_program_alive() function get_active_lock_count { brick=$1 + i1=$2 + i2=$3 + pattern="ACTIVE.*client-${brick: -1}" + sdump=$(generate_brick_statedump $V0 $H0 $brick) - lock_count="$(grep ACTIVE $sdump| wc -l)" - echo "$lock_count" + lock_count1="$(egrep "$i1" $sdump -A3| egrep "$pattern"|uniq|wc -l)" + lock_count2="$(egrep "$i2" $sdump -A3| egrep "$pattern"|uniq|wc -l)" + echo "$((lock_count1+lock_count2))" } TEST glusterd @@ -49,6 +55,11 @@ TEST [ $client_pid ] TEST sleep 5 # By now, the client would have opened an fd on FILE1 and FILE2 and waiting for a SIGUSR1. EXPECT "Y" is_gfapi_program_alive $client_pid +gfid_str1=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/FILE1)) +inode1="FILE1|gfid:$gfid_str1" +gfid_str2=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/FILE2)) +inode2="FILE2|gfid:$gfid_str2" + # Kill brick-3 and let client-1 take lock on both files. TEST kill_brick $V0 $H0 $B0/${V0}2 TEST kill -SIGUSR1 $client_pid @@ -56,15 +67,15 @@ TEST kill -SIGUSR1 $client_pid EXPECT "Y" is_gfapi_program_alive $client_pid # Check lock is present on brick-1 and brick-2 -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" get_active_lock_count $B0/${V0}0 -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" get_active_lock_count $B0/${V0}1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" get_active_lock_count $B0/${V0}0 $inode1 $inode2 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" get_active_lock_count $B0/${V0}1 $inode1 $inode2 # Restart brick-3 and check that the lock has healed on it. TEST $CLI volume start $V0 force EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}2 TEST sleep 10 #Needed for client to re-open fd? Otherwise client_pre_lk_v2() fails with EBADFD for remote-fd. -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" get_active_lock_count $B0/${V0}2 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" get_active_lock_count $B0/${V0}2 $inode1 $inode2 #------------------------------------------------------------------------------ # Kill same brick before heal completes the first time and check it completes the second time. @@ -80,7 +91,7 @@ TEST kill_brick $V0 $H0 $B0/${V0}0 TEST $CLI volume reset $V0 delay-gen TEST $CLI volume start $V0 force EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" get_active_lock_count $B0/${V0}0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" get_active_lock_count $B0/${V0}0 $inode1 $inode2 #------------------------------------------------------------------------------ # Kill 2 bricks and bring it back. The fds must be marked bad. diff --git a/tests/basic/fencing/afr-lock-heal-basic.t b/tests/basic/fencing/afr-lock-heal-basic.t index 5ac05c7aec6..69131af085d 100644 --- a/tests/basic/fencing/afr-lock-heal-basic.t +++ b/tests/basic/fencing/afr-lock-heal-basic.t @@ -45,6 +45,9 @@ TEST sleep 5 # By now, the 2 clients would have opened an fd on FILE and waitin EXPECT "Y" is_gfapi_program_alive $client1_pid EXPECT "Y" is_gfapi_program_alive $client2_pid +gfid_str=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}0/FILE)) +inode="FILE|gfid:$gfid_str" + # Kill brick-3 and let client-1 take lock on the file. TEST kill_brick $V0 $H0 $B0/${V0}2 TEST kill -SIGUSR1 $client1_pid @@ -53,9 +56,9 @@ EXPECT "Y" is_gfapi_program_alive $client1_pid # Check lock is present on brick-1 and brick-2 b1_sdump=$(generate_brick_statedump $V0 $H0 $B0/${V0}0) +c1_lock_on_b1="$(egrep "$inode" $b1_sdump -A3| egrep 'ACTIVE.*client-0'| uniq| awk '{print $1,$2,$3,S4,$5,$6,$7,$8}'|tr -d '(,), ,')" b2_sdump=$(generate_brick_statedump $V0 $H0 $B0/${V0}1) -c1_lock_on_b1="$(grep ACTIVE $b1_sdump| awk '{print $1,$2,$3,S4,$5,$6,$7,$8}'|tr -d '(,), ,')" -c1_lock_on_b2="$(grep ACTIVE $b2_sdump| awk '{print $1,$2,$3,S4,$5,$6,$7,$8}'|tr -d '(,), ,')" +c1_lock_on_b2="$(egrep "$inode" $b2_sdump -A3| egrep 'ACTIVE.*client-1'| uniq| awk '{print $1,$2,$3,S4,$5,$6,$7,$8}'|tr -d '(,), ,')" TEST [ "$c1_lock_on_b1" == "$c1_lock_on_b2" ] # Restart brick-3 and check that the lock has healed on it. @@ -64,7 +67,7 @@ EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}2 TEST sleep 10 #Needed for client to re-open fd? Otherwise client_pre_lk_v2() fails with EBADFD for remote-fd. Also wait for lock heal. b3_sdump=$(generate_brick_statedump $V0 $H0 $B0/${V0}2) -c1_lock_on_b3="$(grep ACTIVE $b3_sdump| awk '{print $1,$2,$3,S4,$5,$6,$7,$8}'|tr -d '(,), ,')" +c1_lock_on_b3="$(egrep "$inode" $b3_sdump -A3| egrep 'ACTIVE.*client-2'| uniq| awk '{print $1,$2,$3,S4,$5,$6,$7,$8}'|tr -d '(,), ,')" TEST [ "$c1_lock_on_b1" == "$c1_lock_on_b3" ] # Kill brick-1 and let client-2 preempt the lock on bricks 2 and 3. @@ -80,11 +83,11 @@ TEST sleep 10 #Needed for client to re-open fd? Otherwise client_pre_lk_v2() fai # Check that all bricks now have locks from client 2 only. b1_sdump=$(generate_brick_statedump $V0 $H0 $B0/${V0}0) +c2_lock_on_b1="$(egrep "$inode" $b1_sdump -A3| egrep 'ACTIVE.*client-0'| uniq| awk '{print $1,$2,$3,S4,$5,$6,$7,$8}'|tr -d '(,), ,')" b2_sdump=$(generate_brick_statedump $V0 $H0 $B0/${V0}1) +c2_lock_on_b2="$(egrep "$inode" $b2_sdump -A3| egrep 'ACTIVE.*client-1'| uniq| awk '{print $1,$2,$3,S4,$5,$6,$7,$8}'|tr -d '(,), ,')" b3_sdump=$(generate_brick_statedump $V0 $H0 $B0/${V0}2) -c2_lock_on_b1="$(grep ACTIVE $b1_sdump| awk '{print $1,$2,$3,S4,$5,$6,$7,$8}'|tr -d '(,), ,')" -c2_lock_on_b2="$(grep ACTIVE $b2_sdump| awk '{print $1,$2,$3,S4,$5,$6,$7,$8}'|tr -d '(,), ,')" -c2_lock_on_b3="$(grep ACTIVE $b3_sdump| awk '{print $1,$2,$3,S4,$5,$6,$7,$8}'|tr -d '(,), ,')" +c2_lock_on_b3="$(egrep "$inode" $b3_sdump -A3| egrep 'ACTIVE.*client-2'| uniq| awk '{print $1,$2,$3,S4,$5,$6,$7,$8}'|tr -d '(,), ,')" TEST [ "$c2_lock_on_b1" == "$c2_lock_on_b2" ] TEST [ "$c2_lock_on_b1" == "$c2_lock_on_b3" ] TEST [ "$c2_lock_on_b1" != "$c1_lock_on_b1" ] diff --git a/tests/basic/fuse/active-io-graph-switch.t b/tests/basic/fuse/active-io-graph-switch.t new file mode 100644 index 00000000000..6ec3e1fcbfa --- /dev/null +++ b/tests/basic/fuse/active-io-graph-switch.t @@ -0,0 +1,65 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +TESTS_EXPECTED_IN_LOOP=12 + +function perform_io_on_mount { + local m="$1" + local f="$2" + local lockfile="$3" + while [ -f "$m/$lockfile" ]; + do + dd if=/dev/zero of=$m/$f bs=1M count=1 + done +} + +function perform_graph_switch { + for i in {1..3} + do + TEST_IN_LOOP $CLI volume set $V0 performance.stat-prefetch off + sleep 3 + TEST_IN_LOOP $CLI volume set $V0 performance.stat-prefetch on + sleep 3 + done +} + +function count_files { + ls $M0 | wc -l +} + +cleanup; +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2} +TEST $CLI volume set $V0 flush-behind off +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 +TEST touch $M0/lock +for i in {1..100}; do perform_io_on_mount $M0 $i lock & done +EXPECT_WITHIN 5 "101" count_files + +perform_graph_switch +TEST rm -f $M0/lock +wait +EXPECT "100" count_files +TEST rm -f $M0/{1..100} +EXPECT "0" count_files + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +#Repeat the tests with reader-thread-count +TEST $GFS --reader-thread-count=10 --volfile-id=/$V0 --volfile-server=$H0 $M0 +TEST touch $M0/lock +for i in {1..100}; do perform_io_on_mount $M0 $i lock & done +EXPECT_WITHIN 5 "101" count_files + +perform_graph_switch +TEST rm -f $M0/lock +wait +EXPECT "100" count_files +TEST rm -f $M0/{1..100} +EXPECT "0" count_files + +cleanup diff --git a/tests/basic/gfapi/gfapi-copy-file-range.t b/tests/basic/gfapi/gfapi-copy-file-range.t index c24c1433edf..a56d3a58e07 100644 --- a/tests/basic/gfapi/gfapi-copy-file-range.t +++ b/tests/basic/gfapi/gfapi-copy-file-range.t @@ -5,20 +5,22 @@ cleanup; +mkfs.xfs 2>&1 | grep reflink +if [ $? -ne 0 ]; then + SKIP_TESTS + exit +fi + + TEST glusterd +TEST truncate -s 2G $B0/xfs_image # for now, a xfs filesystem with reflink support is created. # In future, better to make changes in MKFS_LOOP so that, # once can create a xfs filesystem with reflink enabled in # generic and simple way, instead of doing below steps each # time. -TEST truncate -s 2G $B0/xfs_image -mkfs.xfs 2>&1 | grep reflink -if [ $? -eq 0 ]; then - mkfs.xfs -f -i size=512 -m reflink=1 $B0/xfs_image; -else - mkfs.xfs -f -i size=512 $B0/xfs_image; -fi +TEST mkfs.xfs -f -i size=512 -m reflink=1 $B0/xfs_image; TEST mkdir $B0/bricks TEST mount -t xfs -o loop $B0/xfs_image $B0/bricks diff --git a/tests/basic/gfapi/gfapi-graph-switch-open-fd.t b/tests/basic/gfapi/gfapi-graph-switch-open-fd.t new file mode 100644 index 00000000000..2e666be7ec7 --- /dev/null +++ b/tests/basic/gfapi/gfapi-graph-switch-open-fd.t @@ -0,0 +1,44 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd + +TEST $CLI volume create $V0 replica 3 ${H0}:$B0/brick{0..2}; +EXPECT 'Created' volinfo_field $V0 'Status'; + +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +TEST touch $M0/sync +logdir=`gluster --print-logdir` + +TEST build_tester $(dirname $0)/gfapi-keep-writing.c -lgfapi + + +#Launch a program to keep doing writes on an fd +./$(dirname $0)/gfapi-keep-writing ${H0} $V0 $logdir/gfapi-async-calls-test.log sync & +p=$! +sleep 1 #Let some writes go through +#Check if graph switch will lead to any pending markers for ever +TEST $CLI volume set $V0 performance.quick-read off +TEST $CLI volume set $V0 performance.io-cache off +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume set $V0 performance.read-ahead off + + +TEST rm -f $M0/sync #Make sure the glfd is closed +TEST wait #Wait for background process to die +#Goal is to check if there is permanent FOOL changelog +sleep 5 +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/brick0/glfs_test.txt trusted.afr.dirty +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/brick1/glfs_test.txt trusted.afr.dirty +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/brick2/glfs_test.txt trusted.afr.dirty + +cleanup_tester $(dirname $0)/gfapi-async-calls-test + +cleanup; diff --git a/tests/basic/gfapi/gfapi-keep-writing.c b/tests/basic/gfapi/gfapi-keep-writing.c new file mode 100644 index 00000000000..91b59cea02b --- /dev/null +++ b/tests/basic/gfapi/gfapi-keep-writing.c @@ -0,0 +1,129 @@ +#include <fcntl.h> +#include <unistd.h> +#include <time.h> +#include <limits.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> + +#define LOG_ERR(msg) \ + do { \ + fprintf(stderr, "%s : Error (%s)\n", msg, strerror(errno)); \ + } while (0) + +glfs_t * +init_glfs(const char *hostname, const char *volname, const char *logfile) +{ + int ret = -1; + glfs_t *fs = NULL; + + fs = glfs_new(volname); + if (!fs) { + LOG_ERR("glfs_new failed"); + return NULL; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + if (ret < 0) { + LOG_ERR("glfs_set_volfile_server failed"); + goto out; + } + + ret = glfs_set_logging(fs, logfile, 7); + if (ret < 0) { + LOG_ERR("glfs_set_logging failed"); + goto out; + } + + ret = glfs_init(fs); + if (ret < 0) { + LOG_ERR("glfs_init failed"); + goto out; + } + + ret = 0; +out: + if (ret) { + glfs_fini(fs); + fs = NULL; + } + + return fs; +} + +int +glfs_test_function(const char *hostname, const char *volname, + const char *logfile, const char *syncfile) +{ + int ret = -1; + int flags = O_CREAT | O_RDWR; + glfs_t *fs = NULL; + glfs_fd_t *glfd = NULL; + const char *buff = "This is from my prog\n"; + const char *filename = "glfs_test.txt"; + struct stat buf = {0}; + + fs = init_glfs(hostname, volname, logfile); + if (fs == NULL) { + LOG_ERR("init_glfs failed"); + return -1; + } + + glfd = glfs_creat(fs, filename, flags, 0644); + if (glfd == NULL) { + LOG_ERR("glfs_creat failed"); + goto out; + } + + while (glfs_stat(fs, syncfile, &buf) == 0) { + ret = glfs_write(glfd, buff, strlen(buff), flags); + if (ret < 0) { + LOG_ERR("glfs_write failed"); + goto out; + } + } + + ret = glfs_close(glfd); + if (ret < 0) { + LOG_ERR("glfs_write failed"); + goto out; + } + +out: + ret = glfs_fini(fs); + if (ret) { + LOG_ERR("glfs_fini failed"); + } + + return ret; +} + +int +main(int argc, char *argv[]) +{ + int ret = 0; + char *hostname = NULL; + char *volname = NULL; + char *logfile = NULL; + char *syncfile = NULL; + + if (argc != 5) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + syncfile = argv[4]; + + ret = glfs_test_function(hostname, volname, logfile, syncfile); + if (ret) { + LOG_ERR("glfs_test_function failed"); + } + + return ret; +} diff --git a/tests/basic/gfapi/gfapi-ssl-load-volfile-test.c b/tests/basic/gfapi/gfapi-ssl-load-volfile-test.c new file mode 100644 index 00000000000..7beb8dd1fe4 --- /dev/null +++ b/tests/basic/gfapi/gfapi-ssl-load-volfile-test.c @@ -0,0 +1,127 @@ +#include <fcntl.h> +#include <unistd.h> +#include <time.h> +#include <limits.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> + +#define LOG_ERR(msg) \ + do { \ + fprintf(stderr, "%s : Error (%s)\n", msg, strerror(errno)); \ + } while (0) + +glfs_t * +init_glfs(const char *hostname, const char *volname, const char *volfile, + const char *logfile) +{ + int ret = -1; + glfs_t *fs = NULL; + + fs = glfs_new(volname); + if (!fs) { + LOG_ERR("glfs_new failed"); + return NULL; + } + + ret = glfs_set_volfile(fs, volfile); + if (ret < 0) { + LOG_ERR("glfs_set_volfile failed"); + goto out; + } + + ret = glfs_set_logging(fs, logfile, 7); + if (ret < 0) { + LOG_ERR("glfs_set_logging failed"); + goto out; + } + + ret = glfs_init(fs); + if (ret < 0) { + LOG_ERR("glfs_init failed"); + goto out; + } + + ret = 0; +out: + if (ret) { + glfs_fini(fs); + fs = NULL; + } + + return fs; +} + +int +glfs_test_function(const char *hostname, const char *volname, + const char *volfile, const char *logfile) +{ + int ret = -1; + int flags = O_CREAT | O_RDWR; + glfs_t *fs = NULL; + glfs_fd_t *glfd = NULL; + const char *buff = "This is from my prog\n"; + const char *filename = "glfs_test.txt"; + + fs = init_glfs(hostname, volname, volfile, logfile); + if (fs == NULL) { + LOG_ERR("init_glfs failed"); + return -1; + } + + glfd = glfs_creat(fs, filename, flags, 0644); + if (glfd == NULL) { + LOG_ERR("glfs_creat failed"); + goto out; + } + + ret = glfs_write(glfd, buff, strlen(buff), flags); + if (ret < 0) { + LOG_ERR("glfs_write failed"); + goto out; + } + + ret = glfs_close(glfd); + if (ret < 0) { + LOG_ERR("glfs_write failed"); + goto out; + } + +out: + ret = glfs_fini(fs); + if (ret) { + LOG_ERR("glfs_fini failed"); + } + + return ret; +} + +int +main(int argc, char *argv[]) +{ + int ret = 0; + char *hostname = NULL; + char *volname = NULL; + char *volfile = NULL; + char *logfile = NULL; + + if (argc != 5) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + volfile = argv[3]; + logfile = argv[4]; + + ret = glfs_test_function(hostname, volname, volfile, logfile); + if (ret) { + LOG_ERR("glfs_test_function failed"); + } + + return ret; +} diff --git a/tests/basic/gfapi/gfapi-ssl-load-volfile-test.t b/tests/basic/gfapi/gfapi-ssl-load-volfile-test.t new file mode 100755 index 00000000000..8e94df9d321 --- /dev/null +++ b/tests/basic/gfapi/gfapi-ssl-load-volfile-test.t @@ -0,0 +1,76 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../traps.rc +. $(dirname $0)/../../ssl.rc + +cleanup; + +sed -e "s,@@HOSTNAME@@,${H0},g" -e "s,@@BRICKPATH@@,${B0}/brick1,g" \ + -e "s,@@SSL@@,off,g" \ + $(dirname ${0})/protocol-client-ssl.vol.in \ + > $(dirname ${0})/protocol-client-ssl.vol + +TEST create_self_signed_certs + +TEST glusterd + +TEST $CLI volume create $V0 $H0:$B0/brick1; +EXPECT 'Created' volinfo_field $V0 'Status'; + +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" online_brick_count + +logdir=`gluster --print-logdir` + +TEST build_tester $(dirname $0)/gfapi-ssl-load-volfile-test.c -lgfapi + +# Run test without I/O or management encryption +TEST $(dirname $0)/gfapi-ssl-load-volfile-test $H0 $V0 \ + $(dirname ${0})/protocol-client-ssl.vol \ + $logdir/gfapi-ssl-load-volfile-test.log + +# Enable management encryption +touch $GLUSTERD_WORKDIR/secure-access + +killall_gluster + +TEST glusterd +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" online_brick_count + +# Run test with management encryption (No I/O encryption) +TEST $(dirname $0)/gfapi-ssl-load-volfile-test $H0 $V0 \ + $(dirname ${0})/protocol-client-ssl.vol \ + $logdir/gfapi-ssl-load-volfile-test.log + +# Enable I/O encryption +TEST $CLI volume set $V0 server.ssl on + +killall_gluster + +sed -e "s,@@HOSTNAME@@,${H0},g" -e "s,@@BRICKPATH@@,${B0}/brick1,g" \ + -e "s,@@SSL@@,on,g" \ + $(dirname ${0})/protocol-client-ssl.vol.in \ + > $(dirname ${0})/protocol-client-ssl.vol + +TEST glusterd +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" online_brick_count + +# Run test without I/O or management encryption +TEST $(dirname $0)/gfapi-ssl-load-volfile-test $H0 $V0 \ + $(dirname ${0})/protocol-client-ssl.vol \ + $logdir/gfapi-ssl-load-volfile-test.log + +cleanup_tester $(dirname $0)/gfapi-ssl-load-volfile-test + +TEST $CLI volume stop $V0 +TEST $CLI volume delete $V0 + +cleanup; + +# NetBSD build scripts are not up to date therefore this test +# is failing in NetBSD. Therefore skipping the test in NetBSD +# as of now. +#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 diff --git a/tests/basic/gfapi/protocol-client-ssl.vol.in b/tests/basic/gfapi/protocol-client-ssl.vol.in new file mode 100644 index 00000000000..cdc0c9d0671 --- /dev/null +++ b/tests/basic/gfapi/protocol-client-ssl.vol.in @@ -0,0 +1,15 @@ +# +# This .vol file expects that there is +# +# 1. GlusterD listening on @@HOSTNAME@@ +# 2. a volume that provides a brick on @@BRICKPATH@@ +# 3. the volume with the brick has been started +# +volume test + type protocol/client + option remote-host @@HOSTNAME@@ + option remote-subvolume @@BRICKPATH@@ + option transport-type socket + option transport.socket.ssl-enabled @@SSL@@ +end-volume + diff --git a/tests/basic/metadisp/fsyncdir.c b/tests/basic/metadisp/fsyncdir.c new file mode 100644 index 00000000000..62b532b9ce4 --- /dev/null +++ b/tests/basic/metadisp/fsyncdir.c @@ -0,0 +1,29 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <fcntl.h> + +int +main(int argc, char **argv) +{ + int pfd; + + pfd = open(argv[1], O_RDONLY | O_DIRECTORY); + if (pfd == (-1)) { + perror("open"); + return EXIT_FAILURE; + } + + if (rename(argv[2], argv[3]) == (-1)) { + perror("rename"); + return EXIT_FAILURE; + } + + if (fsync(pfd) == (-1)) { + perror("fsync"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/tests/basic/metadisp/ftruncate.c b/tests/basic/metadisp/ftruncate.c new file mode 100644 index 00000000000..c9185212c31 --- /dev/null +++ b/tests/basic/metadisp/ftruncate.c @@ -0,0 +1,34 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <fcntl.h> + +int +main(int argc, char **argv) +{ + int pfd; + + pfd = open(argv[1], O_RDWR); + if (pfd == (-1)) { + perror("open"); + return EXIT_FAILURE; + } + + if (ftruncate(pfd, 0) == (-1)) { + perror("ftruncate"); + return EXIT_FAILURE; + } + + if (write(pfd, "hello", 5) == (-1)) { + perror("write"); + return EXIT_FAILURE; + } + + if (fsync(pfd) == (-1)) { + perror("fsync"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/tests/basic/metadisp/fxattr.c b/tests/basic/metadisp/fxattr.c new file mode 100644 index 00000000000..e552057778a --- /dev/null +++ b/tests/basic/metadisp/fxattr.c @@ -0,0 +1,107 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <fcntl.h> +#include <string.h> +#include <sys/types.h> +#include <sys/xattr.h> + +static char MY_XATTR[] = "user.fxtest"; +static char *PROGRAM; +#define CONSUME(v) \ + do { \ + if (!argc) { \ + fprintf(stderr, "missing argument\n"); \ + return EXIT_FAILURE; \ + } \ + v = argv[0]; \ + ++argv; \ + --argc; \ + } while (0) + +static int +do_get(int argc, char **argv, int fd) +{ + char *value; + int ret; + char buf[1024]; + + CONSUME(value); + + ret = fgetxattr(fd, MY_XATTR, buf, sizeof(buf)); + if (ret == (-1)) { + perror("fgetxattr"); + return EXIT_FAILURE; + } + + if (strncmp(buf, value, ret) != 0) { + fprintf(stderr, "data mismatch\n"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static int +do_set(int argc, char **argv, int fd) +{ + char *value; + int ret; + + CONSUME(value); + + ret = fsetxattr(fd, MY_XATTR, value, strlen(value), 0); + if (ret == (-1)) { + perror("fsetxattr"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static int +do_remove(int argc, char **argv, int fd) +{ + int ret; + + ret = fremovexattr(fd, MY_XATTR); + if (ret == (-1)) { + perror("femovexattr"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +int +main(int argc, char **argv) +{ + int fd; + char *path; + char *cmd; + + CONSUME(PROGRAM); + CONSUME(path); + CONSUME(cmd); + + fd = open(path, O_RDWR); + if (fd == (-1)) { + perror("open"); + return EXIT_FAILURE; + } + + if (strcmp(cmd, "get") == 0) { + return do_get(argc, argv, fd); + } + + if (strcmp(cmd, "set") == 0) { + return do_set(argc, argv, fd); + } + + if (strcmp(cmd, "remove") == 0) { + return do_remove(argc, argv, fd); + } + + return EXIT_SUCCESS; +} diff --git a/tests/basic/metadisp/gfs-fsetxattr.c b/tests/basic/metadisp/gfs-fsetxattr.c new file mode 100644 index 00000000000..63578bc528f --- /dev/null +++ b/tests/basic/metadisp/gfs-fsetxattr.c @@ -0,0 +1,141 @@ +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int gfapi = 1; + +int +main(int argc, char *argv[]) +{ + glfs_t *fs = NULL; + int ret = 0; + int i = 0; + glfs_fd_t *fd = NULL; + char *topdir = "topdir", *filename = "file1"; + char *buf = NULL; + char *logfile = NULL; + char *hostname = NULL; + char *basename = NULL; + char *dir1 = NULL, *dir2 = NULL, *filename1 = NULL, *filename2 = NULL; + struct stat sb = { + 0, + }; + + if (argc != 5) { + fprintf( + stderr, + "Expect following args %s <hostname> <Vol> <log file> <basename>\n", + argv[0]); + return -1; + } + + hostname = argv[1]; + logfile = argv[3]; + basename = argv[4]; + + fs = glfs_new(argv[2]); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL (%s)\n", strerror(errno)); + return -1; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + if (ret < 0) { + fprintf(stderr, "glfs_set_volfile_server failed ret:%d (%s)\n", ret, + strerror(errno)); + return -1; + } + + ret = glfs_set_logging(fs, logfile, 7); + if (ret < 0) { + fprintf(stderr, "glfs_set_logging failed with ret: %d (%s)\n", ret, + strerror(errno)); + return -1; + } + + ret = glfs_init(fs); + if (ret < 0) { + fprintf(stderr, "glfs_init failed with ret: %d (%s)\n", ret, + strerror(errno)); + return -1; + } + + ret = asprintf(&dir1, "%s-dir", basename); + if (ret < 0) { + fprintf(stderr, "cannot construct filename (%s)", strerror(errno)); + return ret; + } + + ret = glfs_mkdir(fs, dir1, 0755); + if (ret < 0) { + fprintf(stderr, "mkdir(%s): %s\n", dir1, strerror(errno)); + return -1; + } + + fd = glfs_opendir(fs, dir1); + if (!fd) { + fprintf(stderr, "/: %s\n", strerror(errno)); + return -1; + } + + ret = glfs_fsetxattr(fd, "user.dirfattr", "fsetxattr", 9, 0); + if (ret < 0) { + fprintf(stderr, "fsetxattr(%s): %d (%s)\n", dir1, ret, strerror(errno)); + return -1; + } + + ret = glfs_closedir(fd); + if (ret < 0) { + fprintf(stderr, "glfs_closedir failed with ret: %d (%s)\n", ret, + strerror(errno)); + return -1; + } + + ret = asprintf(&filename1, "%s-file", basename); + if (ret < 0) { + fprintf(stderr, "cannot construct filename (%s)", strerror(errno)); + return ret; + } + + ret = asprintf(&filename2, "%s-file-renamed", basename); + if (ret < 0) { + fprintf(stderr, "cannot construct filename (%s)", strerror(errno)); + return ret; + } + + fd = glfs_creat(fs, filename1, O_RDWR, 0644); + if (!fd) { + fprintf(stderr, "%s: (%p) %s\n", filename1, fd, strerror(errno)); + return -1; + } + + ret = glfs_rename(fs, filename1, filename2); + if (ret < 0) { + fprintf(stderr, "glfs_rename failed with ret: %d (%s)\n", ret, + strerror(errno)); + return -1; + } + + ret = glfs_lstat(fs, filename2, &sb); + if (ret < 0) { + fprintf(stderr, "glfs_lstat failed with ret: %d (%s)\n", ret, + strerror(errno)); + return -1; + } + + ret = glfs_fsetxattr(fd, "user.filefattr", "fsetxattr", 9, 0); + if (ret < 0) { + fprintf(stderr, "fsetxattr(%s): %d (%s)\n", dir1, ret, strerror(errno)); + return -1; + } + + ret = glfs_close(fd); + if (ret < 0) { + fprintf(stderr, "glfs_close failed with ret: %d (%s)\n", ret, + strerror(errno)); + return -1; + } +} diff --git a/tests/basic/metadisp/metadisp.t b/tests/basic/metadisp/metadisp.t new file mode 100644 index 00000000000..894ffe07226 --- /dev/null +++ b/tests/basic/metadisp/metadisp.t @@ -0,0 +1,316 @@ +#!/usr/bin/env bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + + +# Considering `--enable-metadisp` is an option for `./configure`, +# which is disabled by default, this test will never pass regression. +# But to see the value of this test, run below after configuring +# with above option : +# `prove -vmfe '/bin/bash' tests/basic/metadisp/metadisp.t` + +#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST + +cleanup; + +TEST mkdir -p $B0/b0/{0,1} + +TEST setfattr -n trusted.glusterfs.volume-id -v 0xddab9eece7b64a95b07351a1f748f56f ${B0}/b0/0 +TEST setfattr -n trusted.glusterfs.volume-id -v 0xddab9eece7b64a95b07351a1f748f56f ${B0}/b0/1 + +TEST $GFS --volfile=$(dirname $0)/metadisp.vol --volfile-id=$V0 $M0; + +NUM_FILES=40 +TEST touch $M0/{1..${NUM_FILES}} + +# each drive should get 40 files +TEST [ $(dir -1 $B0/b0/0/ | wc -l) -eq $NUM_FILES ] +TEST [ $(dir -1 $B0/b0/1/ | wc -l) -eq $NUM_FILES ] + +# now write some data to a file +echo "hello" > $M0/3 +filename=$$ +echo "hello" > /tmp/metadisp-write-${filename} +checksum=$(md5sum /tmp/metadisp-write-${filename} | awk '{print $1}') +TEST [ "$(md5sum $M0/3 | awk '{print $1}')" == "$checksum" ] + +# check that the backend file exists on b1 +gfid=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/b0/*/3)) +TEST [ $(dir -1 $B0/b0/1/$gfid | wc -l) -eq 1 ] + +# check that the backend file matches the frontend +TEST [ "$(md5sum $B0/b0/1/$gfid | awk '{print $1}')" == "$checksum" ] + +# delete the file +TEST rm $M0/3 + +# ensure the frontend and backend files are cleaned up +TEST ! -e $M0/3 +TEST ! [ stat $B0/b*/*/$gfid ] + +# Test TRUNCATE + WRITE flow +echo "hello" | tee $M0/4 +echo "goo" | tee $M0/4 +filename=$$ +echo "goo" | tee /tmp/metadisp-truncate-${filename} +checksum=$(md5sum /tmp/metadisp-truncate-${filename} | awk '{print $1}') +TEST [ "$(md5sum $M0/4 | awk '{print $1}')" == "$checksum" ] + +# Test mkdir + rmdir. +TEST mkdir $M0/rmdir_me +nfiles=$(ls -d $B0/b*/*/rmdir_me 2> /dev/null | wc -l) +TEST [ "$nfiles" = "1" ] +TEST rmdir $M0/rmdir_me +nfiles=$(ls -d $B0/b*/*/rmdir_me 2> /dev/null | wc -l) +TEST [ "$nfiles" = "0" ] + +# Test rename. +TEST touch $M0/rename_me +nfiles=$(ls $B0/b*/*/rename_me 2> /dev/null | wc -l) +TEST [ "$nfiles" = "1" ] +nfiles=$(ls $B0/b*/*/such_rename 2> /dev/null | wc -l) +TEST [ "$nfiles" = "0" ] +TEST mv $M0/rename_me $M0/such_rename +nfiles=$(ls $B0/b*/*/rename_me 2> /dev/null | wc -l) +TEST [ "$nfiles" = "0" ] +nfiles=$(ls $B0/b*/*/such_rename 2> /dev/null | wc -l) +TEST [ "$nfiles" = "1" ] + +# Test rename of a file that doesn't exist. +TEST ! mv $M0/does-not-exist $M0/neither-does-this + + +# cleanup all the other files. +TEST rm -v $M0/1 $M0/2 $M0/{4..${NUM_FILES}} +TEST rm $M0/such_rename +TEST [ $(ls /d/backends/b0/0/ | wc -l) -eq 0 ] +TEST [ $(ls /d/backends/b0/1/ | wc -l) -eq 0 ] + +# Test CREATE flow +NUM_FILES=40 +TEST touch $M0/{1..${NUM_FILES}} +TEST [ $(ls /d/backends/b0/0/ | wc -l) -eq $NUM_FILES ] +TEST [ $(ls /d/backends/b0/1/ | wc -l) -eq $NUM_FILES ] + +# Test UNLINK flow +# No drives should have any files +TEST rm -v $M0/{1..${NUM_FILES}} +TEST [ $(ls /d/backends/b0/0/ | wc -l) -eq 0 ] +TEST [ $(ls /d/backends/b0/1/ | wc -l) -eq 0 ] + +# Test CREATE + WRITE + READ flow +filename=$$ +dd if=/dev/urandom of=/tmp/${filename} bs=1M count=10 +checksum=$(md5sum /tmp/${filename} | awk '{print $1}') +TEST cp -v /tmp/${filename} $M0/1 +TEST cp -v /tmp/${filename} $M0/2 +TEST cp -v /tmp/${filename} $M0/3 +TEST cp -v /tmp/${filename} $M0/4 +TEST [ "$(md5sum $M0/1 | awk '{print $1}')" == "$checksum" ] +TEST [ "$(md5sum $M0/2 | awk '{print $1}')" == "$checksum" ] +TEST [ "$(md5sum $M0/3 | awk '{print $1}')" == "$checksum" ] +TEST [ "$(md5sum $M0/4 | awk '{print $1}')" == "$checksum" ] + +# Test TRUNCATE + WRITE flow +TEST dd if=/dev/zero of=$M0/1 bs=1M count=20 + +# Check that readdir stats the files properly and we get the correct sizes +TEST [ $(find $M0 -size +9M | wc -l) -eq 4 ]; + +# Test mkdir + rmdir. +TEST mkdir $M0/rmdir_me +nfiles=$(ls -d $B0/b*/*/rmdir_me 2> /dev/null | wc -l) +TEST [ "$nfiles" = "1" ] +TEST rmdir $M0/rmdir_me +nfiles=$(ls -d $B0/b*/*/rmdir_me 2> /dev/null | wc -l) +TEST [ "$nfiles" = "0" ] + +# Test rename. +# Still flaky, so disabled until it can be debugged. +TEST touch $M0/rename_me +nfiles=$(ls $B0/b*/*/rename_me 2> /dev/null | wc -l) +TEST [ "$nfiles" = "1" ] +nfiles=$(ls $B0/b*/*/such_rename 2> /dev/null | wc -l) +TEST [ "$nfiles" = "0" ] +TEST mv $M0/rename_me $M0/such_rename +nfiles=$(ls $B0/b*/*/rename_me 2> /dev/null | wc -l) +TEST [ "$nfiles" = "0" ] +nfiles=$(ls $B0/b*/*/such_rename 2> /dev/null | wc -l) +TEST [ "$nfiles" = "1" ] + +# Test rename of a file that doesn't exist. +TEST ! mv $M0/does-not-exist $M0/neither-does-this + +# Test rename over an existing file. +ok=yes +for i in $(seq 0 9); do + echo foo > $M0/src$i + echo bar > $M0/dst$i +done +for i in $(seq 0 9); do + mv $M0/src$i $M0/dst$i +done +for i in $(seq 0 9); do + nfiles=$(cat $B0/b0/*/dst$i | wc -l) + if [ "$nfiles" = "2" ]; then + echo "COLLISION on dst$i" + (ls -l $B0/b0/*/dst$i; cat $B0/b0/*/dst$i) | sed "/^/s// /" + ok=no + fi +done +EXPECT "yes" echo $ok + +# Test rename of a directory. +count_copies () { + ls -d $B0/b?/?/$1 2> /dev/null | wc -l +} +TEST mkdir $M0/foo_dir +EXPECT 1 count_copies foo_dir +EXPECT 0 count_copies bar_dir +TEST mv $M0/foo_dir $M0/bar_dir +EXPECT 0 count_copies foo_dir +EXPECT 1 count_copies bar_dir + +for x in $(seq 0 99); do + touch $M0/target$x + ln -s $M0/target$x $M0/link$x +done +on_0=$(ls $B0/b*/0/link* | wc -l) +on_1=$(ls $B0/b*/1/link* | wc -l) +TEST [ "$on_0" -eq 100 ] +TEST [ "$on_1" -eq 0 ] +TEST [ "$(ls -l $M0/link* | wc -l)" = 100 ] + +# Test (hard) link. +_test_hardlink () { + local b + local has_src + local has_dst + local src_inum + local dst_inum + touch $M0/hardsrc$1 + ln $M0/hardsrc$1 $M0/harddst$1 + for b in $B0/b{0}/{0,1}; do + [ -f $b/hardsrc$1 ]; has_src=$? + [ -f $b/harddst$1 ]; has_dst=$? + if [ "$has_src" != "$has_dst" ]; then + echo "MISSING $b/hardxxx$1 $has_src $has_dst" + return + fi + if [ "$has_src$has_dst" = "00" ]; then + src_inum=$(stat -c '%i' $b/hardsrc$1) + dst_inum=$(stat -c '%i' $b/harddst$1) + if [ "$dst_inum" != "$src_inum" ]; then + echo "MISMATCH $b/hardxx$i $src_inum $dst_inum" + return + fi + fi + done + echo "OK" +} + +test_hardlink () { + local result=$(_test_hardlink $*) + # [ "$result" = "OK" ] || echo $result > /dev/tty + echo $result +} + +# Do this multiple times to make sure colocation isn't a fluke. +EXPECT "OK" test_hardlink 0 +EXPECT "OK" test_hardlink 1 +EXPECT "OK" test_hardlink 2 +EXPECT "OK" test_hardlink 3 +EXPECT "OK" test_hardlink 4 +EXPECT "OK" test_hardlink 5 +EXPECT "OK" test_hardlink 6 +EXPECT "OK" test_hardlink 7 +EXPECT "OK" test_hardlink 8 +EXPECT "OK" test_hardlink 9 + +# Test remove hardlink source. ensure deleting one file +# doesn't delete the data unless link-count is 1 +TEST mkdir $M0/hardlink +TEST touch $M0/hardlink/fileA +echo "data" >> $M0/hardlink/fileA +checksum=$(md5sum $M0/hardlink/fileA | awk '{print $1}') +TEST ln $M0/hardlink/fileA $M0/hardlink/fileB +TEST [ $(dir -1 $M0/hardlink/ | wc -l) -eq 2 ] +TEST rm $M0/hardlink/fileA +TEST [ $(dir -1 $M0/hardlink/ | wc -l) -eq 1 ] +TEST [ "$(md5sum $M0/hardlink/fileB | awk '{print $1}')" == "$checksum" ] + +# +# FIXME: statfs values look ok but the test is bad +# +# Test statfs. If we're doing it right, the numbers for the mountpoint should be +# double those for the brick filesystem times the number of bricks, +# but unless we're on a completely idle +# system (which never happens) the numbers can change even while this function +# runs and that would trip us up. Do a sloppy comparison to deal with that. +#compare_fields () { +# val1=$(df $1 | grep / | awk "{print \$$3}") +# val2=$(df $2 | grep / | awk "{print \$$3}") +# [ "$val2" -gt "$(((val1/(29/10))*19/10))" -a "$val2" -lt "$(((val1/(31/10))*21/10))" ] +#} + +#brick_df=$(df $B0 | grep /) +#mount_df=$(df $M0 | grep /) +#TEST compare_fields $B0 $M0 2 # Total blocks +#TEST compare_fields $B0 $M0 3 # Used +#TEST compare_fields $B0 $M0 4 # Available + +# Test removexattr. +#RXATTR_FILE=$(get_file_not_on_disk0 rxtest) +#TEST setfattr -n user.foo -v bar $M0/$RXATTR_FILE +#TEST getfattr -n user.foo $B0/b0/1/$RXATTR_FILE +#TEST setfattr -x user.foo $M0/$RXATTR_FILE +#TEST ! getfattr -n user.foo $B0/b0/1/$RXATTR_FILE + +# Test fsyncdir. We can't really test whether it's doing the right thing, +# but we can test that it doesn't fail and we can hand-check that it's calling +# down to all of the disks instead of just one. +# +# P.S. There's no fsyncdir test in the rest of Gluster, so who even knows if +# other translators are handling it correctly? + +#FSYNCDIR_EXE=$(dirname $0)/fsyncdir +#build_tester ${FSYNCDIR_EXE}.c +#TEST touch $M0/fsyncdir_src +#TEST $FSYNCDIR_EXE $M0 $M0/fsyncdir_src $M0/fsyncdir_dst +#TEST rm -f $FSYNCDIR_EXE + +# Test fsetxattr, fgetxattr, fremovexattr (in that order). +FXATTR_FILE=$M0/fxfile1 +TEST touch $FXATTR_FILE +FXATTR_EXE=$(dirname $0)/fxattr +build_tester ${FXATTR_EXE}.c +TEST ! getfattr -n user.fxtest $FXATTR_FILE +TEST $FXATTR_EXE $FXATTR_FILE set value1 +TEST getfattr -n user.fxtest $FXATTR_FILE +TEST setfattr -n user.fxtest -v value2 $FXATTR_FILE +TEST $FXATTR_EXE $FXATTR_FILE get value2 +TEST $FXATTR_EXE $FXATTR_FILE remove +TEST ! getfattr -n user.fxtest $FXATTR_FILE +TEST rm -f $FXATTR_EXE + +# Test ftruncate +FTRUNCATE_EXE=$(dirname $0)/ftruncate +build_tester ${FTRUNCATE_EXE}.c +FTRUNCATE_FILE=$M0/ftfile1 +TEST dd if=/dev/urandom of=$FTRUNCATE_FILE count=1 bs=1MB +TEST $FTRUNCATE_EXE $FTRUNCATE_FILE +#gfid=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/b0/*/ftfile1)) + +# Test fallocate, discard, zerofill. Actually we don't so much check that these +# *work* as that they don't throw any errors (especially ENOENT because the +# file's not on disk zero). +FALLOC_FILE=fatest1 +TEST touch $M0/$FALLOC_FILE +TEST fallocate -l $((4096*5)) $M0/$FALLOC_FILE +TEST fallocate -p -o 4096 -l 4096 $M0/$FALLOC_FILE +# This actually fails with "operation not supported" on most filesystems, so +# don't leave it enabled except to test changes. +#TEST fallocate -z -o $((4096*3)) -l 4096 $M0/$FALLOC_FILE + +#cleanup; diff --git a/tests/basic/metadisp/metadisp.vol b/tests/basic/metadisp/metadisp.vol new file mode 100644 index 00000000000..58ae2f6f2a8 --- /dev/null +++ b/tests/basic/metadisp/metadisp.vol @@ -0,0 +1,14 @@ +volume posix-0 + type storage/posix + option directory /d/backends/b0/0 +end-volume + +volume posix-1 + type storage/posix + option directory /d/backends/b0/1 +end-volume + +volume metadisp-0 + type features/metadisp + subvolumes posix-0 posix-1 +end-volume diff --git a/tests/basic/open-behind/open-behind.t b/tests/basic/open-behind/open-behind.t new file mode 100644 index 00000000000..5e865d602e2 --- /dev/null +++ b/tests/basic/open-behind/open-behind.t @@ -0,0 +1,183 @@ +#!/bin/bash + +WD="$(dirname "${0}")" + +. ${WD}/../../include.rc +. ${WD}/../../volume.rc + +function assign() { + local _assign_var="${1}" + local _assign_value="${2}" + + printf -v "${_assign_var}" "%s" "${_assign_value}" +} + +function pipe_create() { + local _pipe_create_var="${1}" + local _pipe_create_name + local _pipe_create_fd + + _pipe_create_name="$(mktemp -u)" + mkfifo "${_pipe_create_name}" + exec {_pipe_create_fd}<>"${_pipe_create_name}" + rm "${_pipe_create_name}" + + assign "${_pipe_create_var}" "${_pipe_create_fd}" +} + +function pipe_close() { + local _pipe_close_fd="${!1}" + + exec {_pipe_close_fd}>&- +} + +function tester_start() { + declare -ag tester + local tester_in + local tester_out + + pipe_create tester_in + pipe_create tester_out + + ${WD}/tester <&${tester_in} >&${tester_out} & + + tester=("$!" "${tester_in}" "${tester_out}") +} + +function tester_send() { + declare -ag tester + local tester_res + local tester_extra + + echo "${*}" >&${tester[1]} + + read -t 3 -u ${tester[2]} tester_res tester_extra + echo "${tester_res} ${tester_extra}" + if [[ "${tester_res}" == "OK" ]]; then + return 0 + fi + + return 1 +} + +function tester_stop() { + declare -ag tester + local tester_res + + tester_send "quit" + + tester_res=0 + if ! wait ${tester[0]}; then + tester_res=$? + fi + + unset tester + + return ${tester_res} +} + +function count_open() { + local file="$(realpath "${B0}/${V0}/${1}")" + local count="0" + local inode + local ref + + inode="$(stat -c %i "${file}")" + + for fd in /proc/${BRICK_PID}/fd/*; do + ref="$(readlink "${fd}")" + if [[ "${ref}" == "${B0}/${V0}/"* ]]; then + if [[ "$(stat -c %i "${ref}")" == "${inode}" ]]; then + count="$((${count} + 1))" + fi + fi + done + + echo "${count}" +} + +cleanup + +TEST build_tester ${WD}/tester.c ${WD}/tester-fd.c + +TEST glusterd +TEST pidof glusterd +TEST ${CLI} volume create ${V0} ${H0}:${B0}/${V0} +TEST ${CLI} volume set ${V0} flush-behind off +TEST ${CLI} volume set ${V0} write-behind off +TEST ${CLI} volume set ${V0} quick-read off +TEST ${CLI} volume set ${V0} stat-prefetch on +TEST ${CLI} volume set ${V0} io-cache off +TEST ${CLI} volume set ${V0} open-behind on +TEST ${CLI} volume set ${V0} lazy-open off +TEST ${CLI} volume set ${V0} read-after-open off +TEST ${CLI} volume start ${V0} + +TEST ${GFS} --volfile-id=/${V0} --volfile-server=${H0} ${M0}; + +BRICK_PID="$(get_brick_pid ${V0} ${H0} ${B0}/${V0})" + +TEST touch "${M0}/test" + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST ${GFS} --volfile-id=/${V0} --volfile-server=${H0} ${M0}; + +TEST tester_start + +TEST tester_send fd open 0 "${M0}/test" +EXPECT_WITHIN 5 "1" count_open "/test" +TEST tester_send fd close 0 +EXPECT_WITHIN 5 "0" count_open "/test" + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST ${CLI} volume set ${V0} lazy-open on +TEST ${GFS} --volfile-id=/${V0} --volfile-server=${H0} ${M0}; + +TEST tester_send fd open 0 "${M0}/test" +sleep 2 +EXPECT "0" count_open "/test" +TEST tester_send fd write 0 "test" +EXPECT "1" count_open "/test" +TEST tester_send fd close 0 +EXPECT_WITHIN 5 "0" count_open "/test" + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST ${GFS} --volfile-id=/${V0} --volfile-server=${H0} ${M0}; + +TEST tester_send fd open 0 "${M0}/test" +EXPECT "0" count_open "/test" +EXPECT "test" tester_send fd read 0 64 +# Even though read-after-open is disabled, use-anonymous-fd is also disabled, +# so reads need to open the file first. +EXPECT "1" count_open "/test" +TEST tester_send fd close 0 +EXPECT "0" count_open "/test" + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST ${GFS} --volfile-id=/${V0} --volfile-server=${H0} ${M0}; + +TEST tester_send fd open 0 "${M0}/test" +EXPECT "0" count_open "/test" +TEST tester_send fd open 1 "${M0}/test" +EXPECT "2" count_open "/test" +TEST tester_send fd close 0 +EXPECT_WITHIN 5 "1" count_open "/test" +TEST tester_send fd close 1 +EXPECT_WITHIN 5 "0" count_open "/test" + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST ${CLI} volume set ${V0} read-after-open on +TEST ${GFS} --volfile-id=/${V0} --volfile-server=${H0} ${M0}; + +TEST tester_send fd open 0 "${M0}/test" +EXPECT "0" count_open "/test" +EXPECT "test" tester_send fd read 0 64 +EXPECT "1" count_open "/test" +TEST tester_send fd close 0 +EXPECT_WITHIN 5 "0" count_open "/test" + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +TEST tester_stop + +cleanup diff --git a/tests/basic/open-behind/tester-fd.c b/tests/basic/open-behind/tester-fd.c new file mode 100644 index 00000000000..00f02bc5b0a --- /dev/null +++ b/tests/basic/open-behind/tester-fd.c @@ -0,0 +1,99 @@ +/* + Copyright (c) 2020 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include "tester.h" + +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> + +static int32_t +fd_open(context_t *ctx, command_t *cmd) +{ + obj_t *obj; + int32_t fd; + + obj = cmd->args[0].obj.ref; + + fd = open(cmd->args[1].str.data, O_RDWR); + if (fd < 0) { + return error(errno, "open() failed"); + } + + obj->type = OBJ_TYPE_FD; + obj->fd = fd; + + out_ok("%d", fd); + + return 0; +} + +static int32_t +fd_close(context_t *ctx, command_t *cmd) +{ + obj_t *obj; + + obj = cmd->args[0].obj.ref; + obj->type = OBJ_TYPE_NONE; + + if (close(obj->fd) != 0) { + return error(errno, "close() failed"); + } + + out_ok(); + + return 0; +} + +static int32_t +fd_write(context_t *ctx, command_t *cmd) +{ + ssize_t len, ret; + + len = strlen(cmd->args[1].str.data); + ret = write(cmd->args[0].obj.ref->fd, cmd->args[1].str.data, len); + if (ret < 0) { + return error(errno, "write() failed"); + } + + out_ok("%zd", ret); + + return 0; +} + +static int32_t +fd_read(context_t *ctx, command_t *cmd) +{ + char data[cmd->args[1].num.value + 1]; + ssize_t ret; + + ret = read(cmd->args[0].obj.ref->fd, data, cmd->args[1].num.value); + if (ret < 0) { + return error(errno, "read() failed"); + } + + data[ret] = 0; + + out_ok("%zd %s", ret, data); + + return 0; +} + +command_t fd_commands[] = { + {"open", fd_open, CMD_ARGS(ARG_VAL(OBJ_TYPE_NONE), ARG_STR(1024))}, + {"close", fd_close, CMD_ARGS(ARG_VAL(OBJ_TYPE_FD))}, + {"write", fd_write, CMD_ARGS(ARG_VAL(OBJ_TYPE_FD), ARG_STR(1024))}, + {"read", fd_read, CMD_ARGS(ARG_VAL(OBJ_TYPE_FD), ARG_NUM(0, 1024))}, + CMD_END}; diff --git a/tests/basic/open-behind/tester.c b/tests/basic/open-behind/tester.c new file mode 100644 index 00000000000..b2da71c8385 --- /dev/null +++ b/tests/basic/open-behind/tester.c @@ -0,0 +1,444 @@ +/* + Copyright (c) 2020 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include "tester.h" + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> + +static void * +mem_alloc(size_t size) +{ + void *ptr; + + ptr = malloc(size); + if (ptr == NULL) { + error(ENOMEM, "Failed to allocate memory (%zu bytes)", size); + } + + return ptr; +} + +static void +mem_free(void *ptr) +{ + free(ptr); +} + +static bool +buffer_create(context_t *ctx, size_t size) +{ + ctx->buffer.base = mem_alloc(size); + if (ctx->buffer.base == NULL) { + return false; + } + + ctx->buffer.size = size; + ctx->buffer.len = 0; + ctx->buffer.pos = 0; + + return true; +} + +static void +buffer_destroy(context_t *ctx) +{ + mem_free(ctx->buffer.base); + ctx->buffer.size = 0; + ctx->buffer.len = 0; +} + +static int32_t +buffer_get(context_t *ctx) +{ + ssize_t len; + + if (ctx->buffer.pos >= ctx->buffer.len) { + len = read(0, ctx->buffer.base, ctx->buffer.size); + if (len < 0) { + return error(errno, "read() failed"); + } + if (len == 0) { + return 0; + } + + ctx->buffer.len = len; + ctx->buffer.pos = 0; + } + + return ctx->buffer.base[ctx->buffer.pos++]; +} + +static int32_t +str_skip_spaces(context_t *ctx, int32_t current) +{ + while ((current > 0) && (current != '\n') && isspace(current)) { + current = buffer_get(ctx); + } + + return current; +} + +static int32_t +str_token(context_t *ctx, char *buffer, uint32_t size, int32_t current) +{ + uint32_t len; + + current = str_skip_spaces(ctx, current); + + len = 0; + while ((size > 0) && (current > 0) && (current != '\n') && + !isspace(current)) { + len++; + *buffer++ = current; + size--; + current = buffer_get(ctx); + } + + if (len == 0) { + return error(ENODATA, "Expecting a token"); + } + + if (size == 0) { + return error(ENOBUFS, "Token too long"); + } + + *buffer = 0; + + return current; +} + +static int32_t +str_number(context_t *ctx, uint64_t min, uint64_t max, uint64_t *value, + int32_t current) +{ + char text[32], *ptr; + uint64_t num; + + current = str_token(ctx, text, sizeof(text), current); + if (current > 0) { + num = strtoul(text, &ptr, 0); + if ((*ptr != 0) || (num < min) || (num > max)) { + return error(ERANGE, "Invalid number"); + } + *value = num; + } + + return current; +} + +static int32_t +str_eol(context_t *ctx, int32_t current) +{ + current = str_skip_spaces(ctx, current); + if (current != '\n') { + return error(EINVAL, "Expecting end of command"); + } + + return current; +} + +static void +str_skip(context_t *ctx, int32_t current) +{ + while ((current > 0) && (current != '\n')) { + current = buffer_get(ctx); + } +} + +static int32_t +cmd_parse_obj(context_t *ctx, arg_t *arg, int32_t current) +{ + obj_t *obj; + uint64_t id; + + current = str_number(ctx, 0, ctx->obj_count, &id, current); + if (current <= 0) { + return current; + } + + obj = &ctx->objs[id]; + if (obj->type != arg->obj.type) { + if (obj->type != OBJ_TYPE_NONE) { + return error(EBUSY, "Object is in use"); + } + return error(ENOENT, "Object is not defined"); + } + + arg->obj.ref = obj; + + return current; +} + +static int32_t +cmd_parse_num(context_t *ctx, arg_t *arg, int32_t current) +{ + return str_number(ctx, arg->num.min, arg->num.max, &arg->num.value, + current); +} + +static int32_t +cmd_parse_str(context_t *ctx, arg_t *arg, int32_t current) +{ + return str_token(ctx, arg->str.data, arg->str.size, current); +} + +static int32_t +cmd_parse_args(context_t *ctx, command_t *cmd, int32_t current) +{ + arg_t *arg; + + for (arg = cmd->args; arg->type != ARG_TYPE_NONE; arg++) { + switch (arg->type) { + case ARG_TYPE_OBJ: + current = cmd_parse_obj(ctx, arg, current); + break; + case ARG_TYPE_NUM: + current = cmd_parse_num(ctx, arg, current); + break; + case ARG_TYPE_STR: + current = cmd_parse_str(ctx, arg, current); + break; + default: + return error(EINVAL, "Unknown argument type"); + } + } + + if (current < 0) { + return current; + } + + current = str_eol(ctx, current); + if (current <= 0) { + return error(EINVAL, "Syntax error"); + } + + return cmd->handler(ctx, cmd); +} + +static int32_t +cmd_parse(context_t *ctx, command_t *cmds) +{ + char text[32]; + command_t *cmd; + int32_t current; + + cmd = cmds; + do { + current = str_token(ctx, text, sizeof(text), buffer_get(ctx)); + if (current <= 0) { + return current; + } + + while (cmd->name != NULL) { + if (strcmp(cmd->name, text) == 0) { + if (cmd->handler != NULL) { + return cmd_parse_args(ctx, cmd, current); + } + cmd = cmd->cmds; + break; + } + cmd++; + } + } while (cmd->name != NULL); + + str_skip(ctx, current); + + return error(ENOTSUP, "Unknown command"); +} + +static void +cmd_fini(context_t *ctx, command_t *cmds) +{ + command_t *cmd; + arg_t *arg; + + for (cmd = cmds; cmd->name != NULL; cmd++) { + if (cmd->handler == NULL) { + cmd_fini(ctx, cmd->cmds); + } else { + for (arg = cmd->args; arg->type != ARG_TYPE_NONE; arg++) { + switch (arg->type) { + case ARG_TYPE_STR: + mem_free(arg->str.data); + arg->str.data = NULL; + break; + default: + break; + } + } + } + } +} + +static bool +cmd_init(context_t *ctx, command_t *cmds) +{ + command_t *cmd; + arg_t *arg; + + for (cmd = cmds; cmd->name != NULL; cmd++) { + if (cmd->handler == NULL) { + if (!cmd_init(ctx, cmd->cmds)) { + return false; + } + } else { + for (arg = cmd->args; arg->type != ARG_TYPE_NONE; arg++) { + switch (arg->type) { + case ARG_TYPE_STR: + arg->str.data = mem_alloc(arg->str.size); + if (arg->str.data == NULL) { + return false; + } + break; + default: + break; + } + } + } + } + + return true; +} + +static bool +objs_create(context_t *ctx, uint32_t count) +{ + uint32_t i; + + ctx->objs = mem_alloc(sizeof(obj_t) * count); + if (ctx->objs == NULL) { + return false; + } + ctx->obj_count = count; + + for (i = 0; i < count; i++) { + ctx->objs[i].type = OBJ_TYPE_NONE; + } + + return true; +} + +static int32_t +objs_destroy(context_t *ctx) +{ + uint32_t i; + int32_t err; + + err = 0; + for (i = 0; i < ctx->obj_count; i++) { + if (ctx->objs[i].type != OBJ_TYPE_NONE) { + err = error(ENOTEMPTY, "Objects not destroyed"); + break; + } + } + + mem_free(ctx->objs); + ctx->objs = NULL; + ctx->obj_count = 0; + + return err; +} + +static context_t * +init(size_t size, uint32_t objs, command_t *cmds) +{ + context_t *ctx; + + ctx = mem_alloc(sizeof(context_t)); + if (ctx == NULL) { + goto failed; + } + + if (!buffer_create(ctx, size)) { + goto failed_ctx; + } + + if (!objs_create(ctx, objs)) { + goto failed_buffer; + } + + if (!cmd_init(ctx, cmds)) { + goto failed_objs; + } + + ctx->active = true; + + return ctx; + +failed_objs: + cmd_fini(ctx, cmds); + objs_destroy(ctx); +failed_buffer: + buffer_destroy(ctx); +failed_ctx: + mem_free(ctx); +failed: + return NULL; +} + +static int32_t +fini(context_t *ctx, command_t *cmds) +{ + int32_t ret; + + cmd_fini(ctx, cmds); + buffer_destroy(ctx); + + ret = objs_destroy(ctx); + + ctx->active = false; + + return ret; +} + +static int32_t +exec_quit(context_t *ctx, command_t *cmd) +{ + ctx->active = false; + + return 0; +} + +static command_t commands[] = {{"fd", NULL, CMD_SUB(fd_commands)}, + {"quit", exec_quit, CMD_ARGS()}, + CMD_END}; + +int32_t +main(int32_t argc, char *argv[]) +{ + context_t *ctx; + int32_t res; + + ctx = init(1024, 16, commands); + if (ctx == NULL) { + return 1; + } + + do { + res = cmd_parse(ctx, commands); + if (res < 0) { + out_err(-res); + } + } while (ctx->active); + + res = fini(ctx, commands); + if (res >= 0) { + out_ok(); + return 0; + } + + out_err(-res); + + return 1; +} diff --git a/tests/basic/open-behind/tester.h b/tests/basic/open-behind/tester.h new file mode 100644 index 00000000000..64e940c78fc --- /dev/null +++ b/tests/basic/open-behind/tester.h @@ -0,0 +1,145 @@ +/* + Copyright (c) 2020 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __TESTER_H__ +#define __TESTER_H__ + +#include <stdio.h> +#include <inttypes.h> +#include <stdbool.h> + +enum _obj_type; +typedef enum _obj_type obj_type_t; + +enum _arg_type; +typedef enum _arg_type arg_type_t; + +struct _buffer; +typedef struct _buffer buffer_t; + +struct _obj; +typedef struct _obj obj_t; + +struct _context; +typedef struct _context context_t; + +struct _arg; +typedef struct _arg arg_t; + +struct _command; +typedef struct _command command_t; + +enum _obj_type { OBJ_TYPE_NONE, OBJ_TYPE_FD }; + +enum _arg_type { ARG_TYPE_NONE, ARG_TYPE_OBJ, ARG_TYPE_NUM, ARG_TYPE_STR }; + +struct _buffer { + char *base; + uint32_t size; + uint32_t len; + uint32_t pos; +}; + +struct _obj { + obj_type_t type; + union { + int32_t fd; + }; +}; + +struct _context { + obj_t *objs; + buffer_t buffer; + uint32_t obj_count; + bool active; +}; + +struct _arg { + arg_type_t type; + union { + struct { + obj_type_t type; + obj_t *ref; + } obj; + struct { + uint64_t value; + uint64_t min; + uint64_t max; + } num; + struct { + uint32_t size; + char *data; + } str; + }; +}; + +struct _command { + const char *name; + int32_t (*handler)(context_t *ctx, command_t *cmd); + union { + arg_t *args; + command_t *cmds; + }; +}; + +#define msg(_stream, _fmt, _args...) \ + do { \ + fprintf(_stream, _fmt "\n", ##_args); \ + fflush(_stream); \ + } while (0) + +#define msg_out(_fmt, _args...) msg(stdout, _fmt, ##_args) +#define msg_err(_err, _fmt, _args...) \ + ({ \ + int32_t __msg_err = (_err); \ + msg(stderr, "[%4u:%-15s] " _fmt, __LINE__, __FUNCTION__, __msg_err, \ + ##_args); \ + -__msg_err; \ + }) + +#define error(_err, _fmt, _args...) msg_err(_err, "E(%4d) " _fmt, ##_args) +#define warn(_err, _fmt, _args...) msg_err(_err, "W(%4d) " _fmt, ##_args) +#define info(_err, _fmt, _args...) msg_err(_err, "I(%4d) " _fmt, ##_args) + +#define out_ok(_args...) msg_out("OK " _args) +#define out_err(_err) msg_out("ERR %d", _err) + +#define ARG_END \ + { \ + ARG_TYPE_NONE \ + } + +#define CMD_ARGS1(_x, _args...) \ + .args = (arg_t[]) { _args } +#define CMD_ARGS(_args...) CMD_ARGS1(, ##_args, ARG_END) + +#define CMD_SUB(_cmds) .cmds = _cmds + +#define CMD_END \ + { \ + NULL, NULL, CMD_SUB(NULL) \ + } + +#define ARG_VAL(_type) \ + { \ + ARG_TYPE_OBJ, .obj = {.type = _type } \ + } +#define ARG_NUM(_min, _max) \ + { \ + ARG_TYPE_NUM, .num = {.min = _min, .max = _max } \ + } +#define ARG_STR(_size) \ + { \ + ARG_TYPE_STR, .str = {.size = _size } \ + } + +extern command_t fd_commands[]; + +#endif /* __TESTER_H__ */
\ No newline at end of file diff --git a/tests/basic/posix/zero-fill-enospace.c b/tests/basic/posix/zero-fill-enospace.c index 1371ff59a5f..b1f142c6be9 100644 --- a/tests/basic/posix/zero-fill-enospace.c +++ b/tests/basic/posix/zero-fill-enospace.c @@ -1,4 +1,5 @@ #include <stdio.h> +#include <stdlib.h> #include <glusterfs/api/glfs.h> #include <glusterfs/api/glfs-handles.h> @@ -8,7 +9,7 @@ main(int argc, char *argv[]) glfs_t *fs = NULL; glfs_fd_t *fd = NULL; int ret = 1; - int size = 0; + off_t size = 0; if (argc != 6) { fprintf(stderr, @@ -45,12 +46,12 @@ main(int argc, char *argv[]) goto out; } - size = atoi(argv[5]); + size = strtol(argv[5], NULL, 10); if (size < 0) { fprintf(stderr, "Wrong size %s", argv[5]); goto out; } - ret = glfs_zerofill(fd, 0, atoi(argv[5])); + ret = glfs_zerofill(fd, 0, size); if (ret <= 0) { fprintf(stderr, "glfs_zerofill: returned %d\n", ret); goto out; diff --git a/tests/basic/quick-read-with-upcall.t b/tests/basic/quick-read-with-upcall.t index 2012053d125..dfb751dfcdb 100644 --- a/tests/basic/quick-read-with-upcall.t +++ b/tests/basic/quick-read-with-upcall.t @@ -15,8 +15,8 @@ TEST $CLI volume create $V0 $H0:$B0/${V0}{1..2}; TEST $CLI volume start $V0 # Mount FUSE without selinux: -TEST glusterfs -s $H0 --volfile-id $V0 $M0; -TEST glusterfs -s $H0 --volfile-id $V0 $M1; +TEST glusterfs -s $H0 --volfile-id $V0 --direct-io-mode=enable $M0; +TEST glusterfs -s $H0 --volfile-id $V0 --direct-io-mode=enable $M1; D0="test-message0"; D1="test-message1"; @@ -37,16 +37,13 @@ TEST write_to "$M0/test.txt" "$D1" EXPECT "$D1" cat $M0/test.txt EXPECT "$D0" cat $M1/test.txt -# This is 3.7 for no good reason. We could have kept this to -# any number above 2 seconds. Noticed that when it is 2 seconds, or -# less, there is a possibility of not getting a lookup on the same inode. -sleep 3.7 +sleep 1 # TODO: This line normally fails EXPECT "$D1" cat $M1/test.txt TEST $CLI volume set $V0 features.cache-invalidation on -TEST $CLI volume set $V0 performance.qr-cache-timeout 15 +TEST $CLI volume set $V0 performance.quick-read-cache-timeout 15 TEST $CLI volume set $V0 performance.md-cache-timeout 15 TEST write_to "$M0/test1.txt" "$D0" @@ -73,7 +70,3 @@ EXPECT "$D0" cat $M1/test2.txt TEST write_to "$M0/test2.txt" "$D1" EXPECT "$D1" cat $M0/test2.txt EXPECT "$D1" cat $M1/test2.txt - - -#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=1718191 -#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=1718191 diff --git a/tests/basic/volume-snap-scheduler.t b/tests/basic/volume-snap-scheduler.t new file mode 100644 index 00000000000..a638c5cc46a --- /dev/null +++ b/tests/basic/volume-snap-scheduler.t @@ -0,0 +1,49 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +TEST glusterd; +TEST pidof glusterd; + +TEST $CLI volume create $V0 replica 2 $H0:$B0/${GMV0}{1,2,3,4}; +TEST $CLI volume start $V0 + +## Create, start and mount meta_volume as +## snap_scheduler expects shared storage to be enabled. +## This test is very basic in nature not creating any snapshot +## and purpose is to validate snap scheduling commands. + +TEST $CLI volume create $META_VOL replica 3 $H0:$B0/${META_VOL}{1,2,3}; +TEST $CLI volume start $META_VOL +TEST mkdir -p $META_MNT +TEST glusterfs -s $H0 --volfile-id $META_VOL $META_MNT + +##function to check status +function check_status_scheduler() +{ + local key=$1 + snap_scheduler.py status | grep -F "$key" | wc -l +} + +##Basic snap_scheduler command test init/enable/disable/list + +TEST snap_scheduler.py init + +TEST snap_scheduler.py enable + +EXPECT 1 check_status_scheduler "Enabled" + +TEST snap_scheduler.py disable + +EXPECT 1 check_status_scheduler "Disabled" + +TEST snap_scheduler.py list + +TEST $CLI volume stop $V0; + +TEST $CLI volume delete $V0; + +cleanup; diff --git a/tests/basic/volume.t b/tests/basic/volume.t index 7648ae1d6e1..27fe093d07d 100755..100644 --- a/tests/basic/volume.t +++ b/tests/basic/volume.t @@ -11,7 +11,6 @@ TEST $CLI volume info; TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{1,2,3,4,5,6}; - EXPECT "$V0" volinfo_field $V0 'Volume Name'; EXPECT 'Created' volinfo_field $V0 'Status'; EXPECT '6' brick_count $V0 @@ -28,10 +27,34 @@ EXPECT '6' brick_count $V0 TEST $CLI volume top $V0 read-perf bs 4096 count 1000 TEST $CLI volume top $V0 write-perf bs 1048576 count 2 -TEST $CLI volume stop $V0; -EXPECT 'Stopped' volinfo_field $V0 'Status'; +TEST touch $M0/foo + +# statedump path should be a directory, setting it to a file path should fail + +TEST ! $CLI v set $V0 server.statedump-path $M0/foo; +EXPECT '/var/run/gluster' $CLI v get $V0 server.statedump-path + +#set the statedump path to an existing ditectory which should succeed +TEST mkdir $D0/level; +TEST $CLI v set $V0 server.statedump-path $D0/level +EXPECT '/level' volinfo_field $V0 'server.statedump-path' + +ret=$(ls $D0/level | wc -l); +TEST [ $ret == 0 ] +TEST $CLI v statedump $V0; +ret=$(ls $D0/level | wc -l); +TEST ! [ $ret == 0 ] + +#set the statedump path to a non - existing directory which should fail +TEST ! $CLI v set $V0 server.statedump-path /root/test +EXPECT '/level' volinfo_field $V0 'server.statedump-path' + +TEST rm -rf $D0/level + +TEST $CLI volume stop $V0 +EXPECT 'Stopped' volinfo_field $V0 'Status' -TEST $CLI volume delete $V0; -TEST ! $CLI volume info $V0; +TEST $CLI volume delete $V0 +TEST ! $CLI volume info $V0 cleanup; diff --git a/tests/bugs/bug-1064147.t b/tests/bugs/bug-1064147.t new file mode 100755 index 00000000000..27ffde4eb44 --- /dev/null +++ b/tests/bugs/bug-1064147.t @@ -0,0 +1,72 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +# Initialize +#------------------------------------------------------------ +cleanup; + +# Start glusterd +TEST glusterd; +TEST pidof glusterd; +TEST $CLI volume info; + +# Create a volume +TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2} + +# Verify volume creation +EXPECT "$V0" volinfo_field $V0 'Volume Name'; +EXPECT 'Created' volinfo_field $V0 'Status'; + +# Start volume and verify successful start +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; +#------------------------------------------------------------ + +# Test case 1 - Subvolume down + Healing +#------------------------------------------------------------ +# Kill 2nd brick process +TEST kill_brick $V0 $H0 $B0/${V0}2 +EXPECT_WITHIN ${PROCESS_UP_TIMEOUT} "1" online_brick_count + +# Change root permissions +TEST chmod 444 $M0 + +# Store permission for comparision +TEST permission_new=`stat -c "%A" $M0` + +# Bring up the killed brick process +TEST $CLI volume start $V0 force + +# Perform lookup +sleep 5 +TEST ls $M0 + +# Check brick permissions +TEST brick_perm=`stat -c "%A" $B0/${V0}2` +TEST [ ${brick_perm} = ${permission_new} ] +#------------------------------------------------------------ + +# Test case 2 - Add-brick + Healing +#------------------------------------------------------------ +# Change root permissions +TEST chmod 777 $M0 + +# Store permission for comparision +TEST permission_new_2=`stat -c "%A" $M0` + +# Add a 3rd brick +TEST $CLI volume add-brick $V0 $H0:$B0/${V0}3 + +# Perform lookup +sleep 5 +TEST ls $M0 + +# Check permissions on the new brick +TEST brick_perm2=`stat -c "%A" $B0/${V0}3` + +TEST [ ${brick_perm2} = ${permission_new_2} ] + +cleanup; diff --git a/tests/bugs/bug-1371806.t b/tests/bugs/bug-1371806.t index 7dc1613a4f2..08180525650 100644 --- a/tests/bugs/bug-1371806.t +++ b/tests/bugs/bug-1371806.t @@ -28,6 +28,7 @@ TEST glusterd TEST pidof glusterd TEST $CLI volume create $V0 $H0:$B0/${V0}{0,1,2,3,4,5} TEST $CLI volume start $V0 +EXPECT_WITHIN ${PROCESS_UP_TIMEOUT} "6" online_brick_count TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; diff --git a/tests/bugs/bug-1371806_acl.t b/tests/bugs/bug-1371806_acl.t index a2e5af49bb0..c39165628cc 100644 --- a/tests/bugs/bug-1371806_acl.t +++ b/tests/bugs/bug-1371806_acl.t @@ -39,6 +39,7 @@ TEST pidof glusterd TEST $CLI volume create $V0 $H0:$B0/${V0}{0,1,2,3,4,5} TEST $CLI volume set $V0 diagnostics.client-log-level DEBUG TEST $CLI volume start $V0 +EXPECT_WITHIN ${PROCESS_UP_TIMEOUT} "6" online_brick_count TEST glusterfs --volfile-id=$V0 --acl --volfile-server=$H0 --entry-timeout=0 $M0; diff --git a/tests/bugs/ctime/issue-832.t b/tests/bugs/ctime/issue-832.t new file mode 100755 index 00000000000..740f731ab73 --- /dev/null +++ b/tests/bugs/ctime/issue-832.t @@ -0,0 +1,32 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../traps.rc + +#Trigger trusted.glusterfs.mdata setting codepath and see things work as expected +cleanup + +TEST_USER=test-ctime-user +TEST_UID=27341 + +TEST useradd -o -M -u ${TEST_UID} ${TEST_USER} +push_trapfunc "userdel --force ${TEST_USER}" + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/$V0 +TEST $CLI volume start $V0 + +$GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +echo abc > $M0/test +TEST chmod 755 $M0/ +TEST chmod 744 $M0/test +TEST setfattr -x trusted.glusterfs.mdata $B0/$V0/test +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +$GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +su ${TEST_USER} -c "cat $M0/test" +TEST getfattr -n trusted.glusterfs.mdata $B0/$V0/test + +cleanup diff --git a/tests/bugs/distribute/bug-1600379.t b/tests/bugs/distribute/bug-1600379.t new file mode 100644 index 00000000000..8d2f6154100 --- /dev/null +++ b/tests/bugs/distribute/bug-1600379.t @@ -0,0 +1,54 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +# Initialize +#------------------------------------------------------------ +cleanup; + +# Start glusterd +TEST glusterd; +TEST pidof glusterd; +TEST $CLI volume info; + +# Create a volume +TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2} + +# Verify volume creation +EXPECT "$V0" volinfo_field $V0 'Volume Name'; +EXPECT 'Created' volinfo_field $V0 'Status'; + +# Start volume and verify successful start +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; +#------------------------------------------------------------ + +# Test case - Remove xattr from killed brick on lookup +#------------------------------------------------------------ +# Create a dir and set custom xattr +TEST mkdir $M0/testdir +TEST setfattr -n user.attr -v val $M0/testdir +xattr_val=`getfattr -d $B0/${V0}2/testdir | awk '{print $1}'`; +TEST ${xattr_val}='user.attr="val"'; + +# Kill 2nd brick process +TEST kill_brick $V0 $H0 $B0/${V0}2 +EXPECT_WITHIN ${PROCESS_UP_TIMEOUT} "1" online_brick_count + +# Remove custom xattr +TEST setfattr -x user.attr $M0/testdir + +# Bring up the killed brick process +TEST $CLI volume start $V0 force + +# Perform lookup +sleep 5 +TEST ls $M0/testdir + +# Check brick xattrs +xattr_val_2=`getfattr -d $B0/${V0}2/testdir`; +TEST [ ${xattr_val_2} = ''] ; + +cleanup; diff --git a/tests/bugs/distribute/issue-1327.t b/tests/bugs/distribute/issue-1327.t new file mode 100755 index 00000000000..acd8c8c6614 --- /dev/null +++ b/tests/bugs/distribute/issue-1327.t @@ -0,0 +1,33 @@ +#!/bin/bash + +SCRIPT_TIMEOUT=250 + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../dht.rc + +cleanup + +TEST glusterd +TEST pidof glusterd + +BRICK1=$B0/${V0}-0 +BRICK2=$B0/${V0}-1 + +TEST $CLI volume create $V0 $H0:$BRICK1 $H0:$BRICK2 +TEST $CLI volume start $V0 + +TEST glusterfs -s $H0 --volfile-id $V0 $M0 +TEST mkdir $M0/dir + +#remove dir from one of the brick +TEST rmdir $BRICK2/dir + +#safe cache timeout for lookup to be triggered +sleep 2 + +TEST ls $M0/dir + +TEST stat $BRICK2/dir + +cleanup diff --git a/tests/bugs/fuse/many-groups-for-acl.t b/tests/bugs/fuse/many-groups-for-acl.t index d959f750ee0..a51b1bc7267 100755 --- a/tests/bugs/fuse/many-groups-for-acl.t +++ b/tests/bugs/fuse/many-groups-for-acl.t @@ -38,6 +38,13 @@ do done TEST useradd -o -M -u ${NEW_UID} -g ${NEW_GID} -G ${NEW_USER}-${NEW_GIDS} ${NEW_USER} +# Linux < 3.8 exports only first 32 gids of pid to userspace +kernel_exports_few_gids=0 +if [ "$OSTYPE" = Linux ] && \ + su -m ${NEW_USER} -c "grep ^Groups: /proc/self/status | wc -w | xargs -I@ expr @ - 1 '<' $LAST_GID - $NEW_GID + 1" > /dev/null; then + kernel_exports_few_gids=1 +fi + # preparation done, start the tests TEST glusterd @@ -48,6 +55,8 @@ TEST $CLI volume set $V0 nfs.disable off TEST $CLI volume set ${V0} server.manage-gids off TEST $CLI volume start ${V0} +# This is just a synchronization hack to make sure the bricks are +# up before going on. EXPECT_WITHIN ${NFS_EXPORT_TIMEOUT} "1" is_nfs_export_available # mount the volume with POSIX ACL support, without --resolve-gids @@ -69,8 +78,8 @@ TEST [ $? -eq 0 ] su -m ${NEW_USER} -c "touch ${M0}/first-32-gids-2/success > /dev/null" TEST [ $? -eq 0 ] -su -m ${NEW_USER} -c "touch ${M0}/gid-64/failure > /dev/null" -TEST [ $? -ne 0 ] +su -m ${NEW_USER} -c "touch ${M0}/gid-64/success--if-all-gids-exported > /dev/null" +TEST [ $? -eq $kernel_exports_few_gids ] su -m ${NEW_USER} -c "touch ${M0}/gid-120/failure > /dev/null" TEST [ $? -ne 0 ] diff --git a/tests/bugs/glusterd/brick-mux-validation-in-cluster.t b/tests/bugs/glusterd/brick-mux-validation-in-cluster.t index 4e570381701..b6af487a791 100644 --- a/tests/bugs/glusterd/brick-mux-validation-in-cluster.t +++ b/tests/bugs/glusterd/brick-mux-validation-in-cluster.t @@ -7,6 +7,20 @@ function count_brick_processes { pgrep glusterfsd | wc -l } +function count_brick_pids { + $CLI_1 --xml volume status all | sed -n '/.*<pid>\([^<]*\).*/s//\1/p' \ + | grep -v "N/A" | sort | uniq | wc -l +} + +function count_N/A_brick_pids { + $CLI_1 --xml volume status all | sed -n '/.*<pid>\([^<]*\).*/s//\1/p' \ + | grep -- '\-1' | sort | uniq | wc -l +} + +function check_peers { + $CLI_2 peer status | grep 'Peer in Cluster (Connected)' | wc -l +} + cleanup; TEST launch_cluster 3 @@ -48,4 +62,47 @@ TEST $CLI_1 volume stop $V1 EXPECT 3 count_brick_processes -cleanup +TEST $CLI_1 volume stop $META_VOL + +TEST $CLI_1 volume delete $META_VOL +TEST $CLI_1 volume delete $V0 +TEST $CLI_1 volume delete $V1 + +#bug-1773856 - Brick process fails to come up with brickmux on + +TEST $CLI_1 volume create $V0 $H1:$B1/${V0}1 $H2:$B2/${V0}1 $H3:$B3/${V0}1 force +TEST $CLI_1 volume start $V0 + + +EXPECT 3 count_brick_processes + +#create and start a new volume +TEST $CLI_1 volume create $V1 $H1:$B1/${V1}2 $H2:$B2/${V1}2 $H3:$B3/${V1}2 force +TEST $CLI_1 volume start $V1 + +EXPECT 3 count_brick_processes + +V2=patchy2 +TEST $CLI_1 volume create $V2 $H1:$B1/${V2}3 $H2:$B2/${V2}3 $H3:$B3/${V2}3 force +TEST $CLI_1 volume start $V2 + +EXPECT 3 count_brick_processes + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 3 count_brick_pids + +TEST kill_node 1 + +sleep 10 + +EXPECT_WITHIN $PROBE_TIMEOUT 1 check_peers; + +$CLI_2 volume set $V0 performance.readdir-ahead on +$CLI_2 volume set $V1 performance.readdir-ahead on + +TEST $glusterd_1; +EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 4 count_brick_pids +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 0 count_N/A_brick_pids + +cleanup; diff --git a/tests/bugs/glusterd/brick-mux-validation.t b/tests/bugs/glusterd/brick-mux-validation.t index 03a476823ca..61b0455f9a8 100644 --- a/tests/bugs/glusterd/brick-mux-validation.t +++ b/tests/bugs/glusterd/brick-mux-validation.t @@ -24,7 +24,7 @@ TEST $CLI volume create $V0 $H0:$B0/${V0}{1..3} TEST $CLI volume start $V0 EXPECT 1 count_brick_processes -EXPECT 1 count_brick_pids +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 1 count_brick_pids EXPECT_WITHIN $PROCESS_UP_TIMEOUT 3 online_brick_count pkill gluster @@ -101,4 +101,4 @@ TEST $CLI_IGNORE_PARTITION volume reset-brick $V1 $H0:$B0/${V1}1 $H0:$B0/${V1}1 EXPECT_WITHIN $PROCESS_UP_TIMEOUT 6 online_brick_count EXPECT 1 count_brick_processes -cleanup;
\ No newline at end of file +cleanup; diff --git a/tests/bugs/glusterd/brick-mux.t b/tests/bugs/glusterd/brick-mux.t index eeaa3ebfea8..927940534c1 100644 --- a/tests/bugs/glusterd/brick-mux.t +++ b/tests/bugs/glusterd/brick-mux.t @@ -39,7 +39,7 @@ TEST glusterd EXPECT_WITHIN $PROCESS_UP_TIMEOUT 4 online_brick_count EXPECT 1 count_brick_processes -TEST $CLI volume set $V1 performance.cache-size 32MB +TEST $CLI volume set $V1 performance.io-cache-size 32MB TEST $CLI volume stop $V1 TEST $CLI volume start $V1 diff --git a/tests/bugs/glusterd/brick-order-check-add-brick.t b/tests/bugs/glusterd/brick-order-check-add-brick.t new file mode 100644 index 00000000000..0be31dac768 --- /dev/null +++ b/tests/bugs/glusterd/brick-order-check-add-brick.t @@ -0,0 +1,61 @@ +#!/bin/bash +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../cluster.rc +. $(dirname $0)/../../snapshot.rc + +cleanup; + +TEST verify_lvm_version; +#Create cluster with 3 nodes +TEST launch_cluster 3 -NO_DEBUG -NO_FORCE +TEST setup_lvm 3 + +TEST $CLI_1 peer probe $H2 +TEST $CLI_1 peer probe $H3 +EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count + +TEST $CLI_1 volume create $V0 replica 3 $H1:$L1/$V0 $H2:$L2/$V0 $H3:$L3/$V0 +EXPECT '1 x 3 = 3' volinfo_field $V0 'Number of Bricks' +EXPECT 'Created' volinfo_field $V0 'Status' + +TEST $CLI_1 volume start $V0 +EXPECT 'Started' volinfo_field $V0 'Status' + +#add-brick with or without mentioning the replica count should not fail +TEST $CLI_1 volume add-brick $V0 replica 3 $H1:$L1/${V0}_1 $H2:$L2/${V0}_1 $H3:$L3/${V0}_1 +EXPECT '2 x 3 = 6' volinfo_field $V0 'Number of Bricks' + +TEST $CLI_1 volume add-brick $V0 $H1:$L1/${V0}_2 $H2:$L2/${V0}_2 $H3:$L3/${V0}_2 +EXPECT '3 x 3 = 9' volinfo_field $V0 'Number of Bricks' + +#adding bricks from same host should fail the brick order check +TEST ! $CLI_1 volume add-brick $V0 $H1:$L1/${V0}_3 $H1:$L1/${V0}_4 $H1:$L1/${V0}_5 +EXPECT '3 x 3 = 9' volinfo_field $V0 'Number of Bricks' + +#adding bricks from same host with force should succeed +TEST $CLI_1 volume add-brick $V0 $H1:$L1/${V0}_3 $H1:$L1/${V0}_4 $H1:$L1/${V0}_5 force +EXPECT '4 x 3 = 12' volinfo_field $V0 'Number of Bricks' + +TEST $CLI_1 volume stop $V0 +TEST $CLI_1 volume delete $V0 + +TEST $CLI_1 volume create $V0 replica 2 $H1:$L1/${V0}1 $H2:$L2/${V0}1 +EXPECT '1 x 2 = 2' volinfo_field $V0 'Number of Bricks' +EXPECT 'Created' volinfo_field $V0 'Status' + +TEST $CLI_1 volume start $V0 +EXPECT 'Started' volinfo_field $V0 'Status' + +#Add-brick with Increasing replica count +TEST $CLI_1 volume add-brick $V0 replica 3 $H3:$L3/${V0}1 +EXPECT '1 x 3 = 3' volinfo_field $V0 'Number of Bricks' + +#Add-brick with Increasing replica count from same host should fail +TEST ! $CLI_1 volume add-brick $V0 replica 5 $H1:$L1/${V0}2 $H1:$L1/${V0}3 + +#adding multiple bricks from same host should fail the brick order check +TEST ! $CLI_1 volume add-brick $V0 replica 3 $H1:$L1/${V0}{4..6} $H2:$L2/${V0}{7..9} +EXPECT '1 x 3 = 3' volinfo_field $V0 'Number of Bricks' + +cleanup diff --git a/tests/bugs/glusterd/check_elastic_server.t b/tests/bugs/glusterd/check_elastic_server.t index 8e9e4e5b0eb..41d2140aa2b 100644 --- a/tests/bugs/glusterd/check_elastic_server.t +++ b/tests/bugs/glusterd/check_elastic_server.t @@ -23,6 +23,9 @@ EXPECT 'Created' cluster_volinfo_field 1 $V0 'Status'; $CLI_1 volume start $V0 EXPECT 'Started' cluster_volinfo_field 1 $V0 'Status'; +#Mount invalid volume +TEST ! glusterfs -s $H1 --volfile-id=$V0_NA $M0; + #Mount FUSE TEST glusterfs -s $H1 --volfile-id=$V0 $M0; diff --git a/tests/bugs/glusterd/mgmt-handshake-and-volume-sync-post-glusterd-restart.t b/tests/bugs/glusterd/mgmt-handshake-and-volume-sync-post-glusterd-restart.t index fdc0a73f60c..8001359e6b3 100644 --- a/tests/bugs/glusterd/mgmt-handshake-and-volume-sync-post-glusterd-restart.t +++ b/tests/bugs/glusterd/mgmt-handshake-and-volume-sync-post-glusterd-restart.t @@ -4,7 +4,7 @@ . $(dirname $0)/../../cluster.rc function check_peers { -$CLI_1 peer status | grep 'Peer in Cluster (Connected)' | wc -l +eval \$CLI_$1 peer status | grep 'Peer in Cluster (Connected)' | wc -l } cleanup @@ -36,23 +36,35 @@ TEST [[ $OP_VERS_ORIG == $OP_VERS_NEW ]] #bug-948686 - volume sync after bringing up the killed node TEST $CLI_1 peer probe $H3 -EXPECT_WITHIN $PROBE_TIMEOUT 2 check_peers; +EXPECT_WITHIN $PROBE_TIMEOUT 2 check_peers 1 +EXPECT_WITHIN $PROBE_TIMEOUT 2 check_peers 2 +EXPECT_WITHIN $PROBE_TIMEOUT 2 check_peers 3 TEST $CLI_1 volume create $V0 replica 2 $H1:$B1/$V0 $H1:$B1/${V0}_1 $H2:$B2/$V0 $H3:$B3/$V0 TEST $CLI_1 volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'Started' volinfo_field_1 $V0 'Status' TEST glusterfs --volfile-server=$H1 --volfile-id=$V0 $M0 #kill a node TEST kill_node 3 +EXPECT_WITHIN $PROBE_TIMEOUT 1 check_peers 1 +EXPECT_WITHIN $PROBE_TIMEOUT 1 check_peers 2 #modify volume config to see change in volume-sync TEST $CLI_1 volume set $V0 write-behind off #add some files to the volume to see effect of volume-heal cmd TEST touch $M0/{1..100}; TEST $CLI_1 volume stop $V0; +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT 'Stopped' volinfo_field_1 $V0 'Status' + TEST $glusterd_3; -EXPECT_WITHIN $PROBE_TIMEOUT 2 check_peers +EXPECT_WITHIN $PROBE_TIMEOUT 2 check_peers 1 +EXPECT_WITHIN $PROBE_TIMEOUT 2 check_peers 2 +EXPECT_WITHIN $PROBE_TIMEOUT 2 check_peers 3 + +sleep 5 TEST $CLI_3 volume start $V0; +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'Started' volinfo_field_1 $V0 'Status' TEST $CLI_2 volume stop $V0; TEST $CLI_2 volume delete $V0; diff --git a/tests/bugs/glusterd/enable-shared-storage-and-remove-brick-validation.t b/tests/bugs/glusterd/remove-brick-validation.t index 11ed0d94d79..a0ff4ff6a24 100644 --- a/tests/bugs/glusterd/enable-shared-storage-and-remove-brick-validation.t +++ b/tests/bugs/glusterd/remove-brick-validation.t @@ -18,20 +18,6 @@ TEST $CLI_1 peer probe $H2; EXPECT_WITHIN $PROBE_TIMEOUT 1 peer_count 1 -#test case for bug 1266818 - disabling enable-shared-storage option -##should not delete user created volume with name glusterd_shared_storage - -## creating a volume with name glusterd_shared_storage -TEST $CLI_1 volume create glusterd_shared_storage $H1:$B1/${V0}0 $H2:$B2/${V0}1 -TEST $CLI_1 volume start glusterd_shared_storage - -## disabling enable-shared-storage should not succeed and should not delete the -## user created volume with name "glusterd_shared_storage" -TEST ! $CLI_1 volume all enable-shared-storage disable - -## volume with name should exist -TEST $CLI_1 volume info glusterd_shared_storage - #testcase: bug-1245045-remove-brick-validation TEST $CLI_1 peer probe $H3; diff --git a/tests/bugs/glusterd/removing-multiple-bricks-in-single-remove-brick-command.t b/tests/bugs/glusterd/removing-multiple-bricks-in-single-remove-brick-command.t index 20c84d26b9c..00beab59137 100644 --- a/tests/bugs/glusterd/removing-multiple-bricks-in-single-remove-brick-command.t +++ b/tests/bugs/glusterd/removing-multiple-bricks-in-single-remove-brick-command.t @@ -49,6 +49,7 @@ EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 #Create a 3x3 dist-rep volume TEST $CLI volume create $V1 replica 3 $H0:$B0/${V1}{0,1,2,3,4,5,6,7,8}; TEST $CLI volume start $V1 +EXPECT_WITHIN ${PROCESS_UP_TIMEOUT} "9" brick_count ${V1} # Mount FUSE and create file/directory TEST glusterfs -s $H0 --volfile-id $V1 $M0 diff --git a/tests/bugs/glusterd/serialize-shd-manager-glusterd-restart.t b/tests/bugs/glusterd/serialize-shd-manager-glusterd-restart.t index 3a27c2a9d1b..a871e112d87 100644 --- a/tests/bugs/glusterd/serialize-shd-manager-glusterd-restart.t +++ b/tests/bugs/glusterd/serialize-shd-manager-glusterd-restart.t @@ -4,7 +4,7 @@ . $(dirname $0)/../../cluster.rc function check_peers { -count=`$CLI_1 peer status | grep 'Peer in Cluster (Connected)' | wc -l` +count=`$CLI_3 peer status | grep 'Peer in Cluster (Connected)' | wc -l` echo $count } diff --git a/tests/bugs/glusterd/validating-options-for-replicated-volume.t b/tests/bugs/glusterd/validating-options-for-replicated-volume.t index ee231338ff1..ddc80b17870 100644 --- a/tests/bugs/glusterd/validating-options-for-replicated-volume.t +++ b/tests/bugs/glusterd/validating-options-for-replicated-volume.t @@ -61,10 +61,15 @@ TEST ! $CLI volume set $V0 background-self-heal-count " " TEST $CLI volume set $V0 background-self-heal-count 10 EXPECT "10" volume_option $V0 cluster.background-self-heal-count -TEST ! $CLI volume set $V0 cache-size "" -TEST ! $CLI volume set $V0 cache-size " " -TEST $CLI volume set $V0 cache-size 512MB -EXPECT "512MB" volume_option $V0 performance.cache-size +TEST ! $CLI volume set $V0 io-cache-size "" +TEST ! $CLI volume set $V0 io-cache-size " " +TEST $CLI volume set $V0 io-cache-size 64MB +EXPECT "64MB" volume_option $V0 performance.io-cache-size + +TEST ! $CLI volume set $V0 quick-read-cache-size "" +TEST ! $CLI volume set $V0 quick-read-cache-size " " +TEST $CLI volume set $V0 quick-read-cache-size 512MB +EXPECT "512MB" volume_option $V0 performance.quick-read-cache-size TEST ! $CLI volume set $V0 self-heal-daemon "" TEST ! $CLI volume set $V0 self-heal-daemon " " diff --git a/tests/bugs/glusterfs-server/bug-873549.t b/tests/bugs/glusterfs-server/bug-873549.t index a3b2f9c9bf7..8b5534728fd 100644 --- a/tests/bugs/glusterfs-server/bug-873549.t +++ b/tests/bugs/glusterfs-server/bug-873549.t @@ -10,7 +10,7 @@ TEST $CLI volume info; TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2}; -TEST $CLI volume set $V0 performance.cache-size 512MB +TEST $CLI volume set $V0 performance.quick-read-cache-size 512MB TEST $CLI volume start $V0 TEST $CLI volume statedump $V0 all diff --git a/tests/bugs/glusterfs/bug-873962-spb.t b/tests/bugs/glusterfs/bug-873962-spb.t index db84a223089..db71cc0f6fe 100644 --- a/tests/bugs/glusterfs/bug-873962-spb.t +++ b/tests/bugs/glusterfs/bug-873962-spb.t @@ -14,6 +14,7 @@ TEST $CLI volume set $V0 performance.io-cache off TEST $CLI volume set $V0 performance.write-behind off TEST $CLI volume set $V0 performance.stat-prefetch off TEST $CLI volume set $V0 performance.read-ahead off +TEST $CLI volume set $V0 performance.open-behind off TEST $CLI volume set $V0 cluster.background-self-heal-count 0 TEST $CLI volume start $V0 TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id=$V0 $M0 --direct-io-mode=enable diff --git a/tests/bugs/logging/bug-823081.t b/tests/bugs/logging/bug-823081.t index 0ed8f4c26c1..bd1965d2d49 100755 --- a/tests/bugs/logging/bug-823081.t +++ b/tests/bugs/logging/bug-823081.t @@ -22,20 +22,20 @@ function set_tail () set_tail $V0; TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2}; -tail=`tail -n 1 $logdir/$cmd_log_history | cut -d " " -f 5-` +tail=`tail -n 1 $logdir/$cmd_log_history | cut -d " " -f 6-` TEST [[ \"$tail\" == \"$tail_success\" ]] TEST ! $CLI volume create $V0 $H0:$B0/${V0}{1,2}; -tail=`tail -n 1 $logdir/$cmd_log_history | cut -d " " -f 5-` +tail=`tail -n 1 $logdir/$cmd_log_history | cut -d " " -f 6-` TEST [[ \"$tail\" == \"$tail_failure\" ]] set_tail $V1; TEST gluster volume create $V1 $H0:$B0/${V1}{1,2} force; -tail=`tail -n 1 $logdir/$cmd_log_history | cut -d " " -f 5-` +tail=`tail -n 1 $logdir/$cmd_log_history | cut -d " " -f 6-` TEST [[ \"$tail\" == \"$tail_success_force\" ]] TEST ! gluster volume create $V1 $H0:$B0/${V1}{1,2} force; -tail=`tail -n 1 $logdir/$cmd_log_history | cut -d " " -f 5-` +tail=`tail -n 1 $logdir/$cmd_log_history | cut -d " " -f 6-` TEST [[ \"$tail\" == \"$tail_failure_force\" ]] cleanup; diff --git a/tests/bugs/replicate/bug-1101647.t b/tests/bugs/replicate/bug-1101647.t index 8f420eec012..708bc1a1e29 100644 --- a/tests/bugs/replicate/bug-1101647.t +++ b/tests/bugs/replicate/bug-1101647.t @@ -12,6 +12,8 @@ TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{1,2}; TEST $CLI volume start $V0; TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=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 #Create base entry in indices/xattrop echo "Data">$M0/file diff --git a/tests/bugs/replicate/bug-1586020-mark-dirty-for-entry-txn-on-quorum-failure.t b/tests/bugs/replicate/bug-1586020-mark-dirty-for-entry-txn-on-quorum-failure.t index 26f90497d6f..49c4dea4e9c 100644 --- a/tests/bugs/replicate/bug-1586020-mark-dirty-for-entry-txn-on-quorum-failure.t +++ b/tests/bugs/replicate/bug-1586020-mark-dirty-for-entry-txn-on-quorum-failure.t @@ -53,8 +53,6 @@ TEST ! ls $B0/${V0}1/file$i TEST ls $B0/${V0}2/file$i dirty=$(get_hex_xattr trusted.afr.dirty $B0/${V0}2) TEST [ "$dirty" != "000000000000000000000000" ] -EXPECT "000000010000000100000000" get_hex_xattr trusted.afr.$V0-client-0 $B0/${V0}2/file$i -EXPECT "000000010000000100000000" get_hex_xattr trusted.afr.$V0-client-1 $B0/${V0}2/file$i TEST $CLI volume set $V0 self-heal-daemon on EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status diff --git a/tests/bugs/replicate/bug-1744548-heal-timeout.t b/tests/bugs/replicate/bug-1744548-heal-timeout.t index c208112c8b0..011535066f9 100644 --- a/tests/bugs/replicate/bug-1744548-heal-timeout.t +++ b/tests/bugs/replicate/bug-1744548-heal-timeout.t @@ -25,14 +25,14 @@ TEST ! $CLI volume heal $V0 TEST $CLI volume profile $V0 start TEST $CLI volume profile $V0 info clear TEST $CLI volume heal $V0 enable -# Each brick does 3 opendirs, corresponding to dirty, xattrop and entry-changes -EXPECT_WITHIN $HEAL_TIMEOUT "^333$" get_cumulative_opendir_count +# Each brick does 4 opendirs, corresponding to dirty, xattrop and entry-changes, anonymous-inode +EXPECT_WITHIN 4 "^444$" get_cumulative_opendir_count # Check that a change in heal-timeout is honoured immediately. TEST $CLI volume set $V0 cluster.heal-timeout 5 sleep 10 # Two crawls must have happened. -EXPECT_WITHIN $HEAL_TIMEOUT "^999$" get_cumulative_opendir_count +EXPECT_WITHIN $CHILD_UP_TIMEOUT "^121212$" get_cumulative_opendir_count # shd must not heal if it is disabled and heal-timeout is changed. TEST $CLI volume heal $V0 disable diff --git a/tests/bugs/replicate/issue-1254-prioritize-enospc.t b/tests/bugs/replicate/issue-1254-prioritize-enospc.t new file mode 100644 index 00000000000..fab94b71b27 --- /dev/null +++ b/tests/bugs/replicate/issue-1254-prioritize-enospc.t @@ -0,0 +1,80 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup + +function create_bricks { + TEST truncate -s 100M $B0/brick0 + TEST truncate -s 100M $B0/brick1 + TEST truncate -s 20M $B0/brick2 + LO1=`SETUP_LOOP $B0/brick0` + TEST [ $? -eq 0 ] + TEST MKFS_LOOP $LO1 + LO2=`SETUP_LOOP $B0/brick1` + TEST [ $? -eq 0 ] + TEST MKFS_LOOP $LO2 + LO3=`SETUP_LOOP $B0/brick2` + TEST [ $? -eq 0 ] + TEST MKFS_LOOP $LO3 + TEST mkdir -p $B0/${V0}0 $B0/${V0}1 $B0/${V0}2 + TEST MOUNT_LOOP $LO1 $B0/${V0}0 + TEST MOUNT_LOOP $LO2 $B0/${V0}1 + TEST MOUNT_LOOP $LO3 $B0/${V0}2 +} + +function create_files { + local i=1 + while (true) + do + touch $M0/file$i + if [ -e $B0/${V0}2/file$i ]; + then + ((i++)) + else + break + fi + done +} + +TESTS_EXPECTED_IN_LOOP=13 + +#Arbiter volume: Check for ENOSPC when arbiter brick becomes full# +TEST glusterd +create_bricks +TEST $CLI volume create $V0 replica 3 arbiter 1 $H0:$B0/${V0}{0,1,2} +TEST $CLI volume start $V0 +TEST $CLI volume set $V0 performance.write-behind off +TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0 + +create_files +TEST kill_brick $V0 $H0 $B0/${V0}1 +error1=$(touch $M0/file-1 2>&1) +EXPECT "No space left on device" echo $error1 +error2=$(mkdir $M0/dir-1 2>&1) +EXPECT "No space left on device" echo $error2 +error3=$((echo "Test" > $M0/file-3) 2>&1) +EXPECT "No space left on device" echo $error3 + +cleanup + +#Replica-3 volume: Check for ENOSPC when one of the brick becomes full# +#Keeping the third brick of lower size to simulate disk full scenario# +TEST glusterd +create_bricks +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2} +TEST $CLI volume start $V0 +TEST $CLI volume set $V0 performance.write-behind off +TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0 + +create_files +TEST kill_brick $V0 $H0 $B0/${V0}1 +error1=$(touch $M0/file-1 2>&1) +EXPECT "No space left on device" echo $error1 +error2=$(mkdir $M0/dir-1 2>&1) +EXPECT "No space left on device" echo $error2 +error3=$((cat /dev/zero > $M0/file1) 2>&1) +EXPECT "No space left on device" echo $error3 + +cleanup diff --git a/tests/bugs/replicate/mdata-heal-no-xattrs.t b/tests/bugs/replicate/mdata-heal-no-xattrs.t new file mode 100644 index 00000000000..d3b0c504c80 --- /dev/null +++ b/tests/bugs/replicate/mdata-heal-no-xattrs.t @@ -0,0 +1,59 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2}; +TEST $CLI volume set $V0 cluster.self-heal-daemon off +TEST $CLI volume start $V0 + +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 +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 +echo "Data">$M0/FILE +ret=$? +TEST [ $ret -eq 0 ] + +# Change permission on brick-0: simulates the case where there is metadata +# mismatch but no pending xattrs. This brick will become the source for heal. +TEST chmod +x $B0/$V0"0"/FILE + +# Add gfid to xattrop +xattrop_b0=$(afr_get_index_path $B0/$V0"0") +base_entry_b0=`ls $xattrop_b0` +gfid_str_FILE=$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/$V0"0"/FILE)) +TEST ln $xattrop_b0/$base_entry_b0 $xattrop_b0/$gfid_str_FILE +EXPECT_WITHIN $HEAL_TIMEOUT "^1$" get_pending_heal_count $V0 + +TEST $CLI volume set $V0 cluster.self-heal-daemon on +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 + +# Brick-0 should contain xattrs blaming other 2 bricks. +# The values will be zero because heal is over. +EXPECT "000000000000000000000000" get_hex_xattr trusted.afr.$V0-client-1 $B0/${V0}0/FILE +EXPECT "000000000000000000000000" get_hex_xattr trusted.afr.$V0-client-2 $B0/${V0}0/FILE +TEST ! getfattr -n trusted.afr.$V0-client-0 $B0/${V0}0/FILE + +# Brick-1 and Brick-2 must not contain any afr xattrs. +TEST ! getfattr -n trusted.afr.$V0-client-0 $B0/${V0}1/FILE +TEST ! getfattr -n trusted.afr.$V0-client-1 $B0/${V0}1/FILE +TEST ! getfattr -n trusted.afr.$V0-client-2 $B0/${V0}1/FILE +TEST ! getfattr -n trusted.afr.$V0-client-0 $B0/${V0}2/FILE +TEST ! getfattr -n trusted.afr.$V0-client-1 $B0/${V0}2/FILE +TEST ! getfattr -n trusted.afr.$V0-client-2 $B0/${V0}2/FILE + +# check permission bits. +EXPECT '755' stat -c %a $B0/${V0}0/FILE +EXPECT '755' stat -c %a $B0/${V0}1/FILE +EXPECT '755' stat -c %a $B0/${V0}2/FILE + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +cleanup; diff --git a/tests/bugs/shard/bug-1696136.c b/tests/bugs/shard/bug-1696136.c index b9e8d1375e5..cb650535b09 100644 --- a/tests/bugs/shard/bug-1696136.c +++ b/tests/bugs/shard/bug-1696136.c @@ -87,8 +87,9 @@ main(int argc, char *argv[]) goto out; } - offset = atoi(argv[4]); - len = atoi(argv[5]); + /* Note that off_t is signed but size_t isn't. */ + offset = strtol(argv[4], NULL, 10); + len = strtoul(argv[5], NULL, 10); fd = glfs_open(fs, argv[6], O_RDWR); if (fd == NULL) { diff --git a/tests/bugs/shard/bug-shard-discard.c b/tests/bugs/shard/bug-shard-discard.c index 15dca6c2181..6fa93fb89d1 100644 --- a/tests/bugs/shard/bug-shard-discard.c +++ b/tests/bugs/shard/bug-shard-discard.c @@ -50,8 +50,9 @@ main(int argc, char *argv[]) goto out; } - off = atoi(argv[4]); - len = atoi(argv[5]); + /* Note that off_t is signed but size_t isn't. */ + off = strtol(argv[4], NULL, 10); + len = strtoul(argv[5], NULL, 10); ret = glfs_discard(fd, off, len); if (ret <= 0) { diff --git a/tests/bugs/shard/issue-1243.t b/tests/bugs/shard/issue-1243.t new file mode 100644 index 00000000000..ba22d2b74fe --- /dev/null +++ b/tests/bugs/shard/issue-1243.t @@ -0,0 +1,43 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 $H0:$B0/${V0}{0,1} +TEST $CLI volume set $V0 features.shard on +TEST $CLI volume set $V0 features.shard-block-size 4MB +TEST $CLI volume set $V0 performance.quick-read off +TEST $CLI volume set $V0 performance.io-cache off +TEST $CLI volume set $V0 performance.read-ahead off +TEST $CLI volume set $V0 performance.strict-o-direct on +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0 + +TEST $CLI volume set $V0 md-cache-timeout 10 + +# Write data into a file such that its size crosses shard-block-size +TEST dd if=/dev/zero of=$M0/foo bs=1048576 count=8 oflag=direct + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0 + +# Execute a setxattr on the file. +TEST setfattr -n trusted.libvirt -v some-value $M0/foo + +# Size of the file should be the aggregated size, not the shard-block-size +EXPECT '8388608' stat -c %s $M0/foo + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0 + +# Execute a removexattr on the file. +TEST setfattr -x trusted.libvirt $M0/foo + +# Size of the file should be the aggregated size, not the shard-block-size +EXPECT '8388608' stat -c %s $M0/foo +cleanup diff --git a/tests/bugs/shard/issue-1281.t b/tests/bugs/shard/issue-1281.t new file mode 100644 index 00000000000..9704caa8944 --- /dev/null +++ b/tests/bugs/shard/issue-1281.t @@ -0,0 +1,34 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 $H0:$B0/${V0}{0,1} +TEST $CLI volume set $V0 features.shard on +TEST $CLI volume set $V0 performance.quick-read off +TEST $CLI volume set $V0 performance.io-cache off +TEST $CLI volume set $V0 performance.read-ahead off +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0 + +#Open a file and store descriptor in fd = 5 +exec 5>$M0/foo + +#Unlink the same file which is opened in prev step +TEST unlink $M0/foo + +#Write something on the file using the open fd = 5 +echo "issue-1281" >&5 + +#Write on the descriptor should be succesful +EXPECT 0 echo $? + +#Close the fd = 5 +exec 5>&- + +cleanup diff --git a/tests/bugs/shard/issue-1425.t b/tests/bugs/shard/issue-1425.t new file mode 100644 index 00000000000..bbe82c0e5b2 --- /dev/null +++ b/tests/bugs/shard/issue-1425.t @@ -0,0 +1,45 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +FILE_COUNT_TIME=5 + +function get_file_count { + ls $1* | wc -l +} + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 $H0:$B0/${V0}0 +TEST $CLI volume set $V0 features.shard on +TEST $CLI volume set $V0 features.shard-block-size 4MB +TEST $CLI volume start $V0 +TEST $CLI volume profile $V0 start + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0 + +TEST fallocate -l 20M $M0/foo +gfid_new=$(get_gfid_string $M0/foo) + +# Check for the base shard +TEST stat $M0/foo +TEST stat $B0/${V0}0/foo + +# There should be 4 associated shards +EXPECT_WITHIN $FILE_COUNT_TIME 4 get_file_count $B0/${V0}0/.shard/$gfid_new + +# There should be 1+4 shards and we expect 4 lookups less than on the build without this patch +EXPECT "21" echo `$CLI volume profile $V0 info incremental | grep -w LOOKUP | awk '{print $8}'` + +# Delete the base shard and check shards get cleaned up +TEST unlink $M0/foo + +TEST ! stat $M0/foo +TEST ! stat $B0/${V0}0/foo + +# There should be no shards now +EXPECT_WITHIN $FILE_COUNT_TIME 0 get_file_count $B0/${V0}0/.shard/$gfid_new +cleanup diff --git a/tests/bugs/shard/shard-fallocate.c b/tests/bugs/shard/shard-fallocate.c index 45b9ce00509..cb0714e8564 100644 --- a/tests/bugs/shard/shard-fallocate.c +++ b/tests/bugs/shard/shard-fallocate.c @@ -87,8 +87,9 @@ main(int argc, char *argv[]) goto out; } - offset = atoi(argv[4]); - len = atoi(argv[5]); + /* Note that off_t is signed but size_t isn't. */ + offset = strtol(argv[4], NULL, 10); + len = strtoul(argv[5], NULL, 10); fd = glfs_open(fs, argv[6], O_RDWR); if (fd == NULL) { diff --git a/tests/bugs/snapshot/bug-1111041.t b/tests/bugs/snapshot/bug-1111041.t index f771d64f2a3..efda9688d8b 100755 --- a/tests/bugs/snapshot/bug-1111041.t +++ b/tests/bugs/snapshot/bug-1111041.t @@ -11,6 +11,10 @@ function is_snapd_running { $CLI volume status $1 | grep "Snapshot Daemon" | wc -l; } +function snapd_pid { + $CLI volume status $V0 | grep "Snapshot Daemon" | awk {'print $8'} +} + TEST glusterd; TEST pidof glusterd; @@ -25,14 +29,12 @@ TEST $CLI volume set $V0 features.uss enable; EXPECT "1" is_snapd_running $V0 -SNAPD_PID=$($CLI volume status $V0 | grep "Snapshot Daemon" | awk {'print $8'}); +SNAPD_PID=$(snapd_pid); TEST [ $SNAPD_PID -gt 0 ] kill -9 $SNAPD_PID -SNAPD_PID=$($CLI volume status $V0 | grep "Snapshot Daemon" | awk {'print $8'}); - -TEST [ $SNAPD_PID = 'N/A' ] +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^N/A$" snapd_pid cleanup ; diff --git a/tests/bugs/snapshot/bug-1597662.t b/tests/bugs/snapshot/bug-1597662.t index dc87d17a0ef..f582930476a 100644 --- a/tests/bugs/snapshot/bug-1597662.t +++ b/tests/bugs/snapshot/bug-1597662.t @@ -34,12 +34,13 @@ function is_snap_path EXPECT "1" is_snap_path $CLI snapshot deactivate snap1; - +EXPECT_WITHIN ${PROCESS_DOWN_TIMEOUT} 'Stopped' snapshot_status snap1 # snap is deactivated so snap_path should not exist EXPECT "0" is_snap_path # activate snap again $CLI snapshot activate snap1; +EXPECT_WITHIN ${PROCESS_UP_TIMEOUT} 'Started' snapshot_status snap1 # snap is active so snap_path should exist EXPECT "1" is_snap_path diff --git a/tests/bugs/write-behind/issue-884.c b/tests/bugs/write-behind/issue-884.c new file mode 100644 index 00000000000..e9c33b351ad --- /dev/null +++ b/tests/bugs/write-behind/issue-884.c @@ -0,0 +1,267 @@ + +#define _GNU_SOURCE + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <assert.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <pthread.h> + +#include <glusterfs/api/glfs.h> + +/* Based on a reproducer by Stefan Ring. It seems to be quite sensible to any + * timing modification, so the code has been maintained as is, only with minor + * changes. */ + +struct glfs *glfs; + +pthread_mutex_t the_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t the_cond = PTHREAD_COND_INITIALIZER; + +typedef struct _my_aiocb { + int64_t size; + volatile int64_t seq; + int which; +} my_aiocb; + +typedef struct _worker_data { + my_aiocb cb; + struct iovec iov; + int64_t offset; +} worker_data; + +typedef struct { + worker_data wdata[2]; + + volatile unsigned busy; +} all_data_t; + +all_data_t all_data; + +static void +completion_fnc(struct glfs_fd *fd, ssize_t ret, struct glfs_stat *pre, + struct glfs_stat *post, void *arg) +{ + void *the_thread; + my_aiocb *cb = (my_aiocb *)arg; + long seq = cb->seq; + + assert(ret == cb->size); + + pthread_mutex_lock(&the_mutex); + pthread_cond_broadcast(&the_cond); + + all_data.busy &= ~(1 << cb->which); + cb->seq = -1; + + the_thread = (void *)pthread_self(); + printf("worker %d is done from thread %p, seq %ld!\n", cb->which, + the_thread, seq); + + pthread_mutex_unlock(&the_mutex); +} + +static void +init_wdata(worker_data *data, int which) +{ + data->cb.which = which; + data->cb.seq = -1; + + data->iov.iov_base = malloc(1024 * 1024); + memset(data->iov.iov_base, 6, + 1024 * 1024); /* tail part never overwritten */ +} + +static void +init() +{ + all_data.busy = 0; + + init_wdata(&all_data.wdata[0], 0); + init_wdata(&all_data.wdata[1], 1); +} + +static void +do_write(struct glfs_fd *fd, int content, int size, int64_t seq, + worker_data *wdata, const char *name) +{ + int ret; + + wdata->cb.size = size; + wdata->cb.seq = seq; + + if (content >= 0) + memset(wdata->iov.iov_base, content, size); + wdata->iov.iov_len = size; + + pthread_mutex_lock(&the_mutex); + printf("(%d) dispatching write \"%s\", offset %lx, len %x, seq %ld\n", + wdata->cb.which, name, (long)wdata->offset, size, (long)seq); + pthread_mutex_unlock(&the_mutex); + ret = glfs_pwritev_async(fd, &wdata->iov, 1, wdata->offset, 0, + completion_fnc, &wdata->cb); + assert(ret >= 0); +} + +#define IDLE 0 // both workers must be idle +#define ANY 1 // use any worker, other one may be busy + +int +get_worker(int waitfor, int64_t excl_seq) +{ + int which; + + pthread_mutex_lock(&the_mutex); + + while (waitfor == IDLE && (all_data.busy & 3) != 0 || + waitfor == ANY && + ((all_data.busy & 3) == 3 || + excl_seq >= 0 && (all_data.wdata[0].cb.seq == excl_seq || + all_data.wdata[1].cb.seq == excl_seq))) + pthread_cond_wait(&the_cond, &the_mutex); + + if (!(all_data.busy & 1)) + which = 0; + else + which = 1; + + all_data.busy |= (1 << which); + + pthread_mutex_unlock(&the_mutex); + + return which; +} + +static int +doit(struct glfs_fd *fd) +{ + int ret; + int64_t seq = 0; + int64_t offset = 0; // position in file, in blocks + int64_t base = 0x1000; // where to place the data, in blocks + + int async_mode = ANY; + + init(); + + for (;;) { + int which; + worker_data *wdata; + + // for growing to the first offset + for (;;) { + int gap = base + 0x42 - offset; + if (!gap) + break; + if (gap > 80) + gap = 80; + + which = get_worker(IDLE, -1); + wdata = &all_data.wdata[which]; + + wdata->offset = offset << 9; + do_write(fd, 0, gap << 9, seq++, wdata, "gap-filling"); + + offset += gap; + } + + // 8700 + which = get_worker(IDLE, -1); + wdata = &all_data.wdata[which]; + + wdata->offset = (base + 0x42) << 9; + do_write(fd, 1, 62 << 9, seq++, wdata, "!8700"); + + // 8701 + which = get_worker(IDLE, -1); + wdata = &all_data.wdata[which]; + + wdata->offset = (base + 0x42) << 9; + do_write(fd, 2, 55 << 9, seq++, wdata, "!8701"); + + // 8702 + which = get_worker(async_mode, -1); + wdata = &all_data.wdata[which]; + + wdata->offset = (base + 0x79) << 9; + do_write(fd, 3, 54 << 9, seq++, wdata, "!8702"); + + // 8703 + which = get_worker(async_mode, -1); + wdata = &all_data.wdata[which]; + + wdata->offset = (base + 0xaf) << 9; + do_write(fd, 4, 81 << 9, seq++, wdata, "!8703"); + + // 8704 + // this writes both 5s and 6s + // the range of 5s is the one that overwrites 8703 + + which = get_worker(async_mode, seq - 1); + wdata = &all_data.wdata[which]; + + memset(wdata->iov.iov_base, 5, 81 << 9); + wdata->offset = (base + 0xaf) << 9; + do_write(fd, -1, 1623 << 9, seq++, wdata, "!8704"); + + offset = base + 0x706; + base += 0x1000; + if (base >= 0x100000) + break; + } + + printf("done!\n"); + fflush(stdout); + + pthread_mutex_lock(&the_mutex); + + while ((all_data.busy & 3) != 0) + pthread_cond_wait(&the_cond, &the_mutex); + + pthread_mutex_unlock(&the_mutex); + + ret = glfs_close(fd); + assert(ret >= 0); + /* + ret = glfs_fini(glfs); + assert(ret >= 0); + */ + return 0; +} + +int +main(int argc, char *argv[]) +{ + int ret; + int open_flags = O_RDWR | O_DIRECT | O_TRUNC; + struct glfs_fd *fd; + + glfs = glfs_new(argv[1]); + if (!glfs) { + printf("glfs_new!\n"); + goto out; + } + ret = glfs_set_volfile_server(glfs, "tcp", "localhost", 24007); + if (ret < 0) { + printf("set_volfile!\n"); + goto out; + } + ret = glfs_init(glfs); + if (ret) { + printf("init!\n"); + goto out; + } + fd = glfs_open(glfs, argv[2], open_flags); + if (!fd) { + printf("open!\n"); + goto out; + } + srand(time(NULL)); + return doit(fd); +out: + return 1; +} diff --git a/tests/bugs/write-behind/issue-884.t b/tests/bugs/write-behind/issue-884.t new file mode 100755 index 00000000000..2bcf7d15265 --- /dev/null +++ b/tests/bugs/write-behind/issue-884.t @@ -0,0 +1,40 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +# This test tries to detect a race condition in write-behind. It's based on a +# reproducer written by Stefan Ring that is able to hit it sometimes. On my +# system, it happened around 10% of the runs. This means that if this bug +# appears again, this test will fail once every 10 runs. Most probably this +# failure will be hidden by the automatic test retry of the testing framework. +# +# Please, if this test fails, it needs to be analyzed in detail. + +function run() { + "${@}" >/dev/null +} + +cleanup + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/$V0 +# This makes it easier to hit the issue +TEST $CLI volume set $V0 client-log-level TRACE +TEST $CLI volume start $V0 + +TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0 + +build_tester $(dirname $0)/issue-884.c -lgfapi + +TEST touch $M0/testfile + +# This program generates a file of 535694336 bytes with a fixed pattern +TEST run $(dirname $0)/issue-884 $V0 testfile + +# This is the md5sum of the expected pattern without corruption +EXPECT "ad105f9349345a70fc697632cbb5eec8" echo "$(md5sum $B0/$V0/testfile | awk '{ print $1; }')" + +cleanup diff --git a/tests/cluster.rc b/tests/cluster.rc index 2d826d07e39..34f5b02398f 100644 --- a/tests/cluster.rc +++ b/tests/cluster.rc @@ -11,7 +11,7 @@ function launch_cluster() { define_backends $count; define_hosts $count; define_glusterds $count $2; - define_clis $count; + define_clis $count $3; start_glusterds; } @@ -90,6 +90,20 @@ function kill_glusterd() { kill `cat $pidfile`; } +function restart_glusterd() { + local index=$1 + local b + local pidfile + local g + + b="B$index" + pidfile="${!b}/glusterd.pid" + + kill `cat $pidfile` + + g="glusterd_${index}" + ${!g} +} function kill_node() { local index=$1; @@ -134,8 +148,13 @@ function define_clis() { lopt1="--log-file=$logdir/$logfile1" - eval "CLI_$i='$CLI --glusterd-sock=${!b}/glusterd/gd.sock $lopt'"; - eval "CLI$i='$CLI --glusterd-sock=${!b}/glusterd/gd.sock $lopt1'"; + if [ "$2" == "-NO_FORCE" ]; then + eval "CLI_$i='$CLI_NO_FORCE --glusterd-sock=${!b}/glusterd/gd.sock $lopt'"; + eval "CLI$i='$CLI_NO_FORCE --glusterd-sock=${!b}/glusterd/gd.sock $lopt1'"; + else + eval "CLI_$i='$CLI --glusterd-sock=${!b}/glusterd/gd.sock $lopt'"; + eval "CLI$i='$CLI --glusterd-sock=${!b}/glusterd/gd.sock $lopt1'"; + fi done } diff --git a/tests/env.rc.in b/tests/env.rc.in index c7472a7988d..0478d66aec6 100644 --- a/tests/env.rc.in +++ b/tests/env.rc.in @@ -2,7 +2,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ -PATH=@sbindir@:$PATH +PATH=@bindir@:@sbindir@:$PATH export PATH GLUSTERD_PIDFILEDIR=@localstatedir@/run/gluster diff --git a/tests/features/flock_interrupt.t b/tests/features/flock_interrupt.t index 964a4bc20ef..b8717e30dfb 100644 --- a/tests/features/flock_interrupt.t +++ b/tests/features/flock_interrupt.t @@ -28,6 +28,5 @@ flock $M0/testfile sleep 6 & { sleep 0.3; flock -w 2 $M0/testfile true; echo ok EXPECT_WITHIN 4 ok cat got_lock; ## Finish up -sleep 7; rm -f got_lock; cleanup; diff --git a/tests/features/fuse-lru-limit.t b/tests/features/fuse-lru-limit.t index 9f1211660ce..dd6be2d5397 100644 --- a/tests/features/fuse-lru-limit.t +++ b/tests/features/fuse-lru-limit.t @@ -10,6 +10,7 @@ TEST pidof glusterd TEST $CLI volume create $V0 $H0:$B0/${V0}{0,1} TEST $CLI volume start $V0 TEST glusterfs -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN ${PROCESS_UP_TIMEOUT} "2" online_brick_count EXPECT "1" get_mount_active_size_value $V0 $M0 EXPECT "0" get_mount_lru_size_value $V0 $M0 diff --git a/tests/features/interrupt.t b/tests/features/interrupt.t index bd70ff87545..067eb1b7486 100644 --- a/tests/features/interrupt.t +++ b/tests/features/interrupt.t @@ -43,18 +43,22 @@ function test_interrupt { # If the test helper fails (which is considered a setup error, not failure of the test # case itself), kill will be invoked without argument, and that will be the actual # error which is caught. - TEST "./$(dirname $0)/open_and_sleep $M0/testfile | { sleep 0.1; xargs -n1 kill -INT; }" + TEST "./$(dirname $0)/open_and_sleep $M0/testfile-$handlebool | { sleep 0.1; xargs -n1 kill -INT; }" TEST "grep -E '$logpattern' $log_file" # Basic sanity check, making sure filesystem has not crashed. - TEST test -f $M0/testfile + TEST test -f $M0/testfile-$handlebool } # Theoretically FLUSH might finish before INTERRUPT is handled, -# in which case we'd get the "no handler found" message (but it's unlikely). -test_interrupt yes 'FLUSH.*interrupt handler triggered|INTERRUPT.*no handler found' +# in which case we'd get the "no handler found" message instead of +# "interrupt handler triggered" (but it's unlikely). +# If that's observed, the pattern can be changed to +# 'FLUSH.*interrupt handler triggered|[I]NTERRUPT.*no handler found' +# to fix the test. +test_interrupt yes '[F]LUSH.*interrupt handler triggered' EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 -test_interrupt no 'INTERRUPT.*no handler found' +test_interrupt no '[I]NTERRUPT.*no handler found' ## Finish up TEST $CLI volume stop $V0; diff --git a/tests/features/ssl-authz.t b/tests/features/ssl-authz.t index 132b598ff69..497083e5a3a 100755 --- a/tests/features/ssl-authz.t +++ b/tests/features/ssl-authz.t @@ -67,13 +67,14 @@ echo "Memory consumption for glusterfsd process" for i in $(seq 1 100); do gluster v heal $V0 info >/dev/null done - +#Wait to cleanup memory +sleep 10 end=`pmap -x $glusterfsd_pid | grep total | awk -F " " '{print $4}'` diff=$((end-start)) -# If memory consumption is more than 5M some leak in SSL code path +# If memory consumption is more than 15M some leak in SSL code path -TEST [ $diff -lt 5000 ] +TEST [ $diff -lt 15000 ] # Set ssl-allow to a wildcard that includes our identity. diff --git a/tests/features/ssl-ciphers.t b/tests/features/ssl-ciphers.t index e4bcdf51095..b70fe360e02 100644 --- a/tests/features/ssl-ciphers.t +++ b/tests/features/ssl-ciphers.t @@ -110,8 +110,15 @@ EXPECT "N" openssl_connect -ssl2 -connect $H0:$BRICK_PORT # Test SSLv3 protocol fails EXPECT "N" openssl_connect -ssl3 -connect $H0:$BRICK_PORT -# Test TLSv1 protocol fails -EXPECT "N" openssl_connect -tls1 -connect $H0:$BRICK_PORT +# Test TLSv1 protocol based on openssl version +cmd="openssl version" +ver=$(eval $cmd | awk -F " " '{print $2}' | grep "^1.1") +if [ "x${ver}" = "x" ]; then + supp="N" +else + supp="Y" +fi +EXPECT "${supp}" openssl_connect -tls1 -connect $H0:$BRICK_PORT # Test a HIGH CBC cipher cph=`check_cipher -cipher AES256-SHA -connect $H0:$BRICK_PORT` diff --git a/tests/features/trash.t b/tests/features/trash.t index 472e909e567..da5b50bc85a 100755 --- a/tests/features/trash.t +++ b/tests/features/trash.t @@ -94,105 +94,105 @@ wildcard_not_exists() { if [ $? -eq 0 ]; then echo "Y"; else echo "N"; fi } -# testing glusterd [1-3] +# testing glusterd TEST glusterd TEST pidof glusterd TEST $CLI volume info -# creating distributed volume [4] +# creating distributed volume TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2} -# checking volume status [5-7] +# checking volume status EXPECT "$V0" volinfo_field $V0 'Volume Name' EXPECT 'Created' volinfo_field $V0 'Status' EXPECT '2' brick_count $V0 -# test without enabling trash translator [8] +# test without enabling trash translator TEST start_vol $V0 $M0 -# test on enabling trash translator [9-10] +# test on enabling trash translator TEST $CLI volume set $V0 features.trash on EXPECT 'on' volinfo_field $V0 'features.trash' -# files directly under mount point [11] +# files directly under mount point create_files $M0/file1 $M0/file2 TEST file_exists $V0 file1 file2 -# perform unlink [12] +# perform unlink TEST unlink_op file1 -# perform truncate [13] +# perform truncate TEST truncate_op file2 4 -# create files directory hierarchy and check [14] +# create files directory hierarchy and check mkdir -p $M0/1/2/3 create_files $M0/1/2/3/foo1 $M0/1/2/3/foo2 TEST file_exists $V0 1/2/3/foo1 1/2/3/foo2 -# perform unlink [15] +# perform unlink TEST unlink_op 1/2/3/foo1 -# perform truncate [16] +# perform truncate TEST truncate_op 1/2/3/foo2 4 # create a directory for eliminate pattern mkdir $M0/a -# set the eliminate pattern [17-18] +# set the eliminate pattern TEST $CLI volume set $V0 features.trash-eliminate-path /a EXPECT '/a' volinfo_field $V0 'features.trash-eliminate-path' -# create two files and check [19] +# create two files and check create_files $M0/a/test1 $M0/a/test2 TEST file_exists $V0 a/test1 a/test2 -# remove from eliminate pattern [20] +# remove from eliminate pattern rm -f $M0/a/test1 EXPECT "Y" wildcard_not_exists $M0/.trashcan/a/test1* -# truncate from eliminate path [21-23] +# truncate from eliminate path truncate -s 2 $M0/a/test2 TEST [ -e $M0/a/test2 ] TEST [ `ls -l $M0/a/test2 | awk '{print $5}'` -eq 2 ] EXPECT "Y" wildcard_not_exists $M0/.trashcan/a/test2* -# set internal op on [24-25] +# set internal op on TEST $CLI volume set $V0 features.trash-internal-op on EXPECT 'on' volinfo_field $V0 'features.trash-internal-op' -# again create two files and check [26] +# again create two files and check create_files $M0/inop1 $M0/inop2 TEST file_exists $V0 inop1 inop2 -# perform unlink [27] +# perform unlink TEST unlink_op inop1 -# perform truncate [28] +# perform truncate TEST truncate_op inop2 4 -# remove one brick and restart the volume [28-31] +# remove one brick and restart the volume TEST $CLI volume remove-brick $V0 $H0:$B0/${V0}2 force EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 TEST $CLI volume stop $V0 TEST start_vol $V0 $M0 $M0/.trashcan -# again create two files and check [33] +# again create two files and check create_files $M0/rebal1 $M0/rebal2 TEST file_exists $V0 rebal1 rebal2 -# add one brick [34-35] +# add one brick TEST $CLI volume add-brick $V0 $H0:$B0/${V0}3 TEST [ -d $B0/${V0}3 ] -# perform rebalance [36] +# perform rebalance TEST $CLI volume rebalance $V0 start force EXPECT_WITHIN $REBALANCE_TIMEOUT "0" rebalance_completed #Find out which file was migrated to the new brick file_name=$(ls $B0/${V0}3/rebal*| xargs basename) -# check whether rebalance was succesful [37-40] +# check whether rebalance was succesful EXPECT "Y" wildcard_exists $B0/${V0}3/$file_name* EXPECT "Y" wildcard_exists $B0/${V0}1/.trashcan/internal_op/$file_name* @@ -201,52 +201,42 @@ EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 # force required in case rebalance is not over TEST $CLI volume stop $V0 force -# create a replicated volume [41] +# create a replicated volume TEST $CLI volume create $V1 replica 2 $H0:$B0/${V1}{1,2} -# checking volume status [42-45] +# checking volume status EXPECT "$V1" volinfo_field $V1 'Volume Name' EXPECT 'Replicate' volinfo_field $V1 'Type' EXPECT 'Created' volinfo_field $V1 'Status' EXPECT '2' brick_count $V1 -# enable trash with options and start the replicate volume by disabling automatic self-heal [46-50] +# enable trash with options and start the replicate volume by disabling automatic self-heal TEST $CLI volume set $V1 features.trash on TEST $CLI volume set $V1 features.trash-internal-op on EXPECT 'on' volinfo_field $V1 'features.trash' EXPECT 'on' volinfo_field $V1 'features.trash-internal-op' TEST start_vol $V1 $M1 $M1/.trashcan -# mount and check for trash directory [51] +# mount and check for trash directory TEST [ -d $M1/.trashcan/internal_op ] -# create a file and check [52] +# create a file and check touch $M1/self TEST [ -e $B0/${V1}1/self -a -e $B0/${V1}2/self ] -# kill one brick and delete the file from mount point [53-54] +# kill one brick and delete the file from mount point kill_brick $V1 $H0 $B0/${V1}1 EXPECT_WITHIN ${PROCESS_UP_TIMEOUT} "1" online_brick_count rm -f $M1/self EXPECT "Y" wildcard_exists $B0/${V1}2/.trashcan/self* -# force start the volume and trigger the self-heal manually [55-57] -TEST $CLI volume start $V1 force -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" online_brick_count -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status -# Since we created the file under root of the volume, it will be -# healed automatically - -# check for the removed file in trashcan [58] -EXPECT_WITHIN $HEAL_TIMEOUT "Y" wildcard_exists $B0/${V1}1/.trashcan/internal_op/self* - -# check renaming of trash directory through cli [59-62] +# check renaming of trash directory through cli TEST $CLI volume set $V0 trash-dir abc TEST start_vol $V0 $M0 $M0/abc TEST [ -e $M0/abc -a ! -e $M0/.trashcan ] EXPECT "Y" wildcard_exists $B0/${V0}1/abc/internal_op/rebal* -# ensure that rename and delete operation on trash directory fails [63-65] +# ensure that rename and delete operation on trash directory fails rm -rf $M0/abc/internal_op TEST [ -e $M0/abc/internal_op ] rm -rf $M0/abc/ diff --git a/tests/features/worm.t b/tests/features/worm.t index 8b2574c8a47..40b08cdee02 100755 --- a/tests/features/worm.t +++ b/tests/features/worm.t @@ -72,11 +72,19 @@ sleep 10 TEST `echo "worm 1" >> $M0/file4` TEST ! rm -f $M0/file4 +## Test for state transition if auto-commit-period is 0 +TEST $CLI volume set $V0 features.auto-commit-period 0 +TEST `echo "worm 1" > $M0/file5` +EXPECT '3/10/0' echo $(getfattr -e text --absolute-names --only-value -n "trusted.reten_state" $B0/${V0}1/file5) +EXPECT 'worm 1' cat $M0/file5 +TEST ! rm -f $M0/file5 +TEST $CLI volume set $V0 features.auto-commit-period 5 + ## Test for checking if retention-period is updated on increasing the access time of a WORM-RETAINED file. TEST $CLI volume set $V0 features.worm-files-deletable 1 TEST `echo "worm 1" >> $M0/file1` initial_timestamp=$(date +%s) -current_time_seconds=$(date +%S); +current_time_seconds=$(date +%S | sed 's/^0*//' ); TEST chmod 0444 $M0/file1 EXPECT '3/10/5' echo $(getfattr -e text --absolute-names --only-value -n "trusted.reten_state" $B0/${V0}1/file1) changed_timestamp=$(date +%Y%m%d%H%M --date '60 seconds'); @@ -91,7 +99,7 @@ EXPECT "$initial_timestamp" echo $(stat --printf %X $M0/file1) ## Test for checking if retention-period is updated on decreasing the access time of a WORM-RETAINED file TEST $CLI volume set $V0 features.default-retention-period 120 initial_timestamp=$(date +%s) -current_time_seconds=$(date +%S); +current_time_seconds=$(date +%S | sed 's/^0*//' ); TEST chmod 0444 $M0/file1 EXPECT '3/120/5' echo $(getfattr -e text --absolute-names --only-value -n "trusted.reten_state" $B0/${V0}1/file1) changed_timestamp=$(date +%Y%m%d%H%M --date '60 seconds'); diff --git a/tests/geo-rep.rc b/tests/geo-rep.rc index 84c2c2251c0..9ba4262730e 100644 --- a/tests/geo-rep.rc +++ b/tests/geo-rep.rc @@ -1,4 +1,9 @@ GEO_REP_TIMEOUT=120 +CHECK_MOUNT_TIMEOUT=50 +#check for mount point +function check_mounted () { + df | grep $1 | wc -l +} function check_status_num_rows() { diff --git a/tests/glusterfind/glusterfind-basic.t b/tests/glusterfind/glusterfind-basic.t new file mode 100644 index 00000000000..ccb33fb1fc8 --- /dev/null +++ b/tests/glusterfind/glusterfind-basic.t @@ -0,0 +1,84 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../env.rc + +SCRIPT_TIMEOUT=300 + +##Cleanup and start glusterd +cleanup; +TEST glusterd; +TEST pidof glusterd + +##create .keys +mkdir -p /var/lib/glusterd/glusterfind/.keys + +#create_and_start test_volume +TEST $CLI volume create test-vol $H0:$B0/b1 $H0:$B0/b2 $H0:$B0/b3 +TEST gluster volume start test-vol + +##Mount test-vol +TEST glusterfs -s $H0 --volfile-id test-vol $M0 + +TEST timestamp1=$(date +'%s') + +##Create files and dirs inside the mount point +TEST mkdir -p $M0/dir1 +TEST touch $M0/file1 + +##Glusterfind Create +TEST glusterfind create sess_vol1 test-vol --force + +################################################################################## +#Incremental crawl +################################################################################## +##Glusterfind Pre +TEST glusterfind pre sess_vol1 test-vol output_file.txt + +#Glusterfind Post +TEST glusterfind post sess_vol1 test-vol + +##Glusterfind List +EXPECT '1' echo $(glusterfind list | grep sess_vol1 | wc -l) + +TEST timestamp2=$(date +'%s') + +##Glusterfind Query +TEST glusterfind query test-vol --since-time $timestamp1 --end-time $timestamp2 output_file.txt + +################################################################################# +#Full Crawl +################################################################################# +##Glusterfind Pre +TEST glusterfind pre sess_vol1 test-vol output_file.txt --full --regenerate-outfile +EXPECT '1' echo $(grep 'NEW dir1' output_file.txt | wc -l) +EXPECT '1' echo $(grep 'NEW file1' output_file.txt | wc -l) + +##Glusterfind Query commands +TEST glusterfind query test-vol --full output_file.txt +EXPECT '1' echo $(grep 'NEW dir1' output_file.txt | wc -l) +EXPECT '1' echo $(grep 'NEW file1' output_file.txt | wc -l) + +##using tag, full crawl +TEST glusterfind query test-vol --full --tag-for-full-find NEW output_file.txt +EXPECT '1' echo $(grep 'NEW dir1' output_file.txt | wc -l) +EXPECT '1' echo $(grep 'NEW file1' output_file.txt | wc -l) + +##using -field-separator option, full crawl +glusterfind query test-vol --full output_file.txt --field-separator "==" +EXPECT '1' echo $(grep 'NEW==dir1' output_file.txt | wc -l) +EXPECT '1' echo $(grep 'NEW==file1' output_file.txt | wc -l) + +##Adding or Replacing a Brick from an Existing Glusterfind Session +TEST gluster volume add-brick test-vol $H0:$B0/b4 force + +##To make existing session work after brick add +TEST glusterfind create sess_vol test-vol --force +EXPECT '1' echo $(glusterfind list | grep sess_vol1 | wc -l) + +##glusterfind delete +TEST glusterfind delete sess_vol test-vol + +rm -rf output_file.txt +cleanup; diff --git a/tests/line-coverage/cli-peer-and-volume-operations.t b/tests/line-coverage/cli-peer-and-volume-operations.t index a1545048773..0cf8dbe81f9 100644 --- a/tests/line-coverage/cli-peer-and-volume-operations.t +++ b/tests/line-coverage/cli-peer-and-volume-operations.t @@ -77,6 +77,46 @@ TEST ! $CLI_1 volume status $V0 shd #test explicitly provided options TEST $CLI_1 --timeout=120 --log-level=INFO volume status +#changing timezone to a different one, to check localtime logging feature +TEST export TZ='Asia/Kolkata' +TEST restart_glusterd 1 + +#localtime logging enable +TEST $CLI_1 volume set all cluster.localtime-logging enable +EXPECT '1' logging_time_check $LOGDIR + +#localtime logging disable +TEST $CLI_1 volume set all cluster.localtime-logging disable +EXPECT '0' logging_time_check $LOGDIR + +#changing timezone back to original timezone +TEST export TZ='UTC' + +#negative tests for volume options +#'set' option to enable quota/inode-quota is now depreciated +TEST ! $CLI_1 volume set $V0 quota enable +TEST ! $CLI_1 volume set $V0 inode-quota enable + +#invalid transport type 'rcp' +TEST ! $CLI_1 volume set $V0 config.transport rcp + +#'op-version' option is not valid for a single volume +TEST ! $CLI_1 volume set $V0 cluster.op-version 72000 + +#'op-version' option can't be used with any other option +TEST ! $CLI_1 volume set all cluster.localtime-logging disable cluster.op-version 72000 + +#invalid format of 'op-version' +TEST ! $CLI_1 volume set all cluster.op-version 72-000 + +#provided 'op-version' value is greater than max allowed op-version +op_version=$($CLI_1 volume get all cluster.max-op-version | awk 'NR==3 {print$2}') +op_version=$((op_version+1000)) #this can be any number greater than 0 +TEST ! $CLI_1 volume set all cluster.op-version $op_version + +#provided 'op-verison' value cannot be less than the current cluster op-version value +TEST ! $CLI_1 volume set all cluster.op-version 00000 + # system commnds TEST $CLI_1 system help TEST $CLI_1 system uuid get diff --git a/tests/line-coverage/log-and-brick-ops-negative-case.t b/tests/line-coverage/log-and-brick-ops-negative-case.t new file mode 100644 index 00000000000..d86cb452282 --- /dev/null +++ b/tests/line-coverage/log-and-brick-ops-negative-case.t @@ -0,0 +1,82 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup +TEST glusterd +TEST pidof glusterd + +#create volumes +TEST $CLI volume create ${V0}_1 $H0:$B0/v{1..2} + +TEST $CLI volume create ${V0}_2 replica 3 arbiter 1 $H0:$B0/v{3..5} + +TEST $CLI volume create ${V0}_3 disperse 3 redundancy 1 $H0:$B0/v{6..8} +TEST $CLI volume start ${V0}_3 +EXPECT 'Started' volinfo_field ${V0}_3 'Status' + +TEST $CLI volume create ${V0}_4 replica 3 $H0:$B0/v{9..14} +TEST $CLI volume start ${V0}_4 +EXPECT 'Started' volinfo_field ${V0}_4 'Status' + +#log rotate option +#provided volume does not exist +TEST ! $CLI volume log ${V0}_5 rotate + +#volume must be started before using log rotate option +TEST ! $CLI volume log ${V0}_1 rotate +TEST $CLI volume start ${V0}_1 +EXPECT 'Started' volinfo_field ${V0}_1 'Status' + +#incorrect brick provided for the volume +TEST ! $CLI volume log ${V0}_1 rotate $H0:$B0/v15 + +#add-brick operations +#volume must be in started to state to increase replica count +TEST ! $CLI volume add-brick ${V0}_2 replica 4 $H0:$B0/v15 +TEST $CLI volume start ${V0}_2 +EXPECT 'Started' volinfo_field ${V0}_2 'Status' + +#incorrect number of bricks for a replica 4 volume +TEST ! $CLI volume add-brick ${V0}_1 replica 4 $H0:$B0/v15 + +#replica count provided is less than the current replica count +TEST ! $CLI volume add-brick ${V0}_2 replica 2 $H0:$B0/v15 + +#dispersed to replicated dispersed not possible +TEST ! $CLI volume add-brick ${V0}_3 replica 2 $H0:$B0/v15 + +#remove-brick operations +#replica count option provided for dispersed vol +TEST ! $CLI volume remove-brick ${V0}_3 replica 2 $H0:$B0/v8 start + +#given replica count is greater than the current replica count +TEST ! $CLI volume remove-brick ${V0}_2 replica 4 $H0:$B0/v5 start + +#number of bricks to be removed, must be a multiple of replica count +TEST ! $CLI volume remove-brick ${V0}_2 replica 3 $H0:$B0/v{3..4} start + +#less number of bricks given to reduce the replica count +TEST ! $CLI volume remove-brick ${V0}_2 replica 1 $H0:$B0/v3 start + +#bricks should be from different subvol +TEST ! $CLI volume remove-brick ${V0}_4 replica 2 $H0:$B0/v{13..14} start + +#arbiter must be removed to reduce replica count +TEST ! $CLI volume remove-brick ${V0}_2 replica 1 $H0:$B0/v{3..4} start + +#removal of bricks is not allowed without reducing the replica count explicitly +TEST ! $CLI volume remove-brick ${V0}_2 replica 3 $H0:$B0/v{3..5} start + +#incorrect brick for given vol +TEST ! $CLI volume remove-brick ${V0}_1 $H0:$B0/v15 start + +#removing all the bricks are not allowed +TEST ! $CLI volume remove-brick ${V0}_1 $H0:$B0/v{1..2} start + +#volume must not be stopped state while removing bricks +TEST $CLI volume stop ${V0}_1 +TEST ! $CLI volume remove-brick ${V0}_1 $H0:$B0/v1 start + +cleanup
\ No newline at end of file diff --git a/tests/volume.rc b/tests/volume.rc index 288d491de39..b38848c0e52 100644 --- a/tests/volume.rc +++ b/tests/volume.rc @@ -193,7 +193,7 @@ function afr_child_up_status_meta { local mnt=$1 local repl=$2 local child=$3 - grep "child_up\[$child\]" $mnt/.meta/graphs/active/$repl/private | awk '{print $3}' + grep -E "^child_up\[$child\]" $mnt/.meta/graphs/active/$repl/private | awk '{print $3}' } function client_connected_status_meta { @@ -992,3 +992,11 @@ function get-xml() { $CLI $1 --xml | xmllint --format - | grep $2 | sed 's/\(<"$2">\|<\/"$2">\)//g' } + +function logging_time_check() +{ + local logdir=$1 + local logfile=`echo ${0##*/}`_glusterd1.log + + cat $logdir/1/$logfile | tail -n 2 | head -n 1 | grep $(date +%H:%M) | wc -l +} |