diff options
Diffstat (limited to 'tests/basic')
277 files changed, 20183 insertions, 5182 deletions
diff --git a/tests/basic/afr/add-brick-self-heal.t b/tests/basic/afr/add-brick-self-heal.t index 748d36758e7..c847e22977f 100644 --- a/tests/basic/afr/add-brick-self-heal.t +++ b/tests/basic/afr/add-brick-self-heal.t @@ -6,13 +6,19 @@ cleanup; TEST glusterd TEST pidof glusterd TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1} +EXPECT 'Created' volinfo_field $V0 'Status'; TEST $CLI volume start $V0 +EXPECT 'Started' volinfo_field $V0 'Status'; +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 + TEST $CLI volume set $V0 cluster.data-self-heal off TEST $CLI volume set $V0 cluster.metadata-self-heal off TEST $CLI volume set $V0 cluster.entry-self-heal off +TEST $CLI volume set $V0 cluster.heal-timeout 5 TEST $CLI volume set $V0 self-heal-daemon off -TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0; +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; # Create files for i in {1..5} @@ -25,6 +31,7 @@ TEST setfattr -n user.test -v qwerty $M0/file5.txt # Add brick1 TEST $CLI volume add-brick $V0 replica 3 $H0:$B0/${V0}2 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}2 # New-brick should accuse the old-bricks (Simulating case for data-loss) TEST setfattr -n trusted.afr.$V0-client-0 -v 0x000000000000000000000001 $B0/${V0}2/ 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/afr-no-fsync.t b/tests/basic/afr/afr-no-fsync.t new file mode 100644 index 00000000000..0966d9b0a11 --- /dev/null +++ b/tests/basic/afr/afr-no-fsync.t @@ -0,0 +1,20 @@ +#!/bin/bash +#Tests that sequential write workload doesn't lead to FSYNCs + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/brick{0,1,3} +TEST $CLI volume set $V0 features.shard on +TEST $CLI volume set $V0 performance.flush-behind off +TEST $CLI volume start $V0 +TEST $CLI volume profile $V0 start +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +TEST dd if=/dev/zero of=$M0/a bs=1M count=500 +TEST ! "$CLI volume profile $V0 info incremental | grep FSYNC" + +cleanup; diff --git a/tests/basic/afr/afr-read-hash-mode.t b/tests/basic/afr/afr-read-hash-mode.t new file mode 100644 index 00000000000..eeff10d8ebd --- /dev/null +++ b/tests/basic/afr/afr-read-hash-mode.t @@ -0,0 +1,56 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup + +function reads_brick_count { + $CLI volume profile $V0 info incremental | grep -w READ | wc -l +} + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 arbiter 1 $H0:$B0/${V0}{0..2} + +TEST $CLI volume set $V0 cluster.choose-local off +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 start $V0 + +# Disable all caching +TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0 +TEST dd if=/dev/urandom of=$M0/FILE bs=1M count=8 +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +# TEST if the option gives the intended behavior. The way we perform this test +# is by performing reads from the mount and write to /dev/null. If the +# read-hash-mode is 3, then for a given file, more than 1 brick should serve the +# read-fops where as with the default read-hash-mode (i.e. 1), only 1 brick will. + +# read-hash-mode=1 +TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0 +EXPECT "1" mount_get_option_value $M0 $V0-replicate-0 read-hash-mode +TEST $CLI volume profile $V0 start +TEST dd if=$M0/FILE of=/dev/null bs=1M +count=`reads_brick_count` +TEST [ $count -eq 1 ] +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +# read-hash-mode=3 +TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0 +TEST $CLI volume set $V0 cluster.read-hash-mode 3 +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "3" mount_get_option_value $M0 $V0-replicate-0 read-hash-mode +TEST $CLI volume profile $V0 info clear +TEST dd if=$M0/FILE of=/dev/null bs=1M +count=`reads_brick_count` +TEST [ $count -eq 2 ] + +# Check that the arbiter did not serve any reads +arbiter_reads=$($CLI volume top $V0 read brick $H0:$B0/${V0}2|grep FILE|awk '{print $1}') +TEST [ -z $arbiter_reads ] + +cleanup; diff --git a/tests/basic/afr/afr-seek.t b/tests/basic/afr/afr-seek.t new file mode 100644 index 00000000000..c12ee011660 --- /dev/null +++ b/tests/basic/afr/afr-seek.t @@ -0,0 +1,55 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup + +SEEK=$(dirname $0)/seek +build_tester $(dirname $0)/../seek.c -o ${SEEK} + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info + +TEST mkdir -p $B0/${V0}{0..2} +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0..2} + +TEST $CLI volume start $V0 + +TEST $GFS -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2 + +TEST ${SEEK} create ${M0}/test 0 1 1048576 1 +# Determine underlying filesystem allocation block size +BSIZE="$(($(${SEEK} scan ${M0}/test hole 0) * 2))" + +TEST ${SEEK} create ${M0}/test 0 ${BSIZE} $((${BSIZE} * 4 + 512)) ${BSIZE} + +EXPECT "^0$" ${SEEK} scan ${M0}/test data 0 +EXPECT "^$((${BSIZE} / 2))$" ${SEEK} scan ${M0}/test data $((${BSIZE} / 2)) +EXPECT "^$((${BSIZE} - 1))$" ${SEEK} scan ${M0}/test data $((${BSIZE} - 1)) +EXPECT "^$((${BSIZE} * 4))$" ${SEEK} scan ${M0}/test data ${BSIZE} +EXPECT "^$((${BSIZE} * 4))$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 4)) +EXPECT "^$((${BSIZE} * 5))$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 5)) +EXPECT "^$((${BSIZE} * 5 + 511))$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 5 + 511)) +EXPECT "^ENXIO$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 5 + 512)) +EXPECT "^ENXIO$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 6)) + +EXPECT "^${BSIZE}$" ${SEEK} scan ${M0}/test hole 0 +EXPECT "^${BSIZE}$" ${SEEK} scan ${M0}/test hole $((${BSIZE} / 2)) +EXPECT "^${BSIZE}$" ${SEEK} scan ${M0}/test hole $((${BSIZE} - 1)) +EXPECT "^${BSIZE}$" ${SEEK} scan ${M0}/test hole ${BSIZE} +EXPECT "^$((${BSIZE} * 5 + 512))$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 4)) +EXPECT "^$((${BSIZE} * 5 + 512))$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 5)) +EXPECT "^$((${BSIZE} * 5 + 512))$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 5 + 511)) +EXPECT "^ENXIO$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 5 + 512)) +EXPECT "^ENXIO$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 6)) + +rm -f ${SEEK} +cleanup + +# Centos6 regression slaves seem to not support SEEK_DATA/SEEK_HOLE +#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=000000 diff --git a/tests/basic/afr/afr-up.t b/tests/basic/afr/afr-up.t new file mode 100644 index 00000000000..428aac875e0 --- /dev/null +++ b/tests/basic/afr/afr-up.t @@ -0,0 +1,28 @@ +#!/bin/bash +#Tests that afr up/down works as expected + +. $(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,1,3,4,5,6} +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +EXPECT "1" afr_up_status $V0 $M0 0 +EXPECT "1" afr_up_status $V0 $M0 1 + +#kill two bricks in first replica and check that afr_up_status is 0 for it +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}1 + +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "0" afr_up_status $V0 $M0 0 +EXPECT "1" afr_up_status $V0 $M0 1 + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_up_status $V0 $M0 0 +EXPECT "1" afr_up_status $V0 $M0 1 +cleanup; diff --git a/tests/basic/afr/arbiter-add-brick.t b/tests/basic/afr/arbiter-add-brick.t index 357f59b0852..77b93d9a210 100644 --- a/tests/basic/afr/arbiter-add-brick.t +++ b/tests/basic/afr/arbiter-add-brick.t @@ -10,7 +10,10 @@ TEST pidof glusterd TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1} TEST $CLI volume set $V0 performance.stat-prefetch off TEST $CLI volume start $V0 -TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0; +TEST $CLI volume set $V0 self-heal-daemon off +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 TEST mkdir $M0/dir1 TEST dd if=/dev/urandom of=$M0/file1 bs=1024 count=1 @@ -20,21 +23,38 @@ TEST mkdir $M0/dir2 TEST dd if=/dev/urandom of=$M0/file1 bs=1024 count=1024 +#convert replica 2 to arbiter volume +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 + #syntax check for add-brick. TEST ! $CLI volume add-brick $V0 replica 2 arbiter 1 $H0:$B0/${V0}2 TEST ! $CLI volume add-brick $V0 replica 3 arbiter 2 $H0:$B0/${V0}2 -#convert replica 2 to arbiter volume TEST $CLI volume add-brick $V0 replica 3 arbiter 1 $H0:$B0/${V0}2 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}2 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2 + +#Trigger name heals from client. If we just rely on index heal, the first index +#crawl on B0 fails for /, dir2 and /file either due to lock collision or files +#not being present on the other 2 bricks yet. It is getting healed only in the +#next crawl after priv->shd.timeout (600 seconds) or by manually launching +#index heal again. +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 stat $M0/dir1 +TEST stat $M0/dir2 +TEST stat $M0/file1 #Heal files -TEST $CLI volume start $V0 force -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 +TEST $CLI volume set $V0 self-heal-daemon on EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0 EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1 EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 2 +TEST $CLI volume heal $V0 EXPECT_WITHIN $HEAL_TIMEOUT "0" get_pending_heal_count $V0 #Perform I/O after add-brick @@ -56,5 +76,11 @@ EXPECT "1048576" stat -c %s $M0/file2 EXPECT "0" stat -c %s $B0/${V0}2/file1 EXPECT "0" stat -c %s $B0/${V0}2/file2 +#Increasing replica count of arbiter volumes must not be allowed. +TEST ! $CLI volume add-brick $V0 replica 4 $H0:$B0/${V0}3 +TEST ! $CLI volume add-brick $V0 replica 4 arbiter 1 $H0:$B0/${V0}3 + +#Adding another distribute leg should succeed. +TEST $CLI volume add-brick $V0 replica 3 arbiter 1 $H0:$B0/${V0}{3..5} TEST force_umount $M0 cleanup; diff --git a/tests/basic/afr/arbiter-cli.t b/tests/basic/afr/arbiter-cli.t index 2806b5a376b..ad79de79d02 100644 --- a/tests/basic/afr/arbiter-cli.t +++ b/tests/basic/afr/arbiter-cli.t @@ -16,10 +16,15 @@ TEST ! $CLI volume create $V0 arbiter 3 $H0:$B0/${V0}{0,1,2} # replica count given after arbiter count. TEST ! $CLI volume create $V0 arbiter 1 replica 3 $H0:$B0/${V0}{0,1,2} -#Incorrect values for replica and arbiter count. -TEST ! $CLI volume create $V0 replica 2 arbiter 1 $H0:$B0/${V0}{0,1,2} +# Incorrect values for replica and arbiter count. TEST ! $CLI volume create $V0 replica 3 arbiter 2 $H0:$B0/${V0}{0,1,2} -# Only permissible value is replica=3 and arbiter=1. -TEST $CLI volume create $V0 replica 3 arbiter 1 $H0:$B0/${V0}{0,1,2} +# Correct setup +# Only documented value is replica=2 and arbiter=1. +TEST $CLI volume create $V0 replica 2 arbiter 1 $H0:$B0/${V0}{0,1,2} + +# Earlier documents mentioned 'replica 3 arbiter 1' as the valid option +# Preserve backward compatibility till Oct, 2019. +TEST $CLI volume create ${V0}-old replica 3 arbiter 1 $H0:$B0/${V0}-old{0,1,2} + cleanup diff --git a/tests/basic/afr/arbiter-mount.t b/tests/basic/afr/arbiter-mount.t index 587e808863f..404d334d2f9 100644 --- a/tests/basic/afr/arbiter-mount.t +++ b/tests/basic/afr/arbiter-mount.t @@ -4,6 +4,9 @@ . $(dirname $0)/../../volume.rc . $(dirname $0)/../../afr.rc . $(dirname $0)/../../nfs.rc + +#G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST + cleanup; #Check that mounting fails when only arbiter brick is up. @@ -22,7 +25,7 @@ TEST kill_brick $V0 $H0 $B0/${V0}1 # Doing `mount -t glusterfs $H0:$V0 $M0` fails right away but doesn't work on NetBSD # So check that stat <mount> fails instead. -TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 TEST ! stat $M0 EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 @@ -34,7 +37,7 @@ EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "1" is_nfs_export_available; -TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 TEST stat $M0 EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 diff --git a/tests/basic/afr/arbiter-remove-brick.t b/tests/basic/afr/arbiter-remove-brick.t index 5a6daa95cfd..ec93c8758e4 100644 --- a/tests/basic/afr/arbiter-remove-brick.t +++ b/tests/basic/afr/arbiter-remove-brick.t @@ -11,7 +11,7 @@ TEST $CLI volume create $V0 replica 3 arbiter 1 $H0:$B0/${V0}{0,1,2} EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks" TEST $CLI volume set $V0 performance.stat-prefetch off TEST $CLI volume start $V0 -TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0; +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; #syntax check for remove-brick. TEST ! $CLI volume remove-brick $V0 replica 2 $H0:$B0/${V0}0 force diff --git a/tests/basic/afr/arbiter-statfs.t b/tests/basic/afr/arbiter-statfs.t index 7d136378f11..61cb9e1d04f 100644 --- a/tests/basic/afr/arbiter-statfs.t +++ b/tests/basic/afr/arbiter-statfs.t @@ -29,7 +29,7 @@ TEST MOUNT_LOOP $LO3 $B0/${V0}3 TEST $CLI volume create $V0 replica 3 arbiter 1 $H0:$B0/${V0}{1,2,3}; TEST $CLI volume start $V0 -TEST glusterfs --volfile-server=$H0 --volfile-id=$V0 $M0 +TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0 free_space=$(df -P $M0 | tail -1 | awk '{ print $4}') TEST [ $free_space -gt 100000 ] TEST force_umount $M0 diff --git a/tests/basic/afr/arbiter.t b/tests/basic/afr/arbiter.t index 1abc940b095..7c92a9fe6c9 100644 --- a/tests/basic/afr/arbiter.t +++ b/tests/basic/afr/arbiter.t @@ -16,7 +16,7 @@ EXPECT 'Started' volinfo_field $V0 'Status' EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}2 -TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; TEST ! stat $M0/.meta/graphs/active/$V0-replicate-0/options/arbiter-count EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 TEST $CLI volume stop $V0 @@ -42,7 +42,7 @@ EXPECT 'Started' volinfo_field $V0 'Status' EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}2 -TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --attribute-timeout=0 --entry-timeout=0 $M0; +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; TEST stat $M0/.meta/graphs/active/$V0-replicate-0/options/arbiter-count EXPECT "1" cat $M0/.meta/graphs/active/$V0-replicate-0/options/arbiter-count diff --git a/tests/basic/afr/client-side-heal.t b/tests/basic/afr/client-side-heal.t index d87f4b14063..1e9336184b5 100644..100755 --- a/tests/basic/afr/client-side-heal.t +++ b/tests/basic/afr/client-side-heal.t @@ -13,10 +13,11 @@ TEST $CLI volume set $V0 cluster.data-self-heal off TEST $CLI volume set $V0 cluster.metadata-self-heal off TEST $CLI volume start $V0 -TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; echo "some data" > $M0/datafile EXPECT 0 echo $? TEST touch $M0/mdatafile +TEST touch $M0/mdatafile-backend-direct-modify TEST mkdir $M0/dir #Kill a brick and perform I/O to have pending heals. @@ -29,6 +30,7 @@ EXPECT 0 echo $? #pending metadata heal TEST chmod +x $M0/mdatafile +TEST chmod +x $B0/${V0}0/mdatafile-backend-direct-modify #pending entry heal. Also causes pending metadata/data heals on file{1..5} TEST touch $M0/dir/file{1..5} @@ -40,19 +42,21 @@ TEST $CLI volume start $V0 force EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 #Medatada heal via explicit lookup must not happen -TEST ls $M0/mdatafile +TEST getfattr -d -m. -e hex $M0/mdatafile +TEST ls $M0/mdatafile-backend-direct-modify -#Inode refresh must not trigger data and entry heals. +TEST [[ "$(stat -c %A $B0/${V0}0/mdatafile-backend-direct-modify)" != "$(stat -c %A $B0/${V0}1/mdatafile-backend-direct-modify)" ]] + +#Inode refresh must not trigger data metadata and entry heals. #To trigger inode refresh for sure, the volume is unmounted and mounted each time. #Check that data heal does not happen. EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 -TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; TEST cat $M0/datafile #Check that entry heal does not happen. EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 -TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; TEST ls $M0/dir - #No heal must have happened EXPECT 8 get_pending_heal_count $V0 @@ -61,21 +65,25 @@ 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 -#Metadata heal is triggered by lookup without need for inode refresh. -TEST ls $M0/mdatafile -EXPECT 7 get_pending_heal_count $V0 - -#Inode refresh must trigger data and entry heals. +#Inode refresh must trigger data metadata and entry heals. #To trigger inode refresh for sure, the volume is unmounted and mounted each time. EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 -TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +TEST ls $M0/mdatafile-backend-direct-modify + +TEST [[ "$(stat -c %A $B0/${V0}0/mdatafile-backend-direct-modify)" == "$(stat -c %A $B0/${V0}1/mdatafile-backend-direct-modify)" ]] + + +TEST getfattr -d -m. -e hex $M0/mdatafile +EXPECT_WITHIN $HEAL_TIMEOUT 7 get_pending_heal_count $V0 + TEST cat $M0/datafile EXPECT_WITHIN $HEAL_TIMEOUT 6 get_pending_heal_count $V0 EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 -TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; TEST ls $M0/dir -EXPECT 5 get_pending_heal_count $V0 +EXPECT_WITHIN $HEAL_TIMEOUT 5 get_pending_heal_count $V0 TEST cat $M0/dir/file1 TEST cat $M0/dir/file2 @@ -83,5 +91,5 @@ TEST cat $M0/dir/file3 TEST cat $M0/dir/file4 TEST cat $M0/dir/file5 -EXPECT 0 get_pending_heal_count $V0 +EXPECT_WITHIN $HEAL_TIMEOUT 0 get_pending_heal_count $V0 cleanup; diff --git a/tests/basic/afr/data-self-heal.t b/tests/basic/afr/data-self-heal.t index 5db5d770b6f..0f417b4a0ba 100644 --- a/tests/basic/afr/data-self-heal.t +++ b/tests/basic/afr/data-self-heal.t @@ -77,7 +77,7 @@ TEST $CLI volume start $V0 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 glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0 --entry-timeout=0 --attribute-timeout=0; +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; cd $M0 TEST touch pending-changelog biggest-file-source.txt biggest-file-more-prio-than-changelog.txt same-size-more-prio-to-changelog.txt size-and-witness-same.txt self-accusing-vs-source.txt self-accusing-both.txt self-accusing-vs-innocent.txt self-accusing-bigger-exists.txt size-more-prio-than-self-accused.txt v1-dirty.txt split-brain.txt split-brain-all-dirty.txt split-brain-with-dirty.txt 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/entry-self-heal.t b/tests/basic/afr/entry-self-heal.t index 337b9c59f84..0c1da7d211e 100644 --- a/tests/basic/afr/entry-self-heal.t +++ b/tests/basic/afr/entry-self-heal.t @@ -79,9 +79,12 @@ 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 glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 --use-readdirp=no +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 diff --git a/tests/basic/afr/gfid-heal.t b/tests/basic/afr/gfid-heal.t index fa13c469b24..5e26e3307eb 100644 --- a/tests/basic/afr/gfid-heal.t +++ b/tests/basic/afr/gfid-heal.t @@ -8,7 +8,7 @@ cleanup; function get_gfid_count { - getfattr -d -m. -e hex $B0/brick{0,1,2,3,4,5}/$1 2>&1 | grep trusted.gfid | wc -l + getfattr -d -m. -e hex $B0/brick{0,1,2,3,4,5}/$1 2>&1 | grep trusted.gfid | grep -v gfid2path | wc -l } TEST glusterd diff --git a/tests/basic/afr/gfid-mismatch-resolution-with-cli.t b/tests/basic/afr/gfid-mismatch-resolution-with-cli.t new file mode 100644 index 00000000000..b739ddc49cc --- /dev/null +++ b/tests/basic/afr/gfid-mismatch-resolution-with-cli.t @@ -0,0 +1,168 @@ +#!/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/${V0}{0,1} +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 +TEST $CLI volume set $V0 self-heal-daemon off +TEST $CLI volume set $V0 cluster.entry-self-heal off +TEST $CLI volume set $V0 cluster.metadata-self-heal off +TEST $CLI volume set $V0 cluster.data-self-heal off +cd $M0 + +##### Healing from latest mtime ###### + +TEST kill_brick $V0 $H0 $B0/${V0}0 +echo "Sink based on mtime" > f1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +echo "Source based on mtime" > f1 + +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/f1) +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/f1) +TEST [ "$gfid_0" != "$gfid_1" ] + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1 + +#We know that first brick has the latest mtime +LATEST_MTIME_MD5=$(md5sum $B0/${V0}0/f1 | awk '{print $1}') + +TEST $CLI volume heal $V0 split-brain latest-mtime /f1 + +#gfid split-brain should be resolved +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/f1) +TEST [ "$gfid_0" == "$gfid_1" ] + +#Heal the data and check the md5sum +TEST $CLI volume set $V0 self-heal-daemon on +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1 +TEST $CLI volume heal $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 +HEALED_MD5=$(md5sum $B0/${V0}1/f1 | awk '{print $1}') +TEST [ "$LATEST_MTIME_MD5" == "$HEALED_MD5" ] + + +##### Healing from bigger file ###### + +TEST mkdir test +TEST $CLI volume set $V0 self-heal-daemon off +TEST kill_brick $V0 $H0 $B0/${V0}0 +echo "Bigger file" > test/f2 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +echo "Small file" > test/f2 + +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/test/f2) +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/test/f2) +TEST [ "$gfid_0" != "$gfid_1" ] + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1 + +#We know that second brick has the bigger file +BIGGER_FILE_MD5=$(md5sum $B0/${V0}1/test/f2 | awk '{print $1}') + +TEST $CLI volume heal $V0 split-brain bigger-file /test/f2 + +#gfid split-brain should be resolved +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/test/f2) +TEST [ "$gfid_0" == "$gfid_1" ] + +#Heal the data and check the md5sum +TEST $CLI volume set $V0 self-heal-daemon on +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1 +TEST $CLI volume heal $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 +HEALED_MD5=$(md5sum $B0/${V0}0/test/f2 | awk '{print $1}') +TEST [ "$BIGGER_FILE_MD5" == "$HEALED_MD5" ] + + +#Add one more brick, and heal. +TEST $CLI volume add-brick $V0 replica 3 $H0:$B0/${V0}2 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 +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 0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 2 +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 + + +##### Healing from source brick ###### + +TEST $CLI volume set $V0 self-heal-daemon off +TEST $CLI volume set $V0 cluster.quorum-type none +TEST kill_brick $V0 $H0 $B0/${V0}0 +echo "We will consider these as sinks" > test/f3 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST kill_brick $V0 $H0 $B0/${V0}2 +echo "We will take this as source" > test/f3 + +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/test/f3) +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/test/f3) +gfid_2=$(gf_get_gfid_xattr $B0/${V0}2/test/f3) +TEST [ "$gfid_0" != "$gfid_1" ] +TEST [ "$gfid_1" == "$gfid_2" ] + +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" brick_up_status $V0 $H0 $B0/${V0}2 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 2 + +#We will try to heal the split-brain with bigger file option. +#It should fail, since we have same file size in bricks 1 & 2. +EXPECT "No bigger file for file /test/f3" $CLI volume heal $V0 split-brain bigger-file /test/f3 + +#Now heal from taking the brick 0 as the source +SOURCE_MD5=$(md5sum $B0/${V0}0/test/f3 | awk '{print $1}') + +TEST $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}0 /test/f3 + +#gfid split-brain should be resolved +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/test/f3) +gfid_2=$(gf_get_gfid_xattr $B0/${V0}2/test/f3) +TEST [ "$gfid_0" == "$gfid_1" ] +TEST [ "$gfid_0" == "$gfid_2" ] + +#Heal the data and check the md5sum +TEST $CLI volume set $V0 self-heal-daemon on +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 2 +TEST $CLI volume heal $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 +HEALED_MD5_1=$(md5sum $B0/${V0}1/test/f3 | awk '{print $1}') +HEALED_MD5_2=$(md5sum $B0/${V0}2/test/f3 | awk '{print $1}') +TEST [ "$SOURCE_MD5" == "$HEALED_MD5_1" ] +TEST [ "$SOURCE_MD5" == "$HEALED_MD5_2" ] + +cd - +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 new file mode 100644 index 00000000000..35e295dc170 --- /dev/null +++ b/tests/basic/afr/gfid-mismatch-resolution-with-fav-child-policy.t @@ -0,0 +1,229 @@ +#!/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/${V0}{0,1} +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 +TEST $CLI volume set $V0 cluster.heal-timeout 5 +TEST $CLI volume set $V0 self-heal-daemon off +TEST $CLI volume set $V0 cluster.data-self-heal off +TEST $CLI volume set $V0 cluster.metadata-self-heal off +TEST $CLI volume set $V0 cluster.entry-self-heal off + +##### Healing with favorite-child-policy = mtime ###### +##### and self-heal-daemon ###### + +TEST $CLI volume set $V0 favorite-child-policy mtime +TEST kill_brick $V0 $H0 $B0/${V0}0 +echo "Sink based on mtime" > $M0/f1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +echo "Source based on mtime" > $M0/f1 + +#Gfids of file f1 on bricks 0 & 1 should differ +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/f1) +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/f1) +TEST [ "$gfid_0" != "$gfid_1" ] + +TEST $CLI volume set $V0 self-heal-daemon on +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1 + +#We know that first brick has the latest mtime +LATEST_MTIME_MD5=$(md5sum $B0/${V0}0/f1 | cut -d\ -f1) + +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 + +#gfid split-brain should be resolved +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/f1) +TEST [ "$gfid_0" == "$gfid_1" ] + +HEALED_MD5=$(md5sum $B0/${V0}1/f1 | cut -d\ -f1) +TEST [ "$LATEST_MTIME_MD5" == "$HEALED_MD5" ] + +TEST $CLI volume set $V0 self-heal-daemon off + + +##### Healing with favorite-child-policy = ctime ###### +##### and self-heal-daemon ###### + +#gfid split-brain resolution should work even when the granular-enrty-heal is +#enabled +TEST $CLI volume heal $V0 granular-entry-heal enable + +TEST $CLI volume set $V0 favorite-child-policy ctime +TEST kill_brick $V0 $H0 $B0/${V0}1 +echo "Sink based on ctime" > $M0/f2 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1 +TEST kill_brick $V0 $H0 $B0/${V0}0 +echo "Source based on ctime" > $M0/f2 + +#Gfids of file f2 on bricks 0 & 1 should differ +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/f2) +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/f2) +TEST [ "$gfid_0" != "$gfid_1" ] + +TEST $CLI volume set $V0 self-heal-daemon on +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0 + +#We know that second brick has the latest ctime +LATEST_CTIME_MD5=$(md5sum $B0/${V0}1/f2 | cut -d\ -f1) + +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 + +#gfid split-brain should be resolved +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/f2) +TEST [ "$gfid_0" == "$gfid_1" ] + +HEALED_MD5=$(md5sum $B0/${V0}0/f2 | cut -d\ -f1) +TEST [ "$LATEST_CTIME_MD5" == "$HEALED_MD5" ] + + +#Add one more brick, and heal. +TEST $CLI volume add-brick $V0 replica 3 $H0:$B0/${V0}2 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 +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 0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 2 +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 + +TEST $CLI volume set $V0 self-heal-daemon off + + +##### Healing using favorite-child-policy = size ##### +##### and client side heal ##### + +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 + +#Set the quorum-type to none, and create a gfid split brain +TEST $CLI volume set $V0 cluster.quorum-type none +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +echo "Smallest file" > $M0/f3 + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1 +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST kill_brick $V0 $H0 $B0/${V0}2 +echo "Second smallest file" > $M0/f3 + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1 +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 kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}2 +echo "Biggest among the three files" > $M0/f3 + +#Bring back the down bricks. +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0 +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 + +#Gfids of file f3 on all the bricks should differ +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/f3) +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/f3) +gfid_2=$(gf_get_gfid_xattr $B0/${V0}2/f3) +TEST [ "$gfid_0" != "$gfid_1" ] +TEST [ "$gfid_0" != "$gfid_2" ] +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 #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 +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/f3) +gfid_2=$(gf_get_gfid_xattr $B0/${V0}2/f3) +TEST [ "$gfid_0" == "$gfid_1" ] +TEST [ "$gfid_2" == "$gfid_1" ] + +HEALED_MD5_1=$(md5sum $B0/${V0}0/f3 | cut -d\ -f1) +HEALED_MD5_2=$(md5sum $B0/${V0}2/f3 | cut -d\ -f1) +TEST [ "$BIGGER_FILE_MD5" == "$HEALED_MD5_1" ] +TEST [ "$BIGGER_FILE_MD5" == "$HEALED_MD5_2" ] + + +##### Healing using favorite-child-policy = majority ##### +##### and client side heal ##### + +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +echo "Does not agree with bricks 0 & 1" > $M0/f4 + +TEST $CLI v start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1 +TEST kill_brick $V0 $H0 $B0/${V0}2 +echo "Agree on bricks 0 & 1" > $M0/f4 + +#Gfids of file f4 on bricks 0 & 1 should be same and bricks 0 & 2 should differ +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/f4) +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/f4) +gfid_2=$(gf_get_gfid_xattr $B0/${V0}2/f4) +TEST [ "$gfid_0" == "$gfid_1" ] +TEST [ "$gfid_0" != "$gfid_2" ] + +#We know that first and second bricks agree with each other. Pick any one of +#them as source +MAJORITY_MD5=$(md5sum $B0/${V0}0/f4 | cut -d\ -f1) + +#Bring back the down brick and heal. +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 #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 +gfid_2=$(gf_get_gfid_xattr $B0/${V0}2/f4) +TEST [ "$gfid_0" == "$gfid_2" ] + +HEALED_MD5=$(md5sum $B0/${V0}2/f4 | cut -d\ -f1) +TEST [ "$MAJORITY_MD5" == "$HEALED_MD5" ] + +cleanup; diff --git a/tests/basic/afr/gfid-mismatch.t b/tests/basic/afr/gfid-mismatch.t index c3399215569..fc15793cf5a 100644 --- a/tests/basic/afr/gfid-mismatch.t +++ b/tests/basic/afr/gfid-mismatch.t @@ -13,6 +13,10 @@ TEST $CLI volume set $V0 self-heal-daemon off TEST $CLI volume set $V0 stat-prefetch off TEST $CLI volume start $V0 TEST $CLI volume set $V0 cluster.background-self-heal-count 0 +# We can't count on brick0 getting a copy of the file immediately without this, +# because (especially with multiplexing) it might not have *come up* +# immediately. +TEST $CLI volume set $V0 cluster.quorum-type auto TEST $GFS --volfile-id=$V0 -s $H0 $M0; #Test diff --git a/tests/basic/afr/gfid-self-heal.t b/tests/basic/afr/gfid-self-heal.t index 0bc53de8a6f..5a530681186 100644 --- a/tests/basic/afr/gfid-self-heal.t +++ b/tests/basic/afr/gfid-self-heal.t @@ -15,7 +15,7 @@ TEST $CLI volume set $V0 nfs.disable on TEST touch $B0/${V0}{0,1}/{1,2,3,4} TEST $CLI volume start $V0 -TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 #Test that readdir returns entries even when no gfids are present EXPECT 4 echo $(ls $M0 | grep -v '^\.' | wc -l) sleep 2; @@ -50,6 +50,10 @@ TEST kill_brick $V0 $H0 $B0/${V0}0 TEST touch $M0/a gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/a) TEST touch $B0/${V0}0/a +# storage/posix considers that a file without gfid changed less than a second +# before doesn't exist, so we need to wait for a second to force posix to +# consider that this is a valid file but without gfid. +sleep 1 $CLI volume start $V0 force EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 TEST stat $M0/a @@ -62,6 +66,10 @@ TEST kill_brick $V0 $H0 $B0/${V0}0 TEST touch $M0/b TEST mkdir $B0/${V0}0/b TEST setfattr -x trusted.afr.$V0-client-0 $B0/${V0}1 +# storage/posix considers that a file without gfid changed less than a second +# before doesn't exist, so we need to wait for a second to force posix to +# consider that this is a valid file but without gfid. +sleep 1 $CLI volume start $V0 force EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 TEST ! stat $M0/b @@ -71,6 +79,10 @@ TEST "[[ -z \"$gfid_0\" ]]" #Check gfid assigning doesn't happen when there is type mismatch TEST touch $B0/${V0}1/c TEST mkdir $B0/${V0}0/c +# storage/posix considers that a file without gfid changed less than a second +# before doesn't exist, so we need to wait for a second to force posix to +# consider that this is a valid file but without gfid. +sleep 1 TEST ! stat $M0/c gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/c) gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/c) @@ -81,6 +93,10 @@ TEST "[[ -z \"$gfid_0\" ]]" # gfid split-brain TEST kill_brick $V0 $H0 $B0/${V0}0 TEST touch $B0/${V0}1/d +# storage/posix considers that a file without gfid changed less than a second +# before doesn't exist, so we need to wait for a second to force posix to +# consider that this is a valid file but without gfid. +sleep 1 TEST ! stat $M0/d gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/d) TEST "[[ -z \"$gfid_1\" ]]" diff --git a/tests/basic/afr/granular-esh/cli.t b/tests/basic/afr/granular-esh/cli.t index a655180a095..10b6c6398da 100644 --- a/tests/basic/afr/granular-esh/cli.t +++ b/tests/basic/afr/granular-esh/cli.t @@ -11,7 +11,7 @@ TESTS_EXPECTED_IN_LOOP=4 TEST glusterd TEST pidof glusterd -TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1} +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2} # Test that enabling the option should work on a newly created volume TEST $CLI volume set $V0 cluster.granular-entry-heal on TEST $CLI volume set $V0 cluster.granular-entry-heal off @@ -25,34 +25,6 @@ TEST $CLI volume start $V1 TEST ! $CLI volume heal $V1 granular-entry-heal enable TEST ! $CLI volume heal $V1 granular-entry-heal disable -####################### -###### TIER TEST ###### -####################### -# Execute the same command on a disperse + replicate tiered volume and make -# sure the option is set on the replicate leg of the volume -TEST $CLI volume attach-tier $V1 replica 2 $H0:$B0/${V1}{3,4} -TEST $CLI volume heal $V1 granular-entry-heal enable -EXPECT "enable" volume_get_field $V1 cluster.granular-entry-heal -TEST $CLI volume heal $V1 granular-entry-heal disable -EXPECT "disable" volume_get_field $V1 cluster.granular-entry-heal - -# Kill a disperse brick and make heal be pending on the volume. -TEST kill_brick $V1 $H0 $B0/${V1}0 - -# Now make sure that one offline brick in disperse does not affect enabling the -# option on the volume. -TEST $CLI volume heal $V1 granular-entry-heal enable -EXPECT "enable" volume_get_field $V1 cluster.granular-entry-heal -TEST $CLI volume heal $V1 granular-entry-heal disable -EXPECT "disable" volume_get_field $V1 cluster.granular-entry-heal - -# Now kill a replicate brick. -TEST kill_brick $V1 $H0 $B0/${V1}3 -# Now make sure that one offline brick in replicate causes the command to be -# failed. -TEST ! $CLI volume heal $V1 granular-entry-heal enable -EXPECT "disable" volume_get_field $V1 cluster.granular-entry-heal - ###################### ### REPLICATE TEST ### ###################### @@ -136,7 +108,7 @@ TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$ROOT_GFID TEST $CLI volume reset $V0 # Ensure that granular entry heal is also disabled EXPECT "no" volume_get_field $V0 cluster.granular-entry-heal -EXPECT "on" volume_get_field $V0 cluster.entry-self-heal +EXPECT "off" volume_get_field $V0 cluster.entry-self-heal cleanup #G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=1399038 diff --git a/tests/basic/afr/granular-esh/replace-brick.t b/tests/basic/afr/granular-esh/replace-brick.t index 639ed81b95c..5fc7811a8d8 100644 --- a/tests/basic/afr/granular-esh/replace-brick.t +++ b/tests/basic/afr/granular-esh/replace-brick.t @@ -12,6 +12,7 @@ TEST $CLI volume set $V0 cluster.data-self-heal off TEST $CLI volume set $V0 cluster.metadata-self-heal off TEST $CLI volume set $V0 cluster.entry-self-heal off TEST $CLI volume set $V0 self-heal-daemon off +TEST $CLI volume set $V0 cluster.heal-timeout 5 TEST $CLI volume heal $V0 granular-entry-heal enable TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0; 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/heal-quota.t b/tests/basic/afr/heal-quota.t index 2663906f9d5..96e23363da8 100644 --- a/tests/basic/afr/heal-quota.t +++ b/tests/basic/afr/heal-quota.t @@ -13,7 +13,7 @@ TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1} TEST $CLI volume set $V0 cluster.self-heal-daemon off TEST $CLI volume start $V0 -TEST glusterfs --attribute-timeout=0 --entry-timeout=0 --volfile-id=/$V0 --volfile-server=$H0 $M0; +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; TEST $CLI volume quota $V0 enable TEST $CLI volume quota $V0 limit-usage / 10MB TEST $CLI volume quota $V0 soft-timeout 0 diff --git a/tests/basic/afr/inodelk.t b/tests/basic/afr/inodelk.t new file mode 100644 index 00000000000..a32aa8531b5 --- /dev/null +++ b/tests/basic/afr/inodelk.t @@ -0,0 +1,87 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +cleanup; + +#This test tests that inodelk fails when quorum is not met. Also tests the +#success case where inodelk is obtained and unlocks are done correctly. + +TEST glusterd; +TEST pidof glusterd + +TEST $CLI volume create $V0 replica 3 arbiter 1 $H0:$B0/${V0}{0..5} +TEST $CLI volume start $V0 +TEST $GFS -s $H0 --volfile-id=$V0 $M0 + +#Test success case +TEST mkdir $M0/dir1 +TEST mv $M0/dir1 $M0/dir2 + +#If there is a problem with inodelk unlocking the following would hang. +TEST mv $M0/dir2 $M0/dir1 + +#Test failure case by bringing two of the bricks down +#Test that the directory is not moved partially on some bricks but successful +#on other subvol where quorum meets. Do that for both set of bricks + +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST ! mv $M0/dir1 $M0/dir2 + +TEST stat $B0/${V0}0/dir1 +TEST stat $B0/${V0}1/dir1 +TEST stat $B0/${V0}2/dir1 +TEST stat $B0/${V0}3/dir1 +TEST stat $B0/${V0}4/dir1 +TEST stat $B0/${V0}5/dir1 +TEST ! stat $B0/${V0}0/dir2 +TEST ! stat $B0/${V0}1/dir2 +TEST ! stat $B0/${V0}2/dir2 +TEST ! stat $B0/${V0}3/dir2 +TEST ! stat $B0/${V0}4/dir2 +TEST ! stat $B0/${V0}5/dir2 + +TEST $CLI volume start $V0 force +TEST kill_brick $V0 $H0 $B0/${V0}3 +TEST kill_brick $V0 $H0 $B0/${V0}4 +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 ! mv $M0/dir1 $M0/dir2 +TEST stat $B0/${V0}0/dir1 +TEST stat $B0/${V0}1/dir1 +TEST stat $B0/${V0}2/dir1 +TEST stat $B0/${V0}3/dir1 +TEST stat $B0/${V0}4/dir1 +TEST stat $B0/${V0}5/dir1 +TEST ! stat $B0/${V0}0/dir2 +TEST ! stat $B0/${V0}1/dir2 +TEST ! stat $B0/${V0}2/dir2 +TEST ! stat $B0/${V0}3/dir2 +TEST ! stat $B0/${V0}4/dir2 +TEST ! stat $B0/${V0}5/dir2 + +#Bring the bricks back up and try mv once more, it should succeed. +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 3 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 4 +TEST mv $M0/dir1 $M0/dir2 +cleanup; +#Do similar tests on replica 2 +TEST glusterd; +TEST pidof glusterd +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0..3} +TEST $CLI volume start $V0 +TEST $GFS -s $H0 --volfile-id=$V0 $M0 +TEST mkdir $M0/dir1 +TEST mv $M0/dir1 $M0/dir2 +#Because we don't know hashed subvol, do the same test twice bringing 1 brick +#from each down, quorum calculation should allow it. +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST mv $M0/dir2 $M0/dir1 +TEST $CLI volume start $V0 force +TEST kill_brick $V0 $H0 $B0/${V0}2 +TEST mv $M0/dir1 $M0/dir2 +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST mv $M0/dir2 $M0/dir1 +cleanup diff --git a/tests/basic/afr/lk-quorum.t b/tests/basic/afr/lk-quorum.t new file mode 100644 index 00000000000..3364d8a6a1b --- /dev/null +++ b/tests/basic/afr/lk-quorum.t @@ -0,0 +1,257 @@ +#!/bin/bash + +SCRIPT_TIMEOUT=300 + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../fileio.rc +cleanup; + +TEST glusterd; +TEST pidof glusterd + +#Tests for quorum-type option for replica 2 +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1}; +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.open-behind off +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume set $V0 performance.read-ahead off +TEST $CLI volume start $V0 +TEST $GFS -s $H0 --volfile-id=$V0 --direct-io-mode=enable $M0; + +TEST touch $M0/a + +#When all bricks are up, lock and unlock should succeed +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST flock -x $fd1 +TEST fd_close $fd1 + +#When all bricks are down, lock/unlock should fail +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST $CLI volume stop $V0 +TEST ! flock -x $fd1 +TEST $CLI volume start $V0 +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 fd_close $fd1 + +#Check locking behavior with quorum 'fixed' and quorum-count 2 +TEST $CLI volume set $V0 cluster.quorum-type fixed +TEST $CLI volume set $V0 cluster.quorum-count 2 +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "^fixed$" mount_get_option_value $M0 $V0-replicate-0 quorum-type +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "^2$" mount_get_option_value $M0 $V0-replicate-0 quorum-count + +#When all bricks are up, lock and unlock should succeed +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST flock -x $fd1 +TEST fd_close $fd1 + +#When all bricks are down, lock/unlock should fail +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST $CLI volume stop $V0 +TEST ! flock -x $fd1 +TEST $CLI volume start $V0 +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 fd_close $fd1 + +#When any of the bricks is down lock/unlock should fail +#kill first brick +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST ! flock -x $fd1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST fd_close $fd1 + +#kill 2nd brick +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST ! flock -x $fd1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 +TEST fd_close $fd1 + +#Check locking behavior with quorum 'fixed' and quorum-count 1 +TEST $CLI volume set $V0 cluster.quorum-count 1 +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "^1$" mount_get_option_value $M0 $V0-replicate-0 quorum-count + +#When all bricks are up, lock and unlock should succeed +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST flock -x $fd1 +TEST fd_close $fd1 + +#When all bricks are down, lock/unlock should fail +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST $CLI volume stop $V0 +TEST ! flock -x $fd1 +TEST $CLI volume start $V0 +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 fd_close $fd1 + +#When any of the bricks is down lock/unlock should succeed +#kill first brick +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST flock -x $fd1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST fd_close $fd1 + +#kill 2nd brick +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST flock -x $fd1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 +TEST fd_close $fd1 + +#Check locking behavior with quorum 'auto' +TEST $CLI volume set $V0 cluster.quorum-type auto +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "^auto$" mount_get_option_value $M0 $V0-replicate-0 quorum-type + +#When all bricks are up, lock and unlock should succeed +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST flock -x $fd1 +TEST fd_close $fd1 + +#When all bricks are down, lock/unlock should fail +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST $CLI volume stop $V0 +TEST ! flock -x $fd1 +TEST $CLI volume start $V0 +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 fd_close $fd1 + +#When first brick is down lock/unlock should fail +#kill first brick +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST ! flock -x $fd1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST fd_close $fd1 + +#When second brick is down lock/unlock should succeed +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST flock -x $fd1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 +TEST fd_close $fd1 + +cleanup; +TEST glusterd; +TEST pidof glusterd + +#Tests for replica 3 +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,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.open-behind off +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume set $V0 performance.read-ahead off +TEST $CLI volume start $V0 +TEST $GFS -s $H0 --volfile-id=$V0 --direct-io-mode=enable $M0; + +TEST touch $M0/a + +#When all bricks are up, lock and unlock should succeed +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST flock -x $fd1 +TEST fd_close $fd1 + +#When all bricks are down, lock/unlock should fail +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST $CLI volume stop $V0 +TEST ! flock -x $fd1 +TEST $CLI volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2 +TEST fd_close $fd1 + +#When any of the bricks is down lock/unlock should succeed +#kill first brick +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST flock -x $fd1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST fd_close $fd1 + +#kill 2nd brick +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST flock -x $fd1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 +TEST fd_close $fd1 + +#kill 3rd brick +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST kill_brick $V0 $H0 $B0/${V0}2 +TEST flock -x $fd1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2 +TEST fd_close $fd1 + +#When any two of the bricks are down lock/unlock should fail +#kill first,second bricks +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST ! flock -x $fd1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 +TEST fd_close $fd1 + +#kill 2nd,3rd bricks +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST kill_brick $V0 $H0 $B0/${V0}2 +TEST ! flock -x $fd1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2 +TEST fd_close $fd1 + +#kill 1st,3rd brick +TEST fd1=`fd_available` +TEST fd_open $fd1 'w' $M0/a +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}2 +TEST ! flock -x $fd1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST fd_close $fd1 + +cleanup diff --git a/tests/basic/afr/metadata-self-heal.t b/tests/basic/afr/metadata-self-heal.t index b88c16a93e1..275aecd2175 100644 --- a/tests/basic/afr/metadata-self-heal.t +++ b/tests/basic/afr/metadata-self-heal.t @@ -51,7 +51,7 @@ TEST glusterd TEST pidof glusterd TEST $CLI volume create $V0 replica 2 $H0:$B0/brick{0,1} TEST $CLI volume start $V0 -TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 cd $M0 TEST touch a diff --git a/tests/basic/afr/name-self-heal.t b/tests/basic/afr/name-self-heal.t new file mode 100644 index 00000000000..50fc2ecc6c2 --- /dev/null +++ b/tests/basic/afr/name-self-heal.t @@ -0,0 +1,112 @@ +#!/bin/bash +#Self-heal tests + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../afr.rc +cleanup; + +#Check that when quorum is not enabled name-heal happens correctly +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 2 $H0:$B0/brick{0,1} +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume start $V0 +TEST $CLI volume heal $V0 disable +TEST $CLI volume set $V0 cluster.entry-self-heal off +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; + +TEST touch $M0/a +TEST touch $M0/c +TEST kill_brick $V0 $H0 $B0/brick0 +TEST touch $M0/b +TEST rm -f $M0/a +TEST rm -f $M0/c +TEST touch $M0/c #gfid mismatch case +c_gfid=$(gf_get_gfid_xattr $B0/brick1/c) +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST ! stat $M0/a +TEST ! stat $B0/brick0/a +TEST ! stat $B0/brick1/a + +TEST stat $M0/b +TEST stat $B0/brick0/b +TEST stat $B0/brick1/b +TEST [[ "$(gf_get_gfid_xattr $B0/brick0/b)" == "$(gf_get_gfid_xattr $B0/brick1/b)" ]] + +TEST stat $M0/c +TEST stat $B0/brick0/c +TEST stat $B0/brick1/c +TEST [[ "$(gf_get_gfid_xattr $B0/brick0/c)" == "$c_gfid" ]] + +cleanup; + +#Check that when quorum is enabled name-heal happens as expected +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/brick{0,1,2} +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume start $V0 +TEST $CLI volume heal $V0 disable +TEST $CLI volume set $V0 cluster.entry-self-heal off +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; + +TEST touch $M0/a +TEST touch $M0/c +TEST kill_brick $V0 $H0 $B0/brick0 +TEST touch $M0/b +TEST rm -f $M0/a +TEST rm -f $M0/c +TEST touch $M0/c #gfid mismatch case +c_gfid=$(gf_get_gfid_xattr $B0/brick1/c) +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST ! stat $M0/a +TEST ! stat $B0/brick0/a +TEST ! stat $B0/brick1/a +TEST ! stat $B0/brick2/a + +TEST stat $M0/b +TEST ! stat $B0/brick0/b #Name heal shouldn't be triggered +TEST stat $B0/brick1/b +TEST stat $B0/brick2/b + +TEST stat $M0/c +TEST stat $B0/brick0/c +TEST stat $B0/brick1/c +TEST stat $B0/brick2/c +TEST [[ "$(gf_get_gfid_xattr $B0/brick0/c)" == "$c_gfid" ]] + +TEST $CLI volume set $V0 cluster.quorum-type none +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "none" get_quorum_type $M0 $V0 0 +TEST stat $M0/b +TEST stat $B0/brick0/b #Name heal should be triggered +TEST stat $B0/brick1/b +TEST stat $B0/brick2/b +TEST [[ "$(gf_get_gfid_xattr $B0/brick0/b)" == "$(gf_get_gfid_xattr $B0/brick1/b)" ]] +TEST $CLI volume set $V0 cluster.quorum-type auto +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "auto" get_quorum_type $M0 $V0 0 + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +#Missing parent xattrs cases +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 +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 + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +TEST $CLI volume heal $V0 disable +#In cases where a good parent doesn't have pending xattrs and a file, +#name-heal will be triggered +TEST gf_rm_file_and_gfid_link $B0/brick1 c +TEST stat $M0/c +TEST stat $B0/brick0/c +TEST stat $B0/brick1/c +TEST stat $B0/brick2/c +TEST [[ "$(gf_get_gfid_xattr $B0/brick0/c)" == "$c_gfid" ]] +cleanup diff --git a/tests/basic/afr/quorum.t b/tests/basic/afr/quorum.t index c105290445a..58116ba49f5 100644 --- a/tests/basic/afr/quorum.t +++ b/tests/basic/afr/quorum.t @@ -19,7 +19,7 @@ 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 start $V0 -TEST $GFS -s $H0 --volfile-id=$V0 $M0 --direct-io-mode=enable; +TEST $GFS -s $H0 --volfile-id=$V0 --direct-io-mode=enable $M0; touch $M0/a echo abc > $M0/b @@ -31,11 +31,7 @@ TEST $CLI volume set $V0 cluster.quorum-count 2 TEST test_write TEST kill_brick $V0 $H0 $B0/${V0}1 TEST ! test_write -EXPECT "abc" cat $M0/b -TEST $CLI volume set $V0 cluster.quorum-reads on -EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "1" mount_get_option_value $M0 $V0-replicate-0 quorum-reads TEST ! cat $M0/b -TEST $CLI volume reset $V0 cluster.quorum-reads TEST $CLI volume set $V0 cluster.quorum-type auto EXPECT auto volume_option $V0 cluster.quorum-type @@ -44,11 +40,7 @@ EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 TEST test_write TEST kill_brick $V0 $H0 $B0/${V0}1 TEST ! test_write -EXPECT "abc" cat $M0/b -TEST $CLI volume set $V0 cluster.quorum-reads on -EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "1" mount_get_option_value $M0 $V0-replicate-0 quorum-reads TEST ! cat $M0/b -TEST $CLI volume reset $V0 cluster.quorum-reads TEST $CLI volume set $V0 cluster.quorum-type none EXPECT none volume_option $V0 cluster.quorum-type @@ -57,11 +49,6 @@ TEST test_write TEST $CLI volume reset $V0 cluster.quorum-type TEST test_write EXPECT "abc" cat $M0/b -TEST $CLI volume set $V0 cluster.quorum-reads on -EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "1" mount_get_option_value $M0 $V0-replicate-0 quorum-reads -EXPECT "abc" cat $M0/b -TEST $CLI volume reset $V0 cluster.quorum-reads - cleanup; TEST glusterd; @@ -75,7 +62,7 @@ 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 start $V0 -TEST $GFS -s $H0 --volfile-id=$V0 $M0 --direct-io-mode=enable; +TEST $GFS -s $H0 --volfile-id=$V0 --direct-io-mode=enable $M0; touch $M0/a echo abc > $M0/b @@ -86,24 +73,14 @@ TEST $CLI volume set $V0 cluster.quorum-count 3 TEST test_write TEST kill_brick $V0 $H0 $B0/${V0}1 TEST ! test_write -EXPECT "abc" cat $M0/b -TEST $CLI volume set $V0 cluster.quorum-reads on -EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "1" mount_get_option_value $M0 $V0-replicate-0 quorum-reads TEST ! cat $M0/b -TEST $CLI volume reset $V0 cluster.quorum-reads - TEST $CLI volume set $V0 cluster.quorum-type auto EXPECT auto volume_option $V0 cluster.quorum-type TEST test_write TEST kill_brick $V0 $H0 $B0/${V0}3 TEST ! test_write -EXPECT "abc" cat $M0/b -TEST $CLI volume set $V0 cluster.quorum-reads on -EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "1" mount_get_option_value $M0 $V0-replicate-0 quorum-reads TEST ! cat $M0/b -TEST $CLI volume reset $V0 cluster.quorum-reads - TEST $CLI volume set $V0 cluster.quorum-type none EXPECT none volume_option $V0 cluster.quorum-type 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/replace-brick-self-heal.t b/tests/basic/afr/replace-brick-self-heal.t index fef671a3875..0360db71a2f 100644 --- a/tests/basic/afr/replace-brick-self-heal.t +++ b/tests/basic/afr/replace-brick-self-heal.t @@ -10,9 +10,9 @@ TEST $CLI volume start $V0 TEST $CLI volume set $V0 cluster.data-self-heal off TEST $CLI volume set $V0 cluster.metadata-self-heal off TEST $CLI volume set $V0 cluster.entry-self-heal off - +TEST $CLI volume set $V0 cluster.heal-timeout 5 TEST $CLI volume set $V0 self-heal-daemon off -TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0; +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; # Create files for i in {1..5} diff --git a/tests/basic/afr/resolve.t b/tests/basic/afr/resolve.t index 2d400563c2e..a741eee6e5e 100644 --- a/tests/basic/afr/resolve.t +++ b/tests/basic/afr/resolve.t @@ -23,6 +23,10 @@ echo abc > g TEST kill_brick $V0 $H0 $B0/${V0}0 rm -rf $B0/${V0}0/.glusterfs $B0/${V0}0/a +#Ideally, disk replacement is done using reset-brick or replace-brick gluster CLI +#which will create .glusterfs folder. +mkdir $B0/${V0}0/.glusterfs && chmod 600 $B0/${V0}0/.glusterfs + TEST $CLI volume start $V0 force EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_meta $M0 $V0-replicate-0 0 #Test that the lookup returns ENOENT instead of ESTALE diff --git a/tests/basic/afr/root-squash-self-heal.t b/tests/basic/afr/root-squash-self-heal.t index ff0aa5cecb7..6e12098465a 100644 --- a/tests/basic/afr/root-squash-self-heal.t +++ b/tests/basic/afr/root-squash-self-heal.t @@ -11,8 +11,11 @@ TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1} TEST $CLI volume set $V0 performance.stat-prefetch off TEST $CLI volume set $V0 self-heal-daemon off TEST $CLI volume set $V0 server.root-squash on +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 glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 --no-root-squash=yes --use-readdirp=no +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 --no-root-squash=yes --use-readdirp=no $M0 TEST kill_brick $V0 $H0 $B0/${V0}0 echo abc > $M0/a diff --git a/tests/basic/afr/self-heal.t b/tests/basic/afr/self-heal.t index e1ac17c2d79..10fb152d046 100644 --- a/tests/basic/afr/self-heal.t +++ b/tests/basic/afr/self-heal.t @@ -10,8 +10,6 @@ AREQUAL_PATH=$(dirname $0)/../../utils AREQUAL_BIN=$AREQUAL_PATH/arequal-checksum CFLAGS="" test "`uname -s`" != "Linux" && { - CFLAGS="$CFLAGS -I$(dirname $0)/../../../contrib/argp-standalone "; - CFLAGS="$CFLAGS -L$(dirname $0)/../../../contrib/argp-standalone -largp "; CFLAGS="$CFLAGS -lintl"; } build_tester $AREQUAL_PATH/arequal-checksum.c $CFLAGS diff --git a/tests/basic/afr/self-heald.t b/tests/basic/afr/self-heald.t index af657c66fb3..24c82777921 100644 --- a/tests/basic/afr/self-heald.t +++ b/tests/basic/afr/self-heald.t @@ -50,7 +50,7 @@ TEST $CLI volume set $V0 cluster.background-self-heal-count 0 TEST $CLI volume set $V0 cluster.eager-lock off TEST $CLI volume set $V0 performance.flush-behind off TEST $CLI volume start $V0 -TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 decide_kill=$((`date +"%j"|sed 's/^0*//'` % 2 )) @@ -93,7 +93,7 @@ TEST ! $CLI volume heal $V0 TEST ! $CLI volume heal $V0 full TEST $CLI volume start $V0 force TEST $CLI volume set $V0 cluster.self-heal-daemon on -EXPECT_WITHIN 20 "Y" glustershd_up_status +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status check_bricks_up $V0 @@ -103,7 +103,7 @@ sleep 5 #Until the heal-statistics command implementation TEST [ $HEAL_FILES -gt $(get_pending_heal_count $V0) ] TEST $CLI volume heal $V0 full -EXPECT_WITHIN 30 "0" get_pending_heal_count $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 #Test that ongoing IO is not considered as Pending heal (dd if=/dev/zero of=$M0/file1 bs=1k 2>/dev/null 1>/dev/null)& @@ -135,11 +135,11 @@ kill_multiple_bricks $V0 $H0 $B0 echo abc > $M0/f EXPECT 1 get_pending_heal_count $V0 TEST $CLI volume start $V0 force -EXPECT_WITHIN 20 "Y" glustershd_up_status +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status check_bricks_up $V0 TEST $CLI volume heal $V0 -EXPECT_WITHIN 30 "0" get_pending_heal_count $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 TEST $CLI volume set $V0 cluster.data-self-heal on #METADATA @@ -150,11 +150,11 @@ kill_multiple_bricks $V0 $H0 $B0 TEST chmod 777 $M0/f EXPECT 1 get_pending_heal_count $V0 TEST $CLI volume start $V0 force -EXPECT_WITHIN 20 "Y" glustershd_up_status +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status check_bricks_up $V0 TEST $CLI volume heal $V0 -EXPECT_WITHIN 30 "0" get_pending_heal_count $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 TEST $CLI volume set $V0 cluster.metadata-self-heal on #ENTRY @@ -167,10 +167,10 @@ TEST touch $M0/d/a PENDING=$( get_pending_heal_count $V0 ) TEST test $PENDING -eq 2 -o $PENDING -eq 4 TEST $CLI volume start $V0 force -EXPECT_WITHIN 20 "Y" glustershd_up_status +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status check_bricks_up $V0 TEST $CLI volume heal $V0 -EXPECT_WITHIN 30 "0" get_pending_heal_count $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 TEST $CLI volume set $V0 cluster.entry-self-heal on #Negative test cases 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/afr/split-brain-favorite-child-policy.t b/tests/basic/afr/split-brain-favorite-child-policy.t deleted file mode 100644 index 3df8e718bf0..00000000000 --- a/tests/basic/afr/split-brain-favorite-child-policy.t +++ /dev/null @@ -1,202 +0,0 @@ -#!/bin/bash - -#Test the split-brain resolution CLI commands. -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc - -cleanup; - -TEST glusterd -TEST pidof glusterd - -#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 set $V0 cluster.self-heal-daemon off -TEST $CLI volume set $V0 cluster.entry-self-heal off -TEST $CLI volume set $V0 cluster.data-self-heal off -TEST $CLI volume set $V0 cluster.metadata-self-heal off -TEST $CLI volume start $V0 -TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 -TEST touch $M0/file - -############ Healing using favorite-child-policy = ctime ################# -TEST kill_brick $V0 $H0 $B0/${V0}0 -TEST dd if=/dev/urandom of=$M0/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/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 -TEST $CLI volume set $V0 cluster.self-heal-daemon on -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0 -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1 -TEST $CLI volume heal $V0 - -#file fill in split-brain -cat $M0/file > /dev/null -EXPECT "1" echo $? - -# Umount to prevent further FOPS on the file, then find the brick with latest ctime. -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 -ctime1=`stat -c "%.Z" $B0/${V0}0/file` -ctime2=`stat -c "%.Z" $B0/${V0}1/file` -if (( $(echo "$ctime1 > $ctime2" | bc -l) )); then - LATEST_CTIME_MD5=$(md5sum $B0/${V0}0/file | cut -d\ -f1) -else - LATEST_CTIME_MD5=$(md5sum $B0/${V0}1/file | cut -d\ -f1) -fi -TEST $CLI volume set $V0 cluster.favorite-child-policy ctime -TEST $CLI volume start $V0 force -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 -B0_MD5=$(md5sum $B0/${V0}0/file | cut -d\ -f1) -B1_MD5=$(md5sum $B0/${V0}1/file | cut -d\ -f1) -TEST [ "$LATEST_CTIME_MD5" == "$B0_MD5" ] -TEST [ "$LATEST_CTIME_MD5" == "$B1_MD5" ] -TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 -cat $M0/file > /dev/null -EXPECT "0" echo $? - -############ Healing using favorite-child-policy = mtime ################# -TEST $CLI volume set $V0 cluster.favorite-child-policy none -TEST $CLI volume set $V0 cluster.self-heal-daemon off -TEST kill_brick $V0 $H0 $B0/${V0}1 -TEST dd if=/dev/urandom of=$M0/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 -TEST kill_brick $V0 $H0 $B0/${V0}0 -TEST dd if=/dev/urandom of=$M0/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 $CLI volume set $V0 cluster.self-heal-daemon on -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0 -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1 -TEST $CLI volume heal $V0 - -#file still in split-brain -cat $M0/file > /dev/null -EXPECT "1" echo $? - -#We know that the second brick has latest mtime. -LATEST_CTIME_MD5=$(md5sum $B0/${V0}1/file | cut -d\ -f1) -TEST $CLI volume set $V0 cluster.favorite-child-policy mtime -TEST $CLI volume start $V0 force -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 -cat $M0/file > /dev/null -EXPECT "0" echo $? -HEALED_MD5=$(md5sum $B0/${V0}0/file | cut -d\ -f1) -TEST [ "$LATEST_CTIME_MD5" == "$HEALED_MD5" ] - -############ Healing using favorite-child-policy = size ################# -TEST $CLI volume set $V0 cluster.favorite-child-policy none -TEST $CLI volume set $V0 cluster.self-heal-daemon off -TEST kill_brick $V0 $H0 $B0/${V0}1 -TEST dd if=/dev/urandom of=$M0/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 -TEST kill_brick $V0 $H0 $B0/${V0}0 -TEST dd if=/dev/urandom of=$M0/file bs=1024 count=10240 - -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 $CLI volume set $V0 cluster.self-heal-daemon on -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0 -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1 -TEST $CLI volume heal $V0 - -#file fill in split-brain -cat $M0/file > /dev/null -EXPECT "1" echo $? - -#We know that the second brick has the bigger size file. -BIGGER_FILE_MD5=$(md5sum $B0/${V0}1/file | cut -d\ -f1) -TEST $CLI volume set $V0 cluster.favorite-child-policy size -TEST $CLI volume start $V0 force -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 -cat $M0/file > /dev/null -EXPECT "0" echo $? -HEALED_MD5=$(md5sum $B0/${V0}0/file | cut -d\ -f1) -TEST [ "$BIGGER_FILE_MD5" == "$HEALED_MD5" ] - -############ Healing using favorite-child-policy = majority on replica-3 ################# - -#Convert volume to replica-3 -TEST $CLI volume add-brick $V0 replica 3 $H0:$B0/${V0}2 -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}2 -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2 -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0 -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1 -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 2 -TEST $CLI volume heal $V0 -EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 - -TEST $CLI volume set $V0 cluster.quorum-type none -TEST $CLI volume set $V0 cluster.favorite-child-policy none -TEST $CLI volume set $V0 cluster.self-heal-daemon off -TEST kill_brick $V0 $H0 $B0/${V0}0 -TEST dd if=/dev/urandom of=$M0/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 kill_brick $V0 $H0 $B0/${V0}2 -TEST dd if=/dev/urandom of=$M0/file bs=1024 count=10240 - -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" brick_up_status $V0 $H0 $B0/${V0}2 -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2 -TEST $CLI volume set $V0 cluster.self-heal-daemon on -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0 -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1 -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 2 -TEST $CLI volume heal $V0 - -#file fill in split-brain -cat $M0/file > /dev/null -EXPECT "1" echo $? - -#We know that the second and third bricks agree with each other. Pick any one of them. -MAJORITY_MD5=$(md5sum $B0/${V0}1/file | cut -d\ -f1) -TEST $CLI volume set $V0 cluster.favorite-child-policy majority -TEST $CLI volume start $V0 force -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0 -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1 -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 2 -TEST $CLI volume heal $V0 -EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 -cat $M0/file > /dev/null -EXPECT "0" echo $? -HEALED_MD5=$(md5sum $B0/${V0}0/file | cut -d\ -f1) -TEST [ "$MAJORITY_MD5" == "$HEALED_MD5" ] - -TEST force_umount $M0 -cleanup diff --git a/tests/basic/afr/split-brain-heal-info.t b/tests/basic/afr/split-brain-heal-info.t index eabfbd0880a..2e4742fff08 100644 --- a/tests/basic/afr/split-brain-heal-info.t +++ b/tests/basic/afr/split-brain-heal-info.t @@ -20,7 +20,7 @@ TEST pidof glusterd TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1} TEST $CLI volume start $V0 TEST $CLI volume set $V0 cluster.self-heal-daemon off -TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 TEST mkdir $M0/dspb TEST mkdir $M0/mspb @@ -47,9 +47,11 @@ SPB_FILES=$(($SPB_FILES + 1)) #### Simulate entry-split-brain TEST kill_brick $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN ${PROCESS_DOWN_TIMEOUT} "^0$" afr_child_up_status $V0 0 TEST touch $M0/espb/a volume_start_force $V0 TEST kill_brick $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN ${PROCESS_DOWN_TIMEOUT} "^0$" afr_child_up_status $V0 1 TEST mkdir $M0/espb/a volume_start_force $V0 SPB_FILES=$(($SPB_FILES + 1)) diff --git a/tests/basic/afr/split-brain-healing-ctime.t b/tests/basic/afr/split-brain-healing-ctime.t new file mode 100644 index 00000000000..676788fce3f --- /dev/null +++ b/tests/basic/afr/split-brain-healing-ctime.t @@ -0,0 +1,252 @@ +#!/bin/bash + +#Test the split-brain resolution CLI commands. +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +function get_replicate_subvol_number { + local filename=$1 + #get_backend_paths + if [ -f $B0/${V0}1/$filename ] + then + echo 0 + elif [ -f $B0/${V0}3/$filename ] + then echo 1 + else + echo -1 + fi +} + +cleanup; + +AREQUAL_PATH=$(dirname $0)/../../utils +GET_MDATA_PATH=$(dirname $0)/../../utils +CFLAGS="" +test "`uname -s`" != "Linux" && { + CFLAGS="$CFLAGS -lintl"; +} +build_tester $AREQUAL_PATH/arequal-checksum.c $CFLAGS +build_tester $GET_MDATA_PATH/get-mdata-xattr.c + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{1,2,3,4} +TEST $CLI volume set $V0 cluster.self-heal-daemon off +TEST $CLI volume set $V0 cluster.data-self-heal off +TEST $CLI volume set $V0 cluster.metadata-self-heal off +TEST $CLI volume set $V0 cluster.entry-self-heal off +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 + +cd $M0 +for i in {1..10} +do + echo "Initial content">>file$i +done + +replica_0_files_list=(`ls $B0/${V0}1|grep -v '^\.'`) +replica_1_files_list=(`ls $B0/${V0}3|grep -v '^\.'`) + +############ Create data split-brain in the files. ########################### +TEST kill_brick $V0 $H0 $B0/${V0}1 +for file in ${!replica_0_files_list[*]} +do + echo "B1 is down">>${replica_0_files_list[$file]} +done +TEST kill_brick $V0 $H0 $B0/${V0}3 +for file in ${!replica_1_files_list[*]} +do + echo "B3 is down">>${replica_1_files_list[$file]} +done + +SMALLER_FILE_SIZE=$(stat -c %s file1) + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2 + +TEST kill_brick $V0 $H0 $B0/${V0}2 +for file in ${!replica_0_files_list[*]} +do + echo "B2 is down">>${replica_0_files_list[$file]} + echo "appending more content to make it the bigger file">>${replica_0_files_list[$file]} +done +TEST kill_brick $V0 $H0 $B0/${V0}4 +for file in ${!replica_1_files_list[*]} +do + echo "B4 is down">>${replica_1_files_list[$file]} + echo "appending more content to make it the bigger file">>${replica_1_files_list[$file]} +done + +BIGGER_FILE_SIZE=$(stat -c %s file1) +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 3 + + +############### Acessing the files should now give EIO. ############################### +TEST ! cat file1 +TEST ! cat file2 +TEST ! cat file3 +TEST ! cat file4 +TEST ! cat file5 +TEST ! cat file6 +TEST ! cat file7 +TEST ! cat file8 +TEST ! cat file9 +TEST ! cat file10 +################### +TEST $CLI volume set $V0 cluster.self-heal-daemon on +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 2 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 3 + +################ Heal file1 using the bigger-file option ############## +$CLI volume heal $V0 split-brain bigger-file /file1 +EXPECT "0" echo $? +EXPECT $BIGGER_FILE_SIZE stat -c %s file1 + +################ Heal file2 using the bigger-file option and its gfid ############## +subvolume=$(get_replicate_subvol_number file2) +if [ $subvolume == 0 ] +then + GFID=$(gf_get_gfid_xattr $B0/${V0}1/file2) +elif [ $subvolume == 1 ] +then + GFID=$(gf_get_gfid_xattr $B0/${V0}3/file2) +fi +GFIDSTR="gfid:$(gf_gfid_xattr_to_str $GFID)" +$CLI volume heal $V0 split-brain bigger-file $GFIDSTR +EXPECT "0" echo $? + +################ Heal file3 using the source-brick option ############## +################ Use the brick having smaller file size as source ####### +subvolume=$(get_replicate_subvol_number file3) +if [ $subvolume == 0 ] +then + $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}2 /file3 +elif [ $subvolume == 1 ] +then + $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}4 /file3 +fi +EXPECT "0" echo $? +EXPECT $SMALLER_FILE_SIZE stat -c %s file3 + +################ Heal file4 using the source-brick option and it's gfid ############## +################ Use the brick having smaller file size as source ####### +subvolume=$(get_replicate_subvol_number file4) +if [ $subvolume == 0 ] +then + GFID=$(gf_get_gfid_xattr $B0/${V0}1/file4) + GFIDSTR="gfid:$(gf_gfid_xattr_to_str $GFID)" + $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}2 $GFIDSTR +elif [ $subvolume == 1 ] +then + GFID=$(gf_get_gfid_xattr $B0/${V0}3/file4) + GFIDSTR="gfid:$(gf_gfid_xattr_to_str $GFID)" + $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}4 $GFIDSTR +fi +EXPECT "0" echo $? +EXPECT $SMALLER_FILE_SIZE stat -c %s file4 + +# With ctime enabled, the ctime xattr ("trusted.glusterfs.mdata") gets healed +# as part of metadata heal. So mtime would be same, hence it can't be healed +# using 'latest-mtime' policy, use 'source-brick' option instead. +################ Heal file5 using the source-brick option ############## +subvolume=$(get_replicate_subvol_number file5) +if [ $subvolume == 0 ] +then + $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}1 /file5 +elif [ $subvolume == 1 ] +then + $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}3 /file5 +fi +EXPECT "0" echo $? + +if [ $subvolume == 0 ] +then + mtime1_after_heal=$(get_mtime $B0/${V0}1/file5) + mtime2_after_heal=$(get_mtime $B0/${V0}2/file5) +elif [ $subvolume == 1 ] +then + mtime1_after_heal=$(get_mtime $B0/${V0}3/file5) + mtime2_after_heal=$(get_mtime $B0/${V0}4/file5) +fi + +#TODO: To below comparisons on full sub-second resolution + +TEST [ $mtime1_after_heal -eq $mtime2_after_heal ] + +mtime_mount_after_heal=$(stat -c %Y file5) + +TEST [ $mtime1_after_heal -eq $mtime_mount_after_heal ] + +################ Heal file6 using the source-brick option and its gfid ############## +subvolume=$(get_replicate_subvol_number file6) +if [ $subvolume == 0 ] +then + GFID=$(gf_get_gfid_xattr $B0/${V0}1/file6) + GFIDSTR="gfid:$(gf_gfid_xattr_to_str $GFID)" + $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}1 $GFIDSTR +elif [ $subvolume == 1 ] +then + GFID=$(gf_get_gfid_xattr $B0/${V0}3/file6) + GFIDSTR="gfid:$(gf_gfid_xattr_to_str $GFID)" + $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}3 $GFIDSTR +fi +EXPECT "0" echo $? + +if [ $subvolume == 0 ] +then + mtime1_after_heal=$(get_mtime $B0/${V0}1/file6) + mtime2_after_heal=$(get_mtime $B0/${V0}2/file6) +elif [ $subvolume == 1 ] +then + mtime1_after_heal=$(get_mtime $B0/${V0}3/file6) + mtime2_after_heal=$(get_mtime $B0/${V0}4/file6) +fi + +#TODO: To below comparisons on full sub-second resolution + +TEST [ $mtime1_after_heal -eq $mtime2_after_heal ] + +mtime_mount_after_heal=$(stat -c %Y file6) + +TEST [ $mtime1_after_heal -eq $mtime_mount_after_heal ] + +################ Heal remaining SB'ed files of replica_0 using B1 as source ############## +$CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}1 +EXPECT "0" echo $? + +################ Heal remaining SB'ed files of replica_1 using B3 as source ############## +$CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}3 +EXPECT "0" echo $? + +############### Reading the files should now succeed. ############################### +TEST cat file1 +TEST cat file2 +TEST cat file3 +TEST cat file4 +TEST cat file5 +TEST cat file6 +TEST cat file7 +TEST cat file8 +TEST cat file9 +TEST cat file10 + +################ File contents on the bricks must be same. ################################ +TEST diff <(arequal-checksum -p $B0/$V01 -i .glusterfs) <(arequal-checksum -p $B0/$V02 -i .glusterfs) +TEST diff <(arequal-checksum -p $B0/$V03 -i .glusterfs) <(arequal-checksum -p $B0/$V04 -i .glusterfs) + +############### Trying to heal files not in SB should fail. ############################### +$CLI volume heal $V0 split-brain bigger-file /file1 +EXPECT "1" echo $? +$CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}4 /file3 +EXPECT "1" echo $? + +cd - +TEST rm $AREQUAL_PATH/arequal-checksum +TEST rm $GET_MDATA_PATH/get-mdata-xattr +cleanup diff --git a/tests/basic/afr/split-brain-healing.t b/tests/basic/afr/split-brain-healing.t index c66bb5d44df..315e815eb7e 100644 --- a/tests/basic/afr/split-brain-healing.t +++ b/tests/basic/afr/split-brain-healing.t @@ -20,13 +20,14 @@ function get_replicate_subvol_number { cleanup; AREQUAL_PATH=$(dirname $0)/../../utils +GET_MDATA_PATH=$(dirname $0)/../../utils CFLAGS="" test "`uname -s`" != "Linux" && { - CFLAGS="$CFLAGS -I$(dirname $0)/../../../contrib/argp-standalone "; - CFLAGS="$CFLAGS -L$(dirname $0)/../../../contrib/argp-standalone -largp "; CFLAGS="$CFLAGS -lintl"; } build_tester $AREQUAL_PATH/arequal-checksum.c $CFLAGS +build_tester $GET_MDATA_PATH/get-mdata-xattr.c + TEST glusterd TEST pidof glusterd TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{1,2,3,4} @@ -34,8 +35,9 @@ TEST $CLI volume set $V0 cluster.self-heal-daemon off TEST $CLI volume set $V0 cluster.data-self-heal off TEST $CLI volume set $V0 cluster.metadata-self-heal off TEST $CLI volume set $V0 cluster.entry-self-heal off +TEST $CLI volume set $V0 ctime off TEST $CLI volume start $V0 -TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 cd $M0 for i in {1..10} @@ -78,7 +80,6 @@ do done BIGGER_FILE_SIZE=$(stat -c %s file1) - TEST $CLI volume start $V0 force EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 3 @@ -155,44 +156,74 @@ EXPECT $SMALLER_FILE_SIZE stat -c %s file4 subvolume=$(get_replicate_subvol_number file5) if [ $subvolume == 0 ] then - mtime1=$(stat -c %Y $B0/${V0}1/file5) - mtime2=$(stat -c %Y $B0/${V0}2/file5) + mtime1=$(get_mtime $B0/${V0}1/file5) + mtime2=$(get_mtime $B0/${V0}2/file5) LATEST_MTIME=$(($mtime1 > $mtime2 ? $mtime1:$mtime2)) elif [ $subvolume == 1 ] then - mtime1=$(stat -c %Y $B0/${V0}3/file5) - mtime2=$(stat -c %Y $B0/${V0}4/file5) + mtime1=$(get_mtime $B0/${V0}3/file5) + mtime2=$(get_mtime $B0/${V0}4/file5) LATEST_MTIME=$(($mtime1 > $mtime2 ? $mtime1:$mtime2)) fi $CLI volume heal $V0 split-brain latest-mtime /file5 EXPECT "0" echo $? -#TODO: Uncomment the below after posix_do_utimes() supports utimensat(2) accuracy -#TEST [ $LATEST_MTIME -eq $mtime1 ] -#TEST [ $LATEST_MTIME -eq $mtime2 ] +if [ $subvolume == 0 ] +then + mtime1_after_heal=$(get_mtime $B0/${V0}1/file5) + mtime2_after_heal=$(get_mtime $B0/${V0}2/file5) +elif [ $subvolume == 1 ] +then + mtime1_after_heal=$(get_mtime $B0/${V0}3/file5) + mtime2_after_heal=$(get_mtime $B0/${V0}4/file5) +fi + +#TODO: To below comparisons on full sub-second resolution + +TEST [ $LATEST_MTIME -eq $mtime1_after_heal ] +TEST [ $LATEST_MTIME -eq $mtime2_after_heal ] + +mtime_mount_after_heal=$(stat -c %Y file5) + +TEST [ $LATEST_MTIME -eq $mtime_mount_after_heal ] ################ Heal file6 using the latest-mtime option and its gfid ############## subvolume=$(get_replicate_subvol_number file6) if [ $subvolume == 0 ] then GFID=$(gf_get_gfid_xattr $B0/${V0}1/file6) - mtime1=$(stat -c %Y $B0/${V0}1/file6) - mtime2=$(stat -c %Y $B0/${V0}2/file6) + mtime1=$(get_mtime $B0/${V0}1/file6) + mtime2=$(get_mtime $B0/${V0}2/file6) LATEST_MTIME=$(($mtime1 > $mtime2 ? $mtime1:$mtime2)) elif [ $subvolume == 1 ] then GFID=$(gf_get_gfid_xattr $B0/${V0}3/file6) - mtime1=$(stat -c %Y $B0/${V0}3/file6) - mtime2=$(stat -c %Y $B0/${V0}4/file6) + mtime1=$(get_mtime $B0/${V0}3/file6) + mtime2=$(get_mtime $B0/${V0}4/file6) LATEST_MTIME=$(($mtime1 > $mtime2 ? $mtime1:$mtime2)) fi GFIDSTR="gfid:$(gf_gfid_xattr_to_str $GFID)" $CLI volume heal $V0 split-brain latest-mtime $GFIDSTR EXPECT "0" echo $? -#TODO: Uncomment the below after posix_do_utimes() supports utimensat(2) accuracy -#TEST [ $LATEST_MTIME -eq $mtime1 ] -#TEST [ $LATEST_MTIME -eq $mtime2 ] +if [ $subvolume == 0 ] +then + mtime1_after_heal=$(get_mtime $B0/${V0}1/file6) + mtime2_after_heal=$(get_mtime $B0/${V0}2/file6) +elif [ $subvolume == 1 ] +then + mtime1_after_heal=$(get_mtime $B0/${V0}3/file6) + mtime2_after_heal=$(get_mtime $B0/${V0}4/file6) +fi + +#TODO: To below comparisons on full sub-second resolution + +TEST [ $LATEST_MTIME -eq $mtime1_after_heal ] +TEST [ $LATEST_MTIME -eq $mtime2_after_heal ] + +mtime_mount_after_heal=$(stat -c %Y file6) + +TEST [ $LATEST_MTIME -eq $mtime_mount_after_heal ] ################ Heal remaining SB'ed files of replica_0 using B1 as source ############## $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}1 @@ -226,4 +257,5 @@ EXPECT "1" echo $? cd - TEST rm $AREQUAL_PATH/arequal-checksum +TEST rm $GET_MDATA_PATH/get-mdata-xattr cleanup diff --git a/tests/basic/afr/split-brain-open.t b/tests/basic/afr/split-brain-open.t new file mode 100644 index 00000000000..9b2f2856047 --- /dev/null +++ b/tests/basic/afr/split-brain-open.t @@ -0,0 +1,38 @@ +#!/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/${V0}{0,1} +TEST $CLI volume start $V0 + +#Disable self-heal-daemon +TEST $CLI volume heal $V0 disable + +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; + +TEST touch $M0/data-split-brain.txt + +#Create data split-brain +TEST kill_brick $V0 $H0 $B0/${V0}0 + +`echo "brick1_alive" > $M0/data-split-brain.txt` +TEST [ $? == 0 ]; + +TEST $CLI volume start $V0 force +TEST kill_brick $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 + +`echo "brick0_alive" > $M0/data-split-brain.txt` +TEST [ $? == 0 ]; + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 + +echo "all-alive" >> $M0/data-split-brain.txt +TEST [ $? != 0 ]; + +cleanup; diff --git a/tests/basic/afr/split-brain-resolution.t b/tests/basic/afr/split-brain-resolution.t index 84b2cc8db51..834237c96ec 100644 --- a/tests/basic/afr/split-brain-resolution.t +++ b/tests/basic/afr/split-brain-resolution.t @@ -11,12 +11,15 @@ function get_split_brain_status { TEST glusterd TEST pidof glusterd TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1} +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 #Disable self-heal-daemon TEST $CLI volume set $V0 cluster.self-heal-daemon off -TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; TEST `echo "some-data" > $M0/data-split-brain.txt` TEST `echo "some-data" > $M0/metadata-split-brain.txt` @@ -71,6 +74,18 @@ TEST setfattr -n replica.split-brain-choice -v none $M0/data-split-brain.txt TEST ! getfattr -n user.test $M0/metadata-split-brain.txt TEST ! cat $M0/data-split-brain.txt +#Check that after timeout fops result in EIO again. +#Set one minute timeout +TEST setfattr -n replica.split-brain-choice-timeout -v 1 $M0/ +TEST setfattr -n replica.split-brain-choice -v $V0-client-1 $M0/data-split-brain.txt +EXPECT "brick1_alive" cat $M0/data-split-brain.txt +TEST setfattr -n replica.split-brain-choice -v $V0-client-0 $M0/metadata-split-brain.txt +EXPECT "brick0" get_text_xattr user.test $M0/metadata-split-brain.txt +#Wait until timeout completes and test that the fops fail again +sleep 62 +TEST ! getfattr -n user.test $M0/metadata-split-brain.txt +TEST ! cat $M0/data-split-brain.txt + #Negative test cases should fail TEST ! setfattr -n replica.split-brain-choice -v $V0-client-4 $M0/data-split-brain.txt TEST ! setfattr -n replica.split-brain-heal-finalize -v $V0-client-4 $M0/metadata-split-brain.txt @@ -85,3 +100,6 @@ EXPECT "brick1_alive" cat $M0/data-split-brain.txt EXPECT 0 get_pending_heal_count $V0 cleanup; + +#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=000000 +#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=000000 diff --git a/tests/basic/afr/ta-check-locks.t b/tests/basic/afr/ta-check-locks.t new file mode 100644 index 00000000000..c0102c35b7b --- /dev/null +++ b/tests/basic/afr/ta-check-locks.t @@ -0,0 +1,68 @@ +#!/bin/bash +#This test checks if all the locks on +#ta file are being held and released properly + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../thin-arbiter.rc + +function get_lock_count_on_ta() +{ + tapid=`cat $B0/ta.pid` + local sfile=$(generate_statedump $tapid) + count=$(grep "inodelk-count" $sfile | cut -f2 -d'=' | tail -1) + ncount=$(grep "inodelk.inodelk" $sfile | grep "len=1" | wc -l) + echo "count = $count : ncount = $ncount" + if [ "$count" = "" ] + then + count=0 + fi + + if [ "$count" -eq "$ncount" ] + then + echo "$count" + else + echo "-1" + fi +} + +cleanup; +TEST ta_create_brick_and_volfile brick0 +TEST ta_create_brick_and_volfile brick1 +TEST ta_create_ta_and_volfile ta +TEST ta_start_brick_process brick0 +TEST ta_start_brick_process brick1 +TEST ta_start_ta_process ta + +TEST ta_create_mount_volfile brick0 brick1 ta +TEST ta_start_mount_process $M0 +TEST ta_start_mount_process $M1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ta_up_status $V0 $M0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ta_up_status $V0 $M1 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "trusted.afr.patchy-ta-2" ls $B0/ta + +TEST ta_create_shd_volfile brick0 brick1 ta +TEST ta_start_shd_process glustershd +shd_pid=$(cat $B0/glustershd.pid) + +TEST touch $M0/a.txt +echo "Hello" >> $M0/a.txt +EXPECT_WITHIN $IO_WAIT_TIMEOUT "0" get_lock_count_on_ta + +TEST ta_kill_brick brick0 +echo "Hello" >> $M0/a.txt +EXPECT_WITHIN $IO_WAIT_TIMEOUT "1" get_lock_count_on_ta + +echo "Hello" >> $M1/a.txt +EXPECT_WITHIN $IO_WAIT_TIMEOUT "2" get_lock_count_on_ta + +echo "xyz" >> $M0/a.txt +EXPECT_WITHIN $IO_WAIT_TIMEOUT "2" get_lock_count_on_ta + +chmod 0666 $M0/a.txt +EXPECT_WITHIN $IO_WAIT_TIMEOUT "2" get_lock_count_on_ta + +TEST ta_start_brick_process brick0 +EXPECT_WITHIN $HEAL_TIMEOUT "0" get_lock_count_on_ta + +cleanup; diff --git a/tests/basic/afr/ta-read.t b/tests/basic/afr/ta-read.t new file mode 100644 index 00000000000..3cfc16b9b8a --- /dev/null +++ b/tests/basic/afr/ta-read.t @@ -0,0 +1,64 @@ +#!/bin/bash + +# Test read transaction logic for thin-arbiter. + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../thin-arbiter.rc +cleanup; +TEST ta_create_brick_and_volfile brick0 +TEST ta_create_brick_and_volfile brick1 +TEST ta_create_ta_and_volfile ta +TEST ta_start_brick_process brick0 +TEST ta_start_brick_process brick1 +TEST ta_start_ta_process ta + +TEST ta_create_mount_volfile brick0 brick1 ta +TEST ta_start_mount_process $M0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ta_up_status $V0 $M0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "trusted.afr.patchy-ta-2" ls $B0/ta + +TEST touch $M0/FILE +TEST ls $B0/brick0/FILE +TEST ls $B0/brick1/FILE +TEST ! ls $B0/ta/FILE + +# Kill one brick and write to FILE. +TEST ta_kill_brick brick0 +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "0" ta_mount_child_up_status $M0 $V0 0 +echo "brick0 down">> $M0/FILE +TEST [ $? -eq 0 ] +EXPECT "000000010000000000000000" get_hex_xattr trusted.afr.$V0-client-0 $B0/brick1/FILE +EXPECT "000000010000000000000000" get_hex_xattr trusted.afr.$V0-client-0 $B0/ta/trusted.afr.patchy-ta-2 + +#Umount and mount to remove cached data. +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST ta_start_mount_process $M0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ta_up_status $V0 $M0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ta_mount_child_up_status $M0 $V0 1 +# Read must be allowed since good brick is up. +TEST cat $M0/FILE + +#Umount and mount to remove cached data. +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST ta_start_mount_process $M0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ta_up_status $V0 $M0 0 +# Toggle good and bad data brick processes. +TEST ta_start_brick_process brick0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ta_mount_child_up_status $M0 $V0 0 +TEST ta_kill_brick brick1 +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "0" ta_mount_child_up_status $M0 $V0 1 +# Read must now fail. +TEST ! cat $M0/FILE + +# Bring all data bricks up, and kill TA. +TEST ta_start_brick_process brick1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ta_mount_child_up_status $M0 $V0 1 +TA_PID=$(ta_get_pid_by_brick_name ta) +TEST [ -n $TA_PID ] +TEST ta_kill_brick ta +TA_PID=$(ta_get_pid_by_brick_name ta) +TEST [ -z $TA_PID ] +# Read must now succeed. +TEST cat $M0/FILE +cleanup; diff --git a/tests/basic/afr/ta-shd.t b/tests/basic/afr/ta-shd.t new file mode 100644 index 00000000000..96ecfc678e0 --- /dev/null +++ b/tests/basic/afr/ta-shd.t @@ -0,0 +1,49 @@ +#!/bin/bash +#Self-heal tests + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../thin-arbiter.rc +cleanup; +TEST ta_create_brick_and_volfile brick0 +TEST ta_create_brick_and_volfile brick1 +TEST ta_create_ta_and_volfile ta +TEST ta_start_brick_process brick0 +TEST ta_start_brick_process brick1 +TEST ta_start_ta_process ta + +TEST ta_create_mount_volfile brick0 brick1 ta +TEST ta_start_mount_process $M0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ta_up_status $V0 $M0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "trusted.afr.patchy-ta-2" ls $B0/ta + +TEST ta_create_shd_volfile brick0 brick1 ta +TEST ta_start_shd_process glustershd + +TEST touch $M0/a.txt +TEST ta_kill_brick brick0 +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "0" ta_mount_child_up_status $M0 $V0 0 +echo "Hello" >> $M0/a.txt +EXPECT "000000010000000000000000" get_hex_xattr trusted.afr.$V0-client-0 $B0/brick1/a.txt +EXPECT "000000010000000000000000" get_hex_xattr trusted.afr.$V0-client-0 $B0/ta/trusted.afr.$V0-ta-2 + +#TODO: After the write txn changes are merged, take statedump of TA process and +#check whether AFR_TA_DOM_NOTIFY lock is held by the client here. Take the +#statedump again after line #38 to check AFR_TA_DOM_NOTIFY lock is released by +#the SHD process. + +TEST ta_start_brick_process brick0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" ta_mount_child_up_status $M0 $V0 0 +EXPECT_WITHIN $HEAL_TIMEOUT "000000000000000000000000" get_hex_xattr trusted.afr.$V0-client-0 $B0/brick1/a.txt +EXPECT_WITHIN $HEAL_TIMEOUT "000000000000000000000000" get_hex_xattr trusted.afr.$V0-client-0 $B0/ta/trusted.afr.$V0-ta-2 + +#Kill the previously up brick and try reading from other brick. Since the heal +#has happened file content should be same. +TEST ta_kill_brick brick1 +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "0" ta_mount_child_up_status $M0 $V0 1 +#Umount and mount to remove cached data. +TEST umount $M0 +TEST ta_start_mount_process $M0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ta_up_status $V0 $M0 0 +EXPECT "Hello" cat $M0/a.txt +cleanup; diff --git a/tests/basic/afr/ta-write-on-bad-brick.t b/tests/basic/afr/ta-write-on-bad-brick.t new file mode 100644 index 00000000000..096ca9f47cf --- /dev/null +++ b/tests/basic/afr/ta-write-on-bad-brick.t @@ -0,0 +1,51 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../thin-arbiter.rc +cleanup; +TEST ta_create_brick_and_volfile brick0 +TEST ta_create_brick_and_volfile brick1 +TEST ta_create_ta_and_volfile ta +TEST ta_start_brick_process brick0 +TEST ta_start_brick_process brick1 +TEST ta_start_ta_process ta + +TEST ta_create_mount_volfile brick0 brick1 ta +TEST ta_start_mount_process $M0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ta_up_status $V0 $M0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "trusted.afr.patchy-ta-2" ls $B0/ta + +TEST touch $M0/a.txt +TEST ls $B0/brick0/a.txt +TEST ls $B0/brick1/a.txt +TEST ! ls $B0/ta/a.txt + +TEST dd if=/dev/zero of=$M0/a.txt bs=1M count=5 + +#Good Data brick is down. TA and bad brick are UP + +TEST ta_kill_brick brick1 +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "0" ta_mount_child_up_status $M0 $V0 1 +TEST dd if=/dev/zero of=$M0/a.txt bs=1M count=5 +TEST ta_kill_brick brick0 +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "0" ta_mount_child_up_status $M0 $V0 0 +TEST ta_start_brick_process brick1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" ta_mount_child_up_status $M0 $V0 1 +TEST ! dd if=/dev/zero of=$M0/a.txt bs=1M count=5 + +# Good Data brick is UP. Bad and TA are down +TEST ta_kill_brick brick1 +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "0" ta_mount_child_up_status $M0 $V0 1 +TEST ta_start_brick_process brick0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" ta_mount_child_up_status $M0 $V0 0 +TEST ta_kill_brick ta +TEST ! dd if=/dev/zero of=$M0/a.txt bs=1M count=5 + +# Good and Bad data bricks are UP. TA is down +TEST ta_start_brick_process brick1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ta_mount_child_up_status $M0 $V0 1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ta_mount_child_up_status $M0 $V0 0 +TEST dd if=/dev/zero of=$M0/a.txt bs=1M count=5 + +cleanup; diff --git a/tests/basic/afr/ta.t b/tests/basic/afr/ta.t new file mode 100644 index 00000000000..05d48431c95 --- /dev/null +++ b/tests/basic/afr/ta.t @@ -0,0 +1,54 @@ +#!/bin/bash +#Self-heal tests + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../thin-arbiter.rc +cleanup; +TEST ta_create_brick_and_volfile brick0 +TEST ta_create_brick_and_volfile brick1 +TEST ta_create_ta_and_volfile ta +TEST ta_start_brick_process brick0 +TEST ta_start_brick_process brick1 +TEST ta_start_ta_process ta + +TEST ta_create_mount_volfile brick0 brick1 ta +TEST ta_start_mount_process $M0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ta_up_status $V0 $M0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "trusted.afr.patchy-ta-2" ls $B0/ta + +TEST touch $M0/a.txt +TEST ls $B0/brick0/a.txt +TEST ls $B0/brick1/a.txt +TEST ! ls $B0/ta/a.txt + +TEST ta_kill_brick brick0 +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "0" afr_child_up_status_meta $M0 $V0-replicate-0 0 +TEST touch $M0/b.txt +EXPECT "000000000000000000000001" get_hex_xattr trusted.afr.$V0-client-0 $B0/brick1 +EXPECT "000000010000000200000000" get_hex_xattr trusted.afr.$V0-client-0 $B0/brick1/b.txt +#New entry mark lead to pending data on the file and on ta +EXPECT "000000010000000100000000" get_hex_xattr trusted.afr.$V0-client-0 $B0/ta/trusted.afr.patchy-ta-2 +TEST ! ls $B0/brick0/b.txt +TEST ls $B0/brick1/b.txt + +#Try to create an entry while good brick is down and bad brick is UP. Should not create +TEST ta_start_brick_process brick0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_meta $M0 $V0-replicate-0 0 +TEST ta_kill_brick brick1 +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "0" afr_child_up_status_meta $M0 $V0-replicate-0 1 +TEST ! touch $M0/d.txt +EXPECT "000000010000000100000000" get_hex_xattr trusted.afr.$V0-client-0 $B0/ta/trusted.afr.patchy-ta-2 + +TEST ta_start_brick_process brick1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_meta $M0 $V0-replicate-0 1 +TEST ta_kill_brick brick0 +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "0" afr_child_up_status_meta $M0 $V0-replicate-0 0 + +TEST ta_kill_brick ta +# Entry create must fail if only one brick is UP, even if that is a good brick. +TEST ! touch $M0/c.txt +TEST ! ls $B0/brick0/c.txt +TEST ! ls $B0/brick1/c.txt + +cleanup; diff --git a/tests/basic/afr/tarissue.t b/tests/basic/afr/tarissue.t index b1fdda6822b..83f7463130c 100644 --- a/tests/basic/afr/tarissue.t +++ b/tests/basic/afr/tarissue.t @@ -4,6 +4,8 @@ . $(dirname $0)/../../volume.rc . $(dirname $0)/../../nfs.rc +#G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST + TESTS_EXPECTED_IN_LOOP=10 cleanup; @@ -35,6 +37,3 @@ TEST rm -f /tmp/dir1.tar.gz EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $N0 cleanup; - -#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=1337795 -#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=1337795 diff --git a/tests/basic/all_squash.t b/tests/basic/all_squash.t new file mode 100644 index 00000000000..29766c50af7 --- /dev/null +++ b/tests/basic/all_squash.t @@ -0,0 +1,74 @@ +#!/bin/bash +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../nfs.rc + +#G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 $H0:$B0/${V0}{0,1} +TEST $CLI volume set $V0 nfs.disable false +TEST $CLI volume start $V0; + +TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0; +EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "1" is_nfs_export_available; +TEST mount_nfs $H0:/$V0 $N0 nolock; + +# random uid/gid +uid=22162 +gid=5845 + +TEST $CLI volume set $V0 server.anonuid $uid; +TEST $CLI volume set $V0 server.anongid $gid; + +# Ensure server.all-squash is disabled +TEST $CLI volume set $V0 server.all-squash disable; + +# Tests for the fuse mount +mkdir $M0/other; +chown $uid:$gid $M0/other; + +TEST $CLI volume set $V0 server.all-squash enable; + +touch $M0/file 2>/dev/null; +TEST [ $? -ne 0 ] +mkdir $M0/dir 2>/dev/null; +TEST [ $? -ne 0 ] + +TEST touch $M0/other/file 2>/dev/null; +TEST [ "$(stat -c %u:%g $M0/other/file)" = "$uid:$gid" ]; +TEST mkdir $M0/other/dir 2>/dev/null; +TEST [ "$(stat -c %u:%g $M0/other/dir)" = "$uid:$gid" ]; + +TEST $CLI volume set $V0 server.all-squash disable; +TEST rm -rf $M0/other; + +sleep 1; + +# tests for nfs mount +mkdir $N0/other; +chown $uid:$gid $N0/other; + +TEST $CLI volume set $V0 server.all-squash enable; + +touch $N0/file 2>/dev/null; +TEST [ $? -ne 0 ] +mkdir $N0/dir 2>/dev/null; +TEST [ $? -ne 0 ] + +TEST touch $N0/other/file 2>/dev/null; +TEST [ "$(stat -c %u:%g $N0/other/file)" = "$uid:$gid" ]; +TEST mkdir $N0/other/dir 2>/dev/null; +TEST [ "$(stat -c %u:%g $N0/other/dir)" = "$uid:$gid" ]; + +TEST $CLI volume set $V0 server.all-squash disable; +TEST rm -rf $N0/other; +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $N0 + +TEST $CLI volume stop $V0; +TEST $CLI volume delete $V0; + +cleanup; diff --git a/tests/basic/bd.t b/tests/basic/bd.t deleted file mode 100755 index 63622edd709..00000000000 --- a/tests/basic/bd.t +++ /dev/null @@ -1,142 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../include.rc -. $(dirname $0)/../volume.rc - -function execute() -{ - cmd=$1 - shift - ${cmd} $@ >/dev/null 2>&1 -} - -function bd_cleanup() -{ - execute vgremove -f ${V0} - execute pvremove ${ld} - execute losetup -d ${ld} - execute rm ${BD_DISK} - cleanup -} - -function check() -{ - if [ $? -ne 0 ]; then - echo prerequsite $@ failed - bd_cleanup - exit - fi -} - -SIZE=256 #in MB - -bd_cleanup; - -## Configure environment needed for BD backend volumes -## Create a file with configured size and -## set it as a temporary loop device to create -## physical volume & VG. These are basic things needed -## for testing BD xlator if anyone of these steps fail, -## test script exits -function configure() -{ - GLDIR=`$CLI system:: getwd` - BD_DISK=${GLDIR}/bd_disk - - execute truncate -s${SIZE}M ${BD_DISK} - check ${BD_DISK} creation - - execute losetup -f - check losetup - ld=`losetup -f` - - execute losetup ${ld} ${BD_DISK} - check losetup ${BD_DISK} - execute pvcreate -f ${ld} - check pvcreate ${ld} - execute vgcreate ${V0} ${ld} - check vgcreate ${V0} - execute lvcreate --thin ${V0}/pool --size 128M -} - -function volinfo_field() -{ - local vol=$1; - local field=$2; - $CLI volume info $vol | grep "^$field: " | sed 's/.*: //'; -} - -function volume_type() -{ - getfattr -n volume.type $M0/. --only-values --absolute-names -e text -} - -case $OSTYPE in -NetBSD) - echo "Skip test on LVM which is not available on NetBSD" >&2 - SKIP_TESTS - exit 0 - ;; -*) - ;; -esac - -TEST glusterd -TEST pidof glusterd -configure - -TEST $CLI volume create $V0 ${H0}:/$B0/$V0?${V0} -EXPECT "$V0" volinfo_field $V0 'Volume Name'; -EXPECT 'Created' volinfo_field $V0 'Status'; - -## Start volume and verify -TEST $CLI volume start $V0; -EXPECT 'Started' volinfo_field $V0 'Status' - -TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; -EXPECT '1' volume_type - -## Create posix file -TEST touch $M0/posix - -TEST touch $M0/lv -gfid=`getfattr -n glusterfs.gfid.string $M0/lv --only-values --absolute-names` -TEST setfattr -n user.glusterfs.bd -v "lv:4MB" $M0/lv -# Check if LV is created -TEST stat /dev/$V0/${gfid} - -## Create filesystem -sleep 1 -TEST mkfs.ext4 -qF $M0/lv -# Cloning -TEST touch $M0/lv_clone -gfid=`getfattr -n glusterfs.gfid.string $M0/lv_clone --only-values --absolute-names` -TEST setfattr -n clone -v ${gfid} $M0/lv -TEST stat /dev/$V0/${gfid} - -sleep 1 -## Check mounting -TEST mount -o loop $M0/lv $M1 -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M1 - -# Snapshot -TEST touch $M0/lv_sn -gfid=`getfattr -n glusterfs.gfid.string $M0/lv_sn --only-values --absolute-names` -TEST setfattr -n snapshot -v ${gfid} $M0/lv -TEST stat /dev/$V0/${gfid} - -# Merge -sleep 1 -TEST setfattr -n merge -v "$M0/lv_sn" $M0/lv_sn -TEST ! stat $M0/lv_sn -TEST ! stat /dev/$V0/${gfid} - - -rm $M0/* -f - -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 -TEST $CLI volume stop ${V0} -EXPECT 'Stopped' volinfo_field $V0 'Status'; -TEST $CLI volume delete ${V0} - -bd_cleanup diff --git a/tests/basic/changelog/changelog-api.t b/tests/basic/changelog/changelog-api.t new file mode 100644 index 00000000000..516c2f2f60d --- /dev/null +++ b/tests/basic/changelog/changelog-api.t @@ -0,0 +1,37 @@ +#!/bin/bash +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../env.rc + +cleanup; + +CHANGELOG_BIN_PATH=$(dirname $0)/../../utils/changelog +build_tester $CHANGELOG_BIN_PATH/test-changelog-api.c -lgfchangelog + +CHANGELOG_PATH_0="$B0/${V0}0/.glusterfs/changelogs" +ROLLOVER_TIME=2 + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/${V0}0 +TEST $CLI volume set $V0 changelog.changelog on +TEST $CLI volume set $V0 changelog.rollover-time $ROLLOVER_TIME +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; + +sleep 3; + +#Listen to changelog journal notifcations +$CHANGELOG_BIN_PATH/test-changelog-api & +for i in {1..12};do echo "data" > $M0/file$i 2>/dev/null; sleep 1;done & + +#Wait for changelogs to be in .processed directory +sleep 12 + +EXPECT "Y" processed_changelogs "/tmp/scratch_v1/.processed" +TEST rm $CHANGELOG_BIN_PATH/test-changelog-api +rm -rf /tmp/scratch_v1 + +cleanup; diff --git a/tests/basic/changelog/changelog-history.t b/tests/basic/changelog/changelog-history.t new file mode 100644 index 00000000000..ea952619652 --- /dev/null +++ b/tests/basic/changelog/changelog-history.t @@ -0,0 +1,91 @@ +#!/bin/bash +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../env.rc + +cleanup; + +SCRIPT_TIMEOUT=300 +HISTORY_BIN_PATH=$(dirname $0)/../../utils/changelog +build_tester $HISTORY_BIN_PATH/get-history.c -lgfchangelog + +time_before_enable1=$(date '+%s') +CHANGELOG_PATH_0="$B0/${V0}0/.glusterfs/changelogs" +ROLLOVER_TIME=2 + +TEST glusterd +TEST pidof glusterd + +sleep 3 +time_before_enable2=$(date '+%s') + +sleep 3 +TEST $CLI volume create $V0 $H0:$B0/${V0}0 +TEST $CLI volume set $V0 changelog.changelog on +TEST $CLI volume set $V0 changelog.rollover-time $ROLLOVER_TIME +TEST $CLI volume start $V0 + +sleep 3 +time_after_enable1=$(date '+%s') + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +touch $M0/file{1..10} + +sleep 3 +time_after_enable2=$(date '+%s') + +let time_future=time_after_enable2+600 + +#Fails as start falls before changelog enable +EXPECT "-3" $HISTORY_BIN_PATH/get-history $time_before_enable1 $time_before_enable2 + +#Fails as start falls before changelog enable +EXPECT "-3" $HISTORY_BIN_PATH/get-history $time_before_enable2 $time_after_enable1 + +#Passes as start and end falls in same htime file +EXPECT "0" $HISTORY_BIN_PATH/get-history $time_after_enable1 $time_after_enable2 + +#Passes, gives the changelogs till continuous changelogs are available +# but returns 1 +EXPECT "1" $HISTORY_BIN_PATH/get-history $time_after_enable2 $time_future + +#Disable and enable changelog +TEST $CLI volume set $V0 changelog.changelog off +sleep 6 +time_between_htime=$(date '+%s') +sleep 6 +TEST $CLI volume set $V0 changelog.changelog on + +sleep 6 +touch $M0/test{1..10} +time_in_sec_htime1=$(date '+%s') + +sleep 6 +touch $M0/test1{1..10} +time_in_sec_htime2=$(date '+%s') + +sleep 3 +TEST $CLI volume set $V0 changelog.changelog off +sleep 3 +time_after_disable=$(date '+%s') + +TEST $CLI volume set $V0 changelog.changelog on +sleep 5 + +#Passes, gives the changelogs till continuous changelogs are available +# but returns 1 +EXPECT_WITHIN 10 "1" $HISTORY_BIN_PATH/get-history $time_after_enable1 $time_in_sec_htime2 + +#Fails as start falls between htime files +EXPECT_WITHIN 10 "-3" $HISTORY_BIN_PATH/get-history $time_between_htime $time_in_sec_htime1 + +#Passes as start and end falls in same htime file +EXPECT_WITHIN 10 "0" $HISTORY_BIN_PATH/get-history $time_in_sec_htime1 $time_in_sec_htime2 + +#Passes, gives the changelogs till continuous changelogs are available +EXPECT_WITHIN 10 "0" $HISTORY_BIN_PATH/get-history $time_in_sec_htime2 $time_after_disable + +TEST rm $HISTORY_BIN_PATH/get-history +rm -rf /tmp/scratch_v1/* + +cleanup; diff --git a/tests/basic/changelog/changelog-rename.t b/tests/basic/changelog/changelog-rename.t new file mode 100644 index 00000000000..9a0ef527b5b --- /dev/null +++ b/tests/basic/changelog/changelog-rename.t @@ -0,0 +1,44 @@ +#!/bin/bash +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +cleanup; + +CHANGELOG_PATH_0="$B0/${V0}0/.glusterfs/changelogs" +ROLLOVER_TIME=30 + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 $H0:$B0/${V0}0 +TEST $CLI volume set $V0 changelog.changelog on +TEST $CLI volume set $V0 changelog.rollover-time $ROLLOVER_TIME +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +touch $M0/file1 +mv $M0/file1 $M0/rn_file1 +mkdir $M0/dir1 +mv $M0/dir1 $M0/rn_dir1 + +EXPECT "2" check_changelog_op ${CHANGELOG_PATH_0} "RENAME" + +cleanup; + +#####Test on multiple subvolume##### +#==========================================# + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 $H0:$B0/${V0}{0,1} +TEST $CLI volume set $V0 changelog.changelog on +TEST $CLI volume set $V0 changelog.rollover-time $ROLLOVER_TIME +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +touch $M0/gluster_file +mv $M0/gluster_file $M0/rn_gluster_file +mkdir $M0/dir1 +mv $M0/dir1 $M0/rn_dir1 + +EXPECT "2" check_changelog_op ${CHANGELOG_PATH_0} "RENAME" + +cleanup; diff --git a/tests/basic/changelog/history-api.t b/tests/basic/changelog/history-api.t new file mode 100644 index 00000000000..9e63118cef9 --- /dev/null +++ b/tests/basic/changelog/history-api.t @@ -0,0 +1,42 @@ +#!/bin/bash +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../env.rc + +cleanup; + +HISTORY_BIN_PATH=$(dirname $0)/../../utils/changelog +build_tester $HISTORY_BIN_PATH/test-history-api.c -lgfchangelog + +CHANGELOG_PATH_0="$B0/${V0}0/.glusterfs/changelogs" +ROLLOVER_TIME=2 + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/${V0}0 +TEST $CLI volume set $V0 changelog.changelog on +TEST $CLI volume set $V0 changelog.rollover-time $ROLLOVER_TIME +TEST $CLI volume start $V0 + +sleep 3 +start=$(date '+%s') + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +touch $M0/file{1..10} + +for i in {1..12};do echo "data" > $M0/file$i; sleep 1;done +end=$(date '+%s') +sleep 2 + +#Passes as start and end falls in same htime file +EXPECT "0" $HISTORY_BIN_PATH/test-history-api $start $end + +#Wait for changelogs to be in .processed directory +sleep 2 + +EXPECT "Y" processed_changelogs "/tmp/scratch_v1/.history/.processed" +TEST rm $HISTORY_BIN_PATH/test-history-api +rm -rf /tmp/scratch_v1 + +cleanup; diff --git a/tests/basic/cloudsync-sanity.t b/tests/basic/cloudsync-sanity.t new file mode 100644 index 00000000000..834ba96430c --- /dev/null +++ b/tests/basic/cloudsync-sanity.t @@ -0,0 +1,29 @@ +#!/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}{1,2,3,4,5,6,7,8,9}; +TEST $CLI volume set $V0 features.cloudsync enable; +TEST $CLI volume start $V0; + +## Mount FUSE +TEST $GFS -s $H0 --volfile-id $V0 $M1; + +# This test covers lookup, mkdir, mknod, symlink, link, rename, +# create operations +TEST $(dirname $0)/rpc-coverage.sh $M1 + + +TEST cp $(dirname ${0})/gfapi/glfsxmp-coverage.c glfsxmp.c +TEST build_tester ./glfsxmp.c -lgfapi +./glfsxmp $V0 $H0 +cleanup_tester ./glfsxmp +rm ./glfsxmp.c + +cleanup; diff --git a/tests/basic/ctime/ctime-ec-heal.t b/tests/basic/ctime/ctime-ec-heal.t new file mode 100644 index 00000000000..142237c5014 --- /dev/null +++ b/tests/basic/ctime/ctime-ec-heal.t @@ -0,0 +1,70 @@ +#!/bin/bash +# +# This will test self healing of ctime xattr 'trusted.glusterfs.mdata' +# +### + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../afr.rc + +cleanup + +#cleate and start volume +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{1..3} +TEST $CLI volume start $V0 + +#Mount the volume +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; + +# Create files +mkdir $M0/dir1 +echo "Initial content" > $M0/file1 + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/file1 + +# Kill brick +TEST kill_brick $V0 $H0 $B0/${V0}3 + +echo "B3 is down" >> $M0/file1 +echo "Change dir1 time attributes" > $M0/dir1/dir1_file1 +echo "Entry heal file" > $M0/entry_heal_file1 +mkdir $M0/entry_heal_dir1 + +# Check xattr +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_uniq_count $B0/${V0}{1..3}/dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_uniq_count $B0/${V0}{1..3}/file1 + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_count $B0/${V0}{1..3}/dir1/dir1_file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1/dir1_file1 + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_count $B0/${V0}{1..3}/entry_heal_file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_count $B0/${V0}{1..3}/entry_heal_dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_dir1 + +TEST $CLI volume start $V0 force +$CLI volume heal $V0 + +# Check xattr +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/file1 + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1/dir1_file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1/dir1_file1 + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/entry_heal_file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/entry_heal_dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_dir1 + +cleanup; diff --git a/tests/basic/ctime/ctime-ec-rebalance.t b/tests/basic/ctime/ctime-ec-rebalance.t new file mode 100644 index 00000000000..2b73bcdd103 --- /dev/null +++ b/tests/basic/ctime/ctime-ec-rebalance.t @@ -0,0 +1,43 @@ +#!/bin/bash +# +# This will test healing of ctime xattr 'trusted.glusterfs.mdata' after add-brick and rebalance +# +### + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../fallocate.rc + +cleanup + +#cleate and start volume +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0..5} +TEST $CLI volume start $V0 + +#Mount the volume +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 + +# Create files +mkdir $M0/dir1 +echo "test data" > $M0/dir1/file1 + +# Add brick +TEST $CLI volume add-brick $V0 $H0:$B0/${V0}{6..8} + +#Trigger rebalance +TEST $CLI volume rebalance $V0 start force +EXPECT_WITHIN $REBALANCE_TIMEOUT "completed" rebalance_status_field $V0 + +#Verify ctime xattr heal on directory +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}6/dir1" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}7/dir1" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}8/dir1" + +b6_mdata=$(get_mdata "$B0/${V0}6/dir1") +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "${b6_mdata}" get_mdata $B0/${V0}7/dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "${b6_mdata}" get_mdata $B0/${V0}8/dir1 + +cleanup; diff --git a/tests/basic/ctime/ctime-glfs-init.c b/tests/basic/ctime/ctime-glfs-init.c new file mode 100644 index 00000000000..e4f197b8f30 --- /dev/null +++ b/tests/basic/ctime/ctime-glfs-init.c @@ -0,0 +1,68 @@ +#include <fcntl.h> +#include <unistd.h> +#include <time.h> +#include <limits.h> +#include <string.h> +#include <unistd.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) + +int +main(int argc, char *argv[]) +{ + int ret = 0; + char *hostname = NULL; + char *volname = NULL; + char *logfile = NULL; + glfs_t *fs = NULL; + + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + fs = glfs_new(volname); + if (!fs) { + LOG_ERR("glfs_new failed"); + return -1; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + if (ret < 0) { + LOG_ERR("glfs_set_volfile_server failed"); + goto err; + } + + ret = glfs_set_logging(fs, logfile, 7); + if (ret < 0) { + LOG_ERR("glfs_set_logging failed"); + goto err; + } + + ret = glfs_init(fs); + if (ret < 0) { + LOG_ERR("glfs_init failed"); + goto err; + } + + glfs_fini(fs); + fs = NULL; + return 0; +err: + glfs_fini(fs); + fs = NULL; + + return -1; +} diff --git a/tests/basic/ctime/ctime-glfs-init.t b/tests/basic/ctime/ctime-glfs-init.t new file mode 100644 index 00000000000..56d7d6caee0 --- /dev/null +++ b/tests/basic/ctime/ctime-glfs-init.t @@ -0,0 +1,23 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd + +TEST $CLI volume create $V0 replica 3 ${H0}:$B0/brick{1,2,3}; +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume start $V0; + +logdir=`gluster --print-logdir` + +TEST build_tester $(dirname $0)/ctime-glfs-init.c -lgfapi -lpthread + +TEST ./$(dirname $0)/ctime-glfs-init ${H0} $V0 $logdir/ctime-glfs-init.log + +cleanup_tester $(dirname $0)/ctime-glfs-init + +cleanup; + diff --git a/tests/basic/ctime/ctime-heal-symlinks.t b/tests/basic/ctime/ctime-heal-symlinks.t new file mode 100644 index 00000000000..547b1807e94 --- /dev/null +++ b/tests/basic/ctime/ctime-heal-symlinks.t @@ -0,0 +1,65 @@ +#!/bin/bash +. $(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,1,2} +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume start $V0 + +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; + +cd $M0 +TEST "echo hello_world > FILE" +TEST ln -s FILE SOFTLINK + +# Remove symlink only (not the .glusterfs entry) and trigger named heal. +TEST rm -f $B0/${V0}2/SOFTLINK +TEST stat SOFTLINK + +# To heal and clear new-entry mark on source bricks. +TEST $CLI volume heal $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +EXPECT 2 stat -c %h $B0/${V0}2/SOFTLINK +EXPECT "hello_world" cat $B0/${V0}2/SOFTLINK + +cd - +cleanup +############################################################################### + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0,1,2} +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume start $V0 + +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; + +cd $M0 +TEST "echo hello_world > FILE" +TEST ln -s FILE SOFTLINK + +# Remove symlink only (not the .glusterfs entry) and trigger named heal. +TEST rm -f $B0/${V0}2/SOFTLINK +TEST stat SOFTLINK + +# To heal and clear new-entry mark on source bricks. +TEST $CLI volume heal $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +EXPECT 2 stat -c %h $B0/${V0}2/SOFTLINK +TEST kill_brick $V0 $H0 $B0/${V0}0 +cd - +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; +cd $M0 +EXPECT "hello_world" cat SOFTLINK + +cd - +cleanup +############################################################################### diff --git a/tests/basic/ctime/ctime-mdata-legacy-files.t b/tests/basic/ctime/ctime-mdata-legacy-files.t new file mode 100644 index 00000000000..2e782d5c99d --- /dev/null +++ b/tests/basic/ctime/ctime-mdata-legacy-files.t @@ -0,0 +1,83 @@ +#!/bin/bash +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../afr.rc +cleanup; + +############################################################################### +#Replica volume + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2} +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume start $V0 + +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; + +#Disable ctime and create file, file doesn't contain "trusted.glusterfs.mdata" xattr +TEST $CLI volume set $V0 ctime off + +TEST "mkdir $M0/DIR" +TEST "echo hello_world > $M0/DIR/FILE" + +#Verify absence of xattr +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}0/DIR" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}0/DIR/FILE" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}1/DIR" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}1/DIR/FILE" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}2/DIR" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}2/DIR/FILE" + +#Enable ctime +TEST $CLI volume set $V0 ctime on +sleep 3 +TEST stat $M0/DIR/FILE + +#Verify presence "trusted.glusterfs.mdata" xattr on backend +#The lookup above should have created xattr +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}0/DIR" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}0/DIR/FILE" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}1/DIR" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}1/DIR/FILE" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}2/DIR" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}2/DIR/FILE" + +############################################################################### +#Disperse Volume + +TEST $CLI volume create $V1 disperse 3 redundancy 1 $H0:$B0/${V1}{0,1,2} +TEST $CLI volume set $V1 performance.stat-prefetch off +TEST $CLI volume start $V1 + +TEST glusterfs --volfile-id=$V1 --volfile-server=$H0 --entry-timeout=0 $M1; + +#Disable ctime and create file, file doesn't contain "trusted.glusterfs.mdata" xattr +TEST $CLI volume set $V1 ctime off +TEST "mkdir $M1/DIR" +TEST "echo hello_world > $M1/DIR/FILE" + +#Verify absence of xattr +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}0/DIR" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}0/DIR/FILE" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}1/DIR" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}1/DIR/FILE" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}2/DIR" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}2/DIR/FILE" + +#Enable ctime +TEST $CLI volume set $V1 ctime on +sleep 3 +TEST stat $M1/DIR/FILE + +#Verify presence "trusted.glusterfs.mdata" xattr on backend +#The lookup above should have created xattr +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}0/DIR" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}0/DIR/FILE" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}1/DIR" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}1/DIR/FILE" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}2/DIR" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}2/DIR/FILE" + +cleanup; +############################################################################### diff --git a/tests/basic/ctime/ctime-noatime.t b/tests/basic/ctime/ctime-noatime.t new file mode 100644 index 00000000000..609ccbd72c1 --- /dev/null +++ b/tests/basic/ctime/ctime-noatime.t @@ -0,0 +1,49 @@ +#!/bin/bash +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../afr.rc +cleanup; + +function atime_compare { + local atime=$1 + local file_name=$2 + local atime1=$(stat -c "%X" $file_name) + + if [ $atime == $atime1 ] + then + echo "0" + else + echo "1" + fi +} + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2} +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume set $V0 performance.read-ahead off +TEST $CLI volume set $V0 performance.quick-read off +TEST $CLI volume set $V0 performance.read-after-open off +TEST $CLI volume set $V0 performance.open-behind off +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume set $V0 performance.io-cache off + +TEST $CLI volume start $V0 + +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; + +cd $M0 +TEST "echo hello_world > FILE" +atime1=$(stat -c "%X" FILE) + +TEST "cat FILE > /dev/null" +EXPECT "0" atime_compare $atime1 FILE + +sleep 1 + +TEST $CLI volume set $V0 noatime off +TEST "cat FILE > /dev/null" +EXPECT "1" atime_compare $atime1 FILE + +cd - +cleanup diff --git a/tests/basic/ctime/ctime-readdir.c b/tests/basic/ctime/ctime-readdir.c new file mode 100644 index 00000000000..8760db29ae8 --- /dev/null +++ b/tests/basic/ctime/ctime-readdir.c @@ -0,0 +1,29 @@ +#include <stdio.h> +#include <dirent.h> +#include <string.h> +#include <assert.h> + +int +main(int argc, char **argv) +{ + DIR *dir = NULL; + struct dirent *entry = NULL; + int ret = 0; + char *path = NULL; + + assert(argc == 2); + path = argv[1]; + + dir = opendir(path); + if (!dir) { + printf("opendir(%s) failed.\n", path); + return -1; + } + + while ((entry = readdir(dir)) != NULL) { + } + if (dir) + closedir(dir); + + return ret; +} diff --git a/tests/basic/ctime/ctime-readdir.t b/tests/basic/ctime/ctime-readdir.t new file mode 100644 index 00000000000..4564fc1b667 --- /dev/null +++ b/tests/basic/ctime/ctime-readdir.t @@ -0,0 +1,50 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd + +TEST $CLI volume create $V0 replica 3 ${H0}:$B0/brick{1,2,3}; +TEST $CLI volume set $V0 performance.stat-prefetch on +TEST $CLI volume set $V0 performance.readdir-ahead off +TEST $CLI volume start $V0; + +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; + +TEST mkdir $M0/dir0 +TEST "echo hello_world > $M0/dir0/FILE" + +ctime1=$(stat -c %Z $M0/dir0/FILE) +echo "Mount change time: $ctime1" + +sleep 2 + +#Write to back end directly to modify ctime of backend file +TEST "echo write_from_backend >> $B0/brick1/dir0/FILE" +TEST "echo write_from_backend >> $B0/brick2/dir0/FILE" +TEST "echo write_from_backend >> $B0/brick3/dir0/FILE" +echo "Backend change time" +echo "brick1: $(stat -c %Z $B0/brick1/dir0/FILE)" +echo "brick2: $(stat -c %Z $B0/brick2/dir0/FILE)" +echo "brick3: $(stat -c %Z $B0/brick3/dir0/FILE)" + +#Stop and start to hit the case of no inode for readdir +TEST umount $M0 +TEST $CLI volume stop $V0 +TEST $CLI volume start $V0 +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; + +TEST build_tester $(dirname $0)/ctime-readdir.c + +#Do readdir +TEST ./$(dirname $0)/ctime-readdir $M0/dir0 + +EXPECT "$ctime1" stat -c %Z $M0/dir0/FILE +echo "Mount change time after readdir $(stat -c %Z $M0/dir0/FILE)" + +cleanup_tester $(dirname $0)/ctime-readdir + +cleanup; diff --git a/tests/basic/ctime/ctime-rep-heal.t b/tests/basic/ctime/ctime-rep-heal.t new file mode 100644 index 00000000000..20517c74971 --- /dev/null +++ b/tests/basic/ctime/ctime-rep-heal.t @@ -0,0 +1,70 @@ +#!/bin/bash +# +# This will test self healing of ctime xattr 'trusted.glusterfs.mdata' +# +### + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../afr.rc + +cleanup + +#cleate and start volume +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{1..3} +TEST $CLI volume start $V0 + +#Mount the volume +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; + +# Create files +mkdir $M0/dir1 +echo "Initial content" > $M0/file1 + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/file1 + +# Kill brick +TEST kill_brick $V0 $H0 $B0/${V0}3 + +echo "B3 is down" >> $M0/file1 +echo "Change dir1 time attributes" > $M0/dir1/dir1_file1 +echo "Entry heal file" > $M0/entry_heal_file1 +mkdir $M0/entry_heal_dir1 + +# Check xattr +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_uniq_count $B0/${V0}{1..3}/dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_uniq_count $B0/${V0}{1..3}/file1 + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_count $B0/${V0}{1..3}/dir1/dir1_file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1/dir1_file1 + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_count $B0/${V0}{1..3}/entry_heal_file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '2' get_mdata_count $B0/${V0}{1..3}/entry_heal_dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_dir1 + +TEST $CLI volume start $V0 force +$CLI volume heal $V0 + +# Check xattr +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/file1 + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/dir1/dir1_file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/dir1/dir1_file1 + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/entry_heal_file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_file1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '3' get_mdata_count $B0/${V0}{1..3}/entry_heal_dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT '1' get_mdata_uniq_count $B0/${V0}{1..3}/entry_heal_dir1 + +cleanup; diff --git a/tests/basic/ctime/ctime-rep-rebalance.t b/tests/basic/ctime/ctime-rep-rebalance.t new file mode 100644 index 00000000000..866cf87e6cb --- /dev/null +++ b/tests/basic/ctime/ctime-rep-rebalance.t @@ -0,0 +1,41 @@ +#!/bin/bash +# +# This will test healing of ctime xattr 'trusted.glusterfs.mdata' after add-brick and rebalance +# +### + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../afr.rc + +cleanup + +#cleate and start volume +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0..5} +TEST $CLI volume start $V0 + +#Mount the volume +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; + +# Create files +mkdir $M0/dir1 + +# Add brick +TEST $CLI volume add-brick $V0 $H0:$B0/${V0}{6..8} + +#Trigger rebalance +TEST $CLI volume rebalance $V0 start force +EXPECT_WITHIN $REBALANCE_TIMEOUT "completed" rebalance_status_field $V0 + +#Verify ctime xattr heal on directory +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}6/dir1" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}7/dir1" +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}8/dir1" + +b6_mdata=$(get_mdata "$B0/${V0}6/dir1") +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "${b6_mdata}" get_mdata $B0/${V0}7/dir1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "${b6_mdata}" get_mdata $B0/${V0}8/dir1 + +cleanup; diff --git a/tests/basic/ctime/ctime-utimesat.t b/tests/basic/ctime/ctime-utimesat.t new file mode 100644 index 00000000000..540e57aec83 --- /dev/null +++ b/tests/basic/ctime/ctime-utimesat.t @@ -0,0 +1,28 @@ +#!/bin/bash +. $(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,1,2} +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume set $V0 performance.read-ahead off +TEST $CLI volume set $V0 performance.quick-read off +TEST $CLI volume set $V0 performance.read-after-open off +TEST $CLI volume set $V0 performance.open-behind off +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume set $V0 performance.io-cache off + +TEST $CLI volume start $V0 + +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; + +touch $M0/FILE + +atime=$(stat -c "%.X" $M0/FILE) +EXPECT $atime stat -c "%.Y" $M0/FILE +EXPECT $atime stat -c "%.Z" $M0/FILE + +cleanup diff --git a/tests/basic/distribute/brick-down.t b/tests/basic/distribute/brick-down.t new file mode 100644 index 00000000000..522ccc07210 --- /dev/null +++ b/tests/basic/distribute/brick-down.t @@ -0,0 +1,83 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../common-utils.rc +. $(dirname $0)/../../dht.rc + +# Test 1 overview: +# ---------------- +# Test whether lookups are sent after a brick comes up again +# +# 1. Create a 3 brick pure distribute volume +# 2. Fuse mount the volume so the layout is set on the root +# 3. Kill one brick and try to create a directory which hashes to that brick. +# It should fail with EIO. +# 4. Restart the brick that was killed. +# 5. Do not remount the volume. Try to create the same directory as in step 3. + +cleanup + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/$V0-{1..3} +TEST $CLI volume start $V0 + +# We want the lookup to reach DHT +TEST $CLI volume set $V0 performance.stat-prefetch off + +# Mount using FUSE and lookup the mount so a layout is set on the brick root +TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0 + +ls $M0/ + +TEST mkdir $M0/level1 + +# Find a dirname that will hash to the brick we are going to kill +hashed=$V0-client-1 +TEST dht_first_filename_with_hashsubvol "$hashed" $M0 "dir-" +roottestdir=$fn_return_val + +hashed=$V0-client-1 +TEST dht_first_filename_with_hashsubvol "$hashed" $M0/level1 "dir-" +level1testdir=$fn_return_val + + +TEST kill_brick $V0 $H0 $B0/$V0-2 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "0" brick_up_status $V0 $H0 $B0/$V0-2 + +TEST $CLI volume status $V0 + + +# Unmount and mount the volume again so dht has an incomplete in memory layout + +umount -f $M0 +TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0 + + +mkdir $M0/$roottestdir +TEST [ $? -ne 0 ] + +mkdir $M0/level1/$level1testdir +TEST [ $? -ne 0 ] + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/$V0-2 + +#$CLI volume status + +# It takes a while for the client to reconnect to the brick +sleep 5 + + +mkdir $M0/$roottestdir +TEST [ $? -eq 0 ] + +mkdir $M0/$level1/level1testdir +TEST [ $? -eq 0 ] + +# Cleanup +cleanup + + diff --git a/tests/basic/distribute/bug-1265677-use-readdirp.t b/tests/basic/distribute/bug-1265677-use-readdirp.t index 5b274d62667..eef8affc8b9 100644 --- a/tests/basic/distribute/bug-1265677-use-readdirp.t +++ b/tests/basic/distribute/bug-1265677-use-readdirp.t @@ -8,8 +8,7 @@ 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 create $V0 $H0:$B0/${V0}{0..1} TEST $CLI volume set $V0 nfs.disable yes TEST $CLI volume set $V0 dht.force-readdirp yes TEST $CLI volume set $V0 performance.readdir-ahead off diff --git a/tests/basic/distribute/debug-xattrs.t b/tests/basic/distribute/debug-xattrs.t new file mode 100644 index 00000000000..6d87c0e8671 --- /dev/null +++ b/tests/basic/distribute/debug-xattrs.t @@ -0,0 +1,54 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../nfs.rc +. $(dirname $0)/../../common-utils.rc + +# Test overview: Test the virtual xattrs dht provides for debugging + +# Test 1 : "dht.file.hashed-subvol.<filename>" +# Get the hashed subvolume for file1 in dir1 using xattr +# Create file1 in dir1 +# Check if the file is created in the brick returned by xattr + +hashdebugxattr="dht.file.hashed-subvol." + +cleanup + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/$V0-{0..3} +TEST $CLI volume start $V0 + +# Mount using FUSE and create a file +TEST glusterfs -s $H0 --volfile-id $V0 $M0 + +# Test 1 : "dht.file.hashed-subvol.<filename>" +# Get the hashed subvolume for file1 in dir1 using xattr +# Create file1 in dir1 +# Check if the file is created in the brick returned by xattr +# Create a directory on $M0 + +TEST mkdir $M0/dir1 + +xattrname=$hashdebugxattr"file1" + +hashed=$(getfattr --only-values -n "$xattrname" $M0/dir1) + +# Get the brick path for $hashed +brickpath=$(cat "$M0/.meta/graphs/active/$hashed/options/remote-subvolume") +brickpath=$brickpath"/dir1/file1" + +# Create the file for which we checked the xattr +TEST touch $M0/dir1/file1 +TEST stat $brickpath + +# Non-existent directory +TEST ! getfattr --only-values -n "$xattrname" $M0/dir2 + + +# Cleanup +cleanup + diff --git a/tests/basic/distribute/dir-heal.t b/tests/basic/distribute/dir-heal.t new file mode 100644 index 00000000000..851f765b245 --- /dev/null +++ b/tests/basic/distribute/dir-heal.t @@ -0,0 +1,145 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../nfs.rc +. $(dirname $0)/../../common-utils.rc + +# Test 1 overview: +# ---------------- +# +# 1. Kill one brick of the volume. +# 2. Create directories and change directory properties. +# 3. Bring up the brick and access the directory +# 4. Check the permissions and xattrs on the backend + +cleanup + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/$V0-{1..3} +TEST $CLI volume start $V0 + +# We want the lookup to reach DHT +TEST $CLI volume set $V0 performance.stat-prefetch off + +# Mount using FUSE , kill a brick and create directories +TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0 + +ls $M0/ +cd $M0 + +TEST kill_brick $V0 $H0 $B0/$V0-1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "0" brick_up_status $V0 $H0 $B0/$V0-1 + +TEST mkdir dir{1..4} + +# No change for dir1 +# Change permissions for dir2 +# Set xattr on dir3 +# Change permissions and set xattr on dir4 + +TEST chmod 777 $M0/dir2 + +TEST setfattr -n "user.test" -v "test" $M0/dir3 + +TEST chmod 777 $M0/dir4 +TEST setfattr -n "user.test" -v "test" $M0/dir4 + + +# Start all bricks + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/$V0-1 + +#$CLI volume status + +# It takes a while for the client to reconnect to the brick +sleep 5 + +stat $M0/dir* > /dev/null + +# Check that directories have been created on the brick that was killed + +TEST ls $B0/$V0-1/dir1 + +TEST ls $B0/$V0-1/dir2 +EXPECT "777" stat -c "%a" $B0/$V0-1/dir2 + +TEST ls $B0/$V0-1/dir3 +EXPECT "test" getfattr -n "user.test" --absolute-names --only-values $B0/$V0-1/dir3 + + +TEST ls $B0/$V0-1/dir4 +EXPECT "777" stat -c "%a" $B0/$V0-1/dir4 +EXPECT "test" getfattr -n "user.test" --absolute-names --only-values $B0/$V0-1/dir4 + + +TEST rm -rf $M0/* + +cd + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + + +# Test 2 overview: +# ---------------- +# 1. Create directories with all bricks up. +# 2. Kill a brick and change directory properties and set user xattr. +# 2. Bring up the brick and access the directory +# 3. Check the permissions and xattrs on the backend + + +TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0 + +ls $M0/ +cd $M0 +TEST mkdir dir{1..4} + +TEST kill_brick $V0 $H0 $B0/$V0-1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "0" brick_up_status $V0 $H0 $B0/$V0-1 + +# No change for dir1 +# Change permissions for dir2 +# Set xattr on dir3 +# Change permissions and set xattr on dir4 + +TEST chmod 777 $M0/dir2 + +TEST setfattr -n "user.test" -v "test" $M0/dir3 + +TEST chmod 777 $M0/dir4 +TEST setfattr -n "user.test" -v "test" $M0/dir4 + + +# Start all bricks + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/$V0-1 + +#$CLI volume status + +# It takes a while for the client to reconnect to the brick +sleep 5 + +stat $M0/dir* > /dev/null + +# Check directories on the brick that was killed + +TEST ls $B0/$V0-1/dir2 +EXPECT "777" stat -c "%a" $B0/$V0-1/dir2 + +TEST ls $B0/$V0-1/dir3 +EXPECT "test" getfattr -n "user.test" --absolute-names --only-values $B0/$V0-1/dir3 + + +TEST ls $B0/$V0-1/dir4 +EXPECT "777" stat -c "%a" $B0/$V0-1/dir4 +EXPECT "test" getfattr -n "user.test" --absolute-names --only-values $B0/$V0-1/dir4 +cd + + +# Cleanup +cleanup + diff --git a/tests/basic/distribute/file-create.t b/tests/basic/distribute/file-create.t new file mode 100644 index 00000000000..41b662eefe2 --- /dev/null +++ b/tests/basic/distribute/file-create.t @@ -0,0 +1,120 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../common-utils.rc +. $(dirname $0)/../../dht.rc + +# Test overview: Test file creation in various scenarios + + +# Test 1 : "dht.file.hashed-subvol.<filename>" +# Get the hashed subvolume for file1 in dir1 using xattr +# Create file1 in dir1 +# Check if the file is created in the brick returned by xattr + +hashdebugxattr="dht.file.hashed-subvol." + +cleanup + +TEST glusterd +TEST pidof glusterd + +# We want fixed size bricks to test min-free-disk + +# Create 2 loop devices, one per brick. +TEST truncate -s 25M $B0/brick1 +TEST truncate -s 25M $B0/brick2 + +TEST L1=`SETUP_LOOP $B0/brick1` +TEST MKFS_LOOP $L1 + +TEST L2=`SETUP_LOOP $B0/brick2` +TEST MKFS_LOOP $L2 + + +TEST mkdir -p $B0/${V0}{1,2} + +TEST MOUNT_LOOP $L1 $B0/${V0}1 +TEST MOUNT_LOOP $L2 $B0/${V0}2 + + +# Create a plain distribute volume with 2 subvols. +TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2}; +TEST $CLI volume start $V0; +EXPECT "Started" volinfo_field $V0 'Status'; + +TEST $CLI volume set $V0 cluster.min-free-disk 40% +#TEST $CLI volume set $V0 client-log-level DEBUG + +# Mount using FUSE and create a file +TEST glusterfs -s $H0 --volfile-id $V0 $M0 + +TEST mkdir $M0/dir1 + +###################################################### +# Test 1 : Test file creation on correct hashed subvol +###################################################### + +hashed="$V0-client-0" +TEST dht_first_filename_with_hashsubvol "$hashed" $M0/dir1 "big-" +firstfile=$fn_return_val + +#Create a large file to fill up $hashed past the min-free-disk limits +TEST dd if=/dev/zero of=$M0/dir1/$firstfile bs=1M count=15 + +brickpath_0=$(cat "$M0/.meta/graphs/active/$hashed/options/remote-subvolume") +brickpath_1=$(cat "$M0/.meta/graphs/active/$V0-client-1/options/remote-subvolume") + +TEST stat "$brickpath_0/dir1/$firstfile" +EXPECT "0" is_dht_linkfile "$brickpath_0/dir1/$firstfile" + + +###################################################### +# Test 2: Create a file which hashes to the subvol which has crossed +# the min-free-disk limit. It should be created on the other subvol +###################################################### + +# DHT only checks disk usage every second. Create a new file and introduce a +# delay here to ensure DHT updates the in memory disk usage +sleep 2 +TEST dd if=/dev/zero of=$M0/dir1/file-2 bs=1024 count=1 + +# Find a file that will hash to $hash_subvol +TEST dht_first_filename_with_hashsubvol $hashed $M0/dir1 "newfile-" +newfile=$fn_return_val +echo $newfile + +# Create $newfile - it should be created on the other subvol as its hash subvol +# has crossed the min-free-disk limit +TEST dd if=/dev/zero of=$M0/dir1/$newfile bs=1024 count=20 +TEST stat "$brickpath_0/dir1/$newfile" +EXPECT "1" is_dht_linkfile "$brickpath_0/dir1/$newfile" + + +#TEST rm -rf $M0/dir1/$firstfile +#TEST rm -rf $M0/dir1/$newfile + + +###################################################### +# Test 3: Test dht_filter_loc_subvol_key +###################################################### + +TEST dht_first_filename_with_hashsubvol $V0-client-1 $M0/dir1 "filter-" +newfile=$fn_return_val +echo $newfile +TEST dd if=/dev/zero of="$M0/dir1/$newfile@$V0-dht:$hashed" bs=1024 count=20 +TEST stat $M0/dir1/$newfile +TEST stat "$brickpath_0/dir1/$newfile" +EXPECT "1" is_dht_linkfile "$brickpath_1/dir1/$newfile" + + +force_umount $M0 +TEST $CLI volume stop $V0 +UMOUNT_LOOP ${B0}/${V0}{1,2} +rm -f ${B0}/brick{1,2} + + +# Cleanup +cleanup + diff --git a/tests/basic/distribute/file-rename.t b/tests/basic/distribute/file-rename.t new file mode 100644 index 00000000000..63111b8ad8f --- /dev/null +++ b/tests/basic/distribute/file-rename.t @@ -0,0 +1,1021 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../nfs.rc +. $(dirname $0)/../../common-utils.rc + +# Test overview: +# Test all combinations of src-hashed/src-cached/dst-hashed/dst-cached + +hashdebugxattr="dht.file.hashed-subvol." + +function get_brick_index { + local inpath=$1 + brickroot=$(getfattr -m . -n trusted.glusterfs.pathinfo $inpath | tr ' ' '\n' | sed -n 's/<POSIX(\(.*\)):.*:.*>.*/\1/p') + echo ${brickroot:(-1)} +} + +function get_brick_path_for_subvol { + local in_subvol=$1 + local in_brickpath + + in_brickpath=$(cat "$M0/.meta/graphs/active/$in_subvol/options/remote-subvolume") + echo $in_brickpath + +} + +#Checks that file exists only on hashed and/or cached +function file_existence_check +{ + local in_file_path=$1 + local in_hashed=$2 + local in_cached=$3 + local in_client_subvol + local in_brickpath + local ret + + for i in {0..3} + do + in_client_subvol="$V0-client-$i" + in_brickpath=$(cat "$M0/.meta/graphs/active/$in_client_subvol/options/remote-subvolume") + stat "$in_brickpath/$in_file_path" 2>/dev/null + ret=$? + # Either the linkto or the data file must exist on the hashed + if [ "$in_client_subvol" == "$in_hashed" ]; then + if [ $ret -ne 0 ]; then + return 1 + fi + continue + fi + + # If the cached is non-null, we expect the file to exist on it + if [ "$in_client_subvol" == "$in_cached" ]; then + if [ $ret -ne 0 ]; then + return 1 + fi + continue + fi + + if [ $ret -eq 0 ]; then + return 2 + fi + done + return 0 +} + + +# Check if file exists on any of the bricks of the volume +function file_does_not_exist +{ + local inpath=$1 + for i in `seq 0 3` + do + file_path=$B0/$V0-$i/$inpath + if [ -f "$file_path" ]; then + echo "1" + return 1 + fi + done + return 0 +} + + +# Input: filename dirpath +function get_hash_subvol +{ + hash_subvol=$(getfattr --only-values -n "$hashdebugxattr$1" $2 2>/dev/null) +} + + + +# Find the first filename that hashes to a subvol +# other than $1 + +function first_filename_with_diff_hashsubvol +{ + local in_subvol=$1 + local in_path=$2 + local file_pattern=$3 + local in_hash_subvol + + for i in {1..100} + do + dstfilename="$file_pattern$i" + in_hash_subvol=$(get_hash_subvol "$dstfilename" "$in_path") + echo $in_hash_subvol + if [ "$in_subvol" != "$in_hash_subvol" ]; then + return 0 + fi + done + return 1 +} + +# Find the first filename that hashes to the same subvol +# as $1 +function first_filename_with_same_hashsubvol +{ + local in_subvol=$1 + local in_path=$2 + local in_hash_subvol + local file_pattern=$3 + + for i in {1..100} + do + dstfilename="$file_pattern$i" + get_hash_subvol "$dstfilename" "$in_path" + in_hash_subvol=$hash_subvol +# echo $in_hash_subvol + if [ "$in_subvol" == "$in_hash_subvol" ]; then + return 0 + fi + done + return 1 +} + +function file_is_linkto +{ + local brick_filepath=$1 + + test=$(stat $brick_filepath 2>&1) + if [ $? -ne 0 ]; then + echo "2" + return + fi + + test=$(getfattr -n trusted.glusterfs.dht.linkto -e text $brick_filepath 2>&1) + + if [ $? -eq 0 ]; then + echo "1" + else + echo "0" + fi +} + + + + +cleanup + +TEST glusterd +TEST pidof glusterd + + +# We need at least 4 bricks to test all combinations of hashed and +# cached files + +TEST $CLI volume create $V0 $H0:$B0/$V0-{0..3} +TEST $CLI volume start $V0 + +# Mount using FUSE +TEST glusterfs -s $H0 --volfile-id $V0 $M0 + + +################################################################ +# The first set of tests are those where the Dst file does not exist +# dst-cached = NULL +# +############################################################### + +################### Test 1 #################################### +# +# src-hashed = src-cached = dst-hashed +# dst-cached = null +# src-file = src-1 + +echo " **** Test 1 **** " + +src_file="src-1" + +TEST mkdir $M0/test-1 +TEST touch $M0/test-1/$src_file + +TEST get_hash_subvol $src_file $M0/test-1 +src_hashed=$hash_subvol +#echo "Hashed subvol for $src_file: " $src_hashed + +# Find a file name that hashes to the same subvol as $src_file +TEST first_filename_with_same_hashsubvol "$src_hashed" "$M0/test-1" "dst-" +#echo "dst-file name: " $dstfilename +dst_hashed=$src_hashed + +src_hash_brick=$(get_brick_path_for_subvol $src_hashed) + +echo "Renaming $src_file to $dstfilename" + +TEST mv $M0/test-1/$src_file $M0/test-1/$dstfilename + +# Expected: +# dst file is accessible from the mount point +# dst file exists only on the hashed brick. +# no linkto files on any bricks +# src files do not exist + + +TEST stat $M0/test-1/$dstfilename 2>/dev/null +TEST file_existence_check test-1/$dstfilename $src_hashed +TEST file_does_not_exist test-1/$src_file +EXPECT "0" file_is_linkto $src_hash_brick/test-1/$dstfilename + + +################### Test 2 #################################### + +# src-hashed = src-cached != dst-hashed +# dst-cached = null + +echo " **** Test 2 **** " + +src_file="src-1" + +TEST mkdir $M0/test-2 +TEST touch $M0/test-2/$src_file + +TEST get_hash_subvol $src_file $M0/test-2 +src_hashed=$hash_subvol +#echo "Hashed subvol for $src_file: " $src_hashed + +# Find a file name that hashes to a diff hashed subvol than $src_file +TEST first_filename_with_diff_hashsubvol "$src_hashed" "$M0/test-2" "dst-" +echo "dst-file name: " $dstfilename +TEST get_hash_subvol $dstfilename $M0/test-2 +dst_hashed=$hash_subvol + +src_hash_brick=$(get_brick_path_for_subvol $src_hashed) +dst_hash_brick=$(get_brick_path_for_subvol $dst_hashed) + +echo "Renaming $src_file to $dstfilename" + +TEST mv $M0/test-2/$src_file $M0/test-2/$dstfilename + + +# Expected: +# dst file is accessible from the mount point +# dst data file on src_hashed and dst linkto file on dst_hashed +# src files do not exist + + +TEST stat $M0/test-2/$dstfilename 2>/dev/null +TEST file_existence_check test-2/$dstfilename $dst_hashed $src_hashed +TEST file_does_not_exist test-2/$src_file +EXPECT "1" file_is_linkto $dst_hash_brick/test-2/$dstfilename +EXPECT "0" file_is_linkto $src_hash_brick/test-2/$dstfilename + +################### Test 3 #################################### + +# src-hashed = dst-hashed != src-cached + +echo " **** Test 3 **** " + +src_file0="abc-1" + +# 1. Create src file with src_cached != src_hashed +TEST mkdir $M0/test-3 +TEST touch $M0/test-3/$src_file0 + +TEST get_hash_subvol $src_file0 $M0/test-3 +src_cached=$hash_subvol +#echo "Hashed subvol for $src_file0: " $src_cached + +# Find a file name that hashes to a diff hashed subvol than $src_file0 +TEST first_filename_with_diff_hashsubvol "$src_cached" "$M0/test-3" "src-" +echo "dst-file name: " $dstfilename +src_file=$dstfilename + +TEST mv $M0/test-3/$src_file0 $M0/test-3/$src_file + +TEST get_hash_subvol $src_file $M0/test-3 +src_hashed=$hash_subvol + + +# 2. Rename src to dst +TEST first_filename_with_same_hashsubvol "$src_hashed" "$M0/test-3" "dst-" +#echo "dst-file name: " $dstfilename + +src_hash_brick=$(get_brick_path_for_subvol $src_hashed) +src_cached_brick=$(get_brick_path_for_subvol $src_cached) + +echo "Renaming $src_file to $dstfilename" + +TEST mv $M0/test-3/$src_file $M0/test-3/$dstfilename + + +# Expected: +# dst file is accessible from the mount point +TEST stat $M0/test-3/$dstfilename 2>/dev/null + +# src file does not exist +TEST file_does_not_exist test-3/$src_file + +# dst linkto file on src_hashed and dst data file on src_cached +TEST file_existence_check test-3/$dstfilename $src_hashed $src_cached + +EXPECT "1" file_is_linkto $src_hash_brick/test-3/$dstfilename +EXPECT "0" file_is_linkto $src_cached_brick/test-3/$dstfilename + + + +################### Test 4 #################################### + +# src-cached = dst-hashed != src-hashed + +echo " **** Test 4 **** " + +src_file0="abc-1" + +# 1. Create src file with src_cached != src_hashed +TEST mkdir $M0/test-4 +TEST touch $M0/test-4/$src_file0 + +TEST get_hash_subvol $src_file0 $M0/test-4 +src_cached=$hash_subvol +#echo "Hashed subvol for $src_file0: " $src_cached + +# Find a file name that hashes to a diff hashed subvol than $src_file0 +TEST first_filename_with_diff_hashsubvol "$src_cached" "$M0/test-4" "src-" +src_file=$dstfilename + +TEST mv $M0/test-4/$src_file0 $M0/test-4/$src_file + +TEST get_hash_subvol $src_file $M0/test-4 +src_hashed=$hash_subvol + + +# 2. Rename src to dst +TEST first_filename_with_same_hashsubvol "$src_cached" "$M0/test-4" "dst-" +#echo "dst-file name: " $dstfilename + +src_hash_brick=$(get_brick_path_for_subvol $src_hashed) +src_cached_brick=$(get_brick_path_for_subvol $src_cached) + +echo "Renaming $src_file to $dstfilename" + +TEST mv $M0/test-4/$src_file $M0/test-4/$dstfilename + +# Expected: +# dst file is accessible from the mount point +TEST stat $M0/test-4/$dstfilename 2>/dev/null + +# src file does not exist +TEST file_does_not_exist test-4/$src_file + +# dst linkto file on src_hashed and dst data file on src_cached +TEST file_existence_check test-4/$dstfilename $src_cached + +EXPECT "0" file_is_linkto $src_cached_brick/test-4/$dstfilename + + +################### Test 5 #################################### + +# src-cached != src-hashed +# src-hashed != dst-hashed +# src-cached != dst-hashed + + +echo " **** Test 5 **** " + +# 1. Create src and dst files + +TEST mkdir $M0/test-5 + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-5" "abc-" +src_file0=$dstfilename + +TEST touch $M0/test-5/$src_file0 + +TEST get_hash_subvol $src_file0 $M0/test-5 +src_cached=$hash_subvol +#echo "Hashed subvol for $src_file0: " $src_cached + +# Find a file name that hashes to a diff hashed subvol than $src_file0 +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-5" "src-" +src_file=$dstfilename + +TEST mv $M0/test-5/$src_file0 $M0/test-5/$src_file + +TEST get_hash_subvol $src_file $M0/test-5 +src_hashed=$hash_subvol + +TEST first_filename_with_same_hashsubvol "$V0-client-2" "$M0/test-5" "dst-" +#echo "dst-file name: " $dstfilename + +dst_hash_brick=$(get_brick_path_for_subvol "$V0-client-2") +src_cached_brick=$(get_brick_path_for_subvol $src_cached) + + +# 2. Rename src to dst +echo "Renaming $src_file to $dstfilename" + +TEST mv $M0/test-5/$src_file $M0/test-5/$dstfilename + + +# 3. Validate + +# Expected: +# dst file is accessible from the mount point +TEST stat $M0/test-5/$dstfilename 2>/dev/null + +# src file does not exist +TEST file_does_not_exist test-5/$src_file + +# dst linkto file on src_hashed and dst data file on src_cached + +EXPECT "0" file_is_linkto $src_cached_brick/test-5/$dstfilename +EXPECT "1" file_is_linkto $dst_hash_brick/test-5/$dstfilename + + +######################################################################## +# +# The Dst file exists +# +######################################################################## + +################### Test 6 #################################### + +# src_hash = src_cached +# dst_hash = dst_cached +# dst_hash = src_hash + + +TEST mkdir $M0/test-6 + +# 1. Create src and dst files + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-6" "src-" +src_file=$dstfilename + +TEST touch $M0/test-6/$src_file + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-6" "dst-" +dst_file=$dstfilename + +TEST touch $M0/test-6/$dst_file + + +# 2. Rename src to dst + +TEST mv $M0/test-6/$src_file $M0/test-6/$dst_file + + +# 3. Validate + +dst_hash_brick=$(get_brick_path_for_subvol "$V0-client-0") + +TEST stat $M0/test-6/$dst_file 2>/dev/null +TEST file_existence_check test-6/$dst_file "$V0-client-0" +TEST file_does_not_exist test-6/$src_file +EXPECT "0" file_is_linkto $dst_hash_brick/test-6/$dst_file + + +################### Test 7 #################################### + +# src_hash = src_cached +# dst_hash = dst_cached +# dst_hash != src_hash + + +echo " **** Test 7 **** " + +TEST mkdir $M0/test-7 + +# 1. Create src and dst files + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-7" "src-" +src_file=$dstfilename + +TEST touch $M0/test-7/$src_file + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-7" "dst-" +dst_file=$dstfilename + +TEST touch $M0/test-7/$dst_file + + +# 2. Rename src to dst + +TEST mv $M0/test-7/$src_file $M0/test-7/$dst_file + + +# 3. Validate + +dst_hash_brick=$(get_brick_path_for_subvol "$V0-client-1") +src_hash_brick=$(get_brick_path_for_subvol "$V0-client-0") + +TEST stat $M0/test-7/$dst_file 2>/dev/null +TEST file_existence_check test-7/$dst_file "$V0-client-1" "$V0-client-0" +TEST file_does_not_exist test-7/$src_file + +EXPECT "0" file_is_linkto $src_hash_brick/test-7/$dst_file +EXPECT "1" file_is_linkto $dst_hash_brick/test-7/$dst_file + + +################### Test 8 #################################### + +# src_hash = src_cached +# dst_hash != dst_cached +# dst_hash != src_hash +# dst_cached != src_hash + +echo " **** Test 8 **** " + +TEST mkdir $M0/test-8 + + +# 1. Create src and dst files + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-8" "src-" +src_file=$dstfilename +TEST touch $M0/test-8/$src_file + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-8" "dst0-" +dst_file0=$dstfilename +TEST touch $M0/test-8/$dst_file0 + +TEST first_filename_with_same_hashsubvol "$V0-client-2" "$M0/test-8" "dst-" +dst_file=$dstfilename + +mv $M0/test-8/$dst_file0 $M0/test-8/$dst_file + + +# 2. Rename the file + +mv $M0/test-8/$src_file $M0/test-8/$dst_file + + +# 3. Validate + +dst_hash_brick=$(get_brick_path_for_subvol "$V0-client-2") +src_hash_brick=$(get_brick_path_for_subvol "$V0-client-0") + +TEST stat $M0/test-8/$dst_file 2>/dev/null +TEST file_existence_check test-8/$dst_file "$V0-client-2" "$V0-client-0" +TEST file_does_not_exist test-8/$src_file + +EXPECT "0" file_is_linkto $src_hash_brick/test-8/$dst_file +EXPECT "1" file_is_linkto $dst_hash_brick/test-8/$dst_file + +################### Test 9 #################################### + +# src_hash = src_cached = dst_hash +# dst_hash != dst_cached + +echo " **** Test 9 **** " + +TEST mkdir $M0/test-9 + + +# 1. Create src and dst files + + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-9" "src-" +src_file=$dstfilename +TEST touch $M0/test-9/$src_file + + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-9" "dst0-" +dst0_file=$dstfilename +TEST touch $M0/test-9/$dst0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-9" "dst-" +dst_file=$dstfilename + +TEST mv $M0/test-9/$dst0_file $M0/test-9/$dst_file + +# 2. Rename the file + +mv $M0/test-9/$src_file $M0/test-9/$dst_file + + +# 3. Validate + +dst_hash_brick=$(get_brick_path_for_subvol "$V0-client-0") + +TEST stat $M0/test-9/$dst_file 2>/dev/null +TEST file_existence_check test-9/$dst_file "$V0-client-0" +TEST file_does_not_exist test-9/$src_file +EXPECT "0" file_is_linkto $dst_hash_brick/test-9/$dst_file + + +################### Test 10 #################################### + +# src_hash = src_cached = dst_cached +# dst_hash != dst_cached + +echo " **** Test 10 **** " + +TEST mkdir $M0/test-10 + + +# 1. Create src and dst files + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-10" "src-" +src_file=$dstfilename +TEST touch $M0/test-10/$src_file + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-10" "dst0-" +dst0_file=$dstfilename +TEST touch $M0/test-10/$dst0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-10" "dst-" +dst_file=$dstfilename + +mv $M0/test-10/$dst0_file $M0/test-10/$dst_file + + +# 2. Rename the file + +mv $M0/test-10/$src_file $M0/test-10/$dst_file + + +# 3. Validate + +dst_hash_brick=$(get_brick_path_for_subvol "$V0-client-1") +dst_cached_brick=$(get_brick_path_for_subvol "$V0-client-0") + +TEST stat $M0/test-10/$dst_file 2>/dev/null +TEST file_existence_check test-10/$dst_file "$V0-client-1" "$V0-client-0" +TEST file_does_not_exist test-10/$src_file +EXPECT "1" file_is_linkto $dst_hash_brick/test-10/$dst_file +EXPECT "0" file_is_linkto $dst_cached_brick/test-10/$dst_file + + +################### Test 11 #################################### + +# src_hash != src_cached +# dst_hash = dst_cached = src_cached + +echo " **** Test 11 **** " + +TEST mkdir $M0/test-11 + + +# 1. Create src and dst files + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-11" "src0-" +src0_file=$dstfilename +TEST touch $M0/test-11/$src0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-11" "src-" +src_file=$dstfilename + +mv $M0/test-11/$src0_file $M0/test-11/$src_file + + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-11" "dst-" +dst_file=$dstfilename +TEST touch $M0/test-11/$dst_file + + +# 2. Rename the file + +mv $M0/test-11/$src_file $M0/test-11/$dst_file + + +# 3. Validate + +dst_hash_brick=$(get_brick_path_for_subvol "$V0-client-0") + +TEST stat $M0/test-11/$dst_file 2>/dev/null +TEST file_existence_check test-11/$dst_file "$V0-client-0" +TEST file_does_not_exist test-11/$src_file +EXPECT "0" file_is_linkto $dst_hash_brick/test-11/$dst_file + + +################### Test 12 #################################### + +# src_hash != src_cached +# dst_hash = dst_cached = src_hash + +echo " **** Test 12 **** " + +TEST mkdir $M0/test-12 + + +# 1. Create src and dst files + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-12" "src0-" +src0_file=$dstfilename +TEST touch $M0/test-12/$src0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-12" "src-" +src_file=$dstfilename + +mv $M0/test-12/$src0_file $M0/test-12/$src_file + + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-12" "dst-" +dst_file=$dstfilename +TEST touch $M0/test-12/$dst_file + + +# 2. Rename the file + +mv $M0/test-12/$src_file $M0/test-12/$dst_file + + +# 3. Validate + +dst_hash_brick=$(get_brick_path_for_subvol "$V0-client-1") +dst_cached_brick=$(get_brick_path_for_subvol "$V0-client-0") + +TEST stat $M0/test-12/$dst_file 2>/dev/null +TEST file_existence_check test-12/$dst_file "$V0-client-1" "$V0-client-0" +TEST file_does_not_exist test-12/$src_file +EXPECT "1" file_is_linkto $dst_hash_brick/test-12/$dst_file +EXPECT "0" file_is_linkto $dst_cached_brick/test-12/$dst_file + +################### Test 13 #################################### + +# src_hash != src_cached +# dst_hash = dst_cached +# dst_hash != src_cached +# dst_hash != src_hash + +echo " **** Test 13 **** " + +TEST mkdir $M0/test-13 + + +# 1. Create src and dst files + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-13" "src0-" +src0_file=$dstfilename +TEST touch $M0/test-13/$src0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-13" "src-" +src_file=$dstfilename + +mv $M0/test-13/$src0_file $M0/test-13/$src_file + + +TEST first_filename_with_same_hashsubvol "$V0-client-2" "$M0/test-13" "dst-" +dst_file=$dstfilename +TEST touch $M0/test-13/$dst_file + +# 2. Rename the file + +mv $M0/test-13/$src_file $M0/test-13/$dst_file + + +# 3. Validate + +dst_hash_brick=$(get_brick_path_for_subvol "$V0-client-2") +dst_cached_brick=$(get_brick_path_for_subvol "$V0-client-0") + +TEST stat $M0/test-13/$dst_file 2>/dev/null +TEST file_existence_check test-13/$dst_file "$V0-client-2" "$V0-client-0" +TEST file_does_not_exist test-13/$src_file +EXPECT "1" file_is_linkto $dst_hash_brick/test-13/$dst_file +EXPECT "0" file_is_linkto $dst_cached_brick/test-13/$dst_file + + +################### Test 14 #################################### + +# src_hash != src_cached +# dst_hash = src_hash +# dst_cached = src_cached + +echo " **** Test 14 **** " + +TEST mkdir $M0/test-14 + + +# 1. Create src and dst files + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-14" "src0-" +src0_file=$dstfilename +TEST touch $M0/test-14/$src0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-14" "src-" +src_file=$dstfilename + +mv $M0/test-14/$src0_file $M0/test-14/$src_file + + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-14" "dst0-" +dst0_file=$dstfilename +TEST touch $M0/test-14/$dst0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-14" "dst-" +dst_file=$dstfilename + +mv $M0/test-14/$dst0_file $M0/test-14/$dst_file + + +# 2. Rename the file + +mv $M0/test-14/$src_file $M0/test-14/$dst_file + + +# 3. Validate + +dst_hash_brick=$(get_brick_path_for_subvol "$V0-client-1") +dst_cached_brick=$(get_brick_path_for_subvol "$V0-client-0") + +TEST stat $M0/test-14/$dst_file 2>/dev/null +TEST file_existence_check test-14/$dst_file "$V0-client-1" "$V0-client-0" +TEST file_does_not_exist test-14/$src_file +EXPECT "1" file_is_linkto $dst_hash_brick/test-14/$dst_file +EXPECT "0" file_is_linkto $dst_cached_brick/test-14/$dst_file + +################### Test 15 #################################### + +# src_hash != src_cached +# dst_hash != src_hash +# dst_hash != src_cached +# dst_cached = src_cached + +echo " **** Test 15 **** " + +TEST mkdir $M0/test-15 + + +# 1. Create src and dst files + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-15" "src0-" +src0_file=$dstfilename +TEST touch $M0/test-15/$src0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-15" "src-" +src_file=$dstfilename + +mv $M0/test-15/$src0_file $M0/test-15/$src_file + + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-15" "dst0-" +dst0_file=$dstfilename +TEST touch $M0/test-15/$dst0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-2" "$M0/test-15" "dst-" +dst_file=$dstfilename + +mv $M0/test-15/$dst0_file $M0/test-15/$dst_file + + +# 2. Rename the file + +mv $M0/test-15/$src_file $M0/test-15/$dst_file + +# 3. Validate + +dst_hash_brick=$(get_brick_path_for_subvol "$V0-client-2") +dst_cached_brick=$(get_brick_path_for_subvol "$V0-client-0") + +TEST stat $M0/test-15/$dst_file 2>/dev/null +TEST file_existence_check test-15/$dst_file "$V0-client-2" "$V0-client-0" +TEST file_does_not_exist test-15/$src_file +EXPECT "1" file_is_linkto $dst_hash_brick/test-15/$dst_file +EXPECT "0" file_is_linkto $dst_cached_brick/test-15/$dst_file + + + +################### Test 16 #################################### + +# src_hash != src_cached +# dst_hash = src_cached +# dst_cached = src_hash + +echo " **** Test 16 **** " + +TEST mkdir $M0/test-16 + + +# 1. Create src and dst files + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-16" "src0-" +src0_file=$dstfilename +TEST touch $M0/test-16/$src0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-16" "src-" +src_file=$dstfilename + +mv $M0/test-16/$src0_file $M0/test-16/$src_file + + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-16" "dst0-" +dst0_file=$dstfilename +TEST touch $M0/test-16/$dst0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-16" "dst-" +dst_file=$dstfilename + +mv $M0/test-16/$dst0_file $M0/test-16/$dst_file + + +# 2. Rename the file + +mv $M0/test-16/$src_file $M0/test-16/$dst_file + +# 3. Validate + +dst_hash_brick=$(get_brick_path_for_subvol "$V0-client-0") + +TEST stat $M0/test-16/$dst_file 2>/dev/null +TEST file_existence_check test-16/$dst_file "$V0-client-0" +TEST file_does_not_exist test-16/$src_file +EXPECT "0" file_is_linkto $dst_hash_brick/test-16/$dst_file + + +################### Test 17 #################################### + +# src_hash != src_cached +# dst_hash != dst_cached +# dst_hash != src_hash != src_cached +# dst_cached = src_hash + + +echo " **** Test 17 **** " + +TEST mkdir $M0/test-17 + + +# 1. Create src and dst files + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-17" "src0-" +src0_file=$dstfilename +TEST touch $M0/test-17/$src0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-17" "src-" +src_file=$dstfilename + +mv $M0/test-17/$src0_file $M0/test-17/$src_file + + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-17" "dst0-" +dst0_file=$dstfilename +TEST touch $M0/test-17/$dst0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-2" "$M0/test-17" "dst-" +dst_file=$dstfilename + +mv $M0/test-17/$dst0_file $M0/test-17/$dst_file + + +# 2. Rename the file + +mv $M0/test-17/$src_file $M0/test-17/$dst_file + +# 3. Validate + +dst_hash_brick=$(get_brick_path_for_subvol "$V0-client-2") +dst_cached_brick=$(get_brick_path_for_subvol "$V0-client-0") + +TEST stat $M0/test-17/$dst_file 2>/dev/null +TEST file_existence_check test-17/$dst_file "$V0-client-2" "$V0-client-0" +TEST file_does_not_exist test-17/$src_file +EXPECT "1" file_is_linkto $dst_hash_brick/test-17/$dst_file +EXPECT "0" file_is_linkto $dst_cached_brick/test-17/$dst_file + + +################### Test 18 #################################### + +# src_hash != src_cached +# dst_hash != dst_cached +# dst_hash != src_hash != src_cached != dst_cached + + +echo " **** Test 18 **** " + +TEST mkdir $M0/test-18 + + +# 1. Create src and dst files + +TEST first_filename_with_same_hashsubvol "$V0-client-0" "$M0/test-18" "src0-" +src0_file=$dstfilename +TEST touch $M0/test-18/$src0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-1" "$M0/test-18" "src-" +src_file=$dstfilename + +mv $M0/test-18/$src0_file $M0/test-18/$src_file + + +TEST first_filename_with_same_hashsubvol "$V0-client-2" "$M0/test-18" "dst0-" +dst0_file=$dstfilename +TEST touch $M0/test-18/$dst0_file + +TEST first_filename_with_same_hashsubvol "$V0-client-3" "$M0/test-18" "dst-" +dst_file=$dstfilename + +mv $M0/test-18/$dst0_file $M0/test-18/$dst_file + + +# 2. Rename the file + +mv $M0/test-18/$src_file $M0/test-18/$dst_file + +# 3. Validate + +dst_hash_brick=$(get_brick_path_for_subvol "$V0-client-3") +dst_cached_brick=$(get_brick_path_for_subvol "$V0-client-0") + +TEST stat $M0/test-18/$dst_file 2>/dev/null +TEST file_existence_check test-18/$dst_file "$V0-client-3" "$V0-client-0" +TEST file_does_not_exist test-18/$src_file +EXPECT "1" file_is_linkto $dst_hash_brick/test-18/$dst_file +EXPECT "0" file_is_linkto $dst_cached_brick/test-18/$dst_file + + +# Cleanup +cleanup + diff --git a/tests/basic/distribute/force-migration.t b/tests/basic/distribute/force-migration.t new file mode 100644 index 00000000000..f6c4997a505 --- /dev/null +++ b/tests/basic/distribute/force-migration.t @@ -0,0 +1,50 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +#This tests checks if the file migration fails with force-migration +#option set to off. + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 $H0:$B0/${V0}0 $H0:$B0/${V0}1 +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 start $V0 +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 +TEST touch $M0/file +#This rename creates a link file for tile in the other brick. +TEST mv $M0/file $M0/tile +#Lets keep writing to the file which will have a open fd +dd if=/dev/zero of=$M0/tile bs=1b & +bg_pid=$! +#Now rebalance will try to skip the file +TEST $CLI volume set $V0 force-migration off +TEST $CLI volume rebalance $V0 start force +EXPECT_WITHIN $REBALANCE_TIMEOUT "completed" rebalance_status_field $V0 +skippedcount=`gluster v rebalance $V0 status | awk 'NR==3{print $6}'` +TEST [[ $skippedcount -eq 1 ]] +#file should be migrated now +TEST $CLI volume set $V0 force-migration on +TEST $CLI volume rebalance $V0 start force +EXPECT_WITHIN $REBALANCE_TIMEOUT "completed" rebalance_status_field $V0 +skippedcount=`gluster v rebalance $V0 status | awk 'NR==3{print $6}'` +rebalancedcount=`gluster v rebalance $V0 status | awk 'NR==3{print $2}'` +TEST [[ $skippedcount -eq 0 ]] +TEST [[ $rebalancedcount -eq 1 ]] +kill -9 $bg_pid > /dev/null 2>&1 +wait > /dev/null 2>&1 +cleanup +#Bad test because we are not sure writes are happening at the time of +#rebalance. We need to write a test case which makes sure client +#writes happen during rebalance. One way would be to set S+T bits on +#src and write to file from client and then start rebalance. Currently +#marking this as bad test. +#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=000000 + diff --git a/tests/basic/distribute/lookup.t b/tests/basic/distribute/lookup.t new file mode 100644 index 00000000000..f757bd99fd9 --- /dev/null +++ b/tests/basic/distribute/lookup.t @@ -0,0 +1,54 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../nfs.rc +. $(dirname $0)/../../common-utils.rc + +# Test overview: +# Check that non-privileged users can also clean up stale linkto files +# +# 1. Use the current parallel-readdir behaviour of changing the DHT child subvols +# in the graph to generate stale linkto files +# 2. Access the file with the stale linkto file as a non-root user +# 3. This should now succeed (returned EIO before commit 3fb1df7870e03c9de) + +cleanup + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/$V0-{1..3} +TEST $CLI volume start $V0 + +# Mount using FUSE and create a file +TEST glusterfs -s $H0 --volfile-id $V0 $M0 +TEST glusterfs -s $H0 --volfile-id $V0 $M1 + +ls $M0/FILE-1 +EXPECT "2" echo $? + + +# Create a file and a directory on $M0 +TEST dd if=/dev/urandom of=$M0/FILE-1 count=1 bs=16k +TEST mkdir $M0/dir1 + +ls $M0/FILE-1 +EXPECT "0" echo $? + +ls $M0/dir1 +EXPECT "0" echo $? + +#Use a fresh mount so as to trigger a fresh lookup +TEST glusterfs -s $H0 --volfile-id $V0 $M1 + +TEST ls $M1/FILE-1 +EXPECT "0" echo $? + + +ls $M1/dir1 +EXPECT "0" echo $? + +# Cleanup +cleanup + diff --git a/tests/basic/distribute/non-root-unlink-stale-linkto.t b/tests/basic/distribute/non-root-unlink-stale-linkto.t new file mode 100644 index 00000000000..d6c866ffc8e --- /dev/null +++ b/tests/basic/distribute/non-root-unlink-stale-linkto.t @@ -0,0 +1,51 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../nfs.rc +. $(dirname $0)/../../common-utils.rc + +# Test overview: +# Check that non-privileged users can also clean up stale linkto files +# +# 1. Use the current parallel-readdir behaviour of changing the DHT child subvols +# in the graph to generate stale linkto files +# 2. Access the file with the stale linkto file as a non-root user +# 3. This should now succeed (returned EIO before commit 3fb1df7870e03c9de) + +USERNAME=user11 +cleanup + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/$V0-{1,2} +TEST $CLI volume start $V0 +TEST $CLI volume set $V0 performance.parallel-readdir on + +# Mount using FUSE and create a file +TEST glusterfs -s $H0 --volfile-id $V0 $M0 + +# Create a file for testing +TEST dd if=/dev/urandom of=$M0/FILE-1 count=1 bs=16k + +#Rename to create a linkto file +TEST mv $M0/FILE-1 $M0/FILE-2 + +# This should change the graph and cause the linkto values to become stale +TEST $CLI volume set $V0 performance.parallel-readdir off + +$CLI volume set $V0 allow-insecure on + + +TEST useradd -m $USERNAME + +#Use a fresh mount so as to trigger a lookup everywhere +TEST glusterfs -s $H0 --volfile-id $V0 $M1 +TEST run_cmd_as_user $USERNAME "ls $M1/FILE-2" + + +# Cleanup +TEST userdel --force $USERNAME +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/distribute/throttle-rebal.t b/tests/basic/distribute/throttle-rebal.t index 89495aee71b..f4823cf4f21 100644 --- a/tests/basic/distribute/throttle-rebal.t +++ b/tests/basic/distribute/throttle-rebal.t @@ -16,6 +16,11 @@ function set_throttle { $CLI volume set $V0 cluster.rebal-throttle $level 2>&1 |grep -oE 'success|failed' } +#Determine number of cores +cores=$(cat /proc/cpuinfo | grep processor | wc -l) +if [ "$cores" == "" ]; then + echo "Could not get number of cores available" +fi THROTTLE_LEVEL="lazy" EXPECT "success" set_throttle $THROTTLE_LEVEL @@ -36,6 +41,15 @@ EXPECT "failed" set_throttle $THROTTLE_LEVEL #check if throttle-level is still aggressive EXPECT "aggressive" echo `$CLI volume info | grep rebal-throttle | awk '{print $2}'` +EXPECT "success" set_throttle $cores + +#Setting thorttle number to be more than the number of cores should fail +THORTTLE_LEVEL=$((cores+1)) +TEST echo $THORTTLE_LEVEL +EXPECT "failed" set_throttle $THROTTLE_LEVEL +EXPECT "$cores" echo `$CLI volume info | grep rebal-throttle | awk '{print $2}'` + + TEST $CLI volume stop $V0; TEST $CLI volume delete $V0; diff --git a/tests/basic/ec/ec-12-4.t b/tests/basic/ec/ec-12-4.t deleted file mode 100644 index 76e6f8e77e8..00000000000 --- a/tests/basic/ec/ec-12-4.t +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc - -# This test checks basic dispersed volume functionality and cli interface - -DISPERSE=12 -REDUNDANCY=4 - -# This must be equal to 36 * $DISPERSE + 109 -TESTS_EXPECTED_IN_LOOP=541 - -. $(dirname $0)/ec-common diff --git a/tests/basic/ec/ec-1468261.t b/tests/basic/ec/ec-1468261.t new file mode 100644 index 00000000000..77d704cf880 --- /dev/null +++ b/tests/basic/ec/ec-1468261.t @@ -0,0 +1,95 @@ +#!/bin/bash +# +# This test case verifies handling node down scenario with optimistic +# changelog enabled on EC volume. +### + +SCRIPT_TIMEOUT=300 + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup + +#cleate and start volume +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 6 redundancy 2 $H0:$B0/${V0}{0..5} +TEST $CLI volume set $V0 disperse.optimistic-change-log on +TEST $CLI volume set $V0 disperse.other-eager-lock on +TEST $CLI volume start $V0 + +#Mount the volume +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 + +#Verify that all is good +TEST mkdir $M0/test_dir +TEST touch $M0/test_dir/file +sleep 2 +EXPECT_WITHIN $IO_WAIT_TIMEOUT "^$" get_hex_xattr trusted.ec.dirty $B0/${V0}0/test_dir +EXPECT_WITHIN $IO_WAIT_TIMEOUT "^$" get_hex_xattr trusted.ec.dirty $B0/${V0}1/test_dir +EXPECT_WITHIN $IO_WAIT_TIMEOUT "^$" get_hex_xattr trusted.ec.dirty $B0/${V0}2/test_dir +EXPECT_WITHIN $IO_WAIT_TIMEOUT "^$" get_hex_xattr trusted.ec.dirty $B0/${V0}3/test_dir +EXPECT_WITHIN $IO_WAIT_TIMEOUT "^$" get_hex_xattr trusted.ec.dirty $B0/${V0}4/test_dir +EXPECT_WITHIN $IO_WAIT_TIMEOUT "^$" get_hex_xattr trusted.ec.dirty $B0/${V0}5/test_dir + +#Kill two bricks and touch a file +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "4" ec_child_up_count $V0 0 +TEST touch $M0/test_dir/new_file +sleep 2 + +#Dirty should be set on up bricks +EXPECT_WITHIN $IO_WAIT_TIMEOUT "^00000000000000010000000000000001$" get_hex_xattr trusted.ec.dirty $B0/${V0}2/test_dir +EXPECT_WITHIN $IO_WAIT_TIMEOUT "^00000000000000010000000000000001$" get_hex_xattr trusted.ec.dirty $B0/${V0}3/test_dir +EXPECT_WITHIN $IO_WAIT_TIMEOUT "^00000000000000010000000000000001$" get_hex_xattr trusted.ec.dirty $B0/${V0}4/test_dir +EXPECT_WITHIN $IO_WAIT_TIMEOUT "^00000000000000010000000000000001$" get_hex_xattr trusted.ec.dirty $B0/${V0}5/test_dir + +#Bring up the down bricks +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 + +#remove mount point contents +TEST rm -rf $M0"/*" 2>/dev/null + +# unmount and remount the volume +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST glusterfs -s $H0 --volfile-id $V0 $M0; + +#Create a tar file +TEST mkdir /tmp/test_dir +seq 1 3000 | xargs -n 1 -P 20 -I {} dd if=/dev/urandom of=/tmp/test_dir/file-{} bs=10K count=1 +tar -cf /tmp/test_dir.tar /tmp/test_dir/ 2>/dev/null +rm -rf /tmp/test_dir/ + +#Untar the tar file +tar -C $M0 -xf /tmp/test_dir.tar 2>/dev/null& + +#Kill 1st and 2nd brick +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "4" ec_child_up_count $V0 0 + +#Stop untaring +TEST kill %1 +rm -f /tmp/test_dir.tar + +#Bring up the down bricks +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 + +#Wait for heal to complete +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +#Kill 3rd and 4th brick +TEST kill_brick $V0 $H0 $B0/${V0}3 +TEST kill_brick $V0 $H0 $B0/${V0}4 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "4" ec_child_up_count $V0 0 + +#remove mount point contents +#this will fail if things are wrong +TEST rm -rf $M0"/*" 2>/dev/null + +cleanup diff --git a/tests/basic/ec/ec-5-1.t b/tests/basic/ec/ec-5-1.t deleted file mode 100644 index 35c205da4b7..00000000000 --- a/tests/basic/ec/ec-5-1.t +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc - -# This test checks basic dispersed volume functionality and cli interface - -DISPERSE=5 -REDUNDANCY=1 - -# This must be equal to 36 * $DISPERSE + 109 -TESTS_EXPECTED_IN_LOOP=289 - -. $(dirname $0)/ec-common diff --git a/tests/basic/ec/ec-7-3.t b/tests/basic/ec/ec-7-3.t deleted file mode 100644 index 9d9d5f691bf..00000000000 --- a/tests/basic/ec/ec-7-3.t +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc - -# This test checks basic dispersed volume functionality and cli interface - -DISPERSE=7 -REDUNDANCY=3 - -# This must be equal to 36 * $DISPERSE + 109 -TESTS_EXPECTED_IN_LOOP=361 - -. $(dirname $0)/ec-common diff --git a/tests/basic/ec/ec-background-heals.t b/tests/basic/ec/ec-background-heals.t index 726e60d8fea..29778a4f818 100644 --- a/tests/basic/ec/ec-background-heals.t +++ b/tests/basic/ec/ec-background-heals.t @@ -16,6 +16,8 @@ TEST $CLI volume set $V0 performance.quick-read off TEST $CLI volume set $V0 performance.read-ahead off TEST $CLI volume set $V0 performance.io-cache off TEST $CLI volume set $V0 disperse.background-heals 0 +TEST $CLI volume set $V0 disperse.eager-lock off +TEST $CLI volume set $V0 disperse.other-eager-lock off TEST $CLI volume start $V0 TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; @@ -23,6 +25,10 @@ EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "0" mount_get_option_value $M0 $V0-disperse-0 background-heals EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "0" mount_get_option_value $M0 $V0-disperse-0 heal-wait-qlength TEST touch $M0/a +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" count_sh_entries $B0/${V0}0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" count_sh_entries $B0/${V0}1 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" count_sh_entries $B0/${V0}2 + TEST kill_brick $V0 $H0 $B0/${V0}2 echo abc > $M0/a EXPECT 2 get_pending_heal_count $V0 #One for each active brick @@ -30,7 +36,6 @@ $CLI volume start $V0 force EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 #Accessing file shouldn't heal the file EXPECT "abc" cat $M0/a -sleep 3 EXPECT 2 get_pending_heal_count $V0 #One for each active brick TEST $CLI volume set $V0 disperse.background-heals 1 EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "1" mount_get_option_value $M0 $V0-disperse-0 background-heals diff --git a/tests/basic/ec/ec-badfd.c b/tests/basic/ec/ec-badfd.c new file mode 100644 index 00000000000..8be23c10eaf --- /dev/null +++ b/tests/basic/ec/ec-badfd.c @@ -0,0 +1,124 @@ +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <time.h> +#include <limits.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> + +int +fill_iov(struct iovec *iov, char fillchar, int count) +{ + int ret = -1; + + iov->iov_base = malloc(count + 1); + if (iov->iov_base == NULL) { + return ret; + } else { + iov->iov_len = count; + ret = 0; + } + memset(iov->iov_base, fillchar, count); + memset(iov->iov_base + count, '\0', 1); + + return ret; +} + +int +write_sync(glfs_t *fs, glfs_fd_t *glfd, int char_count) +{ + ssize_t ret = -1; + int flags = O_RDWR; + struct iovec iov = {0}; + + ret = fill_iov(&iov, 'a', char_count); + if (ret) { + fprintf(stderr, "failed to create iov"); + goto out; + } + + ret = glfs_pwritev(glfd, &iov, 1, 0, flags); +out: + if (ret < 0) { + fprintf(stderr, "glfs_pwritev failed, %d", errno); + } + return ret; +} + +int +main(int argc, char *argv[]) +{ + glfs_t *fs = NULL; + glfs_fd_t *fd = NULL; + int ret = 1; + char volume_cmd[4096] = {0}; + + if (argc != 4) { + fprintf(stderr, "Syntax: %s <host> <volname> <file>\n", argv[0]); + return 1; + } + + fs = glfs_new(argv[2]); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + return 1; + } + + ret = glfs_set_volfile_server(fs, "tcp", argv[1], 24007); + if (ret != 0) { + fprintf(stderr, "glfs_set_volfile_server: returned %d\n", ret); + goto out; + } + ret = glfs_set_logging(fs, "/tmp/ec-badfd.log", 7); + if (ret != 0) { + fprintf(stderr, "glfs_set_logging: returned %d\n", ret); + goto out; + } + ret = glfs_init(fs); + if (ret != 0) { + fprintf(stderr, "glfs_init: returned %d\n", ret); + goto out; + } + + fd = glfs_open(fs, argv[3], O_RDWR); + if (fd == NULL) { + fprintf(stderr, "glfs_open: returned NULL\n"); + goto out; + } + + ret = write_sync(fs, fd, 16); + if (ret < 0) { + fprintf(stderr, "write_sync failed\n"); + } + + snprintf(volume_cmd, sizeof(volume_cmd), + "gluster --mode=script volume stop %s", argv[2]); + /*Stop the volume so that update-size-version fails*/ + system(volume_cmd); + sleep(8); /* 3 seconds more than eager-lock-timeout*/ + snprintf(volume_cmd, sizeof(volume_cmd), + "gluster --mode=script volume start %s", argv[2]); + system(volume_cmd); + sleep(8); /*wait for bricks to come up*/ + ret = glfs_fsync(fd, NULL, NULL); + if (ret == 0) { + fprintf(stderr, "fsync succeeded on a BADFD\n"); + exit(1); + } + + ret = glfs_close(fd); + if (ret == 0) { + fprintf(stderr, "flush succeeded on a BADFD\n"); + exit(1); + } + ret = 0; + +out: + unlink("/tmp/ec-badfd.log"); + glfs_fini(fs); + + return ret; +} diff --git a/tests/basic/ec/ec-badfd.t b/tests/basic/ec/ec-badfd.t new file mode 100755 index 00000000000..56feb47f115 --- /dev/null +++ b/tests/basic/ec/ec-badfd.t @@ -0,0 +1,26 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 disperse 6 redundancy 2 $H0:$B0/${V0}{1..6} +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume set $V0 disperse.eager-lock-timeout 5 + +TEST $CLI volume start $V0 +EXPECT 'Started' volinfo_field $V0 'Status' + +TEST $GFS -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +TEST touch $M0/file + +TEST build_tester $(dirname $0)/ec-badfd.c -lgfapi -Wall -O2 +TEST $(dirname $0)/ec-badfd $H0 $V0 /file +cleanup_tester $(dirname ${0})/ec-badfd + +cleanup; diff --git a/tests/basic/ec/ec-common b/tests/basic/ec/ec-common index 83c4463a912..152e3b51236 100644 --- a/tests/basic/ec/ec-common +++ b/tests/basic/ec/ec-common @@ -45,7 +45,7 @@ for size in $SIZE_LIST; do eval cs_big_truncate[$size]=$(sha1sum $tmp/big1 | awk '{ print $1 }') done -TEST df -h +TEST df -h $M0 TEST stat $M0 for idx in `seq 0 $LAST_BRICK`; do diff --git a/tests/basic/ec/ec-cpu-extensions.t b/tests/basic/ec/ec-cpu-extensions.t new file mode 100644 index 00000000000..c9af27ea234 --- /dev/null +++ b/tests/basic/ec/ec-cpu-extensions.t @@ -0,0 +1,62 @@ +#!/bin/bash + +DISPERSE=18 +REDUNDANCY=2 + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +TESTS_EXPECTED_IN_LOOP=96 + +function check_contents +{ + local src=$1 + local cs=$2 + + TEST cp $src $M0/file + TEST [ -f $M0/file ] + + for ext in none x64 sse avx; do + EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + TEST $CLI volume set $V0 disperse.cpu-extensions $ext + TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 + EXPECT_WITHIN $CHILD_UP_TIMEOUT "$DISPERSE" ec_child_up_count $V0 0 + + EXPECT "$cs" echo $(sha1sum $M0/file | awk '{ print $1 }') + done + + TEST rm -f $M0/file +} + +cleanup + +tmp=`mktemp -p ${LOGDIR} -d -t ${0##*/}.XXXXXX` +if [ ! -d $tmp ]; then + exit 1 +fi + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 redundancy $REDUNDANCY $H0:$B0/${V0}{1..$DISPERSE} +TEST $CLI volume set $V0 performance.flush-behind off +TEST $CLI volume set $V0 disperse.read-policy round-robin +EXPECT 'Created' volinfo_field $V0 'Status' +TEST $CLI volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'Started' volinfo_field $V0 'Status' + +TEST dd if=/dev/urandom of=$tmp/file bs=1048576 count=1 +cs_file=$(sha1sum $tmp/file | awk '{ print $1 }') + +for ext in none x64 sse avx; do + TEST $CLI volume set $V0 disperse.cpu-extensions $ext + TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 + EXPECT_WITHIN $CHILD_UP_TIMEOUT "$DISPERSE" ec_child_up_count $V0 0 + + check_contents $tmp/file $cs_file + + EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +done + +TEST rm -rf $tmp + +cleanup diff --git a/tests/basic/ec/ec-data-heal.t b/tests/basic/ec/ec-data-heal.t new file mode 100755 index 00000000000..2672661c6b1 --- /dev/null +++ b/tests/basic/ec/ec-data-heal.t @@ -0,0 +1,75 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +#This test checks data corruption after heal while IO is going on + +cleanup +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0..2} +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 + +############ Start IO ########### +TEST touch $M0/file +#start background IO on file +dd if=/dev/urandom of=$M0/file conv=fdatasync & +iopid=$(echo $!) + + +############ Kill and start brick0 for heal ########### +TEST kill_brick $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "2" ec_child_up_count $V0 0 +#sleep so that data can be written which will be healed later +sleep 10 +TEST $CLI volume start $V0 force +##wait for heal info to become 0 and kill IO +EXPECT_WITHIN $IO_HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 +kill $iopid +EXPECT_WITHIN $IO_HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +############### Check md5sum ######################### + +## unmount and mount get md5sum after killing brick0 + +TEST kill_brick $V0 $H0 $B0/${V0}0 + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "2" ec_child_up_count $V0 0 +mdsum0=`md5sum $M0/file | awk '{print $1}'` +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 + +## unmount and mount get md5sum after killing brick1 + +TEST kill_brick $V0 $H0 $B0/${V0}1 + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "2" ec_child_up_count $V0 0 +mdsum1=`md5sum $M0/file | awk '{print $1}'` +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 + +## unmount and mount get md5sum after killing brick2 + +TEST kill_brick $V0 $H0 $B0/${V0}2 + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "2" ec_child_up_count $V0 0 +mdsum2=`md5sum $M0/file | awk '{print $1}'` +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 + +# compare all the three md5sums +EXPECT "$mdsum0" echo $mdsum1 +EXPECT "$mdsum0" echo $mdsum2 +EXPECT "$mdsum1" echo $mdsum2 + +cleanup diff --git a/tests/basic/ec/ec-dirty-flags.t b/tests/basic/ec/ec-dirty-flags.t new file mode 100644 index 00000000000..68e66103f08 --- /dev/null +++ b/tests/basic/ec/ec-dirty-flags.t @@ -0,0 +1,23 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +# This checks if the fop keeps the dirty flags settings correctly after +# finishing the fop. + +cleanup +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0..2} +TEST $CLI volume heal $V0 disable +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 +cd $M0 +for i in {1..1000}; do dd if=/dev/zero of=file-${i} bs=512k count=2; done +cd - +EXPECT "^0$" get_pending_heal_count $V0 + +cleanup diff --git a/tests/basic/ec/ec-discard.t b/tests/basic/ec/ec-discard.t new file mode 100644 index 00000000000..001f4498c86 --- /dev/null +++ b/tests/basic/ec/ec-discard.t @@ -0,0 +1,205 @@ +#!/bin/bash +# +# Test discard functionality +# +# Test that basic discard (hole punch) functionality works via the fallocate +# command line tool. Hole punch deallocates a region of a file, creating a hole +# and a zero-filled data region. We verify that hole punch works, frees blocks +# and that subsequent reads do not read stale data (caches are invalidated). +# +# NOTE: fuse fallocate is known to be broken with regard to cache invalidation +# up to 3.9.0 kernels. Therefore, FOPEN_KEEP_CACHE is not used in this +# test (opens will invalidate the fuse cache). +### + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../fallocate.rc +. $(dirname $0)/../../volume.rc + +cleanup + +#cleate and start volume +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 6 redundancy 2 $H0:$B0/${V0}{0..5} +TEST $CLI volume set $V0 disperse.optimistic-change-log on +TEST $CLI volume start $V0 + +#Mount the volume +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 + +#Check for fallocate and hole punch support +require_fallocate -l 1m $M0/file +require_fallocate -p -l 512k $M0/file && rm -f $M0/file + +#Write some data, punch a hole and verify the file content changes +TEST dd if=/dev/urandom of=$M0/file bs=1024k count=1 +TEST cp $M0/file $M0/file.copy.pre +TEST fallocate -p -o 512k -l 128k $M0/file +TEST ! cmp $M0/file.copy.pre $M0/file +TEST rm -f $M0/file $M0/file.copy.pre + +#Allocate some blocks, punch a hole and verify block allocation +TEST fallocate -l 1m $M0/file +blksz=`stat -c %B $M0/file` +nblks=`stat -c %b $M0/file` +TEST [ $(($blksz * $nblks)) -ge 1048576 ] +TEST fallocate -p -o 512k -l 128k $M0/file +nblks=`stat -c %b $M0/file` +TEST [ $(($blksz * $nblks)) -lt $((933889)) ] +TEST unlink $M0/file + +###Punch hole test cases without fallocate +##With write +#Touching starting boundary +TEST dd if=/dev/urandom of=$B0/test_file bs=1024 count=8 +TEST cp $B0/test_file $M0/test_file +TEST fallocate -p -o 0 -l 500 $B0/test_file +TEST fallocate -p -o 0 -l 500 $M0/test_file +TEST md5_sum=`get_md5_sum $B0/test_file` +EXPECT $md5_sum get_md5_sum $M0/test_file +TEST rm -f $B0/test_file $M0/test_file + +#Touching boundary +TEST dd if=/dev/urandom of=$B0/test_file bs=1024 count=8 +TEST cp $B0/test_file $M0/test_file +TEST fallocate -p -o 500 -l 1548 $B0/test_file +TEST fallocate -p -o 500 -l 1548 $M0/test_file +TEST md5_sum=`get_md5_sum $B0/test_file` +EXPECT $md5_sum get_md5_sum $M0/test_file +TEST rm -f $B0/test_file $M0/test_file + +#Not touching boundary +TEST dd if=/dev/urandom of=$B0/test_file bs=1024 count=8 +TEST cp $B0/test_file $M0/test_file +TEST fallocate -p -o 500 -l 1000 $B0/test_file +TEST fallocate -p -o 500 -l 1000 $M0/test_file +TEST md5_sum=`get_md5_sum $B0/test_file` +EXPECT $md5_sum get_md5_sum $M0/test_file +TEST rm -f $B0/test_file $M0/test_file + +#Over boundary +TEST dd if=/dev/urandom of=$B0/test_file bs=1024 count=8 +TEST cp $B0/test_file $M0/test_file +TEST fallocate -p -o 1500 -l 1000 $B0/test_file +TEST fallocate -p -o 1500 -l 1000 $M0/test_file +TEST md5_sum=`get_md5_sum $B0/test_file` +EXPECT $md5_sum get_md5_sum $M0/test_file +TEST rm -f $B0/test_file $M0/test_file + +###Punch hole test cases with fallocate +##Without write + +#Zero size +TEST dd if=/dev/urandom of=$M0/test_file bs=1024 count=8 +TEST ! fallocate -p -o 1500 -l 0 $M0/test_file + +#Negative size +TEST ! fallocate -p -o 1500 -l -100 $M0/test_file +TEST rm -f $M0/test_file + +#Touching boundary +TEST dd if=/dev/urandom of=$B0/test_file bs=1024 count=8 +TEST cp $B0/test_file $M0/test_file +TEST fallocate -p -o 2048 -l 2048 $B0/test_file +TEST fallocate -p -o 2048 -l 2048 $M0/test_file +TEST md5_sum=`get_md5_sum $B0/test_file` +EXPECT $md5_sum get_md5_sum $M0/test_file +TEST rm -f $B0/test_file $M0/test_file + +#Touching boundary,multiple stripe +TEST dd if=/dev/urandom of=$B0/test_file bs=1024 count=8 +TEST cp $B0/test_file $M0/test_file +TEST fallocate -p -o 2048 -l 4096 $B0/test_file +TEST fallocate -p -o 2048 -l 4096 $M0/test_file +TEST md5_sum=`get_md5_sum $B0/test_file` +EXPECT $md5_sum get_md5_sum $M0/test_file +TEST rm -f $B0/test_file $M0/test_file + +##With write + +#Size ends in boundary +TEST dd if=/dev/urandom of=$B0/test_file bs=1024 count=8 +TEST cp $B0/test_file $M0/test_file +TEST fallocate -p -o 600 -l 3496 $B0/test_file +TEST fallocate -p -o 600 -l 3496 $M0/test_file +TEST md5_sum=`get_md5_sum $B0/test_file` +EXPECT $md5_sum get_md5_sum $M0/test_file +TEST rm -f $B0/test_file $M0/test_file + +#Offset at boundary +TEST dd if=/dev/urandom of=$B0/test_file bs=1024 count=8 +TEST cp $B0/test_file $M0/test_file +TEST fallocate -p -o 2048 -l 3072 $B0/test_file +TEST fallocate -p -o 2048 -l 3072 $M0/test_file +TEST md5_sum=`get_md5_sum $B0/test_file` +EXPECT $md5_sum get_md5_sum $M0/test_file +TEST rm -f $B0/test_file $M0/test_file + +#Offset and Size not at boundary covering a stripe +TEST dd if=/dev/urandom of=$B0/test_file bs=1024 count=8 +TEST cp $B0/test_file $M0/test_file +TEST fallocate -p -o 1500 -l 3000 $B0/test_file +TEST fallocate -p -o 1500 -l 3000 $M0/test_file +TEST md5_sum=`get_md5_sum $B0/test_file` +EXPECT $md5_sum get_md5_sum $M0/test_file +TEST rm -f $B0/test_file $M0/test_file + +#Offset and Size not at boundary +TEST dd if=/dev/urandom of=$B0/test_file bs=1024 count=8 +TEST cp $B0/test_file $M0/test_file +TEST fallocate -p -o 1000 -l 3072 $B0/test_file +TEST fallocate -p -o 1000 -l 3072 $M0/test_file +TEST md5_sum=`get_md5_sum $B0/test_file` +EXPECT $md5_sum get_md5_sum $M0/test_file + +#Data Corruption Tests +#Kill brick1 and brick2 +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "4" ec_child_up_count $V0 0 + +#Unmount and mount +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0; +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "4" ec_child_up_count $V0 0 + +#verify md5 sum +EXPECT $md5_sum get_md5_sum $M0/test_file + +#Bring up the bricks +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 + +#Kill brick3 and brick4 +TEST kill_brick $V0 $H0 $B0/${V0}2 +TEST kill_brick $V0 $H0 $B0/${V0}3 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "4" ec_child_up_count $V0 0 + +#Unmount and mount +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0; +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "4" ec_child_up_count $V0 0 + +#verify md5 sum +EXPECT $md5_sum get_md5_sum $M0/test_file + +#Bring up the bricks +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 + +#Kill brick5 and brick6 +TEST kill_brick $V0 $H0 $B0/${V0}4 +TEST kill_brick $V0 $H0 $B0/${V0}5 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "4" ec_child_up_count $V0 0 + +#Unmount and mount +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0; +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "4" ec_child_up_count $V0 0 + +#verify md5 sum +EXPECT $md5_sum get_md5_sum $M0/test_file + +cleanup diff --git a/tests/basic/ec/ec-fallocate.t b/tests/basic/ec/ec-fallocate.t new file mode 100644 index 00000000000..1b827eed7df --- /dev/null +++ b/tests/basic/ec/ec-fallocate.t @@ -0,0 +1,72 @@ +#!/bin/bash +# +# Run several commands to verify basic fallocate functionality. We verify that +# fallocate creates and allocates blocks to a file. We also verify that the keep +# size option does not modify the file size. +### + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../fallocate.rc + +cleanup + +#cleate and start volume +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0..2} +TEST $CLI volume start $V0 + +#Mount the volume +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 + +# check for fallocate support before continuing the test +require_fallocate -l 1m -n $M0/file && rm -f $M0/file + +# fallocate a file and verify blocks are allocated +TEST fallocate -l 1m $M0/file +blksz=`stat -c %b $M0/file` +nblks=`stat -c %B $M0/file` +TEST [ $(($blksz * $nblks)) -eq 1048576 ] + +TEST unlink $M0/file + +# truncate a file to a fixed size, fallocate and verify that the size does not +# change +TEST truncate -s 1M $M0/file +TEST fallocate -l 2m -n $M0/file +blksz=`stat -c %b $M0/file` +nblks=`stat -c %B $M0/file` +sz=`stat -c %s $M0/file` +TEST [ $sz -eq 1048576 ] +# Note that gluster currently incorporates a hack to limit the number of blocks +# reported as allocated to the file by the file size. We have allocated beyond the +# file size here. Just check for non-zero allocation to avoid setting a land mine +# for if/when that behavior might change. +TEST [ ! $(($blksz * $nblks)) -eq 0 ] +TEST unlink $M0/file + +# write some data, fallocate within and outside the range +# and check for data corruption. +TEST dd if=/dev/urandom of=$M0/file bs=1024k count=1 +TEST cp $M0/file $M0/file.copy.pre +TEST fallocate -o 512k -l 128k $M0/file +TEST cp $M0/file $M0/file.copy.post +TEST cmp $M0/file.copy.pre $M0/file.copy.post +TEST fallocate -o 1000k -l 128k $M0/file +TEST cp $M0/file $M0/file.copy.post2 +TEST ! cmp $M0/file.copy.pre $M0/file.copy.post2 +TEST truncate -s 1M $M0/file.copy.post2 +TEST cmp $M0/file.copy.pre $M0/file.copy.post2 +TEST unlink $M0/file + +#Make sure offset/size are modified so that 3 blocks are allocated +TEST touch $M0/f1 +TEST fallocate -o 1280 -l 1024 $M0/f1 +EXPECT "^2304$" stat -c "%s" $M0/f1 +EXPECT "^1536$" stat -c "%s" $B0/${V0}0/f1 + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +cleanup; diff --git a/tests/basic/ec/ec-fast-fgetxattr.c b/tests/basic/ec/ec-fast-fgetxattr.c new file mode 100644 index 00000000000..bf982151861 --- /dev/null +++ b/tests/basic/ec/ec-fast-fgetxattr.c @@ -0,0 +1,129 @@ +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <time.h> +#include <limits.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> + +int cbk_complete = 0; +ssize_t cbk_ret_val = 0; +int +fill_iov(struct iovec *iov, char fillchar, int count) +{ + int ret = -1; + + iov->iov_base = malloc(count + 1); + if (iov->iov_base == NULL) { + return ret; + } else { + iov->iov_len = count; + ret = 0; + } + memset(iov->iov_base, fillchar, count); + memset(iov->iov_base + count, '\0', 1); + + return ret; +} + +void +write_async_cbk(glfs_fd_t *fd, ssize_t ret, struct stat *prestat, + struct stat *poststat, void *cookie) +{ + if (ret < 0) { + fprintf(stderr, "glfs_write failed"); + } + cbk_ret_val = ret; + cbk_complete = 1; +} + +int +write_async(glfs_t *fs, glfs_fd_t *glfd, int char_count) +{ + ssize_t ret = -1; + int flags = O_RDWR; + struct iovec iov = {0}; + + ret = fill_iov(&iov, 'a', char_count); + if (ret) { + fprintf(stderr, "failed to create iov"); + goto out; + } + + ret = glfs_pwritev_async(glfd, &iov, 1, 0, flags, write_async_cbk, NULL); +out: + if (ret < 0) { + fprintf(stderr, "glfs_pwritev async failed"); + } + return ret; +} + +int +main(int argc, char *argv[]) +{ + glfs_t *fs = NULL; + glfs_fd_t *fd = NULL; + int ret = 1; + char buf[1024] = {0}; + + if (argc != 4) { + fprintf(stderr, "Syntax: %s <host> <volname> <file>\n", argv[0]); + return 1; + } + + fs = glfs_new(argv[2]); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + return 1; + } + + ret = glfs_set_volfile_server(fs, "tcp", argv[1], 24007); + if (ret != 0) { + fprintf(stderr, "glfs_set_volfile_server: returned %d\n", ret); + goto out; + } + ret = glfs_set_logging(fs, "/tmp/ec-fgetxattr.log", 7); + if (ret != 0) { + fprintf(stderr, "glfs_set_logging: returned %d\n", ret); + goto out; + } + ret = glfs_init(fs); + if (ret != 0) { + fprintf(stderr, "glfs_init: returned %d\n", ret); + goto out; + } + + fd = glfs_open(fs, argv[3], O_RDWR | O_TRUNC); + if (fd == NULL) { + fprintf(stderr, "glfs_open: returned NULL\n"); + goto out; + } + + ret = write_async(fs, fd, 16); + if (ret) { + fprintf(stderr, "write_async failed\n"); + } + + sleep(1); + ret = glfs_fgetxattr(fd, "trusted.glusterfs.abc", buf, sizeof buf); + while (cbk_complete != 1) { + /* ret will be -ve as xattr doesn't exist, and fgetxattr should + * return waaaayyy before writev */ + ret = 0; + sleep(1); + } + if (cbk_ret_val < 0) { + fprintf(stderr, "cbk_ret_val is -ve\n"); + ret = -1; + } + glfs_close(fd); + +out: + unlink("/tmp/ec-fgetxattr.log"); + glfs_fini(fs); + + return ret; +} diff --git a/tests/basic/ec/ec-fast-fgetxattr.t b/tests/basic/ec/ec-fast-fgetxattr.t new file mode 100755 index 00000000000..eb12fa4a0ba --- /dev/null +++ b/tests/basic/ec/ec-fast-fgetxattr.t @@ -0,0 +1,40 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 disperse 6 redundancy 2 $H0:$B0/${V0}{1..6} +TEST $CLI volume set $V0 performance.quick-read off +TEST $CLI volume set $V0 performance.write-behind 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.client-io-threads off +TEST $CLI volume set $V0 brick-log-level DEBUG +TEST $CLI volume set $V0 delay-gen posix +TEST $CLI volume set $V0 delay-gen.delay-duration 10000000 +TEST $CLI volume set $V0 delay-gen.delay-percentage 100 +TEST $CLI volume set $V0 delay-gen.enable read,write + +TEST $CLI volume start $V0 +EXPECT 'Started' volinfo_field $V0 'Status' + +TEST $GFS -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +TEST touch $M0/file + +# Perform two writes to make sure io-threads have enough threads to perform +# things in parallel when the test execution happens. +echo abc > $M0/file1 & +echo abc > $M0/file2 & +wait + +TEST build_tester $(dirname $0)/ec-fast-fgetxattr.c -lgfapi -Wall -O2 +TEST $(dirname $0)/ec-fast-fgetxattr $H0 $V0 /file +cleanup_tester $(dirname ${0})/ec-fast-fgetxattr + +cleanup; diff --git a/tests/basic/ec/ec-fix-openfd.t b/tests/basic/ec/ec-fix-openfd.t new file mode 100644 index 00000000000..04fdd802c62 --- /dev/null +++ b/tests/basic/ec/ec-fix-openfd.t @@ -0,0 +1,111 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../fileio.rc + +# This test checks for open fd heal on EC + +#Create Volume +cleanup +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0..2} +TEST $CLI volume set $V0 performance.read-after-open yes +TEST $CLI volume set $V0 performance.lazy-open no +TEST $CLI volume set $V0 performance.open-behind off +TEST $CLI volume set $V0 disperse.background-heals 0 +TEST $CLI volume heal $V0 disable +TEST $CLI volume start $V0 + +#Mount the volume +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 + +#Touch a file +TEST touch "$M0/test_file" + +#Kill a brick +TEST kill_brick $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "2" ec_child_up_count $V0 0 + +#Open the file in write mode +TEST fd=`fd_available` +TEST fd_open $fd 'rw' "$M0/test_file" + +#Bring up the killed brick +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 + +sleep 1 + +#Test the fd count +EXPECT "0" get_fd_count $V0 $H0 $B0/${V0}0 test_file +EXPECT "1" get_fd_count $V0 $H0 $B0/${V0}1 test_file +EXPECT "1" get_fd_count $V0 $H0 $B0/${V0}2 test_file + +#Write to file +dd iflag=fullblock if=/dev/urandom bs=1024 count=2 >&$fd 2>/dev/null + +#Test the fd count +EXPECT "1" get_fd_count $V0 $H0 $B0/${V0}0 test_file + +#Close fd +TEST fd_close $fd + +#Stop the volume +TEST $CLI volume stop $V0 + +#Start the volume +TEST $CLI volume start $V0 + +#Kill brick1 +TEST kill_brick $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "2" ec_child_up_count $V0 0 + +#Unmount and mount +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0; +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "2" ec_child_up_count $V0 0 + +#Calculate md5 sum +md5sum0=`get_md5_sum "$M0/test_file"` + +#Bring up the brick +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 + +#Kill brick2 +TEST kill_brick $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "2" ec_child_up_count $V0 0 + +#Unmount and mount +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "2" ec_child_up_count $V0 0 + +#Calculate md5 sum +md5sum1=`get_md5_sum "$M0/test_file"` + +#Bring up the brick +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 + +#Kill brick3 +TEST kill_brick $V0 $H0 $B0/${V0}2 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "2" ec_child_up_count $V0 0 + +#Unmount and mount +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "2" ec_child_up_count $V0 0 + +#Calculate md5 sum +md5sum2=`get_md5_sum "$M0/test_file"` + +#compare the md5sum +EXPECT "$md5sum0" echo $md5sum1 +EXPECT "$md5sum0" echo $md5sum2 +EXPECT "$md5sum1" echo $md5sum2 + +cleanup diff --git a/tests/basic/ec/ec-new-entry.t b/tests/basic/ec/ec-new-entry.t index 50435626d72..be97aecd8e2 100644 --- a/tests/basic/ec/ec-new-entry.t +++ b/tests/basic/ec/ec-new-entry.t @@ -12,6 +12,17 @@ function get_md5sum { md5sum $1 | awk '{print $1}' } +#after replace-brick immediately trusted.ec.version will be absent, so if it +#is present we can assume that heal attempted on root +function root_heal_attempted { + if [ -z $(get_hex_xattr trusted.ec.version $1) ]; + then + echo "N"; + else + echo "Y"; + fi +} + TEST glusterd TEST pidof glusterd TEST $CLI volume create $V0 disperse 6 redundancy 2 $H0:$B0/${V0}{0..5} @@ -25,6 +36,9 @@ TEST mknod $M0/block b 4 5 for i in {1..10}; do dd if=/dev/zero of=$M0/$i bs=1M count=1; done TEST $CLI volume replace-brick $V0 $H0:$B0/${V0}5 $H0:$B0/${V0}6 commit force EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +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 "Y" root_heal_attempted $B0/${V0}6 EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 #ls -l gives "Total" line so number of lines will be 1 more EXPECT "^14$" num_entries $B0/${V0}6 diff --git a/tests/basic/ec/ec-notify.t b/tests/basic/ec/ec-notify.t index 586be91bdbe..53290b7c798 100644 --- a/tests/basic/ec/ec-notify.t +++ b/tests/basic/ec/ec-notify.t @@ -5,11 +5,26 @@ # This test checks notify part of ec +# We *know* some of these mounts will succeed but not be actually usable +# (terrible idea IMO), so speed things up and eliminate some noise by +# overriding this function. +_GFS () { + glusterfs "$@" +} + +ec_up_brick_count () { + local bricknum + for bricknum in $(seq 0 2); do + brick_up_status $V0 $H0 $B0/$V0$bricknum + done | grep -E '^1$' | wc -l +} + cleanup TEST glusterd TEST pidof glusterd TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0..2} TEST $CLI volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "3" ec_up_brick_count #First time mount tests. # When all the bricks are up, mount should succeed and up-children @@ -33,6 +48,7 @@ EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 TEST $CLI volume start $V0 TEST kill_brick $V0 $H0 $B0/${V0}2 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" ec_up_brick_count TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; EXPECT_WITHIN $CHILD_UP_TIMEOUT "2" ec_child_up_count $V0 0 TEST stat $M0 @@ -40,6 +56,7 @@ EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 # When only 1 brick is up mount should fail. TEST kill_brick $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ec_up_brick_count TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; # Wait for 5 seconds even after that up_count should show 1 sleep 5 @@ -51,28 +68,33 @@ EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 # state changes in ec. TEST $CLI volume stop $V0 TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "3" ec_up_brick_count TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 TEST touch $M0/a # kill 1 brick and the up_count should become 2, fops should still succeed TEST kill_brick $V0 $H0 $B0/${V0}1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" ec_up_brick_count EXPECT_WITHIN $CHILD_UP_TIMEOUT "2" ec_child_up_count $V0 0 TEST touch $M0/b # kill one more brick and the up_count should become 1, fops should fail TEST kill_brick $V0 $H0 $B0/${V0}2 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ec_up_brick_count EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" ec_child_up_count $V0 0 TEST ! touch $M0/c # kill one more brick and the up_count should become 0, fops should still fail TEST kill_brick $V0 $H0 $B0/${V0}0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "0" ec_up_brick_count EXPECT_WITHIN $CHILD_UP_TIMEOUT "0" ec_child_up_count $V0 0 TEST ! touch $M0/c # Bring up all the bricks up and see that up_count is 3 and fops are succeeding # again. TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "3" ec_up_brick_count EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 TEST touch $M0/c diff --git a/tests/basic/ec/ec-optimistic-changelog.t b/tests/basic/ec/ec-optimistic-changelog.t new file mode 100644 index 00000000000..a372cd39a64 --- /dev/null +++ b/tests/basic/ec/ec-optimistic-changelog.t @@ -0,0 +1,153 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +# This test checks optimistic-change-log option + +cleanup +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0..2} +TEST $CLI volume heal $V0 disable + +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume set $V0 performance.quick-read off +TEST $CLI volume set $V0 performance.read-ahead off +TEST $CLI volume set $V0 performance.io-cache off +TEST $CLI volume set $V0 disperse.background-heals 0 +TEST $CLI volume set $V0 disperse.optimistic-change-log off +TEST $CLI volume set $V0 disperse.eager-lock off +TEST $CLI volume set $V0 disperse.other-eager-lock off +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "0" mount_get_option_value $M0 $V0-disperse-0 background-heals +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "0" mount_get_option_value $M0 $V0-disperse-0 heal-wait-qlength + +TEST $CLI volume set $V0 disperse.background-heals 1 +TEST touch $M0/a +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" count_sh_entries $B0/${V0}0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" count_sh_entries $B0/${V0}1 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" count_sh_entries $B0/${V0}2 + + + +### optimistic-change-log = off ; All bricks good. Test file operation +echo abc > $M0/a +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +############################################################ + +## optimistic-change-log = off ; Kill one brick . Test file operation +TEST kill_brick $V0 $H0 $B0/${V0}2 +echo abc > $M0/a +EXPECT 2 get_pending_heal_count $V0 #One for each active brick +$CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 +#Accessing file should heal the file now +EXPECT "abc" cat $M0/a +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +############################################################ + +## optimistic-change-log = off ; All bricks good. Test entry operation +TEST touch $M0/b +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +############################################################ + +## optimistic-change-log = off ; All bricks good. Test metadata operation +TEST chmod 0777 $M0/b +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +############################################################ + +## optimistic-change-log = off ; Kill one brick. Test entry operation + +TEST kill_brick $V0 $H0 $B0/${V0}2 +TEST touch $M0/c +EXPECT 4 get_pending_heal_count $V0 #two for each active brick +$CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 +getfattr -d -m. -e hex $M0 2>&1 > /dev/null +getfattr -d -m. -e hex $M0/c 2>&1 > /dev/null +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +############################################################ + +## optimistic-change-log = off ; Kill one brick. Test metadata operation +TEST kill_brick $V0 $H0 $B0/${V0}2 +TEST chmod 0777 $M0/c +EXPECT 2 get_pending_heal_count $V0 #One for each active brick +$CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 +getfattr -d -m. -e hex $M0/c 2>&1 > /dev/null +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +############################################################ + +TEST $CLI volume set $V0 disperse.optimistic-change-log on + +### optimistic-change-log = on ; All bricks good. Test file operation + +echo abc > $M0/aa +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +############################################################ + +## optimistic-change-log = on ; Kill one brick. Test file operation + +TEST kill_brick $V0 $H0 $B0/${V0}2 +echo abc > $M0/aa +EXPECT 2 get_pending_heal_count $V0 #One for each active brick +$CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 +#Accessing file should heal the file now +getfattr -d -m. -e hex $M0/aa 2>&1 > /dev/null +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +############################################################ + +## optimistic-change-log = on ; All bricks good. Test entry operation + +TEST touch $M0/bb +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +############################################################ + +## optimistic-change-log = on ; All bricks good. Test metadata operation + +TEST chmod 0777 $M0/bb +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +############################################################ + +## optimistic-change-log = on ; Kill one brick. Test entry operation + +TEST kill_brick $V0 $H0 $B0/${V0}2 +TEST touch $M0/cc +EXPECT 4 get_pending_heal_count $V0 #two for each active brick +$CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 +getfattr -d -m. -e hex $M0 2>&1 > /dev/null +getfattr -d -m. -e hex $M0/cc 2>&1 > /dev/null +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +############################################################ + +## optimistic-change-log = on ; Kill one brick. Test metadata operation + +TEST kill_brick $V0 $H0 $B0/${V0}2 +TEST chmod 0777 $M0/cc +EXPECT 2 get_pending_heal_count $V0 #One for each active brick +$CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 +getfattr -d -m. -e hex $M0/cc 2>&1 > /dev/null +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +############################################################ + +cleanup diff --git a/tests/basic/ec/ec-quorum-count.t b/tests/basic/ec/ec-quorum-count.t new file mode 100644 index 00000000000..9310ebbb8f2 --- /dev/null +++ b/tests/basic/ec/ec-quorum-count.t @@ -0,0 +1,167 @@ + #!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../ec.rc + +cleanup +TEST glusterd +TEST pidof glusterd +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 + +#Should succeed on a valid range +TEST ! $CLI volume set $V0 disperse.quorum-count 0 +TEST ! $CLI volume set $V0 disperse.quorum-count -0 +TEST ! $CLI volume set $V0 disperse.quorum-count abc +TEST ! $CLI volume set $V0 disperse.quorum-count 10abc +TEST ! $CLI volume set $V0 disperse.quorum-count 1 +TEST ! $CLI volume set $V0 disperse.quorum-count 2 +TEST ! $CLI volume set $V0 disperse.quorum-count 3 +TEST $CLI volume set $V0 disperse.quorum-count 4 +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 + +#Test that the option is reflected in the mount +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "^4$" ec_option_value $V0 $M0 0 quorum-count +TEST $CLI volume reset $V0 disperse.quorum-count +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "^0$" ec_option_value $V0 $M0 0 quorum-count +TEST $CLI volume set $V0 disperse.quorum-count 6 +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "^6$" ec_option_value $V0 $M0 0 quorum-count + +TEST touch $M0/a +TEST touch $M0/data +TEST setfattr -n trusted.def -v def $M0/a +TEST touch $M0/src +TEST touch $M0/del-me +TEST mkdir $M0/dir1 +TEST dd if=/dev/zero of=$M0/read-file bs=1M count=1 oflag=direct +TEST dd if=/dev/zero of=$M0/del-file bs=1M count=1 oflag=direct +TEST gf_rm_file_and_gfid_link $B0/${V0}0 del-file +#modify operations should fail as the file is not in quorum +TEST ! dd if=/dev/zero of=$M0/del-file bs=1M count=1 oflag=direct +TEST kill_brick $V0 $H0 $B0/${V0}0 +#Read should succeed even when quorum-count is not met +TEST dd if=$M0/read-file of=/dev/null iflag=direct +TEST ! touch $M0/a2 +TEST ! mkdir $M0/dir2 +TEST ! mknod $M0/b2 b 4 5 +TEST ! ln -s $M0/a $M0/symlink +TEST ! ln $M0/a $M0/link +TEST ! mv $M0/src $M0/dst +TEST ! rm -f $M0/del-me +TEST ! rmdir $M0/dir1 +TEST ! dd if=/dev/zero of=$M0/a bs=1M count=1 conv=notrunc +TEST ! dd if=/dev/zero of=$M0/data bs=1M count=1 conv=notrunc +TEST ! truncate -s 0 $M0/a +TEST ! setfattr -n trusted.abc -v abc $M0/a +TEST ! setfattr -x trusted.def $M0/a +TEST ! chmod +x $M0/a +TEST ! fallocate -l 2m -n $M0/a +TEST ! fallocate -p -l 512k $M0/a +TEST $CLI volume start $V0 force +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count ${V0} + +# reset the option and check whether the default redundancy count is +# accepted or not. +TEST $CLI volume reset $V0 disperse.quorum-count +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "^0$" ec_option_value $V0 $M0 0 quorum-count +TEST touch $M0/a1 +TEST touch $M0/data1 +TEST setfattr -n trusted.def -v def $M0/a1 +TEST touch $M0/src1 +TEST touch $M0/del-me1 +TEST mkdir $M0/dir11 +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST touch $M0/a21 +TEST mkdir $M0/dir21 +TEST mknod $M0/b21 b 4 5 +TEST ln -s $M0/a1 $M0/symlink1 +TEST ln $M0/a1 $M0/link1 +TEST mv $M0/src1 $M0/dst1 +TEST rm -f $M0/del-me1 +TEST rmdir $M0/dir11 +TEST dd if=/dev/zero of=$M0/a1 bs=1M count=1 conv=notrunc +TEST dd if=/dev/zero of=$M0/data1 bs=1M count=1 conv=notrunc +TEST truncate -s 0 $M0/a1 +TEST setfattr -n trusted.abc -v abc $M0/a1 +TEST setfattr -x trusted.def $M0/a1 +TEST chmod +x $M0/a1 +TEST fallocate -l 2m -n $M0/a1 +TEST fallocate -p -l 512k $M0/a1 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 + +TEST touch $M0/a2 +TEST touch $M0/data2 +TEST setfattr -n trusted.def -v def $M0/a1 +TEST touch $M0/src2 +TEST touch $M0/del-me2 +TEST mkdir $M0/dir12 +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST kill_brick $V0 $H0 $B0/${V0}2 +TEST ! touch $M0/a22 +TEST ! mkdir $M0/dir22 +TEST ! mknod $M0/b22 b 4 5 +TEST ! ln -s $M0/a2 $M0/symlink2 +TEST ! ln $M0/a2 $M0/link2 +TEST ! mv $M0/src2 $M0/dst2 +TEST ! rm -f $M0/del-me2 +TEST ! rmdir $M0/dir12 +TEST ! dd if=/dev/zero of=$M0/a2 bs=1M count=1 conv=notrunc +TEST ! dd if=/dev/zero of=$M0/data2 bs=1M count=1 conv=notrunc +TEST ! truncate -s 0 $M0/a2 +TEST ! setfattr -n trusted.abc -v abc $M0/a2 +TEST ! setfattr -x trusted.def $M0/a2 +TEST ! chmod +x $M0/a2 +TEST ! fallocate -l 2m -n $M0/a2 +TEST ! fallocate -p -l 512k $M0/a2 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count ${V0} + +# Set quorum-count to 5 and kill 1 brick and the fops should pass +TEST $CLI volume set $V0 disperse.quorum-count 5 +EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "^5$" ec_option_value $V0 $M0 0 quorum-count +TEST touch $M0/a3 +TEST touch $M0/data3 +TEST setfattr -n trusted.def -v def $M0/a3 +TEST touch $M0/src3 +TEST touch $M0/del-me3 +TEST mkdir $M0/dir13 +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST touch $M0/a31 +TEST mkdir $M0/dir31 +TEST mknod $M0/b31 b 4 5 +TEST ln -s $M0/a3 $M0/symlink3 +TEST ln $M0/a3 $M0/link3 +TEST mv $M0/src3 $M0/dst3 +TEST rm -f $M0/del-me3 +TEST rmdir $M0/dir13 +TEST dd if=/dev/zero of=$M0/a3 bs=1M count=1 conv=notrunc +TEST dd if=/dev/zero of=$M0/data3 bs=1M count=1 conv=notrunc +TEST truncate -s 0 $M0/a3 +TEST setfattr -n trusted.abc -v abc $M0/a3 +TEST setfattr -x trusted.def $M0/a3 +TEST chmod +x $M0/a3 +TEST fallocate -l 2m -n $M0/a3 +TEST fallocate -p -l 512k $M0/a3 +TEST dd if=/dev/urandom of=$M0/heal-file bs=1M count=1 oflag=direct +cksum_before_heal="$(md5sum $M0/heal-file | awk '{print $1}')" +TEST $CLI volume start $V0 force +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count ${V0} +TEST kill_brick $V0 $H0 $B0/${V0}4 +TEST kill_brick $V0 $H0 $B0/${V0}5 +cksum_after_heal=$(dd if=$M0/heal-file iflag=direct | md5sum | awk '{print $1}') +TEST [[ $cksum_before_heal == $cksum_after_heal ]] +cleanup; diff --git a/tests/basic/ec/ec-read-mask.t b/tests/basic/ec/ec-read-mask.t new file mode 100644 index 00000000000..ddb556f2973 --- /dev/null +++ b/tests/basic/ec/ec-read-mask.t @@ -0,0 +1,114 @@ + #!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../ec.rc + +cleanup +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 6 redundancy 2 $H0:$B0/${V0}{0..5} +TEST $CLI volume start $V0 + +#Empty read-mask should fail +TEST ! $GFS --xlator-option=*.ec-read-mask="" -s $H0 --volfile-id $V0 $M0 + +#Less than 4 number of bricks should fail +TEST ! $GFS --xlator-option="*.ec-read-mask=0" -s $H0 --volfile-id $V0 $M0 +TEST ! $GFS --xlator-option="*.ec-read-mask=0:1" -s $H0 --volfile-id $V0 $M0 +TEST ! $GFS --xlator-option=*.ec-read-mask="0:1:2" -s $H0 --volfile-id $V0 $M0 + +#ids greater than 5 should fail +TEST ! $GFS --xlator-option="*.ec-read-mask=0:1:2:6" -s $H0 --volfile-id $V0 $M0 + +#ids less than 0 should fail +TEST ! $GFS --xlator-option="*.ec-read-mask=0:-1:2:5" -s $H0 --volfile-id $V0 $M0 + +#read-mask with non-alphabet or comma should fail +TEST ! $GFS --xlator-option="*.ec-read-mask=0:1:2:5:abc" -s $H0 --volfile-id $V0 $M0 +TEST ! $GFS --xlator-option="*.ec-read-mask=0:1:2:5a" -s $H0 --volfile-id $V0 $M0 + +#mount with at least 4 read-mask-ids and all of them valid should pass +TEST $GFS --xlator-option="*.ec-read-mask=0:1:2:5:4:3" -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +EXPECT "^111111$" ec_option_value $V0 $M0 0 read-mask +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +TEST $GFS --xlator-option="*.ec-read-mask=0:1:2:5" -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +EXPECT "^100111$" ec_option_value $V0 $M0 0 read-mask + +TEST dd if=/dev/urandom of=$M0/a bs=1M count=1 +md5=$(md5sum $M0/a | awk '{print $1}') +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +#Read on the file should fail if any of the read-mask is down when number of +#ids is data-count +TEST $GFS --xlator-option="*.ec-read-mask=0:1:2:5" -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +EXPECT "^100111$" ec_option_value $V0 $M0 0 read-mask +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST ! dd if=$M0/a of=/dev/null +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $CLI volume start $V0 force + +TEST $GFS --xlator-option="*.ec-read-mask=0:1:2:5" -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +EXPECT "^100111$" ec_option_value $V0 $M0 0 read-mask +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST ! dd if=$M0/a of=/dev/null +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $CLI volume start $V0 force + +TEST $GFS --xlator-option="*.ec-read-mask=0:1:2:5" -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +EXPECT "^100111$" ec_option_value $V0 $M0 0 read-mask +TEST kill_brick $V0 $H0 $B0/${V0}2 +TEST ! dd if=$M0/a of=/dev/null +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $CLI volume start $V0 force + +TEST $GFS --xlator-option="*.ec-read-mask=0:1:2:5" -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +EXPECT "^100111$" ec_option_value $V0 $M0 0 read-mask +TEST kill_brick $V0 $H0 $B0/${V0}5 +TEST ! dd if=$M0/a of=/dev/null +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $CLI volume start $V0 force + +#Read on file should succeed when non-read-mask bricks are down +TEST $GFS --xlator-option="*.ec-read-mask=0:1:2:5" -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +EXPECT "^100111$" ec_option_value $V0 $M0 0 read-mask +TEST kill_brick $V0 $H0 $B0/${V0}3 +EXPECT "^$md5$" echo $(dd if=$M0/a | md5sum | awk '{print $1}') +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $CLI volume start $V0 force + +TEST $GFS --xlator-option="*.ec-read-mask=0:1:2:5" -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +EXPECT "^100111$" ec_option_value $V0 $M0 0 read-mask +TEST kill_brick $V0 $H0 $B0/${V0}4 +EXPECT "^$md5$" echo $(dd if=$M0/a | md5sum | awk '{print $1}') +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $CLI volume start $V0 force + +TEST $GFS --xlator-option="*.ec-read-mask=0:1:2:5" -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +EXPECT "^100111$" ec_option_value $V0 $M0 0 read-mask +TEST kill_brick $V0 $H0 $B0/${V0}3 +TEST kill_brick $V0 $H0 $B0/${V0}4 +EXPECT "^$md5$" echo $(dd if=$M0/a | md5sum | awk '{print $1}') +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $CLI volume start $V0 force + +#Deliberately corrupt chunks 3: 4 and check that reads still give correct data +TEST dd if=/dev/zero of=$B0/${V0}3/a bs=256k count=1 +TEST dd if=/dev/zero of=$B0/${V0}4/a bs=256k count=1 +TEST $GFS --xlator-option="*.ec-read-mask=0:1:2:5" -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +EXPECT "^100111$" ec_option_value $V0 $M0 0 read-mask +EXPECT "^$md5$" echo $(dd if=$M0/a | md5sum | awk '{print $1}') +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +cleanup; diff --git a/tests/basic/ec/ec-read-policy.t b/tests/basic/ec/ec-read-policy.t index e4390aa07cb..fe6fe6576e7 100644 --- a/tests/basic/ec/ec-read-policy.t +++ b/tests/basic/ec/ec-read-policy.t @@ -20,10 +20,9 @@ TEST $CLI volume start $V0 TEST glusterfs --direct-io-mode=yes --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0 EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 #TEST volume operations work fine -EXPECT "round-robin" mount_get_option_value $M0 $V0-disperse-0 read-policy -TEST $CLI volume set $V0 disperse.read-policy gfid-hash -EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "gfid-hash" mount_get_option_value $M0 $V0-disperse-0 read-policy -TEST $CLI volume reset $V0 disperse.read-policy + +EXPECT "gfid-hash" mount_get_option_value $M0 $V0-disperse-0 read-policy +TEST $CLI volume set $V0 disperse.read-policy round-robin EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "round-robin" mount_get_option_value $M0 $V0-disperse-0 read-policy #TEST if the option gives the intended behavior. The way we perform this test diff --git a/tests/basic/ec/ec-rebalance.t b/tests/basic/ec/ec-rebalance.t new file mode 100644 index 00000000000..6cda3a3e4be --- /dev/null +++ b/tests/basic/ec/ec-rebalance.t @@ -0,0 +1,61 @@ +#!/bin/bash +# +# This will test the rebalance failure reported in 1447559 +# +### + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../fallocate.rc + +cleanup + +#cleate and start volume +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0..2} +TEST $CLI volume set $V0 lookup-optimize on +TEST $CLI volume start $V0 + +#Mount the volume +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 + +# Create files +for i in {1..10} +do + dd if=/dev/urandom of=$M0/file$i bs=1024k count=1 +done + +md5_1=$(md5sum $M0/file1 | awk '{print $1}') +md5_2=$(md5sum $M0/file2 | awk '{print $1}') +md5_3=$(md5sum $M0/file3 | awk '{print $1}') +md5_4=$(md5sum $M0/file4 | awk '{print $1}') +md5_5=$(md5sum $M0/file5 | awk '{print $1}') +md5_6=$(md5sum $M0/file6 | awk '{print $1}') +md5_7=$(md5sum $M0/file7 | awk '{print $1}') +md5_8=$(md5sum $M0/file8 | awk '{print $1}') +md5_9=$(md5sum $M0/file9 | awk '{print $1}') +md5_10=$(md5sum $M0/file10 | awk '{print $1}') +# Add brick +TEST $CLI volume add-brick $V0 $H0:$B0/${V0}{3..5} + +#Trigger rebalance +TEST $CLI volume rebalance $V0 start force +EXPECT_WITHIN $REBALANCE_TIMEOUT "completed" rebalance_status_field $V0 + +#Remount to avoid any caches +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +EXPECT "$md5_1" echo $(md5sum $M0/file1 | awk '{print $1}') +EXPECT "$md5_2" echo $(md5sum $M0/file2 | awk '{print $1}') +EXPECT "$md5_3" echo $(md5sum $M0/file3 | awk '{print $1}') +EXPECT "$md5_4" echo $(md5sum $M0/file4 | awk '{print $1}') +EXPECT "$md5_5" echo $(md5sum $M0/file5 | awk '{print $1}') +EXPECT "$md5_6" echo $(md5sum $M0/file6 | awk '{print $1}') +EXPECT "$md5_7" echo $(md5sum $M0/file7 | awk '{print $1}') +EXPECT "$md5_8" echo $(md5sum $M0/file8 | awk '{print $1}') +EXPECT "$md5_9" echo $(md5sum $M0/file9 | awk '{print $1}') +EXPECT "$md5_10" echo $(md5sum $M0/file10 | awk '{print $1}') + +cleanup; 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/ec-root-heal.t b/tests/basic/ec/ec-root-heal.t index 91e668c4702..11ea7cdf9d4 100644 --- a/tests/basic/ec/ec-root-heal.t +++ b/tests/basic/ec/ec-root-heal.t @@ -16,13 +16,14 @@ TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $ EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 touch $M0/{1..10} TEST $CLI volume replace-brick $V0 $H0:$B0/${V0}5 $H0:$B0/${V0}6 commit force -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count_shd $V0 0 # active heal TEST $CLI volume heal $V0 full #ls -l gives "Total" line so number of lines will be 1 more -EXPECT_WITHIN $HEAL_TIMEOUT "^11$" num_entries $B0/${V0}6 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count ${V0} +EXPECT "^11$" num_entries $B0/${V0}6 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 diff --git a/tests/basic/ec/ec-seek.t b/tests/basic/ec/ec-seek.t new file mode 100644 index 00000000000..5a7d31b9f8f --- /dev/null +++ b/tests/basic/ec/ec-seek.t @@ -0,0 +1,58 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup + +SEEK=$(dirname $0)/seek +build_tester $(dirname $0)/../seek.c -o ${SEEK} + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info + +TEST mkdir -p $B0/${V0}{0..2} +TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0..2} + +EXPECT "$V0" volinfo_field $V0 'Volume Name' +EXPECT 'Created' volinfo_field $V0 'Status' +EXPECT '3' brick_count $V0 + +TEST $CLI volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'Started' volinfo_field $V0 'Status' + +TEST $GFS -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 + +TEST ${SEEK} create ${M0}/test 0 1 1048576 1 +# Determine underlying filesystem allocation block size +BSIZE="$(($(${SEEK} scan ${M0}/test hole 0) * 2))" + +TEST ${SEEK} create ${M0}/test 0 ${BSIZE} $((${BSIZE} * 4 + 512)) ${BSIZE} + +EXPECT "^0$" ${SEEK} scan ${M0}/test data 0 +EXPECT "^$((${BSIZE} / 2))$" ${SEEK} scan ${M0}/test data $((${BSIZE} / 2)) +EXPECT "^$((${BSIZE} - 1))$" ${SEEK} scan ${M0}/test data $((${BSIZE} - 1)) +EXPECT "^$((${BSIZE} * 4))$" ${SEEK} scan ${M0}/test data ${BSIZE} +EXPECT "^$((${BSIZE} * 4))$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 4)) +EXPECT "^$((${BSIZE} * 5))$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 5)) +EXPECT "^$((${BSIZE} * 5 + 511))$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 5 + 511)) +EXPECT "^ENXIO$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 5 + 512)) +EXPECT "^ENXIO$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 6)) + +EXPECT "^${BSIZE}$" ${SEEK} scan ${M0}/test hole 0 +EXPECT "^${BSIZE}$" ${SEEK} scan ${M0}/test hole $((${BSIZE} / 2)) +EXPECT "^${BSIZE}$" ${SEEK} scan ${M0}/test hole $((${BSIZE} - 1)) +EXPECT "^${BSIZE}$" ${SEEK} scan ${M0}/test hole ${BSIZE} +EXPECT "^$((${BSIZE} * 5 + 512))$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 4)) +EXPECT "^$((${BSIZE} * 5 + 512))$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 5)) +EXPECT "^$((${BSIZE} * 5 + 512))$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 5 + 511)) +EXPECT "^ENXIO$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 5 + 512)) +EXPECT "^ENXIO$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 6)) + +rm -f ${SEEK} +cleanup + +# Centos6 regression slaves seem to not support SEEK_DATA/SEEK_HOLE +#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=000000 diff --git a/tests/basic/ec/ec-stripe.t b/tests/basic/ec/ec-stripe.t new file mode 100644 index 00000000000..98b92294feb --- /dev/null +++ b/tests/basic/ec/ec-stripe.t @@ -0,0 +1,227 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +# These tests will check the stripe cache functionality of +# disperse volume + +test_index=0 +stripe_count=4 +loop_test=0 + +TESTS_EXPECTED_IN_LOOP=182 + +function get_mount_stripe_cache { + local sd=$1 + local field=$2 + local val=$(grep "$field" $sd | cut -f2 -d'=' | tail -1) + echo $val +} + +function get_stripes_in_cache { + local target=$1 + local count=$2 + local c=0 + for (( c=0; c<$count; c++ )) + do + let x=102+$c*1024 + echo yy | dd of=$target oflag=seek_bytes,sync seek=$x conv=notrunc + if [ $? != 0 ] + then + break + fi + done + echo "$c" +} +# tests in this loop = 7 +function mount_get_test_files { + let test_index+=1 + let loop_test+=7 + echo "Test Case $test_index" + local stripe_count=$1 + TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; + EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 + TEST dd if=/dev/urandom of=$B0/test_file bs=1024 count=20 + TEST cp $B0/test_file $M0/test_file + TEST dd if=/dev/urandom of=$B0/misc_file bs=1024 count=20 + EXPECT_WITHIN $UMOUNT_TIMEOUT "$stripe_count" get_stripes_in_cache $B0/test_file $stripe_count + EXPECT_WITHIN $UMOUNT_TIMEOUT "$stripe_count" get_stripes_in_cache $M0/test_file $stripe_count +} + +#check_statedump_md5sum (hitcount misscount) +#tests in this loop = 4 +function check_statedump_md5sum { + statedump=$(generate_mount_statedump $V0) + let loop_test+=4 + sleep 1 + nhits=$(get_mount_stripe_cache $statedump "hits") + nmisses=$(get_mount_stripe_cache $statedump "misses") + EXPECT "$1" echo $nhits + EXPECT "$2" echo $nmisses + TEST md5_sum=`get_md5_sum $B0/test_file` + EXPECT $md5_sum get_md5_sum $M0/test_file +} + +#tests in this loop = 2 +function clean_file_unmount { + let loop_test+=2 + TEST rm -f $B0/test_file $M0/test_file $B0/misc_file + cleanup_mount_statedump $V0 + EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +} + +cleanup +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0..2} +TEST $CLI volume heal $V0 disable +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume set $V0 performance.quick-read off +TEST $CLI volume set $V0 performance.read-ahead off +TEST $CLI volume set $V0 performance.io-cache off +TEST $CLI volume set $V0 disperse.background-heals 0 +TEST $CLI volume set $V0 disperse.eager-lock on +TEST $CLI volume set $V0 disperse.other-eager-lock on +TEST $CLI volume set $V0 disperse.stripe-cache 8 +TEST $CLI volume start $V0 + +### 1 - offset and size in one stripes #### + +mount_get_test_files $stripe_count +# This should have 4 hits on cached stripes +get_stripes_in_cache $M0/test_file $stripe_count +check_statedump_md5sum 4 4 +clean_file_unmount + +### 2 - Length less than a stripe size, covering two stripes #### + +mount_get_test_files $stripe_count +TEST dd if=$B0/misc_file of=$B0/test_file bs=1022 count=1 oflag=seek_bytes,sync seek=102 conv=notrunc +TEST dd if=$B0/misc_file of=$M0/test_file bs=1022 count=1 oflag=seek_bytes,sync seek=102 conv=notrunc +check_statedump_md5sum 2 4 +clean_file_unmount + +### 3 -Length exactly equal to the stripe size, covering a single stripe #### + +mount_get_test_files $stripe_count +TEST dd if=$B0/misc_file of=$B0/test_file bs=1024 count=1 oflag=seek_bytes,sync seek=0 conv=notrunc +TEST dd if=$B0/misc_file of=$M0/test_file bs=1024 count=1 oflag=seek_bytes,sync seek=0 conv=notrunc +check_statedump_md5sum 0 4 +clean_file_unmount + +### 4 - Length exactly equal to the stripe size, covering two stripes #### + +mount_get_test_files $stripe_count +TEST dd if=$B0/misc_file of=$B0/test_file bs=2048 count=1 oflag=seek_bytes,sync seek=1024 conv=notrunc +TEST dd if=$B0/misc_file of=$M0/test_file bs=2048 count=1 oflag=seek_bytes,sync seek=1024 conv=notrunc +check_statedump_md5sum 0 4 +clean_file_unmount + +### 5 - Length greater than a stripe size, covering two stripes #### + +mount_get_test_files $stripe_count +TEST dd if=$B0/misc_file of=$B0/test_file bs=1030 count=1 oflag=seek_bytes,sync seek=500 conv=notrunc +TEST dd if=$B0/misc_file of=$M0/test_file bs=1030 count=1 oflag=seek_bytes,sync seek=500 conv=notrunc +check_statedump_md5sum 2 4 +clean_file_unmount + +### 6 - Length greater than a stripe size, covering three stripes #### + +mount_get_test_files $stripe_count +TEST dd if=$B0/misc_file of=$B0/test_file bs=2078 count=1 oflag=seek_bytes,sync seek=1000 conv=notrunc +TEST dd if=$B0/misc_file of=$M0/test_file bs=2078 count=1 oflag=seek_bytes,sync seek=1000 conv=notrunc +check_statedump_md5sum 2 4 +clean_file_unmount + +### 7 - Discard range - all stripe from cache should be invalidated complete stripes #### + +mount_get_test_files $stripe_count +TEST fallocate -p -o 0 -l 5120 $B0/test_file +TEST fallocate -p -o 0 -l 5120 $M0/test_file +TEST dd if=$B0/misc_file of=$B0/test_file bs=1024 count=6 oflag=seek_bytes,sync seek=1030 conv=notrunc +TEST dd if=$B0/misc_file of=$M0/test_file bs=1024 count=6 oflag=seek_bytes,sync seek=1030 conv=notrunc +check_statedump_md5sum 5 11 +clean_file_unmount + +### 8 - Discard range - starts in the middle of stripe, ends on the middle of next stripe#### + +mount_get_test_files $stripe_count +TEST fallocate -p -o 500 -l 1024 $B0/test_file +TEST fallocate -p -o 500 -l 1024 $M0/test_file +TEST dd if=$B0/misc_file of=$B0/test_file bs=1024 count=5 oflag=seek_bytes,sync seek=500 conv=notrunc +TEST dd if=$B0/misc_file of=$M0/test_file bs=1024 count=5 oflag=seek_bytes,sync seek=500 conv=notrunc +check_statedump_md5sum 10 6 +clean_file_unmount + +### 9 - Discard range - starts in the middle of stripe, ends on the middle of 3rd stripe##### + +mount_get_test_files $stripe_count +TEST fallocate -p -o 500 -l 2048 $B0/test_file +TEST fallocate -p -o 500 -l 2048 $M0/test_file +TEST dd if=$B0/misc_file of=$B0/test_file bs=1024 count=5 oflag=seek_bytes,sync seek=500 conv=notrunc +TEST dd if=$B0/misc_file of=$M0/test_file bs=1024 count=5 oflag=seek_bytes,sync seek=500 conv=notrunc +check_statedump_md5sum 9 7 +clean_file_unmount + +### 10 - Discard range - starts and end within one stripe #### + +mount_get_test_files $stripe_count +TEST fallocate -p -o 500 -l 100 $B0/test_file +TEST fallocate -p -o 500 -l 100 $M0/test_file +TEST dd if=$B0/misc_file of=$B0/test_file bs=1024 count=1 oflag=seek_bytes,sync seek=0 conv=notrunc +TEST dd if=$B0/misc_file of=$M0/test_file bs=1024 count=1 oflag=seek_bytes,sync seek=0 conv=notrunc +check_statedump_md5sum 1 4 +clean_file_unmount + +### 11 - Discard range - starts and end in one complete stripe #### + +mount_get_test_files $stripe_count +TEST fallocate -p -o 0 -l 1024 $B0/test_file +TEST fallocate -p -o 0 -l 1024 $M0/test_file +TEST dd if=$B0/misc_file of=$B0/test_file bs=1024 count=1 oflag=seek_bytes,sync seek=512 conv=notrunc +TEST dd if=$B0/misc_file of=$M0/test_file bs=1024 count=1 oflag=seek_bytes,sync seek=512 conv=notrunc +check_statedump_md5sum 1 5 +clean_file_unmount + +### 12 - Discard range - starts and end two complete stripe #### + +mount_get_test_files $stripe_count +TEST fallocate -p -o 0 -l 2048 $B0/test_file +TEST fallocate -p -o 0 -l 2048 $M0/test_file +TEST dd if=$B0/misc_file of=$B0/test_file bs=1024 count=4 oflag=seek_bytes,sync seek=300 conv=notrunc +TEST dd if=$B0/misc_file of=$M0/test_file bs=1024 count=4 oflag=seek_bytes,sync seek=300 conv=notrunc +check_statedump_md5sum 5 7 +clean_file_unmount + +### 13 - Truncate to invalidate all the stripe in cache #### + +mount_get_test_files $stripe_count +TEST truncate -s 0 $B0/test_file +TEST truncate -s 0 $M0/test_file +TEST dd if=$B0/misc_file of=$B0/test_file bs=1022 count=5 oflag=seek_bytes,sync seek=400 conv=notrunc +TEST dd if=$B0/misc_file of=$M0/test_file bs=1022 count=5 oflag=seek_bytes,sync seek=400 conv=notrunc +check_statedump_md5sum 4 4 +clean_file_unmount + +### 14 - Truncate to invalidate all but one the stripe in cache #### + +mount_get_test_files $stripe_count +TEST truncate -s 500 $B0/test_file +TEST truncate -s 500 $M0/test_file +TEST dd if=$B0/misc_file of=$B0/test_file bs=1024 count=1 oflag=seek_bytes,sync seek=525 conv=notrunc +TEST dd if=$B0/misc_file of=$M0/test_file bs=1024 count=1 oflag=seek_bytes,sync seek=525 conv=notrunc +check_statedump_md5sum 2 4 +clean_file_unmount + +### 15 - Truncate to invalidate all but one the stripe in cache #### +mount_get_test_files $stripe_count +TEST truncate -s 2148 $B0/test_file +TEST truncate -s 2148 $M0/test_file +TEST dd if=$B0/misc_file of=$B0/test_file bs=1000 count=1 oflag=seek_bytes,sync seek=2050 conv=notrunc +TEST dd if=$B0/misc_file of=$M0/test_file bs=1000 count=1 oflag=seek_bytes,sync seek=2050 conv=notrunc +check_statedump_md5sum 2 4 +clean_file_unmount +echo "Total loop tests $loop_test" +cleanup diff --git a/tests/basic/ec/ec-up.t b/tests/basic/ec/ec-up.t new file mode 100644 index 00000000000..d54e7e1d022 --- /dev/null +++ b/tests/basic/ec/ec-up.t @@ -0,0 +1,28 @@ +#!/bin/bash +#Tests that ec subvolume is up/down correctly + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../ec.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse-data 2 redundancy 1 $H0:$B0/${V0}{0,1,3,4,5,6} +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +EXPECT "1" ec_up_status $V0 $M0 0 +EXPECT "1" ec_up_status $V0 $M0 1 + +#kill two bricks in first disperse subvolume and check that ec_up_status is 0 for it +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}1 + +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "0" ec_up_status $V0 $M0 0 +EXPECT "1" ec_up_status $V0 $M0 1 + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" ec_up_status $V0 $M0 0 +EXPECT "1" ec_up_status $V0 $M0 1 +cleanup; diff --git a/tests/basic/ec/ec.t b/tests/basic/ec/ec.t index fdbc43f0f38..cc882771501 100644 --- a/tests/basic/ec/ec.t +++ b/tests/basic/ec/ec.t @@ -11,6 +11,12 @@ function my_getfattr { getfattr --only-values -e text $* 2> /dev/null } +function get_rep_count { + v=$(my_getfattr -n trusted.jbr.rep-count $1) + #echo $v > /dev/tty + echo $v +} + function create_file { dd if=/dev/urandom of=$1 bs=4k count=$2 conv=sync 2> /dev/null } diff --git a/tests/basic/ec/gfapi-ec-open-truncate.c b/tests/basic/ec/gfapi-ec-open-truncate.c new file mode 100644 index 00000000000..fb16807003a --- /dev/null +++ b/tests/basic/ec/gfapi-ec-open-truncate.c @@ -0,0 +1,171 @@ +#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) + +int +fill_iov(struct iovec *iov, char fillchar, int count) +{ + int ret = -1; + + iov->iov_base = calloc(count + 1, sizeof(fillchar)); + if (iov->iov_base == NULL) { + return ret; + } else { + iov->iov_len = count; + ret = 0; + } + memset(iov->iov_base, fillchar, count); + memset(iov->iov_base + count, '\0', 1); + + return ret; +} + +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 +main(int argc, char *argv[]) +{ + char *hostname = NULL; + char *volname = NULL; + char *logfile = NULL; + glfs_t *fs = NULL; + glfs_fd_t *glfd = NULL; + int ret = 0; + int i = 0; + int count = 200; + struct iovec iov = {0}; + int flags = O_RDWR; + int bricksup = 0; + int fdopen = 0; + + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + fs = init_glfs(hostname, volname, logfile); + if (fs == NULL) { + LOG_ERR("init_glfs failed"); + return -1; + } + + /* Brick is down and we are opening a file to trigger fd heal. */ + /* Bypass Write-behind */ + glfd = glfs_open(fs, "a", O_WRONLY | O_TRUNC | O_SYNC); + if (glfd == NULL) { + LOG_ERR("glfs_open_truncate failed"); + exit(1); + } + system("gluster --mode=script volume start patchy force"); + /*CHILD_UP_TIMEOUT is 20 seconds*/ + for (i = 0; i < 20; i++) { + ret = system( + "[ $(gluster --mode=script volume status patchy | " + "grep \" Y \" | awk '{print $(NF-1)}' | wc -l) == 3 ]"); + if (WIFEXITED(ret) && WEXITSTATUS(ret)) { + printf("Ret value of system: %d\n, ifexited: %d, exitstatus: %d", + ret, WIFEXITED(ret), WEXITSTATUS(ret)); + sleep(1); + continue; + } + printf("Number of loops: %d\n", i); + bricksup = 1; + break; + } + if (!bricksup) { + system("gluster --mode=script volume status patchy"); + LOG_ERR("Bricks didn't come up\n"); + exit(1); + } + + /*Not sure how to check that the child-up reached EC, so sleep 3 for now*/ + sleep(3); + ret = fill_iov(&iov, 'a', 200); + if (ret) { + LOG_ERR("failed to create iov"); + exit(1); + } + + /*write will trigger re-open*/ + ret = glfs_pwritev(glfd, &iov, 1, 0, flags); + if (ret < 0) { + LOG_ERR("glfs_test_function failed"); + exit(1); + } + /*Check reopen happened by checking for open-fds on the brick*/ + for (i = 0; i < 20; i++) { + ret = system( + "[ $(for i in $(pgrep glusterfsd); do ls -l /proc/$i/fd | grep " + "\"[.]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)); + sleep(1); + continue; + } + fdopen = 1; + break; + } + + if (!fdopen) { + LOG_ERR("fd reopen didn't succeed"); + exit(1); + } + + return 0; +} diff --git a/tests/basic/ec/gfapi-ec-open-truncate.t b/tests/basic/ec/gfapi-ec-open-truncate.t new file mode 100644 index 00000000000..e22562c6ea3 --- /dev/null +++ b/tests/basic/ec/gfapi-ec-open-truncate.t @@ -0,0 +1,48 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +#This .t tests the functionality of open-fd-heal when opened with O_TRUNC. +#If re-open is not done with O_TRUNC then the test will pass. + +cleanup + +TEST glusterd + +TEST $CLI volume create $V0 disperse 3 ${H0}:$B0/brick{1,2,3} +EXPECT 'Created' volinfo_field $V0 'Status' +#Disable heals to prevent any chance of heals masking the problem +TEST $CLI volume set $V0 disperse.background-heals 0 +TEST $CLI volume set $V0 disperse.heal-wait-qlength 0 +TEST $CLI volume set $V0 performance.write-behind off + +#We need truncate fop to go through before pre-op completes for the write-fop +#which triggers open-fd heal. Otherwise truncate won't be allowed on 'bad' brick +TEST $CLI volume set $V0 delay-gen posix +TEST $CLI volume set $V0 delay-gen.enable fxattrop +TEST $CLI volume set $V0 delay-gen.delay-percentage 100 +TEST $CLI volume set $V0 delay-gen.delay-duration 1000000 + +TEST $CLI volume heal $V0 disable + +TEST $CLI volume start $V0 +TEST $CLI volume profile $V0 start +EXPECT 'Started' volinfo_field $V0 'Status' +TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 +TEST touch $M0/a +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +TEST kill_brick $V0 $H0 $B0/brick1 +logdir=`gluster --print-logdir` + +TEST build_tester $(dirname $0)/gfapi-ec-open-truncate.c -lgfapi + +TEST $CLI volume profile $V0 info clear +TEST ./$(dirname $0)/gfapi-ec-open-truncate ${H0} $V0 $logdir/gfapi-ec-open-truncate.log + +EXPECT "^2$" echo $($CLI volume profile $V0 info incremental | grep -i truncate | wc -l) +cleanup_tester $(dirname $0)/gfapi-ec-open-truncate + +cleanup diff --git a/tests/basic/ec/heal-info.t b/tests/basic/ec/heal-info.t new file mode 100644 index 00000000000..1549d5fcdb0 --- /dev/null +++ b/tests/basic/ec/heal-info.t @@ -0,0 +1,74 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +# This test checks if heal info works as expected or not + +function create_files { + for i in {21..1000}; + do + dd if=/dev/zero of=$M0/$i bs=1M count=1 2>&1 > /dev/null; + done + rm -f $M0/lock +} + +cleanup + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 redundancy 2 $H0:$B0/${V0}{0..5} +TEST $CLI volume set $V0 client-log-level DEBUG +TEST $CLI volume heal $V0 disable +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 --direct-io-mode=yes $M0; +# Wait until all 6 childs have been recognized by the ec xlator +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 + +#heal info should give zero entries to be healed when I/O is going on +dd if=/dev/zero of=$M0/a bs=1M count=2048 & +dd_pid=$! +sleep 3 #Wait for I/O to proceed for some time +EXPECT "^0$" get_pending_heal_count $V0 +kill -9 $dd_pid +touch $M0/lock +create_files & + +total_heal_count=0 +while [ -f $M0/lock ]; +do + heal_count=$(get_pending_heal_count $V0) + total_heal_count=$((heal_count+total_heal_count)) +done +EXPECT "^0$" echo $total_heal_count + +#When only data heal is required it should print it +#There is no easy way to create this using commands so assigning xattrs directly +TEST setfattr -n trusted.ec.version -v 0x00000000000000020000000000000000 $B0/${V0}0/1000 +TEST setfattr -n trusted.ec.version -v 0x00000000000000020000000000000000 $B0/${V0}1/1000 +TEST setfattr -n trusted.ec.version -v 0x00000000000000020000000000000000 $B0/${V0}2/1000 +TEST setfattr -n trusted.ec.version -v 0x00000000000000020000000000000000 $B0/${V0}3/1000 +TEST setfattr -n trusted.ec.version -v 0x00000000000000020000000000000000 $B0/${V0}4/1000 +TEST setfattr -n trusted.ec.version -v 0x00000000000000010000000000000000 $B0/${V0}5/1000 +index_path=$B0/${V0}5/.glusterfs/indices/xattrop/$(gf_gfid_xattr_to_str $(gf_get_gfid_xattr $B0/${V0}5/1000)) +while [ -f $index_path ]; do :; done +TEST touch $index_path +EXPECT "^1$" get_pending_heal_count $V0 +TEST rm -f $M0/1000 + +#When files/directories need heal test that it prints them +TEST touch $M0/{1..10} +TEST kill_brick $V0 $H0 $B0/${V0}0 +for i in {11..20}; +do + echo abc > $M0/$i #Data + entry + metadata heal +done +for i in {1..10}; +do + chmod +x $M0/$i; +done + +EXPECT "^105$" get_pending_heal_count $V0 + +cleanup +#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=1533815 diff --git a/tests/basic/ec/lock-contention.t b/tests/basic/ec/lock-contention.t new file mode 100644 index 00000000000..8f86cee16ad --- /dev/null +++ b/tests/basic/ec/lock-contention.t @@ -0,0 +1,62 @@ +#!/bin/bash + +# This test verifies that when 'lock-notify-contention' option is enabled, +# locks xlator actually sends an upcall notification that causes the acquired +# lock from one client to be released before it's supposed to when another +# client accesses the file. + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +function elapsed_time() { + local start="`date +%s`" + + if [[ "test" == `cat "$1"` ]]; then + echo "$((`date +%s` - ${start}))" + fi +} + +cleanup + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0..2} +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume set $V0 performance.quick-read off +TEST $CLI volume set $V0 performance.read-ahead off +TEST $CLI volume set $V0 performance.io-cache off +TEST $CLI volume set $V0 features.locks-notify-contention off +TEST $CLI volume set $V0 disperse.eager-lock on +TEST $CLI volume set $V0 disperse.eager-lock-timeout 6 +TEST $CLI volume set $V0 disperse.other-eager-lock on +TEST $CLI volume set $V0 disperse.other-eager-lock-timeout 6 +TEST $CLI volume start $V0 + +TEST $GFS --direct-io-mode=yes --volfile-id=/$V0 --volfile-server=$H0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 $M0 + +TEST $GFS --direct-io-mode=yes --volfile-id=/$V0 --volfile-server=$H0 $M1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 $M1 + +TEST $(echo "test" >$M0/file) + +# With locks-notify-contention set to off, accessing the file from another +# client should take 6 seconds. Checking against 3 seconds to be safe. +elapsed="$(elapsed_time $M1/file)" +TEST [[ ${elapsed} -ge 3 ]] + +elapsed="$(elapsed_time $M0/file)" +TEST [[ ${elapsed} -ge 3 ]] + +TEST $CLI volume set $V0 features.locks-notify-contention on + +# With locks-notify-contention set to on, accessing the file from another +# client should be fast. Checking against 3 seconds to be safe. +elapsed="$(elapsed_time $M1/file)" +TEST [[ ${elapsed} -le 3 ]] + +elapsed="$(elapsed_time $M0/file)" +TEST [[ ${elapsed} -le 3 ]] + +cleanup diff --git a/tests/basic/ec/nfs.t b/tests/basic/ec/nfs.t index f0bdff93d5f..3f51a640ef7 100755 --- a/tests/basic/ec/nfs.t +++ b/tests/basic/ec/nfs.t @@ -3,6 +3,8 @@ . $(dirname $0)/../../include.rc . $(dirname $0)/../../nfs.rc +#G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST + cleanup TEST glusterd diff --git a/tests/basic/ec/quota.t b/tests/basic/ec/quota.t index b023240b87e..c9612c8b76a 100755 --- a/tests/basic/ec/quota.t +++ b/tests/basic/ec/quota.t @@ -40,7 +40,6 @@ EXPECT_WITHIN $MARKER_UPDATE_TIMEOUT "8.0MB" quotausage "/test" TEST rm $M0/test/file2.txt EXPECT_WITHIN $MARKER_UPDATE_TIMEOUT "0Bytes" quotausage "/test" TEST $CLI volume stop $V0 -EXPECT "1" get_aux rm -f $QDD cleanup; diff --git a/tests/basic/ec/self-heal-read-write-fail.t b/tests/basic/ec/self-heal-read-write-fail.t new file mode 100644 index 00000000000..0ba591b5bb2 --- /dev/null +++ b/tests/basic/ec/self-heal-read-write-fail.t @@ -0,0 +1,69 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +#This test verifies that self-heal fails when read/write fails as part of heal +cleanup + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info + +TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0,1,2} +TEST $CLI volume heal $V0 disable +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 +TEST touch $M0/a +TEST kill_brick $V0 $H0 $B0/${V0}0 +echo abc >> $M0/a + +# Umount the volume to force all pending writes to reach the bricks +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +#Load error-gen and fail read fop and test that heal fails +TEST $CLI volume stop $V0 #Stop volume so that error-gen can be loaded +TEST $CLI volume set $V0 debug.error-gen posix +TEST $CLI volume set $V0 debug.error-fops read +TEST $CLI volume set $V0 debug.error-number EBADF +TEST $CLI volume set $V0 debug.error-failure 100 + +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 +EXPECT_WITHIN $HEAL_TIMEOUT "^2$" get_pending_heal_count $V0 +TEST ! getfattr -n trusted.ec.heal $M0/a +EXPECT_WITHIN $HEAL_TIMEOUT "^2$" get_pending_heal_count $V0 + +#fail write fop and test that heal fails +TEST $CLI volume stop $V0 +TEST $CLI volume set $V0 debug.error-fops write + +TEST $CLI volume start $V0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 +EXPECT_WITHIN $HEAL_TIMEOUT "^2$" get_pending_heal_count $V0 +TEST ! getfattr -n trusted.ec.heal $M0/a +EXPECT_WITHIN $HEAL_TIMEOUT "^2$" get_pending_heal_count $V0 + +TEST $CLI volume stop $V0 #Stop volume so that error-gen can be disabled +TEST $CLI volume reset $V0 debug.error-gen +TEST $CLI volume reset $V0 debug.error-fops +TEST $CLI volume reset $V0 debug.error-number +TEST $CLI volume reset $V0 debug.error-failure + +TEST $CLI volume start $V0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 +EXPECT_WITHIN $HEAL_TIMEOUT "^2$" get_pending_heal_count $V0 +TEST getfattr -n trusted.ec.heal $M0/a +EXPECT "^0$" get_pending_heal_count $V0 + +#Test that heal worked as expected by forcing read from brick0 +#remount to make sure data is not served from any cache +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 +TEST kill_brick $V0 $H0 $B0/${V0}2 +EXPECT "abc" cat $M0/a + +cleanup diff --git a/tests/basic/ec/self-heal.t b/tests/basic/ec/self-heal.t index 98dd9232c73..6329bb60248 100644 --- a/tests/basic/ec/self-heal.t +++ b/tests/basic/ec/self-heal.t @@ -1,5 +1,7 @@ #!/bin/bash +SCRIPT_TIMEOUT=300 + . $(dirname $0)/../../include.rc . $(dirname $0)/../../volume.rc @@ -9,6 +11,7 @@ cleanup function check_mount_dir { + getfattr -d -m. -e hex $M0 2>&1 > /dev/null for i in {1..20}; do ls -l $M0/ | grep "dir1" if [ $? -ne 0 ]; then @@ -21,7 +24,7 @@ function check_mount_dir function check_size { - stat $M0/$1 + cat $M0/$1 2>&1 > /dev/null for i in "${brick[@]}"; do res=`stat -c "%s" $i/$1` if [ "$res" != "$2" ]; then @@ -35,7 +38,7 @@ function check_size function check_mode { - stat $M0/$1 + getfattr -d -m. -e hex $M0/$1 2>&1 > /dev/null for i in "${brick[@]}"; do res=`stat -c "%A" $i/$1` if [ "$res" != "$2" ]; then @@ -49,7 +52,7 @@ function check_mode function check_date { - stat $M0/$1 + getfattr -d -m. -e hex $M0/$1 2>&1 > /dev/null for i in "${brick[@]}"; do res=`stat -c "%Y" $i/$1` if [ "$res" != "$2" ]; then @@ -63,7 +66,7 @@ function check_date function check_xattr { - stat $M0/$1 + getfattr -d -m. -e hex $M0/$1 2>&1 > /dev/null for i in "${brick[@]}"; do getfattr -n $2 $i/$1 2>/dev/null if [ $? -eq 0 ]; then @@ -77,7 +80,7 @@ function check_xattr function check_dir { - getfattr -m. -d $M0/dir1 + getfattr -m. -d $M0/dir1 2>&1 > /dev/null for i in "${brick[@]}"; do if [ ! -d $i/dir1 ]; then echo "N" @@ -90,7 +93,7 @@ function check_dir function check_soft_link { - stat $M0/test3 + getfattr -d -m. -e hex $M0/test3 2>&1 > /dev/null for i in "${brick[@]}"; do if [ ! -h $i/test3 ]; then echo "N" @@ -103,7 +106,7 @@ function check_soft_link function check_hard_link { - stat $M0/test4 + getfattr -d -m. -e hex $M0/test4 2>&1 > /dev/null for i in "${brick[@]}"; do res=`stat -c "%h" $i/test4` if [ "$res" != "3" ]; then @@ -125,10 +128,16 @@ TESTS_EXPECTED_IN_LOOP=194 TEST glusterd TEST pidof glusterd TEST $CLI volume create $V0 redundancy 2 $H0:$B0/${V0}{0..5} +TEST $CLI volume set $V0 client-log-level DEBUG +#Write-behind has a bug where lookup can race over write which leads to size mismatch on the mount after a 'cp' +TEST $CLI volume set $V0 performance.write-behind off +#md-cache can return stale stat due to default timeout being 1 sec +TEST $CLI volume set $V0 performance.stat-prefetch off EXPECT "Created" volinfo_field $V0 'Status' TEST $CLI volume start $V0 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Started" volinfo_field $V0 'Status' -TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +#direct-io-mode is to make sure 'cat' leads to READ fop which triggers heal +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 --direct-io-mode=yes $M0; # Wait until all 6 childs have been recognized by the ec xlator EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 @@ -136,7 +145,7 @@ TEST dd if=/dev/urandom of=$tmp/test bs=1024 count=1024 cs=$(sha1sum $tmp/test | awk '{ print $1 }') -TEST df -h +TEST df -h $M0 TEST stat $M0 for idx in {0..5}; do diff --git a/tests/basic/exports_parsing.t b/tests/basic/exports_parsing.t index fdaf9c2822e..da88bbcb2cc 100644 --- a/tests/basic/exports_parsing.t +++ b/tests/basic/exports_parsing.t @@ -32,7 +32,20 @@ function test_bad_opt () glusterfsd --print-exports $1 2>&1 | sed -n 1p } -EXPECT_KEYWORD "/test @test(rw,anonuid=0,sec=sys,) 10.35.11.31(rw,anonuid=0,sec=sys,)" test_good_file $EXP_FILES/exports +function check_export_line() { + if [ "$1" == "$2" ]; then + echo "Y" + else + echo "N" + fi + return +} + +export_result=$(test_good_file $EXP_FILES/exports) +EXPECT "Y" check_export_line '/test @test(rw,anonuid=0,sec=sys,) 10.35.11.31(rw,anonuid=0,sec=sys,) ' "$export_result" + +export_result=$(test_good_file $EXP_FILES/exports-v6) +EXPECT "Y" check_export_line '/test @test(rw,anonuid=0,sec=sys,) 2401:db00:11:1:face:0:3d:0(rw,anonuid=0,sec=sys,) ' "$export_result" EXPECT_KEYWORD "Error parsing netgroups for:" test_bad_line $EXP_FILES/bad_exports EXPECT_KEYWORD "Error parsing netgroups for:" test_long_netgroup $EXP_FILES/bad_exports diff --git a/tests/basic/fencing/afr-lock-heal-advanced.c b/tests/basic/fencing/afr-lock-heal-advanced.c new file mode 100644 index 00000000000..e202ccd5b29 --- /dev/null +++ b/tests/basic/fencing/afr-lock-heal-advanced.c @@ -0,0 +1,227 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <signal.h> +#include <unistd.h> +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> + +#define GF_ENFORCE_MANDATORY_LOCK "trusted.glusterfs.enforce-mandatory-lock" + +FILE *logfile_fp; + +#define LOG_ERR(func, err) \ + do { \ + if (!logfile_fp) { \ + fprintf(stderr, "%\n%d %s : returned error (%s)\n", __LINE__, \ + func, strerror(err)); \ + fflush(stderr); \ + } else { \ + fprintf(logfile_fp, "\n%d %s : returned error (%s)\n", __LINE__, \ + func, strerror(err)); \ + fflush(logfile_fp); \ + } \ + } while (0) + +glfs_t * +setup_client(char *hostname, char *volname, char *log_file) +{ + int ret = 0; + glfs_t *fs = NULL; + + fs = glfs_new(volname); + if (!fs) { + fprintf(logfile_fp, "\nglfs_new: returned NULL (%s)\n", + strerror(errno)); + goto error; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + if (ret < 0) { + fprintf(logfile_fp, "\nglfs_set_volfile_server failed ret:%d (%s)\n", + ret, strerror(errno)); + goto error; + } + + ret = glfs_set_logging(fs, log_file, 7); + if (ret < 0) { + fprintf(logfile_fp, "\nglfs_set_logging failed with ret: %d (%s)\n", + ret, strerror(errno)); + goto error; + } + + ret = glfs_init(fs); + if (ret < 0) { + fprintf(logfile_fp, "\nglfs_init failed with ret: %d (%s)\n", ret, + strerror(errno)); + goto error; + } + +out: + return fs; +error: + return NULL; +} + +glfs_fd_t * +open_file(glfs_t *fs, char *fname) +{ + glfs_fd_t *fd = NULL; + + fd = glfs_creat(fs, fname, O_CREAT, 0644); + if (!fd) { + LOG_ERR("glfs_creat", errno); + goto out; + } +out: + return fd; +} + +int +acquire_mandatory_lock(glfs_t *fs, glfs_fd_t *fd) +{ + struct flock lock; + int ret = 0; + + /* initialize lock */ + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 100; + + ret = glfs_fsetxattr(fd, GF_ENFORCE_MANDATORY_LOCK, "set", 8, 0); + if (ret < 0) { + LOG_ERR("glfs_fsetxattr", errno); + ret = -1; + goto out; + } + + /* take a write mandatory lock */ + ret = glfs_file_lock(fd, F_SETLKW, &lock, GLFS_LK_MANDATORY); + if (ret) { + LOG_ERR("glfs_file_lock", errno); + ret = -1; + goto out; + } + +out: + return ret; +} + +int +perform_test(glfs_t *fs, char *file1, char *file2) +{ + int ret = 0; + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + char *buf = "0123456789"; + + fd1 = open_file(fs, file1); + if (!fd1) { + ret = -1; + goto out; + } + fd2 = open_file(fs, file2); + if (!fd2) { + ret = -1; + goto out; + } + + /* Kill one brick from the .t.*/ + pause(); + + ret = acquire_mandatory_lock(fs, fd1); + if (ret) { + goto out; + } + ret = acquire_mandatory_lock(fs, fd2); + if (ret) { + goto out; + } + + /* Bring the brick up and let the locks heal. */ + pause(); + /*At this point, the .t would have killed and brought back 2 bricks, marking + * the fd bad.*/ + + ret = glfs_write(fd1, buf, 10, 0); + if (ret > 0) { + /* Write is supposed to fail with EBADFD*/ + LOG_ERR("glfs_write", ret); + goto out; + } + + ret = 0; +out: + if (fd1) + glfs_close(fd1); + if (fd2) + glfs_close(fd2); + return ret; +} + +static void +sigusr1_handler(int signo) +{ + /*Signal caught. Just continue with the execution.*/ +} + +int +main(int argc, char *argv[]) +{ + int ret = 0; + glfs_t *fs = NULL; + char *volname = NULL; + char log_file[100]; + char *hostname = NULL; + char *fname1 = NULL; + char *fname2 = NULL; + + if (argc != 7) { + fprintf(stderr, + "Expect following args %s <host> <volname> <file1> <file2> " + "<log file " + "location> <log_file_suffix>\n", + argv[0]); + return -1; + } + + hostname = argv[1]; + volname = argv[2]; + fname1 = argv[3]; + fname2 = argv[4]; + + /*Use SIGUSR1 and pause()as a means of hitting break-points this program + *when signalled from the .t test case.*/ + if (signal(SIGUSR1, sigusr1_handler) == SIG_ERR) { + LOG_ERR("SIGUSR1 handler error", errno); + exit(EXIT_FAILURE); + } + + sprintf(log_file, "%s/%s.%s.%s", argv[5], "lock-heal.c", argv[6], "log"); + logfile_fp = fopen(log_file, "w"); + if (!logfile_fp) { + fprintf(stderr, "\nfailed to open %s\n", log_file); + fflush(stderr); + return -1; + } + + sprintf(log_file, "%s/%s.%s.%s", argv[5], "glfs-client", argv[6], "log"); + fs = setup_client(hostname, volname, log_file); + if (!fs) { + LOG_ERR("setup_client", errno); + return -1; + } + + ret = perform_test(fs, fname1, fname2); + +error: + if (fs) { + /*glfs_fini(fs)*/; // glfs fini path is racy and crashes the program + } + + fclose(logfile_fp); + + return ret; +} diff --git a/tests/basic/fencing/afr-lock-heal-advanced.t b/tests/basic/fencing/afr-lock-heal-advanced.t new file mode 100644 index 00000000000..8a5b5989b5e --- /dev/null +++ b/tests/basic/fencing/afr-lock-heal-advanced.t @@ -0,0 +1,115 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; +PROCESS_UP_TIMEOUT=90 + +function is_gfapi_program_alive() +{ + pid=$1 + ps -p $pid + if [ $? -eq 0 ] + then + echo "Y" + else + echo "N" + fi +} + +function get_active_lock_count { + brick=$1 + i1=$2 + i2=$3 + pattern="ACTIVE.*client-${brick: -1}" + + sdump=$(generate_brick_statedump $V0 $H0 $brick) + 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 +TEST pidof glusterd +TEST $CLI volume info; + +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2} +EXPECT 'Created' volinfo_field $V0 'Status'; +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume set $V0 performance.open-behind off +TEST $CLI volume set $V0 locks.mandatory-locking forced +TEST $CLI volume set $V0 enforce-mandatory-lock on +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; + +logdir=`gluster --print-logdir` +TEST build_tester $(dirname $0)/afr-lock-heal-advanced.c -lgfapi -ggdb + +#------------------------------------------------------------------------------ +# Use more than 1 fd from same client so that list_for_each_* loops are executed more than once. +$(dirname $0)/afr-lock-heal-advanced $H0 $V0 "/FILE1" "/FILE2" $logdir C1& +client_pid=$! +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 +# If program is still alive, glfs_file_lock() was a success. +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 $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 $inode1 $inode2 + +#------------------------------------------------------------------------------ +# Kill same brick before heal completes the first time and check it completes the second time. +TEST $CLI volume set $V0 delay-gen locks +TEST $CLI volume set $V0 delay-gen.delay-duration 5000000 +TEST $CLI volume set $V0 delay-gen.delay-percentage 100 +TEST $CLI volume set $V0 delay-gen.enable finodelk + +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +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 $inode1 $inode2 + +#------------------------------------------------------------------------------ +# Kill 2 bricks and bring it back. The fds must be marked bad. +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +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" brick_up_status $V0 $H0 $B0/${V0}1 + +# TODO: `gluster v statedump $V0 client localhost:$client_pid` is not working, +# so sleep for 20 seconds for the client to connect to connect to the bricks. +TEST sleep $CHILD_UP_TIMEOUT + +# Try to write to FILE1 from the .c; it must fail. +TEST kill -SIGUSR1 $client_pid +wait $client_pid +ret=$? +TEST [ $ret == 0 ] + +cleanup_tester $(dirname $0)/afr-lock-heal-advanced +cleanup; diff --git a/tests/basic/fencing/afr-lock-heal-basic.c b/tests/basic/fencing/afr-lock-heal-basic.c new file mode 100644 index 00000000000..768c9e57181 --- /dev/null +++ b/tests/basic/fencing/afr-lock-heal-basic.c @@ -0,0 +1,182 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <signal.h> +#include <unistd.h> +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> + +#define GF_ENFORCE_MANDATORY_LOCK "trusted.glusterfs.enforce-mandatory-lock" + +FILE *logfile_fp; + +#define LOG_ERR(func, err) \ + do { \ + if (!logfile_fp) { \ + fprintf(stderr, "%\n%d %s : returned error (%s)\n", __LINE__, \ + func, strerror(err)); \ + fflush(stderr); \ + } else { \ + fprintf(logfile_fp, "\n%d %s : returned error (%s)\n", __LINE__, \ + func, strerror(err)); \ + fflush(logfile_fp); \ + } \ + } while (0) + +glfs_t * +setup_client(char *hostname, char *volname, char *log_file) +{ + int ret = 0; + glfs_t *fs = NULL; + + fs = glfs_new(volname); + if (!fs) { + fprintf(logfile_fp, "\nglfs_new: returned NULL (%s)\n", + strerror(errno)); + goto error; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + if (ret < 0) { + fprintf(logfile_fp, "\nglfs_set_volfile_server failed ret:%d (%s)\n", + ret, strerror(errno)); + goto error; + } + + ret = glfs_set_logging(fs, log_file, 7); + if (ret < 0) { + fprintf(logfile_fp, "\nglfs_set_logging failed with ret: %d (%s)\n", + ret, strerror(errno)); + goto error; + } + + ret = glfs_init(fs); + if (ret < 0) { + fprintf(logfile_fp, "\nglfs_init failed with ret: %d (%s)\n", ret, + strerror(errno)); + goto error; + } + +out: + return fs; +error: + return NULL; +} + +int +acquire_mandatory_lock(glfs_t *fs, char *fname) +{ + struct flock lock; + int ret = 0; + glfs_fd_t *fd = NULL; + + fd = glfs_creat(fs, fname, O_CREAT, 0644); + if (!fd) { + if (errno != EEXIST) { + LOG_ERR("glfs_creat", errno); + ret = -1; + goto out; + } + fd = glfs_open(fs, fname, O_RDWR | O_NONBLOCK); + if (!fd) { + LOG_ERR("glfs_open", errno); + ret = -1; + goto out; + } + } + + /* initialize lock */ + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 100; + + ret = glfs_fsetxattr(fd, GF_ENFORCE_MANDATORY_LOCK, "set", 8, 0); + if (ret < 0) { + LOG_ERR("glfs_fsetxattr", errno); + ret = -1; + goto out; + } + + pause(); + + /* take a write mandatory lock */ + ret = glfs_file_lock(fd, F_SETLKW, &lock, GLFS_LK_MANDATORY); + if (ret) { + LOG_ERR("glfs_file_lock", errno); + goto out; + } + + pause(); + +out: + if (fd) { + glfs_close(fd); + } + + return ret; +} + +static void +sigusr1_handler(int signo) +{ + /*Signal caught. Just continue with the execution.*/ +} + +int +main(int argc, char *argv[]) +{ + int ret = 0; + glfs_t *fs = NULL; + char *volname = NULL; + char log_file[100]; + char *hostname = NULL; + char *fname = NULL; + + if (argc != 6) { + fprintf(stderr, + "Expect following args %s <host> <volname> <file> <log file " + "location> <log_file_suffix>\n", + argv[0]); + return -1; + } + + hostname = argv[1]; + volname = argv[2]; + fname = argv[3]; + + /*Use SIGUSR1 and pause()as a means of hitting break-points this program + *when signalled from the .t test case.*/ + if (signal(SIGUSR1, sigusr1_handler) == SIG_ERR) { + LOG_ERR("SIGUSR1 handler error", errno); + exit(EXIT_FAILURE); + } + + sprintf(log_file, "%s/%s.%s.%s", argv[4], "lock-heal-basic.c", argv[5], + "log"); + logfile_fp = fopen(log_file, "w"); + if (!logfile_fp) { + fprintf(stderr, "\nfailed to open %s\n", log_file); + fflush(stderr); + return -1; + } + + sprintf(log_file, "%s/%s.%s.%s", argv[4], "glfs-client", argv[5], "log"); + fs = setup_client(hostname, volname, log_file); + if (!fs) { + LOG_ERR("setup_client", errno); + return -1; + } + + ret = acquire_mandatory_lock(fs, fname); + +error: + if (fs) { + /*glfs_fini(fs)*/; // glfs fini path is racy and crashes the program + } + + fclose(logfile_fp); + + return ret; +} diff --git a/tests/basic/fencing/afr-lock-heal-basic.t b/tests/basic/fencing/afr-lock-heal-basic.t new file mode 100644 index 00000000000..69131af085d --- /dev/null +++ b/tests/basic/fencing/afr-lock-heal-basic.t @@ -0,0 +1,102 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +function is_gfapi_program_alive() +{ + pid=$1 + ps -p $pid + if [ $? -eq 0 ] + then + echo "Y" + else + echo "N" + fi +} + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info; + +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2} +EXPECT 'Created' volinfo_field $V0 'Status'; +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume set $V0 performance.open-behind off +TEST $CLI volume set $V0 locks.mandatory-locking forced +TEST $CLI volume set $V0 enforce-mandatory-lock on +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; + +logdir=`gluster --print-logdir` +TEST build_tester $(dirname $0)/afr-lock-heal-basic.c -lgfapi -ggdb + +$(dirname $0)/afr-lock-heal-basic $H0 $V0 "/FILE" $logdir C1& +client1_pid=$! +TEST [ $client1_pid ] + +$(dirname $0)/afr-lock-heal-basic $H0 $V0 "/FILE" $logdir C2& +client2_pid=$! +TEST [ $client2_pid ] + +TEST sleep 5 # By now, the 2 clients would have opened an fd on FILE and waiting for a SIGUSR1. +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 +# If program is still alive, glfs_file_lock() was a success. +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_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. +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. Also wait for lock heal. + +b3_sdump=$(generate_brick_statedump $V0 $H0 $B0/${V0}2) +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. +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill -SIGUSR1 $client2_pid +# If program is still alive, glfs_file_lock() was a success. +EXPECT "Y" is_gfapi_program_alive $client2_pid + +# Restart brick-1 and let lock healing complete. +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0 +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. + +# 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_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" ] + +#Let the client programs run and exit. +TEST kill -SIGUSR1 $client1_pid +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "N" is_gfapi_program_alive $client1_pid +TEST kill -SIGUSR1 $client2_pid +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "N" is_gfapi_program_alive $client2_pid + +cleanup_tester $(dirname $0)/afr-lock-heal-basic +cleanup; diff --git a/tests/basic/fencing/fence-basic.c b/tests/basic/fencing/fence-basic.c new file mode 100644 index 00000000000..4aa452e19b0 --- /dev/null +++ b/tests/basic/fencing/fence-basic.c @@ -0,0 +1,229 @@ +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define NO_INIT 1 +#define GF_ENFORCE_MANDATORY_LOCK "trusted.glusterfs.enforce-mandatory-lock" + +FILE *fp; +char *buf = "0123456789"; + +#define LOG_ERR(func, err) \ + do { \ + if (!fp) { \ + fprintf(stderr, "%\n%d %s : returned error (%s)\n", __LINE__, \ + func, strerror(err)); \ + fflush(stderr); \ + } else { \ + fprintf(fp, "\n%d %s : returned error (%s)\n", __LINE__, func, \ + strerror(err)); \ + fflush(fp); \ + } \ + } while (0) + +glfs_t * +setup_new_client(char *hostname, char *volname, char *log_file, int flag) +{ + int ret = 0; + glfs_t *fs = NULL; + + fs = glfs_new(volname); + if (!fs) { + fprintf(fp, "\nglfs_new: returned NULL (%s)\n", strerror(errno)); + goto error; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + if (ret < 0) { + fprintf(fp, "\nglfs_set_volfile_server failed ret:%d (%s)\n", ret, + strerror(errno)); + goto error; + } + + ret = glfs_set_logging(fs, log_file, 7); + if (ret < 0) { + fprintf(fp, "\nglfs_set_logging failed with ret: %d (%s)\n", ret, + strerror(errno)); + goto error; + } + + if (flag == NO_INIT) + goto out; + + ret = glfs_init(fs); + if (ret < 0) { + fprintf(fp, "\nglfs_init failed with ret: %d (%s)\n", ret, + strerror(errno)); + goto error; + } + +out: + return fs; +error: + return NULL; +} + +/* test plan + * + * - take mandatory lock from client 1 + * - preempt mandatory lock from client 2 + * - write from client 1 which should fail + */ + +int +test(glfs_t *fs1, glfs_t *fs2, char *fname) +{ + struct flock lock; + int ret = 0; + glfs_fd_t *fd1, *fd2 = NULL; + + fd1 = glfs_creat(fs1, fname, O_RDWR, 0777); + if (ret) { + LOG_ERR("glfs_creat", errno); + ret = -1; + goto out; + } + + fd2 = glfs_open(fs2, fname, O_RDWR | O_NONBLOCK); + if (ret) { + LOG_ERR("glfs_open", errno); + ret = -1; + goto out; + } + + /* initialize lock */ + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 100; + + ret = glfs_fsetxattr(fd1, GF_ENFORCE_MANDATORY_LOCK, "set", 8, 0); + if (ret < 0) { + LOG_ERR("glfs_fsetxattr", errno); + ret = -1; + goto out; + } + + /* take a write mandatory lock */ + ret = glfs_file_lock(fd1, F_SETLKW, &lock, GLFS_LK_MANDATORY); + if (ret) { + LOG_ERR("glfs_file_lock", errno); + goto out; + } + + ret = glfs_write(fd1, buf, 10, 0); + if (ret != 10) { + LOG_ERR("glfs_write", errno); + ret = -1; + goto out; + } + + /* write should fail */ + ret = glfs_write(fd2, buf, 10, 0); + if (ret != -1) { + LOG_ERR("glfs_write", errno); + ret = -1; + goto out; + } + + /* preempt mandatory lock from client 1*/ + ret = glfs_file_lock(fd2, F_SETLKW, &lock, GLFS_LK_MANDATORY); + if (ret) { + LOG_ERR("glfs_file_lock", errno); + goto out; + } + + /* write should succeed from client 2 */ + ret = glfs_write(fd2, buf, 10, 0); + if (ret == -1) { + LOG_ERR("glfs_write", errno); + goto out; + } + + /* write should fail from client 1 */ + ret = glfs_write(fd1, buf, 10, 0); + if (ret == 10) { + LOG_ERR("glfs_write", errno); + ret = -1; + goto out; + } + + ret = 0; + +out: + if (fd1) { + glfs_close(fd1); + } + + if (fd2) { + glfs_close(fd2); + } + + return ret; +} + +int +main(int argc, char *argv[]) +{ + int ret = 0; + glfs_t *fs1 = NULL; + glfs_t *fs2 = NULL; + char *volname = NULL; + char log_file[100]; + char *hostname = NULL; + char *fname = "/file"; + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + + if (argc != 4) { + fprintf( + stderr, + "Expect following args %s <hostname> <Vol> <log file location>\n", + argv[0]); + return -1; + } + + hostname = argv[1]; + volname = argv[2]; + + sprintf(log_file, "%s/%s", argv[3], "fence-basic.log"); + fp = fopen(log_file, "w"); + if (!fp) { + fprintf(stderr, "\nfailed to open %s\n", log_file); + fflush(stderr); + return -1; + } + + sprintf(log_file, "%s/%s", argv[3], "glfs-client-1.log"); + fs1 = setup_new_client(hostname, volname, log_file, 0); + if (!fs1) { + LOG_ERR("setup_new_client", errno); + return -1; + } + + sprintf(log_file, "%s/%s", argv[3], "glfs-client-2.log"); + fs2 = setup_new_client(hostname, volname, log_file, 0); + if (!fs2) { + LOG_ERR("setup_new_client", errno); + ret = -1; + goto error; + } + + ret = test(fs1, fs2, fname); + +error: + if (fs1) { + glfs_fini(fs1); + } + + if (fs2) { + glfs_fini(fs2); + } + + fclose(fp); + + return ret; +} diff --git a/tests/basic/fencing/fence-basic.t b/tests/basic/fencing/fence-basic.t new file mode 100755 index 00000000000..30f379e7b20 --- /dev/null +++ b/tests/basic/fencing/fence-basic.t @@ -0,0 +1,31 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info; + +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'; + +TEST $CLI volume set $V0 diagnostics.client-log-flush-timeout 30 +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume set $V0 locks.mandatory-locking forced +TEST $CLI volume set $V0 enforce-mandatory-lock on + + +logdir=`gluster --print-logdir` + +TEST build_tester $(dirname $0)/fence-basic.c -lgfapi -ggdb +TEST $(dirname $0)/fence-basic $H0 $V0 $logdir + +cleanup_tester $(dirname $0)/fence-basic + +cleanup;
\ No newline at end of file diff --git a/tests/basic/fencing/fencing-crash-conistency.t b/tests/basic/fencing/fencing-crash-conistency.t new file mode 100644 index 00000000000..0c69411e90c --- /dev/null +++ b/tests/basic/fencing/fencing-crash-conistency.t @@ -0,0 +1,62 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +# with lock enforcement flag write should fail with out lock + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info; + +TEST $CLI volume create $V0 $H0:$B0/${V0}1 +EXPECT 'Created' volinfo_field $V0 'Status'; +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; +TEST $CLI volume set $V0 performance.write-behind off +TEST glusterfs -s $H0 --volfile-id $V0 $M0 + +TEST touch $M0/file + +#write should pass +TEST "echo "test" > $M0/file" +TEST "truncate -s 0 $M0/file" + +#enable mandatory locking +TEST $CLI volume set $V0 locks.mandatory-locking forced +TEST $CLI volume set $V0 enforce-mandatory-lock on + +#write should pass +TEST "echo "test" >> $M0/file" +TEST "truncate -s 0 $M0/file" + +#enforce lock on the file +TEST setfattr -n trusted.glusterfs.enforce-mandatory-lock -v 1 $M0/file + +#write should fail +TEST ! "echo "test" >> $M0/file" +TEST ! "truncate -s 0 $M0/file" + +#remove lock enforcement flag +TEST setfattr -x trusted.glusterfs.enforce-mandatory-lock $M0/file + +#write should pass +TEST "echo "test" >> $M0/file" +TEST "truncate -s 0 $M0/file" + +#enforce lock on the file +TEST setfattr -n trusted.glusterfs.enforce-mandatory-lock -v 1 $M0/file +#kill brick +TEST kill_brick $V0 $H0 $B0/${V0}1 + +TEST $CLI volume start $V0 force + +# wait one second for the brick to come online +sleep 2 +#write should fail (lock xlator gets lock enforcement info from disk) +TEST ! "echo "test" >> $M0/file" +TEST ! "truncate -s 0 $M0/file" + +cleanup;
\ No newline at end of file diff --git a/tests/basic/fencing/test-fence-option.t b/tests/basic/fencing/test-fence-option.t new file mode 100644 index 00000000000..115cbe7dbdf --- /dev/null +++ b/tests/basic/fencing/test-fence-option.t @@ -0,0 +1,37 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +# with lock enforcement flag write should fail with out lock + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info; + +TEST $CLI volume create $V0 $H0:$B0/${V0}1 +EXPECT 'Created' volinfo_field $V0 'Status'; +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; +TEST glusterfs -s $H0 --volfile-id $V0 $M0 + +TEST touch $M0/file + +#setfattr for mandatory-enforcement will fail +TEST ! setfattr -n trusted.glusterfs.enforce-mandatory-lock -v 1 $M0/file + +#enable mandatory locking +TEST $CLI volume set $V0 locks.mandatory-locking forced + +#setfattr will fail +TEST ! setfattr -n trusted.glusterfs.enforce-mandatory-lock -v 1 $M0/file + +#set lock-enforcement option +TEST $CLI volume set $V0 enforce-mandatory-lock on + +#setfattr should succeed +TEST setfattr -n trusted.glusterfs.enforce-mandatory-lock -v 1 $M0/file + +cleanup;
\ No newline at end of file diff --git a/tests/basic/first-test.t b/tests/basic/first-test.t deleted file mode 100755 index 535b269e6b3..00000000000 --- a/tests/basic/first-test.t +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../include.rc - -cat << EOF -This test should run first for http://review.gluster.org/#/c/13439/ and should -be removed once that patch has been merged. -EOF - -TEST true diff --git a/tests/basic/fops-sanity.c b/tests/basic/fops-sanity.c index 1e2ccde6bd8..ef00aa0f088 100644 --- a/tests/basic/fops-sanity.c +++ b/tests/basic/fops-sanity.c @@ -26,6 +26,7 @@ #include <errno.h> #include <string.h> #include <dirent.h> +#include <sys/sysmacros.h> #ifndef linux #include <sys/socket.h> @@ -34,858 +35,904 @@ #endif /* for fd based fops after unlink */ -int fd_based_fops_1 (char *filename); +int +fd_based_fops_1(char *filename); /* for fd based fops before unlink */ -int fd_based_fops_2 (char *filename); +int +fd_based_fops_2(char *filename); /* fops based on fd after dup */ -int dup_fd_based_fops (char *filename); +int +dup_fd_based_fops(char *filename); /* for fops based on path */ -int path_based_fops (char *filename); +int +path_based_fops(char *filename); /* for fops which operate on directory */ -int dir_based_fops (char *filename); +int +dir_based_fops(char *filename); /* for fops which operate in link files (symlinks) */ -int link_based_fops (char *filename); +int +link_based_fops(char *filename); /* to test open syscall with open modes available. */ -int test_open_modes (char *filename); +int +test_open_modes(char *filename); /* generic function which does open write and read. */ -int generic_open_read_write (char *filename, int flag, mode_t mode); +int +generic_open_read_write(char *filename, int flag, mode_t mode); -#define OPEN_MODE 0666 +#define OPEN_MODE 0666 int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - int ret = -1; - int result = 0; - char filename[255] = {0,}; - - if (argc > 1) - strcpy(filename, argv[1]); - else - strcpy(filename, "temp-xattr-test-file"); - - ret = fd_based_fops_1 (strcat(filename, "_1")); - if (ret < 0) { - fprintf (stderr, "fd based file operation 1 failed\n"); - result |= ret; - } else { - fprintf (stdout, "fd based file operation 1 passed\n"); - } - - ret = fd_based_fops_2 (strcat(filename, "_2")); - if (ret < 0) { - result |= ret; - fprintf (stderr, "fd based file operation 2 failed\n"); - } else { - fprintf (stdout, "fd based file operation 2 passed\n"); - } - - ret = dup_fd_based_fops (strcat (filename, "_3")); - if (ret < 0) { - result |= ret; - fprintf (stderr, "dup fd based file operation failed\n"); - } else { - fprintf (stdout, "dup fd based file operation passed\n"); - } - - ret = path_based_fops (strcat (filename, "_4")); - if (ret < 0) { - result |= ret; - fprintf (stderr, "path based file operation failed\n"); - } else { - fprintf (stdout, "path based file operation passed\n"); - } - - ret = dir_based_fops (strcat (filename, "_5")); - if (ret < 0) { - result |= ret; - fprintf (stderr, "directory based file operation failed\n"); - } else { - fprintf (stdout, "directory based file operation passed\n"); - } - - ret = link_based_fops (strcat (filename, "_5")); - if (ret < 0) { - result |= ret; - fprintf (stderr, "link based file operation failed\n"); - } else { - fprintf (stdout, "link based file operation passed\n"); - } - - ret = test_open_modes (strcat (filename, "_5")); - if (ret < 0) { - result |= ret; - fprintf (stderr, "testing modes of `open' call failed\n"); - } else { - fprintf (stdout, "testing modes of `open' call passed\n"); - } - return result; + int ret = -1; + int result = 0; + char filename[255] = { + 0, + }; + + if (argc > 1) + strcpy(filename, argv[1]); + else + strcpy(filename, "temp-xattr-test-file"); + + ret = fd_based_fops_1(strcat(filename, "_1")); + if (ret < 0) { + fprintf(stderr, "fd based file operation 1 failed\n"); + result |= ret; + } else { + fprintf(stdout, "fd based file operation 1 passed\n"); + } + + ret = fd_based_fops_2(strcat(filename, "_2")); + if (ret < 0) { + result |= ret; + fprintf(stderr, "fd based file operation 2 failed\n"); + } else { + fprintf(stdout, "fd based file operation 2 passed\n"); + } + + ret = dup_fd_based_fops(strcat(filename, "_3")); + if (ret < 0) { + result |= ret; + fprintf(stderr, "dup fd based file operation failed\n"); + } else { + fprintf(stdout, "dup fd based file operation passed\n"); + } + + ret = path_based_fops(strcat(filename, "_4")); + if (ret < 0) { + result |= ret; + fprintf(stderr, "path based file operation failed\n"); + } else { + fprintf(stdout, "path based file operation passed\n"); + } + + ret = dir_based_fops(strcat(filename, "_5")); + if (ret < 0) { + result |= ret; + fprintf(stderr, "directory based file operation failed\n"); + } else { + fprintf(stdout, "directory based file operation passed\n"); + } + + ret = link_based_fops(strcat(filename, "_5")); + if (ret < 0) { + result |= ret; + fprintf(stderr, "link based file operation failed\n"); + } else { + fprintf(stdout, "link based file operation passed\n"); + } + + ret = test_open_modes(strcat(filename, "_5")); + if (ret < 0) { + result |= ret; + fprintf(stderr, "testing modes of `open' call failed\n"); + } else { + fprintf(stdout, "testing modes of `open' call passed\n"); + } + return result; } /* Execute all possible fops on a fd which is unlinked */ int -fd_based_fops_1 (char *filename) +fd_based_fops_1(char *filename) { - int fd = 0; - int ret = -1; - int result = 0; - struct stat stbuf = {0,}; - char wstr[50] = {0,}; - char rstr[50] = {0,}; - - fd = open (filename, O_RDWR|O_CREAT, OPEN_MODE); - if (fd < 0) { - fprintf (stderr, "open failed : %s\n", strerror (errno)); - return ret; - } - - ret = unlink (filename); - if (ret < 0) { - fprintf (stderr, "unlink failed : %s\n", strerror (errno)); - result |= ret; - } - - strcpy (wstr, "This is my string\n"); - ret = write (fd, wstr, strlen(wstr)); - if (ret <= 0) { - fprintf (stderr, "write failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = lseek (fd, 0, SEEK_SET); - if (ret < 0) { - fprintf (stderr, "lseek failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = read (fd, rstr, strlen(wstr)); - if (ret <= 0) { - fprintf (stderr, "read failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = memcmp (rstr, wstr, strlen (wstr)); - if (ret != 0) { - fprintf (stderr, "read returning junk\n"); - result |= ret; - } - - ret = ftruncate (fd, 0); - if (ret < 0) { - fprintf (stderr, "ftruncate failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fstat (fd, &stbuf); - if (ret < 0) { - fprintf (stderr, "fstat failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fsync (fd); - if (ret < 0) { - fprintf (stderr, "fsync failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fdatasync (fd); - if (ret < 0) { - fprintf (stderr, "fdatasync failed : %s\n", strerror (errno)); - result |= ret; - } - -/* - * These metadata operations fail at the moment because kernel doesn't - * pass the client fd in the operation. - * The following bug tracks this change. - * https://bugzilla.redhat.com/show_bug.cgi?id=1084422 - * ret = fchmod (fd, 0640); - * if (ret < 0) { - * fprintf (stderr, "fchmod failed : %s\n", strerror (errno)); - * result |= ret; - * } - - * ret = fchown (fd, 10001, 10001); - * if (ret < 0) { - * fprintf (stderr, "fchown failed : %s\n", strerror (errno)); - * result |= ret; - * } - - * ret = fsetxattr (fd, "trusted.xattr-test", "working", 8, 0); - * if (ret < 0) { - * fprintf (stderr, "fsetxattr failed : %s\n", strerror (errno)); - * result |= ret; - * } - - * ret = flistxattr (fd, NULL, 0); - * if (ret <= 0) { - * fprintf (stderr, "flistxattr failed : %s\n", strerror (errno)); - * result |= ret; - * } - - * ret = fgetxattr (fd, "trusted.xattr-test", NULL, 0); - * if (ret <= 0) { - * fprintf (stderr, "fgetxattr failed : %s\n", strerror (errno)); - * result |= ret; - * } - - * ret = fremovexattr (fd, "trusted.xattr-test"); - * if (ret < 0) { - * fprintf (stderr, "fremovexattr failed : %s\n", strerror (errno)); - * result |= ret; - * } - */ - - if (fd) - close(fd); - return result; + int fd = 0; + int ret = -1; + int result = 0; + struct stat stbuf = { + 0, + }; + char wstr[50] = { + 0, + }; + char rstr[50] = { + 0, + }; + + fd = open(filename, O_RDWR | O_CREAT, OPEN_MODE); + if (fd < 0) { + fprintf(stderr, "open failed : %s\n", strerror(errno)); + return ret; + } + + ret = unlink(filename); + if (ret < 0) { + fprintf(stderr, "unlink failed : %s\n", strerror(errno)); + result |= ret; + } + + strcpy(wstr, "This is my string\n"); + ret = write(fd, wstr, strlen(wstr)); + if (ret <= 0) { + fprintf(stderr, "write failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = lseek(fd, 0, SEEK_SET); + if (ret < 0) { + fprintf(stderr, "lseek failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = read(fd, rstr, strlen(wstr)); + if (ret <= 0) { + fprintf(stderr, "read failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = memcmp(rstr, wstr, strlen(wstr)); + if (ret != 0) { + fprintf(stderr, "read returning junk\n"); + result |= ret; + } + + ret = ftruncate(fd, 0); + if (ret < 0) { + fprintf(stderr, "ftruncate failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fstat(fd, &stbuf); + if (ret < 0) { + fprintf(stderr, "fstat failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fsync(fd); + if (ret < 0) { + fprintf(stderr, "fsync failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fdatasync(fd); + if (ret < 0) { + fprintf(stderr, "fdatasync failed : %s\n", strerror(errno)); + result |= ret; + } + + /* + * These metadata operations fail at the moment because kernel doesn't + * pass the client fd in the operation. + * The following bug tracks this change. + * https://bugzilla.redhat.com/show_bug.cgi?id=1084422 + * ret = fchmod (fd, 0640); + * if (ret < 0) { + * fprintf (stderr, "fchmod failed : %s\n", strerror (errno)); + * result |= ret; + * } + + * ret = fchown (fd, 10001, 10001); + * if (ret < 0) { + * fprintf (stderr, "fchown failed : %s\n", strerror (errno)); + * result |= ret; + * } + + * ret = fsetxattr (fd, "trusted.xattr-test", "working", 8, 0); + * if (ret < 0) { + * fprintf (stderr, "fsetxattr failed : %s\n", strerror + (errno)); + * result |= ret; + * } + + * ret = flistxattr (fd, NULL, 0); + * if (ret <= 0) { + * fprintf (stderr, "flistxattr failed : %s\n", strerror + (errno)); + * result |= ret; + * } + + * ret = fgetxattr (fd, "trusted.xattr-test", NULL, 0); + * if (ret <= 0) { + * fprintf (stderr, "fgetxattr failed : %s\n", strerror + (errno)); + * result |= ret; + * } + + * ret = fremovexattr (fd, "trusted.xattr-test"); + * if (ret < 0) { + * fprintf (stderr, "fremovexattr failed : %s\n", strerror + (errno)); + * result |= ret; + * } + */ + + if (fd) + close(fd); + return result; } - int -fd_based_fops_2 (char *filename) +fd_based_fops_2(char *filename) { - int fd = 0; - int ret = -1; - int result = 0; - struct stat stbuf = {0,}; - char wstr[50] = {0,}; - char rstr[50] = {0,}; - - fd = open (filename, O_RDWR|O_CREAT, OPEN_MODE); - if (fd < 0) { - fprintf (stderr, "open failed : %s\n", strerror (errno)); - return ret; - } - - ret = ftruncate (fd, 0); - if (ret < 0) { - fprintf (stderr, "ftruncate failed : %s\n", strerror (errno)); - result |= ret; - } - - strcpy (wstr, "This is my second string\n"); - ret = write (fd, wstr, strlen (wstr)); - if (ret < 0) { - fprintf (stderr, "write failed: %s\n", strerror (errno)); - result |= ret; - } - - lseek (fd, 0, SEEK_SET); - if (ret < 0) { - fprintf (stderr, "lseek failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = read (fd, rstr, strlen (wstr)); - if (ret <= 0) { - fprintf (stderr, "read failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = memcmp (rstr, wstr, strlen (wstr)); - if (ret != 0) { - fprintf (stderr, "read returning junk\n"); - result |= ret; - } - - ret = fstat (fd, &stbuf); - if (ret < 0) { - fprintf (stderr, "fstat failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fchmod (fd, 0640); - if (ret < 0) { - fprintf (stderr, "fchmod failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fchown (fd, 10001, 10001); - if (ret < 0) { - fprintf (stderr, "fchown failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fsync (fd); - if (ret < 0) { - fprintf (stderr, "fsync failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fsetxattr (fd, "trusted.xattr-test", "working", 8, 0); - if (ret < 0) { - fprintf (stderr, "fsetxattr failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fdatasync (fd); - if (ret < 0) { - fprintf (stderr, "fdatasync failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = flistxattr (fd, NULL, 0); - if (ret <= 0) { - fprintf (stderr, "flistxattr failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fgetxattr (fd, "trusted.xattr-test", NULL, 0); - if (ret <= 0) { - fprintf (stderr, "fgetxattr failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fremovexattr (fd, "trusted.xattr-test"); - if (ret < 0) { - fprintf (stderr, "fremovexattr failed : %s\n", strerror (errno)); - result |= ret; - } - - if (fd) - close (fd); - unlink (filename); - - return result; + int fd = 0; + int ret = -1; + int result = 0; + struct stat stbuf = { + 0, + }; + char wstr[50] = { + 0, + }; + char rstr[50] = { + 0, + }; + + fd = open(filename, O_RDWR | O_CREAT, OPEN_MODE); + if (fd < 0) { + fprintf(stderr, "open failed : %s\n", strerror(errno)); + return ret; + } + + ret = ftruncate(fd, 0); + if (ret < 0) { + fprintf(stderr, "ftruncate failed : %s\n", strerror(errno)); + result |= ret; + } + + strcpy(wstr, "This is my second string\n"); + ret = write(fd, wstr, strlen(wstr)); + if (ret < 0) { + fprintf(stderr, "write failed: %s\n", strerror(errno)); + result |= ret; + } + + lseek(fd, 0, SEEK_SET); + if (ret < 0) { + fprintf(stderr, "lseek failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = read(fd, rstr, strlen(wstr)); + if (ret <= 0) { + fprintf(stderr, "read failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = memcmp(rstr, wstr, strlen(wstr)); + if (ret != 0) { + fprintf(stderr, "read returning junk\n"); + result |= ret; + } + + ret = fstat(fd, &stbuf); + if (ret < 0) { + fprintf(stderr, "fstat failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fchmod(fd, 0640); + if (ret < 0) { + fprintf(stderr, "fchmod failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fchown(fd, 10001, 10001); + if (ret < 0) { + fprintf(stderr, "fchown failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fsync(fd); + if (ret < 0) { + fprintf(stderr, "fsync failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fsetxattr(fd, "trusted.xattr-test", "working", 8, 0); + if (ret < 0) { + fprintf(stderr, "fsetxattr failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fdatasync(fd); + if (ret < 0) { + fprintf(stderr, "fdatasync failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = flistxattr(fd, NULL, 0); + if (ret <= 0) { + fprintf(stderr, "flistxattr failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fgetxattr(fd, "trusted.xattr-test", NULL, 0); + if (ret <= 0) { + fprintf(stderr, "fgetxattr failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fremovexattr(fd, "trusted.xattr-test"); + if (ret < 0) { + fprintf(stderr, "fremovexattr failed : %s\n", strerror(errno)); + result |= ret; + } + + if (fd) + close(fd); + unlink(filename); + + return result; } int -path_based_fops (char *filename) +path_based_fops(char *filename) { - int ret = -1; - int fd = 0; - int result = 0; - struct stat stbuf = {0,}; - char newfilename[255] = {0,}; - char *hardlink = "linkfile-hard.txt"; - char *symlnk = "linkfile-soft.txt"; - char buf[1024] = {0,}; - - fd = creat (filename, 0644); - if (fd < 0) { - fprintf (stderr, "creat failed: %s\n", strerror (errno)); - return ret; - } - - ret = truncate (filename, 0); - if (ret < 0) { - fprintf (stderr, "truncate failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = stat (filename, &stbuf); - if (ret < 0) { - fprintf (stderr, "stat failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = chmod (filename, 0640); - if (ret < 0) { - fprintf (stderr, "chmod failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = chown (filename, 10001, 10001); - if (ret < 0) { - fprintf (stderr, "chown failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = setxattr (filename, "trusted.xattr-test", "working", 8, 0); - if (ret < 0) { - fprintf (stderr, "setxattr failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = listxattr (filename, NULL, 0); - if (ret <= 0) { - ret = -1; - fprintf (stderr, "listxattr failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = getxattr (filename, "trusted.xattr-test", NULL, 0); - if (ret <= 0) { - fprintf (stderr, "getxattr failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = removexattr (filename, "trusted.xattr-test"); - if (ret < 0) { - fprintf (stderr, "removexattr failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = access (filename, R_OK|W_OK); - if (ret < 0) { - fprintf (stderr, "access failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = link (filename, hardlink); - if (ret < 0) { - fprintf (stderr, "link failed: %s\n", strerror(errno)); - result |= ret; - } - unlink(hardlink); - - ret = symlink (filename, symlnk); - if (ret < 0) { - fprintf (stderr, "symlink failed: %s\n", strerror(errno)); - result |= ret; - } - - ret = readlink (symlnk, buf, sizeof(buf)); - if (ret < 0) { - fprintf (stderr, "readlink failed: %s\n", strerror(errno)); - result |= ret; - } - unlink(symlnk); - - /* Create a character special file */ - ret = mknod ("cspecial", S_IFCHR|S_IRWXU|S_IRWXG, makedev(2,3)); - if (ret < 0) { - fprintf (stderr, "cpsecial mknod failed: %s\n", - strerror(errno)); - result |= ret; - } - unlink("cspecial"); - - ret = mknod ("bspecial", S_IFBLK|S_IRWXU|S_IRWXG, makedev(4,5)); - if (ret < 0) { - fprintf (stderr, "bspecial mknod failed: %s\n", - strerror(errno)); - result |= ret; - } - unlink("bspecial"); + int ret = -1; + int fd = 0; + int result = 0; + struct stat stbuf = { + 0, + }; + char newfilename[255] = { + 0, + }; + char *hardlink = "linkfile-hard.txt"; + char *symlnk = "linkfile-soft.txt"; + char buf[1024] = { + 0, + }; + + fd = creat(filename, 0644); + if (fd < 0) { + fprintf(stderr, "creat failed: %s\n", strerror(errno)); + return ret; + } + + ret = truncate(filename, 0); + if (ret < 0) { + fprintf(stderr, "truncate failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = stat(filename, &stbuf); + if (ret < 0) { + fprintf(stderr, "stat failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = chmod(filename, 0640); + if (ret < 0) { + fprintf(stderr, "chmod failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = chown(filename, 10001, 10001); + if (ret < 0) { + fprintf(stderr, "chown failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = setxattr(filename, "trusted.xattr-test", "working", 8, 0); + if (ret < 0) { + fprintf(stderr, "setxattr failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = listxattr(filename, NULL, 0); + if (ret <= 0) { + ret = -1; + fprintf(stderr, "listxattr failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = getxattr(filename, "trusted.xattr-test", NULL, 0); + if (ret <= 0) { + fprintf(stderr, "getxattr failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = removexattr(filename, "trusted.xattr-test"); + if (ret < 0) { + fprintf(stderr, "removexattr failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = access(filename, R_OK | W_OK); + if (ret < 0) { + fprintf(stderr, "access failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = link(filename, hardlink); + if (ret < 0) { + fprintf(stderr, "link failed: %s\n", strerror(errno)); + result |= ret; + } + unlink(hardlink); + + ret = symlink(filename, symlnk); + if (ret < 0) { + fprintf(stderr, "symlink failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = readlink(symlnk, buf, sizeof(buf)); + if (ret < 0) { + fprintf(stderr, "readlink failed: %s\n", strerror(errno)); + result |= ret; + } + unlink(symlnk); + + /* Create a character special file */ + ret = mknod("cspecial", S_IFCHR | S_IRWXU | S_IRWXG, makedev(2, 3)); + if (ret < 0) { + fprintf(stderr, "cpsecial mknod failed: %s\n", strerror(errno)); + result |= ret; + } + unlink("cspecial"); + + ret = mknod("bspecial", S_IFBLK | S_IRWXU | S_IRWXG, makedev(4, 5)); + if (ret < 0) { + fprintf(stderr, "bspecial mknod failed: %s\n", strerror(errno)); + result |= ret; + } + unlink("bspecial"); #ifdef linux - ret = mknod ("fifo", S_IFIFO|S_IRWXU|S_IRWXG, 0); + ret = mknod("fifo", S_IFIFO | S_IRWXU | S_IRWXG, 0); #else - ret = mkfifo ("fifo", 0); + ret = mkfifo("fifo", 0); #endif - if (ret < 0) { - fprintf (stderr, "fifo mknod failed: %s\n", - strerror(errno)); - result |= ret; - } - unlink("fifo"); + if (ret < 0) { + fprintf(stderr, "fifo mknod failed: %s\n", strerror(errno)); + result |= ret; + } + unlink("fifo"); #ifdef linux - ret = mknod ("sock", S_IFSOCK|S_IRWXU|S_IRWXG, 0); - if (ret < 0) { - fprintf (stderr, "sock mknod failed: %s\n", - strerror(errno)); - result |= ret; - } + ret = mknod("sock", S_IFSOCK | S_IRWXU | S_IRWXG, 0); + if (ret < 0) { + fprintf(stderr, "sock mknod failed: %s\n", strerror(errno)); + result |= ret; + } #else - { - int s; - const char *pathname = "sock"; - struct sockaddr_un addr; - - s = socket(PF_LOCAL, SOCK_STREAM, 0); - memset(&addr, 0, sizeof(addr)); - strncpy(addr.sun_path, pathname, sizeof(addr.sun_path)); - ret = bind(s, (const struct sockaddr *)&addr, SUN_LEN(&addr)); - if (ret < 0) { - fprintf (stderr, "fifo mknod failed: %s\n", - strerror(errno)); - result |= ret; - } - close(s); - } -#endif - unlink("sock"); + { + int s; + const char *pathname = "sock"; + struct sockaddr_un addr; - strcpy (newfilename, filename); - strcat(newfilename, "_new"); - ret = rename (filename, newfilename); + s = socket(PF_LOCAL, SOCK_STREAM, 0); + memset(&addr, 0, sizeof(addr)); + strncpy(addr.sun_path, pathname, sizeof(addr.sun_path)); + ret = bind(s, (const struct sockaddr *)&addr, SUN_LEN(&addr)); if (ret < 0) { - fprintf (stderr, "rename failed: %s\n", strerror (errno)); - result |= ret; + fprintf(stderr, "fifo mknod failed: %s\n", strerror(errno)); + result |= ret; } - unlink (newfilename); - - if (fd) - close (fd); - - unlink (filename); - return result; + close(s); + } +#endif + unlink("sock"); + + strcpy(newfilename, filename); + strcat(newfilename, "_new"); + ret = rename(filename, newfilename); + if (ret < 0) { + fprintf(stderr, "rename failed: %s\n", strerror(errno)); + result |= ret; + } + unlink(newfilename); + + if (fd) + close(fd); + + unlink(filename); + return result; } int -dup_fd_based_fops (char *filename) +dup_fd_based_fops(char *filename) { - int fd = 0; - int result = 0; - int newfd = 0; - int ret = -1; - struct stat stbuf = {0,}; - char wstr[50] = {0,}; - char rstr[50] = {0,}; - - fd = open (filename, O_RDWR|O_CREAT, OPEN_MODE); - if (fd < 0) { - fprintf (stderr, "open failed : %s\n", strerror (errno)); - return ret; - } - - newfd = dup (fd); - if (newfd < 0) { - fprintf (stderr, "dup failed: %s\n", strerror (errno)); - result |= ret; - } - - close (fd); - - strcpy (wstr, "This is my string\n"); - ret = write (newfd, wstr, strlen(wstr)); - if (ret <= 0) { - fprintf (stderr, "write failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = lseek (newfd, 0, SEEK_SET); - if (ret < 0) { - fprintf (stderr, "lseek failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = read (newfd, rstr, strlen(wstr)); - if (ret <= 0) { - fprintf (stderr, "read failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = memcmp (rstr, wstr, strlen (wstr)); - if (ret != 0) { - fprintf (stderr, "read returning junk\n"); - result |= ret; - } - - ret = ftruncate (newfd, 0); - if (ret < 0) { - fprintf (stderr, "ftruncate failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fstat (newfd, &stbuf); - if (ret < 0) { - fprintf (stderr, "fstat failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fchmod (newfd, 0640); - if (ret < 0) { - fprintf (stderr, "fchmod failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fchown (newfd, 10001, 10001); - if (ret < 0) { - fprintf (stderr, "fchown failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fsync (newfd); - if (ret < 0) { - fprintf (stderr, "fsync failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fsetxattr (newfd, "trusted.xattr-test", "working", 8, 0); - if (ret < 0) { - fprintf (stderr, "fsetxattr failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fdatasync (newfd); - if (ret < 0) { - fprintf (stderr, "fdatasync failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = flistxattr (newfd, NULL, 0); - if (ret <= 0) { - fprintf (stderr, "flistxattr failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fgetxattr (newfd, "trusted.xattr-test", NULL, 0); - if (ret <= 0) { - fprintf (stderr, "fgetxattr failed : %s\n", strerror (errno)); - result |= ret; - } - - ret = fremovexattr (newfd, "trusted.xattr-test"); - if (ret < 0) { - fprintf (stderr, "fremovexattr failed : %s\n", strerror (errno)); - result |= ret; - } - - if (newfd) - close (newfd); - ret = unlink (filename); - if (ret < 0) { - fprintf (stderr, "unlink failed : %s\n", strerror (errno)); - result |= ret; - } - return result; + int fd = 0; + int result = 0; + int newfd = 0; + int ret = -1; + struct stat stbuf = { + 0, + }; + char wstr[50] = { + 0, + }; + char rstr[50] = { + 0, + }; + + fd = open(filename, O_RDWR | O_CREAT, OPEN_MODE); + if (fd < 0) { + fprintf(stderr, "open failed : %s\n", strerror(errno)); + return ret; + } + + newfd = dup(fd); + if (newfd < 0) { + fprintf(stderr, "dup failed: %s\n", strerror(errno)); + result |= ret; + } + + close(fd); + + strcpy(wstr, "This is my string\n"); + ret = write(newfd, wstr, strlen(wstr)); + if (ret <= 0) { + fprintf(stderr, "write failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = lseek(newfd, 0, SEEK_SET); + if (ret < 0) { + fprintf(stderr, "lseek failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = read(newfd, rstr, strlen(wstr)); + if (ret <= 0) { + fprintf(stderr, "read failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = memcmp(rstr, wstr, strlen(wstr)); + if (ret != 0) { + fprintf(stderr, "read returning junk\n"); + result |= ret; + } + + ret = ftruncate(newfd, 0); + if (ret < 0) { + fprintf(stderr, "ftruncate failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fstat(newfd, &stbuf); + if (ret < 0) { + fprintf(stderr, "fstat failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fchmod(newfd, 0640); + if (ret < 0) { + fprintf(stderr, "fchmod failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fchown(newfd, 10001, 10001); + if (ret < 0) { + fprintf(stderr, "fchown failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fsync(newfd); + if (ret < 0) { + fprintf(stderr, "fsync failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fsetxattr(newfd, "trusted.xattr-test", "working", 8, 0); + if (ret < 0) { + fprintf(stderr, "fsetxattr failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fdatasync(newfd); + if (ret < 0) { + fprintf(stderr, "fdatasync failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = flistxattr(newfd, NULL, 0); + if (ret <= 0) { + fprintf(stderr, "flistxattr failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fgetxattr(newfd, "trusted.xattr-test", NULL, 0); + if (ret <= 0) { + fprintf(stderr, "fgetxattr failed : %s\n", strerror(errno)); + result |= ret; + } + + ret = fremovexattr(newfd, "trusted.xattr-test"); + if (ret < 0) { + fprintf(stderr, "fremovexattr failed : %s\n", strerror(errno)); + result |= ret; + } + + if (newfd) + close(newfd); + ret = unlink(filename); + if (ret < 0) { + fprintf(stderr, "unlink failed : %s\n", strerror(errno)); + result |= ret; + } + return result; } int -dir_based_fops (char *dirname) +dir_based_fops(char *dirname) { - int ret = -1; - int result = 0; - DIR *dp = NULL; - char buff[255] = {0,}; - struct dirent *dbuff = {0,}; - struct stat stbuff = {0,}; - char newdname[255] = {0,}; - char *cwd = NULL; - - ret = mkdir (dirname, 0755); - if (ret < 0) { - fprintf (stderr, "mkdir failed: %s\n", strerror (errno)); - return ret; - } - - dp = opendir (dirname); - if (dp == NULL) { - fprintf (stderr, "opendir failed: %s\n", strerror (errno)); - result |= ret; - } - - dbuff = readdir (dp); - if (NULL == dbuff) { - fprintf (stderr, "readdir failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = closedir (dp); - if (ret < 0) { - fprintf (stderr, "closedir failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = stat (dirname, &stbuff); - if (ret < 0) { - fprintf (stderr, "stat failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = chmod (dirname, 0744); - if (ret < 0) { - fprintf (stderr, "chmod failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = chown (dirname, 10001, 10001); - if (ret < 0) { - fprintf (stderr, "chmod failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = setxattr (dirname, "trusted.xattr-test", "working", 8, 0); - if (ret < 0) { - fprintf (stderr, "setxattr failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = listxattr (dirname, NULL, 0); - if (ret <= 0) { - ret = -1; - fprintf (stderr, "listxattr failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = getxattr (dirname, "trusted.xattr-test", NULL, 0); - if (ret <= 0) { - ret = -1; - fprintf (stderr, "getxattr failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = removexattr (dirname, "trusted.xattr-test"); - if (ret < 0) { - fprintf (stderr, "removexattr failed: %s\n", strerror (errno)); - result |= ret; - } - - strcpy (newdname, dirname); - strcat (newdname, "/../"); - ret = chdir (newdname); - if (ret < 0) { - fprintf (stderr, "chdir failed: %s\n", strerror (errno)); - result |= ret; - } - - cwd = getcwd (buff, 255); - if (NULL == cwd) { - fprintf (stderr, "getcwd failed: %s\n", strerror (errno)); - result |= ret; - } - - strcpy (newdname, dirname); - strcat (newdname, "new"); - ret = rename (dirname, newdname); - if (ret < 0) { - fprintf (stderr, "rename failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = rmdir (newdname); - if (ret < 0) { - fprintf (stderr, "rmdir failed: %s\n", strerror (errno)); - result |= ret; - } - - rmdir (dirname); - return result; + int ret = -1; + int result = 0; + DIR *dp = NULL; + char buff[255] = { + 0, + }; + struct dirent *dbuff = { + 0, + }; + struct stat stbuff = { + 0, + }; + char newdname[255] = { + 0, + }; + char *cwd = NULL; + + ret = mkdir(dirname, 0755); + if (ret < 0) { + fprintf(stderr, "mkdir failed: %s\n", strerror(errno)); + return ret; + } + + dp = opendir(dirname); + if (dp == NULL) { + fprintf(stderr, "opendir failed: %s\n", strerror(errno)); + result |= ret; + } + + dbuff = readdir(dp); + if (NULL == dbuff) { + fprintf(stderr, "readdir failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = closedir(dp); + if (ret < 0) { + fprintf(stderr, "closedir failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = stat(dirname, &stbuff); + if (ret < 0) { + fprintf(stderr, "stat failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = chmod(dirname, 0744); + if (ret < 0) { + fprintf(stderr, "chmod failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = chown(dirname, 10001, 10001); + if (ret < 0) { + fprintf(stderr, "chmod failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = setxattr(dirname, "trusted.xattr-test", "working", 8, 0); + if (ret < 0) { + fprintf(stderr, "setxattr failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = listxattr(dirname, NULL, 0); + if (ret <= 0) { + ret = -1; + fprintf(stderr, "listxattr failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = getxattr(dirname, "trusted.xattr-test", NULL, 0); + if (ret <= 0) { + ret = -1; + fprintf(stderr, "getxattr failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = removexattr(dirname, "trusted.xattr-test"); + if (ret < 0) { + fprintf(stderr, "removexattr failed: %s\n", strerror(errno)); + result |= ret; + } + + strcpy(newdname, dirname); + strcat(newdname, "/../"); + ret = chdir(newdname); + if (ret < 0) { + fprintf(stderr, "chdir failed: %s\n", strerror(errno)); + result |= ret; + } + + cwd = getcwd(buff, 255); + if (NULL == cwd) { + fprintf(stderr, "getcwd failed: %s\n", strerror(errno)); + result |= ret; + } + + strcpy(newdname, dirname); + strcat(newdname, "new"); + ret = rename(dirname, newdname); + if (ret < 0) { + fprintf(stderr, "rename failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = rmdir(newdname); + if (ret < 0) { + fprintf(stderr, "rmdir failed: %s\n", strerror(errno)); + result |= ret; + } + + rmdir(dirname); + return result; } int -link_based_fops (char *filename) +link_based_fops(char *filename) { - int ret = -1; - int result = 0; - int fd = 0; - char newname[255] = {0,}; - char linkname[255] = {0,}; - struct stat lstbuf = {0,}; - - fd = creat (filename, 0644); - if (fd < 0) { - fd = 0; - fprintf (stderr, "creat failed: %s\n", strerror (errno)); - return ret; - } - - strcpy (newname, filename); - strcat (newname, "_hlink"); - ret = link (filename, newname); - if (ret < 0) { - fprintf (stderr, "link failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = unlink (filename); - if (ret < 0) { - fprintf (stderr, "unlink failed: %s\n", strerror (errno)); - result |= ret; - } - - strcpy (linkname, filename); - strcat (linkname, "_slink"); - ret = symlink (newname, linkname); - if (ret < 0) { - fprintf (stderr, "symlink failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = lstat (linkname, &lstbuf); - if (ret < 0) { - fprintf (stderr, "lstbuf failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = lchown (linkname, 10001, 10001); - if (ret < 0) { - fprintf (stderr, "lchown failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = lsetxattr (linkname, "trusted.lxattr-test", "working", 8, 0); - if (ret < 0) { - fprintf (stderr, "lsetxattr failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = llistxattr (linkname, NULL, 0); - if (ret < 0) { - ret = -1; - fprintf (stderr, "llistxattr failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = lgetxattr (linkname, "trusted.lxattr-test", NULL, 0); - if (ret < 0) { - ret = -1; - fprintf (stderr, "lgetxattr failed: %s\n", strerror (errno)); - result |= ret; - } - - ret = lremovexattr (linkname, "trusted.lxattr-test"); - if (ret < 0) { - fprintf (stderr, "lremovexattr failed: %s\n", strerror (errno)); - result |= ret; - } - - if (fd) - close(fd); - unlink (linkname); - unlink (newname); - return result; + int ret = -1; + int result = 0; + int fd = 0; + char newname[255] = { + 0, + }; + char linkname[255] = { + 0, + }; + struct stat lstbuf = { + 0, + }; + + fd = creat(filename, 0644); + if (fd < 0) { + fd = 0; + fprintf(stderr, "creat failed: %s\n", strerror(errno)); + return ret; + } + + strcpy(newname, filename); + strcat(newname, "_hlink"); + ret = link(filename, newname); + if (ret < 0) { + fprintf(stderr, "link failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = unlink(filename); + if (ret < 0) { + fprintf(stderr, "unlink failed: %s\n", strerror(errno)); + result |= ret; + } + + strcpy(linkname, filename); + strcat(linkname, "_slink"); + ret = symlink(newname, linkname); + if (ret < 0) { + fprintf(stderr, "symlink failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = lstat(linkname, &lstbuf); + if (ret < 0) { + fprintf(stderr, "lstbuf failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = lchown(linkname, 10001, 10001); + if (ret < 0) { + fprintf(stderr, "lchown failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = lsetxattr(linkname, "trusted.lxattr-test", "working", 8, 0); + if (ret < 0) { + fprintf(stderr, "lsetxattr failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = llistxattr(linkname, NULL, 0); + if (ret < 0) { + ret = -1; + fprintf(stderr, "llistxattr failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = lgetxattr(linkname, "trusted.lxattr-test", NULL, 0); + if (ret < 0) { + ret = -1; + fprintf(stderr, "lgetxattr failed: %s\n", strerror(errno)); + result |= ret; + } + + ret = lremovexattr(linkname, "trusted.lxattr-test"); + if (ret < 0) { + fprintf(stderr, "lremovexattr failed: %s\n", strerror(errno)); + result |= ret; + } + + if (fd) + close(fd); + unlink(linkname); + unlink(newname); + return result; } int -test_open_modes (char *filename) +test_open_modes(char *filename) { - int ret = -1; - int result = 0; - - ret = generic_open_read_write (filename, O_CREAT|O_WRONLY, OPEN_MODE); - if (ret != 0) { - fprintf (stderr, "flag O_CREAT|O_WRONLY failed: \n"); - result |= ret; - } - - ret = generic_open_read_write (filename, O_CREAT|O_RDWR, OPEN_MODE); - if (ret != 0) { - fprintf (stderr, "flag O_CREAT|O_RDWR failed\n"); - result |= ret; - } - - ret = generic_open_read_write (filename, O_CREAT|O_RDONLY, OPEN_MODE); - if (ret != 0) { - fprintf (stderr, "flag O_CREAT|O_RDONLY failed\n"); - result |= ret; - } - - ret = creat (filename, 0644); - close (ret); - ret = generic_open_read_write (filename, O_WRONLY, 0); - if (ret != 0) { - fprintf (stderr, "flag O_WRONLY failed\n"); - result |= ret; - } - - ret = creat (filename, 0644); - close (ret); - ret = generic_open_read_write (filename, O_RDWR, 0); - if (0 != ret) { - fprintf (stderr, "flag O_RDWR failed\n"); - result |= ret; - } - - ret = creat (filename, 0644); - close (ret); - ret = generic_open_read_write (filename, O_RDONLY, 0); - if (0 != ret) { - fprintf (stderr, "flag O_RDONLY failed\n"); - result |= ret; - } - - ret = creat (filename, 0644); - close (ret); - ret = generic_open_read_write (filename, O_TRUNC|O_WRONLY, 0); - if (0 != ret) { - fprintf (stderr, "flag O_TRUNC|O_WRONLY failed\n"); - result |= ret; - } + int ret = -1; + int result = 0; + + ret = generic_open_read_write(filename, O_CREAT | O_WRONLY, OPEN_MODE); + if (ret != 0) { + fprintf(stderr, "flag O_CREAT|O_WRONLY failed: \n"); + result |= ret; + } + + ret = generic_open_read_write(filename, O_CREAT | O_RDWR, OPEN_MODE); + if (ret != 0) { + fprintf(stderr, "flag O_CREAT|O_RDWR failed\n"); + result |= ret; + } + + ret = generic_open_read_write(filename, O_CREAT | O_RDONLY, OPEN_MODE); + if (ret != 0) { + fprintf(stderr, "flag O_CREAT|O_RDONLY failed\n"); + result |= ret; + } + + ret = creat(filename, 0644); + close(ret); + ret = generic_open_read_write(filename, O_WRONLY, 0); + if (ret != 0) { + fprintf(stderr, "flag O_WRONLY failed\n"); + result |= ret; + } + + ret = creat(filename, 0644); + close(ret); + ret = generic_open_read_write(filename, O_RDWR, 0); + if (0 != ret) { + fprintf(stderr, "flag O_RDWR failed\n"); + result |= ret; + } + + ret = creat(filename, 0644); + close(ret); + ret = generic_open_read_write(filename, O_RDONLY, 0); + if (0 != ret) { + fprintf(stderr, "flag O_RDONLY failed\n"); + result |= ret; + } + + ret = creat(filename, 0644); + close(ret); + ret = generic_open_read_write(filename, O_TRUNC | O_WRONLY, 0); + if (0 != ret) { + fprintf(stderr, "flag O_TRUNC|O_WRONLY failed\n"); + result |= ret; + } #if 0 /* undefined behaviour, unable to reliably test */ ret = creat (filename, 0644); @@ -897,87 +944,90 @@ test_open_modes (char *filename) } #endif - ret = generic_open_read_write (filename, O_CREAT|O_RDWR|O_SYNC, - OPEN_MODE); - if (0 != ret) { - fprintf (stderr, "flag O_CREAT|O_RDWR|O_SYNC failed\n"); - result |= ret; - } - - ret = creat (filename, 0644); - close (ret); - ret = generic_open_read_write (filename, O_CREAT|O_EXCL, OPEN_MODE); - if (0 != ret) { - fprintf (stderr, "flag O_CREAT|O_EXCL failed\n"); - result |= ret; - } - - return result; + ret = generic_open_read_write(filename, O_CREAT | O_RDWR | O_SYNC, + OPEN_MODE); + if (0 != ret) { + fprintf(stderr, "flag O_CREAT|O_RDWR|O_SYNC failed\n"); + result |= ret; + } + + ret = creat(filename, 0644); + close(ret); + ret = generic_open_read_write(filename, O_CREAT | O_EXCL, OPEN_MODE); + if (0 != ret) { + fprintf(stderr, "flag O_CREAT|O_EXCL failed\n"); + result |= ret; + } + + return result; } int -generic_open_read_write (char *filename, int flag, mode_t mode) +generic_open_read_write(char *filename, int flag, mode_t mode) { - int fd = 0; - int ret = -1; - char wstring[50] = {0,}; - char rstring[50] = {0,}; - - fd = open (filename, flag, mode); - if (fd < 0) { - if (flag == (O_CREAT|O_EXCL) && errno == EEXIST) { - unlink (filename); - return 0; - } - else { - fprintf (stderr, "open failed: %s\n", strerror (errno)); - return -1; - } - } - - strcpy (wstring, "My string to write\n"); - ret = write (fd, wstring, strlen(wstring)); - if (ret <= 0) { - if (errno != EBADF) { - fprintf (stderr, "write failed: %s\n", strerror (errno)); - close (fd); - unlink(filename); - return ret; - } - } - - ret = lseek (fd, 0, SEEK_SET); - if (ret < 0) { - close (fd); - unlink(filename); - return ret; - } - - ret = read (fd, rstring, strlen(wstring)); - if (ret < 0 && flag != (O_CREAT|O_WRONLY) && flag != O_WRONLY && \ - flag != (O_TRUNC|O_WRONLY)) { - close (fd); - unlink (filename); - return ret; - } - - /* Compare the rstring with wstring. But we do not want to return - * error when the flag is either O_RDONLY, O_CREAT|O_RDONLY or - * O_TRUNC|O_RDONLY. Because in that case we are not writing - * anything to the file.*/ - - ret = memcmp (wstring, rstring, strlen (wstring)); - if (0 != ret && flag != (O_TRUNC|O_WRONLY) && flag != O_WRONLY && \ - flag != (O_CREAT|O_WRONLY) && !(flag == \ - (O_CREAT|O_RDONLY) || flag == O_RDONLY \ - || flag == (O_TRUNC|O_RDONLY))) { - fprintf (stderr, "read is returning junk\n"); - close (fd); - unlink (filename); - return ret; - } - - close (fd); - unlink (filename); - return 0; + int fd = 0; + int ret = -1; + char wstring[50] = { + 0, + }; + char rstring[50] = { + 0, + }; + + fd = open(filename, flag, mode); + if (fd < 0) { + if (flag == (O_CREAT | O_EXCL) && errno == EEXIST) { + unlink(filename); + return 0; + } else { + fprintf(stderr, "open failed: %s\n", strerror(errno)); + return -1; + } + } + + strcpy(wstring, "My string to write\n"); + ret = write(fd, wstring, strlen(wstring)); + if (ret <= 0) { + if (errno != EBADF) { + fprintf(stderr, "write failed: %s\n", strerror(errno)); + close(fd); + unlink(filename); + return ret; + } + } + + ret = lseek(fd, 0, SEEK_SET); + if (ret < 0) { + close(fd); + unlink(filename); + return ret; + } + + ret = read(fd, rstring, strlen(wstring)); + if (ret < 0 && flag != (O_CREAT | O_WRONLY) && flag != O_WRONLY && + flag != (O_TRUNC | O_WRONLY)) { + close(fd); + unlink(filename); + return ret; + } + + /* Compare the rstring with wstring. But we do not want to return + * error when the flag is either O_RDONLY, O_CREAT|O_RDONLY or + * O_TRUNC|O_RDONLY. Because in that case we are not writing + * anything to the file.*/ + + ret = memcmp(wstring, rstring, strlen(wstring)); + if (0 != ret && flag != (O_TRUNC | O_WRONLY) && flag != O_WRONLY && + flag != (O_CREAT | O_WRONLY) && + !(flag == (O_CREAT | O_RDONLY) || flag == O_RDONLY || + flag == (O_TRUNC | O_RDONLY))) { + fprintf(stderr, "read is returning junk\n"); + close(fd); + unlink(filename); + return ret; + } + + close(fd); + unlink(filename); + return 0; } diff --git a/tests/basic/fuse/Makefile.am b/tests/basic/fuse/Makefile index c446d253228..c446d253228 100644 --- a/tests/basic/fuse/Makefile.am +++ b/tests/basic/fuse/Makefile 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/fuse/seek.c b/tests/basic/fuse/seek.c index e4db41c03d7..30943ad0f33 100644 --- a/tests/basic/fuse/seek.c +++ b/tests/basic/fuse/seek.c @@ -17,64 +17,66 @@ #include <unistd.h> int -main (int argc, char **argv) +main(int argc, char **argv) { - int ret = EXIT_SUCCESS; - int fd = -1; - char *filename = NULL; - struct stat st = { 0, }; - off_t hole_start = 0; - off_t hole_end = 0; + int ret = EXIT_SUCCESS; + int fd = -1; + char *filename = NULL; + struct stat st = { + 0, + }; + off_t hole_start = 0; + off_t hole_end = 0; - if (argc != 2) { - fprintf (stderr, "Invalid argument, use %s <file>\n", argv[0]); - return EXIT_FAILURE; - } - - filename = argv[1]; + if (argc != 2) { + fprintf(stderr, "Invalid argument, use %s <file>\n", argv[0]); + return EXIT_FAILURE; + } - fd = open (filename, O_RDONLY); - if (fd <= 0) { - perror ("open"); - return EXIT_FAILURE; - } + filename = argv[1]; - if (fstat (fd, &st)) { - perror ("fstat"); - return EXIT_FAILURE; - } + fd = open(filename, O_RDONLY); + if (fd <= 0) { + perror("open"); + return EXIT_FAILURE; + } - while (hole_end < st.st_size) { - hole_start = lseek (fd, hole_end, SEEK_HOLE); - if (hole_start == -1 && errno == ENXIO) { - /* no more holes */ - break; - } else if (hole_start == -1 && errno == ENOTSUP) { - /* SEEK_HOLE is not supported */ - perror ("lseek(SEEK_HOLE)"); - ret = EXIT_FAILURE; - break; - } else if (hole_start == -1) { - perror ("no more holes"); - break; - } + if (fstat(fd, &st)) { + perror("fstat"); + return EXIT_FAILURE; + } - hole_end = lseek (fd, hole_start, SEEK_DATA); - if (hole_end == -1 && errno == ENXIO) { - /* no more data */ - break; - } else if (hole_end == -1 && errno == ENOTSUP) { - /* SEEK_DATA is not supported */ - perror ("lseek(SEEK_DATA)"); - ret = EXIT_FAILURE; - break; - } + while (hole_end < st.st_size) { + hole_start = lseek(fd, hole_end, SEEK_HOLE); + if (hole_start == -1 && errno == ENXIO) { + /* no more holes */ + break; + } else if (hole_start == -1 && errno == ENOTSUP) { + /* SEEK_HOLE is not supported */ + perror("lseek(SEEK_HOLE)"); + ret = EXIT_FAILURE; + break; + } else if (hole_start == -1) { + perror("no more holes"); + break; + } - printf ("HOLE found: %ld - %ld%s\n", hole_start, hole_end, - (hole_end == st.st_size) ? " (EOF)" : ""); + hole_end = lseek(fd, hole_start, SEEK_DATA); + if (hole_end == -1 && errno == ENXIO) { + /* no more data */ + break; + } else if (hole_end == -1 && errno == ENOTSUP) { + /* SEEK_DATA is not supported */ + perror("lseek(SEEK_DATA)"); + ret = EXIT_FAILURE; + break; } - close (fd); + printf("HOLE found: %ld - %ld%s\n", hole_start, hole_end, + (hole_end == st.st_size) ? " (EOF)" : ""); + } + + close(fd); - return ret; + return ret; } diff --git a/tests/basic/geo-replication/marker-xattrs.t b/tests/basic/geo-replication/marker-xattrs.t index dd5483d7e95..7e5ea8eebec 100755 --- a/tests/basic/geo-replication/marker-xattrs.t +++ b/tests/basic/geo-replication/marker-xattrs.t @@ -7,7 +7,7 @@ TEST glusterd TEST pidof glusterd ## Start and create a replicated volume -TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}-{0,1,2,3} +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}-{0,1,2,3,4,5} TEST $CLI volume set $V0 indexing on @@ -24,11 +24,11 @@ TEST touch $M0 vol_uuid=$(get_volume_mark $M1) xtime=trusted.glusterfs.$vol_uuid.xtime -TEST "getfattr -n $xtime $M1 | grep -q ${xtime}=" +TEST "getfattr -n $xtime $B0/${V0}-1 | grep -q ${xtime}=" TEST kill_brick $V0 $H0 $B0/${V0}-0 -TEST "getfattr -n $xtime $M1 | grep -q ${xtime}=" +TEST "getfattr -n $xtime $B0/${V0}-1 | grep -q ${xtime}=" TEST getfattr -d -m. -e hex $M1 EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 @@ -61,13 +61,13 @@ vol_uuid=$(get_volume_mark $M1) xtime=trusted.glusterfs.$vol_uuid.xtime stime=trusted.glusterfs.$vol_uuid.stime -stime_val=$(getfattr -e hex -n $xtime $M1 | grep ${xtime}= | cut -f2 -d'=') +stime_val=$(getfattr -e hex -n $xtime $B0/${V0}-1 | grep ${xtime}= | cut -f2 -d'=') TEST "setfattr -n $stime -v $stime_val $B0/${V0}-1" -TEST "getfattr -n $xtime $M1 | grep -q ${xtime}=" +TEST "getfattr -n $xtime $B0/${V0}-1 | grep -q ${xtime}=" TEST kill_brick $V0 $H0 $B0/${V0}-0 -TEST "getfattr -n $xtime $M1 | grep -q ${xtime}=" +TEST "getfattr -n $xtime $B0/${V0}-1 | grep -q ${xtime}=" TEST "getfattr -n $stime $M1 | grep -q ${stime}=" TEST getfattr -d -m. -e hex $M1 @@ -78,37 +78,3 @@ TEST $CLI volume stop $V0; TEST $CLI volume delete $V0; cleanup -TEST glusterd -TEST pidof glusterd -## Start and create a stripe volume -TEST $CLI volume create $V0 stripe 2 $H0:$B0/${V0}-{0,1} - -TEST $CLI volume set $V0 indexing on - -TEST $CLI volume start $V0; - -## Mount native -TEST glusterfs --volfile-server=$H0 --volfile-id=$V0 $M0 - -## Mount client-pid=-1 -TEST glusterfs --volfile-server=$H0 --volfile-id=$V0 --client-pid=-1 $M1 - -TEST touch $M0 - -vol_uuid=$(get_volume_mark $M1) -xtime=trusted.glusterfs.$vol_uuid.xtime - -TEST "getfattr -n $xtime $M1 | grep -q ${xtime}=" - -TEST kill_brick $V0 $H0 $B0/${V0}-0 - -#Stripe doesn't tolerate ENOTCONN -TEST ! "getfattr -n $xtime $M1 | grep -q ${xtime}=" - -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M1 - -TEST $CLI volume stop $V0; -TEST $CLI volume delete $V0; - -cleanup diff --git a/tests/basic/gfapi/Makefile.am b/tests/basic/gfapi/Makefile index 3cad969672e..1c5cf03ca3d 100644 --- a/tests/basic/gfapi/Makefile.am +++ b/tests/basic/gfapi/Makefile @@ -5,7 +5,8 @@ CFLAGS = -Wall -g $(shell pkg-config --cflags glusterfs-api) LDFLAGS = $(shell pkg-config --libs glusterfs-api) BINARIES = upcall-cache-invalidate libgfapi-fini-hang anonymous_fd seek \ - bug1283983 bug1291259 gfapi-ssl-test + bug1283983 bug1291259 gfapi-ssl-test gfapi-load-volfile \ + mandatory-lock-optimal %: %.c $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ diff --git a/tests/basic/gfapi/anonymous_fd_read_write.c b/tests/basic/gfapi/anonymous_fd_read_write.c index 6945dd634f0..fc276ca4310 100644 --- a/tests/basic/gfapi/anonymous_fd_read_write.c +++ b/tests/basic/gfapi/anonymous_fd_read_write.c @@ -9,95 +9,98 @@ #include <glusterfs/api/glfs.h> #include <glusterfs/api/glfs-handles.h> -#define LOG_ERR(func, ret) do { \ - if (ret != 0) { \ - fprintf (stderr, "%s : returned error %d (%s)\n", \ - func, ret, strerror (errno)); \ - goto out; \ - } else { \ - fprintf (stderr, "%s : returned %d\n", func, ret); \ - } \ - } while (0) +#define LOG_ERR(func, ret) \ + do { \ + if (ret != 0) { \ + fprintf(stderr, "%s : returned error %d (%s)\n", func, ret, \ + strerror(errno)); \ + goto out; \ + } else { \ + fprintf(stderr, "%s : returned %d\n", func, ret); \ + } \ + } while (0) int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - int ret = 0; - glfs_t *fs = NULL; - struct glfs_object *root = NULL, *file_obj = NULL; - struct stat sb = {0, }; - char readbuf[32], writebuf[32]; - char *filename = "file.txt"; - char *logfile = NULL; - char *volname = NULL; - char *hostname = NULL; - - if (argc != 4) { - fprintf (stderr, "Invalid argument\n"); - exit(1); - } - - hostname = argv[1]; - volname = argv[2]; - logfile = argv[3]; - - fs = glfs_new (volname); - if (!fs) { - fprintf (stderr, "glfs_new: returned NULL\n"); - ret = -1; - } - - ret = glfs_set_volfile_server (fs, "tcp", hostname, 24007); - LOG_ERR("glfs_set_volfile_server", ret); - - ret = glfs_set_logging (fs, logfile, 7); - LOG_ERR("glfs_set_logging", ret); - - ret = glfs_init (fs); - LOG_ERR("glfs_init", ret); - - root = glfs_h_lookupat (fs, NULL, "/", &sb, 0); - if (root == NULL) { - fprintf (stderr, "glfs_h_lookupat: error on lookup of / ,%s\n", - strerror (errno)); - goto out; - } - - file_obj = glfs_h_creat (fs, root, filename, O_CREAT, 0644, &sb); - if (file_obj == NULL) { - fprintf (stderr, "glfs_h_creat: error on create of %s: from (%p),%s\n", - filename, root, strerror (errno)); - goto out; - } - - /* test read/write based on anonymous fd */ - memcpy (writebuf, "abcdefghijklmnopqrstuvwxyz012345", 32); - - ret = glfs_h_anonymous_write (fs, file_obj, writebuf, 32, 0); - if (ret < 0) - LOG_ERR ("glfs_h_anonymous_write", ret); - - ret = glfs_h_anonymous_read (fs, file_obj, readbuf, 32, 0); - if (ret < 0) - LOG_ERR ("glfs_h_anonymous_read", ret); - - if (memcmp (readbuf, writebuf, 32)) { - fprintf (stderr, "Failed to read what I wrote: %s %s\n", readbuf, - writebuf); - ret = -1; - goto out; - } - - ret = 0; + int ret = 0; + glfs_t *fs = NULL; + struct glfs_object *root = NULL, *file_obj = NULL; + struct stat sb = { + 0, + }; + char readbuf[32], writebuf[32]; + char *filename = "file.txt"; + char *logfile = NULL; + char *volname = NULL; + char *hostname = NULL; + + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + fs = glfs_new(volname); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + ret = -1; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + LOG_ERR("glfs_set_volfile_server", ret); + + ret = glfs_set_logging(fs, logfile, 7); + LOG_ERR("glfs_set_logging", ret); + + ret = glfs_init(fs); + LOG_ERR("glfs_init", ret); + + root = glfs_h_lookupat(fs, NULL, "/", &sb, 0); + if (root == NULL) { + fprintf(stderr, "glfs_h_lookupat: error on lookup of / ,%s\n", + strerror(errno)); + goto out; + } + + file_obj = glfs_h_creat(fs, root, filename, O_CREAT, 0644, &sb); + if (file_obj == NULL) { + fprintf(stderr, "glfs_h_creat: error on create of %s: from (%p),%s\n", + filename, root, strerror(errno)); + goto out; + } + + /* test read/write based on anonymous fd */ + memcpy(writebuf, "abcdefghijklmnopqrstuvwxyz012345", 32); + + ret = glfs_h_anonymous_write(fs, file_obj, writebuf, 32, 0); + if (ret < 0) + LOG_ERR("glfs_h_anonymous_write", ret); + + ret = glfs_h_anonymous_read(fs, file_obj, readbuf, 32, 0); + if (ret < 0) + LOG_ERR("glfs_h_anonymous_read", ret); + + if (memcmp(readbuf, writebuf, 32)) { + fprintf(stderr, "Failed to read what I wrote: %s %s\n", readbuf, + writebuf); + ret = -1; + goto out; + } + + ret = 0; out: - if (file_obj) - glfs_h_close (file_obj); - - if (fs) { - ret = glfs_fini(fs); - fprintf (stderr, "glfs_fini(fs) returned %d \n", ret); - } - if (ret) - exit(1); - exit(0); + if (file_obj) + glfs_h_close(file_obj); + + if (fs) { + ret = glfs_fini(fs); + fprintf(stderr, "glfs_fini(fs) returned %d \n", ret); + } + if (ret) + exit(1); + exit(0); } diff --git a/tests/basic/gfapi/bug-1241104.c b/tests/basic/gfapi/bug-1241104.c index 311323f672a..78c87595a71 100644 --- a/tests/basic/gfapi/bug-1241104.c +++ b/tests/basic/gfapi/bug-1241104.c @@ -12,81 +12,82 @@ int gfapi = 1; -#define LOG_ERR(func, ret) do { \ - if (ret != 0) { \ - fprintf (stderr, "%s : returned error %d (%s)\n", \ - func, ret, strerror (errno)); \ - goto out; \ - } else { \ - fprintf (stderr, "%s : returned %d\n", func, ret); \ - } \ - } while (0) +#define LOG_ERR(func, ret) \ + do { \ + if (ret != 0) { \ + fprintf(stderr, "%s : returned error %d (%s)\n", func, ret, \ + strerror(errno)); \ + goto out; \ + } else { \ + fprintf(stderr, "%s : returned %d\n", func, ret); \ + } \ + } while (0) int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - glfs_t *fs = NULL; - int ret = 0, i, status = 0; - glfs_fd_t *fd = NULL; - char *filename = "file_tmp"; - char *volname = NULL; - char *logfile = NULL; - char *hostname = NULL; - struct flock lock = {0, }; - - if (argc != 4) { - fprintf (stderr, "Invalid argument\n"); - exit(1); - } - - hostname = argv[1]; - volname = argv[2]; - logfile = argv[3]; - - fs = glfs_new (volname); - if (!fs) { - fprintf (stderr, "glfs_new: returned NULL\n"); - return -1; - } - - ret = glfs_set_volfile_server (fs, "tcp", hostname, 24007); - LOG_ERR("glfs_set_volfile_server", ret); - - ret = glfs_set_logging (fs, logfile, 7); - LOG_ERR("glfs_set_logging", ret); - - ret = glfs_init (fs); - LOG_ERR("glfs_init", ret); - - fd = glfs_creat(fs, filename, O_RDWR|O_SYNC, 0644); - if (fd <= 0) { - ret = -1; - LOG_ERR ("glfs_creat", ret); - } - fprintf (stderr, "glfs-create fd - %d\n", fd); - - /* validate locks for negative range */ - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 10; - lock.l_len = -9; - - ret = glfs_posix_lock (fd, F_SETLK, &lock); - LOG_ERR ("glfs_posix_lock", ret); + glfs_t *fs = NULL; + int ret = 0, i, status = 0; + glfs_fd_t *fd = NULL; + char *filename = "file_tmp"; + char *volname = NULL; + char *logfile = NULL; + char *hostname = NULL; + struct flock lock = { + 0, + }; + + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + fs = glfs_new(volname); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + return -1; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + LOG_ERR("glfs_set_volfile_server", ret); + + ret = glfs_set_logging(fs, logfile, 7); + LOG_ERR("glfs_set_logging", ret); + + ret = glfs_init(fs); + LOG_ERR("glfs_init", ret); + + fd = glfs_creat(fs, filename, O_RDWR | O_SYNC, 0644); + if (fd <= 0) { + ret = -1; + LOG_ERR("glfs_creat", ret); + } + fprintf(stderr, "glfs-create fd - %d\n", fd); + + /* validate locks for negative range */ + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 10; + lock.l_len = -9; + + ret = glfs_posix_lock(fd, F_SETLK, &lock); + LOG_ERR("glfs_posix_lock", ret); err: - glfs_close(fd); - LOG_ERR ("glfs_close", ret); + glfs_close(fd); + LOG_ERR("glfs_close", ret); out: - if (fs) { - ret = glfs_fini(fs); - fprintf (stderr, "glfs_fini(fs) returned %d \n", ret); - } - - if (ret) - exit(1); - exit(0); + if (fs) { + ret = glfs_fini(fs); + fprintf(stderr, "glfs_fini(fs) returned %d \n", ret); + } + + if (ret) + exit(1); + exit(0); } - - diff --git a/tests/basic/gfapi/bug-1507896.c b/tests/basic/gfapi/bug-1507896.c new file mode 100644 index 00000000000..1cc20849c2b --- /dev/null +++ b/tests/basic/gfapi/bug-1507896.c @@ -0,0 +1,49 @@ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> + +#define VALIDATE_AND_GOTO_LABEL_ON_ERROR(func, ret, label) \ + do { \ + if (ret < 0) { \ + fprintf(stderr, "%s : returned error %d (%s)\n", func, ret, \ + strerror(errno)); \ + goto label; \ + } \ + } while (0) + +int +main(int argc, char *argv[]) +{ + int ret = -1; + glfs_t *fs = NULL; + char *volname = NULL; + char *logfile = NULL; + char *hostname = NULL; + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + fs = glfs_new(volname); + if (!fs) + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_new(fs)", ret, out); + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_volfile_server(fs)", ret, out); + + ret = glfs_set_logging(fs, logfile, 7); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_logging(fs)", ret, out); + + ret = glfs_init(fs); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_init(fs)", ret, out); + +out: + if (fs) { + ret = glfs_fini(fs); + if (ret) + fprintf(stderr, "glfs_fini(fs) returned %d\n", ret); + } + return ret; +} diff --git a/tests/basic/gfapi/bug-1507896.t b/tests/basic/gfapi/bug-1507896.t new file mode 100644 index 00000000000..4764e650232 --- /dev/null +++ b/tests/basic/gfapi/bug-1507896.t @@ -0,0 +1,33 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +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'; + +logdir=`gluster --print-logdir` + +TEST build_tester $(dirname $0)/bug-1507896.c -lgfapi + +TEST ./$(dirname $0)/bug-1507896 $H0 $V0 $logdir/bug-1507896.log + +#volume name precedding with '/' +TEST ! ./$(dirname $0)/bug-1507896 $H0 /$V0 $logdir/bug-1507896.log + +#volume name passed with any special characters +TEST ! ./$(dirname $0)/bug-1507896 $H0 test@_$V0 $logdir/bug-1507896.log + +cleanup_tester $(dirname $0)/bug-1507896 + +TEST $CLI volume stop $V0 +TEST $CLI volume delete $V0 + +cleanup; diff --git a/tests/basic/gfapi/bug1283983.c b/tests/basic/gfapi/bug1283983.c index 3334b290d9e..b920013d0e0 100644 --- a/tests/basic/gfapi/bug1283983.c +++ b/tests/basic/gfapi/bug1283983.c @@ -10,114 +10,113 @@ #include <glusterfs/api/glfs-handles.h> int gfapi = 1; -#define LOG_ERR(func, ret) do { \ - if (ret != 0) { \ - fprintf (stderr, "%s : returned error ret(%d), errno(%d)\n", \ - func, ret, errno); \ - exit(1); \ - } else { \ - fprintf (stderr, "%s : returned %d\n", func, ret); \ - } \ - } while (0) -#define LOG_IF_NO_ERR(func, ret) do { \ - if (ret == 0) { \ - fprintf (stderr, "%s : hasn't returned error %d\n", \ - func, ret); \ - exit(1); \ - } else { \ - fprintf (stderr, "%s : returned %d\n", func, ret); \ - } \ - } while (0) +#define LOG_ERR(func, ret) \ + do { \ + if (ret != 0) { \ + fprintf(stderr, "%s : returned error ret(%d), errno(%d)\n", func, \ + ret, errno); \ + exit(1); \ + } else { \ + fprintf(stderr, "%s : returned %d\n", func, ret); \ + } \ + } while (0) +#define LOG_IF_NO_ERR(func, ret) \ + do { \ + if (ret == 0) { \ + fprintf(stderr, "%s : hasn't returned error %d\n", func, ret); \ + exit(1); \ + } else { \ + fprintf(stderr, "%s : returned %d\n", func, ret); \ + } \ + } while (0) int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - glfs_t *fs = NULL; - int ret = 0, i; - glfs_fd_t *fd = NULL; - char *filename = "/a1"; - char *filename2 = "/a2"; - struct stat sb = {0, }; - struct glfs_upcall *cbk = NULL; - char *logfile = NULL; - char *volname = NULL; - int cnt = 1; - struct glfs_upcall_inode *in_arg = NULL; - struct glfs_object *root = NULL, *leaf = NULL; - - fprintf (stderr, "Starting libgfapi_fini\n"); - if (argc != 4) { - fprintf (stderr, "Invalid argument\n"); - exit(1); + glfs_t *fs = NULL; + int ret = 0, i; + glfs_fd_t *fd = NULL; + char *filename = "/a1"; + char *filename2 = "/a2"; + struct stat sb = { + 0, + }; + struct glfs_upcall *cbk = NULL; + char *logfile = NULL; + char *volname = NULL; + int cnt = 1; + struct glfs_upcall_inode *in_arg = NULL; + struct glfs_object *root = NULL, *leaf = NULL; + + fprintf(stderr, "Starting libgfapi_fini\n"); + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1] volname = argv[2]; + logfile = argv[3]; + + fs = glfs_new(volname); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + return 1; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + LOG_ERR("glfs_set_volfile_server", ret); + + ret = glfs_set_logging(fs, logfile, 7); + LOG_ERR("glfs_set_logging", ret); + + ret = glfs_init(fs); + LOG_ERR("glfs_init", ret); + + sleep(2); + root = glfs_h_lookupat(fs, NULL, "/", &sb, 0); + if (!root) { + ret = -1; + LOG_ERR("glfs_h_lookupat root", ret); + } + leaf = glfs_h_lookupat(fs, root, filename, &sb, 0); + if (!leaf) { + ret = -1; + LOG_IF_NO_ERR("glfs_h_lookupat leaf", ret); + } + + leaf = glfs_h_creat(fs, root, filename, O_RDWR, 0644, &sb); + if (!leaf) { + ret = -1; + LOG_ERR("glfs_h_lookupat leaf", ret); + } + fprintf(stderr, "glfs_h_create leaf - %p\n", leaf); + + leaf = glfs_h_lookupat(fs, root, filename2, &sb, 0); + if (!leaf) { + ret = -1; + LOG_IF_NO_ERR("glfs_h_lookupat leaf", ret); + } + + ret = glfs_h_rename(fs, root, filename, root, filename2); + LOG_ERR("glfs_rename", ret); + + while (cnt++ < 5) { + ret = glfs_h_poll_upcall(fs, &cbk); + LOG_ERR("glfs_h_poll_upcall", ret); + + /* There should not be any upcalls sent */ + if (glfs_upcall_get_reason(cbk) != GLFS_UPCALL_EVENT_NULL) { + fprintf(stderr, "Error: Upcall received(%d)\n", + glfs_upcall_get_reason(cbk)); + exit(1); } - hostname = argv[1] - volname = argv[2]; - logfile = argv[3]; + glfs_free(cbk); + } + ret = glfs_fini(fs); + LOG_ERR("glfs_fini", ret); - fs = glfs_new (volname); - if (!fs) { - fprintf (stderr, "glfs_new: returned NULL\n"); - return 1; - } - - ret = glfs_set_volfile_server (fs, "tcp", hostname, 24007); - LOG_ERR("glfs_set_volfile_server", ret); - - ret = glfs_set_logging (fs, logfile, 7); - LOG_ERR("glfs_set_logging", ret); - - ret = glfs_init (fs); - LOG_ERR("glfs_init", ret); - - sleep (2); - root = glfs_h_lookupat (fs, NULL, "/", &sb, 0); - if (!root) { - ret = -1; - LOG_ERR ("glfs_h_lookupat root", ret); - } - leaf = glfs_h_lookupat (fs, root, filename, &sb, 0); - if (!leaf) { - ret = -1; - LOG_IF_NO_ERR ("glfs_h_lookupat leaf", ret); - } - - leaf = glfs_h_creat (fs, root, filename, O_RDWR, 0644, &sb); - if (!leaf) { - ret = -1; - LOG_ERR ("glfs_h_lookupat leaf", ret); - } - fprintf (stderr, "glfs_h_create leaf - %p\n", leaf); - - leaf = glfs_h_lookupat (fs, root, filename2, &sb, 0); - if (!leaf) { - ret = -1; - LOG_IF_NO_ERR ("glfs_h_lookupat leaf", ret); - } - - ret = glfs_h_rename (fs, root, filename, root, filename2); - LOG_ERR("glfs_rename", ret); - - while (cnt++ < 5) { - ret = glfs_h_poll_upcall(fs, &cbk); - LOG_ERR ("glfs_h_poll_upcall", ret); - - /* There should not be any upcalls sent */ - if (glfs_upcall_get_reason(cbk) != GLFS_UPCALL_EVENT_NULL) { - fprintf (stderr, "Error: Upcall received(%d)\n", - glfs_upcall_get_reason(cbk)); - exit (1); - } - - glfs_free (cbk); - } - - ret = glfs_fini(fs); - LOG_ERR("glfs_fini", ret); - - fprintf (stderr, "End of libgfapi_fini\n"); + fprintf(stderr, "End of libgfapi_fini\n"); - exit(0); + exit(0); } - - diff --git a/tests/basic/gfapi/bug1291259.c b/tests/basic/gfapi/bug1291259.c index 78b95c6dcfd..cd7bc65268b 100644 --- a/tests/basic/gfapi/bug1291259.c +++ b/tests/basic/gfapi/bug1291259.c @@ -10,172 +10,172 @@ #include <glusterfs/api/glfs-handles.h> int gfapi = 1; -#define LOG_ERR(func, ret) do { \ - if (ret != 0) { \ - fprintf (stderr, "%s : returned error ret(%d), errno(%d)\n", \ - func, ret, errno); \ - exit(1); \ - } else { \ - fprintf (stderr, "%s : returned %d\n", func, ret); \ - } \ - } while (0) -#define LOG_IF_NO_ERR(func, ret) do { \ - if (ret == 0) { \ - fprintf (stderr, "%s : hasn't returned error %d\n", \ - func, ret); \ - exit(1); \ - } else { \ - fprintf (stderr, "%s : returned %d\n", func, ret); \ - } \ - } while (0) +#define LOG_ERR(func, ret) \ + do { \ + if (ret != 0) { \ + fprintf(stderr, "%s : returned error ret(%d), errno(%d)\n", func, \ + ret, errno); \ + exit(1); \ + } else { \ + fprintf(stderr, "%s : returned %d\n", func, ret); \ + } \ + } while (0) +#define LOG_IF_NO_ERR(func, ret) \ + do { \ + if (ret == 0) { \ + fprintf(stderr, "%s : hasn't returned error %d\n", func, ret); \ + exit(1); \ + } else { \ + fprintf(stderr, "%s : returned %d\n", func, ret); \ + } \ + } while (0) #define GLAPI_UUID_LENGTH 16 int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - glfs_t *fs = NULL; - glfs_t *fs2 = NULL; - int ret = 0, i; - glfs_fd_t *fd = NULL; - char *filename = "/a1"; - char *filename2 = "/a2"; - struct stat sb = {0, }; - char *logfile = NULL; - char *volname = NULL; - char *hostname = NULL; - int cnt = 1; - int upcall_received = 0; - struct glfs_upcall *cbk = NULL; - struct glfs_object *root = NULL, *leaf = NULL; - unsigned char globjhdl[GFAPI_HANDLE_LENGTH]; - unsigned char globjhdl2[GFAPI_HANDLE_LENGTH]; - - fprintf (stderr, "Starting libgfapi_fini\n"); - if (argc != 4) { - fprintf (stderr, "Invalid argument\n"); - exit(1); - } + glfs_t *fs = NULL; + glfs_t *fs2 = NULL; + int ret = 0, i; + glfs_fd_t *fd = NULL; + char *filename = "/a1"; + char *filename2 = "/a2"; + struct stat sb = { + 0, + }; + char *logfile = NULL; + char *volname = NULL; + char *hostname = NULL; + int cnt = 1; + int upcall_received = 0; + struct glfs_upcall *cbk = NULL; + struct glfs_object *root = NULL, *leaf = NULL; + unsigned char globjhdl[GFAPI_HANDLE_LENGTH]; + unsigned char globjhdl2[GFAPI_HANDLE_LENGTH]; + + fprintf(stderr, "Starting libgfapi_fini\n"); + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + fs = glfs_new(volname); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + return 1; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + LOG_ERR("glfs_set_volfile_server", ret); + + ret = glfs_set_logging(fs, logfile, 7); + LOG_ERR("glfs_set_logging", ret); + + ret = glfs_init(fs); + LOG_ERR("glfs_init", ret); + + /* This does not block, but enables caching of events. Real + * applications like NFS-Ganesha run this in a thread before activity + * on the fs (through this instance) happens. */ + ret = glfs_h_poll_upcall(fs, &cbk); + LOG_ERR("glfs_h_poll_upcall", ret); + + fs2 = glfs_new(volname); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + return 1; + } + + ret = glfs_set_volfile_server(fs2, "tcp", hostname, 24007); + LOG_ERR("glfs_set_volfile_server", ret); + + ret = glfs_set_logging(fs2, logfile, 7); + LOG_ERR("glfs_set_logging", ret); + + ret = glfs_init(fs2); + LOG_ERR("glfs_init", ret); + + sleep(2); + root = glfs_h_lookupat(fs, NULL, "/", &sb, 0); + if (!root) { + ret = -1; + LOG_ERR("glfs_h_lookupat root", ret); + } + leaf = glfs_h_lookupat(fs, root, filename, &sb, 0); + if (!leaf) { + ret = -1; + LOG_IF_NO_ERR("glfs_h_lookupat leaf", ret); + } + + root = glfs_h_lookupat(fs2, NULL, "/", &sb, 0); + if (!root) { + ret = -1; + LOG_ERR("glfs_h_lookupat root", ret); + } + leaf = glfs_h_creat(fs2, root, filename, O_RDWR, 0644, &sb); + if (!leaf) { + ret = -1; + LOG_ERR("glfs_h_lookupat leaf", ret); + } + fprintf(stderr, "glfs_h_create leaf - %p\n", leaf); + + while (cnt++ < 5 && !upcall_received) { + enum glfs_upcall_reason reason = 0; + struct glfs_upcall_inode *in_arg = NULL; - hostname = argv[1]; - volname = argv[2]; - logfile = argv[3]; + ret = glfs_h_poll_upcall(fs, &cbk); + LOG_ERR("glfs_h_poll_upcall", ret); + if (ret) + goto retry; + reason = glfs_upcall_get_reason(cbk); + fprintf(stderr, "Upcall received(%d)\n", reason); - fs = glfs_new (volname); - if (!fs) { - fprintf (stderr, "glfs_new: returned NULL\n"); - return 1; - } + if (reason == GLFS_UPCALL_INODE_INVALIDATE) { + struct glfs_object *object = NULL; - ret = glfs_set_volfile_server (fs, "tcp", hostname, 24007); - LOG_ERR("glfs_set_volfile_server", ret); + in_arg = glfs_upcall_get_event(cbk); + object = glfs_upcall_inode_get_object(in_arg); - ret = glfs_set_logging (fs, logfile, 7); - LOG_ERR("glfs_set_logging", ret); + ret = glfs_h_extract_handle(root, globjhdl + GLAPI_UUID_LENGTH, + GFAPI_HANDLE_LENGTH); + LOG_ERR("glfs_h_extract_handle", (ret != 16)); - ret = glfs_init (fs); - LOG_ERR("glfs_init", ret); + ret = glfs_h_extract_handle(object, globjhdl2 + GLAPI_UUID_LENGTH, + GFAPI_HANDLE_LENGTH); + LOG_ERR("glfs_h_extract_handle", (ret != 16)); - /* This does not block, but enables caching of events. Real - * applications like NFS-Ganesha run this in a thread before activity - * on the fs (through this instance) happens. */ - ret = glfs_h_poll_upcall(fs, &cbk); - LOG_ERR ("glfs_h_poll_upcall", ret); - - fs2 = glfs_new (volname); - if (!fs) { - fprintf (stderr, "glfs_new: returned NULL\n"); - return 1; + if (memcmp(globjhdl + GLAPI_UUID_LENGTH, + globjhdl2 + GLAPI_UUID_LENGTH, 16)) { + fprintf(stderr, "Error: gfid mismatch\n"); + exit(1); + } + upcall_received = 1; } - ret = glfs_set_volfile_server (fs2, "tcp", hostname, 24007); - LOG_ERR("glfs_set_volfile_server", ret); - - ret = glfs_set_logging (fs2, logfile, 7); - LOG_ERR("glfs_set_logging", ret); - - ret = glfs_init (fs2); - LOG_ERR("glfs_init", ret); + retry: + if (!upcall_received) + sleep(1); /* glfs_h_poll_upcall() does not block */ - sleep (2); - root = glfs_h_lookupat (fs, NULL, "/", &sb, 0); - if (!root) { - ret = -1; - LOG_ERR ("glfs_h_lookupat root", ret); - } - leaf = glfs_h_lookupat (fs, root, filename, &sb, 0); - if (!leaf) { - ret = -1; - LOG_IF_NO_ERR ("glfs_h_lookupat leaf", ret); - } - - root = glfs_h_lookupat (fs2, NULL, "/", &sb, 0); - if (!root) { - ret = -1; - LOG_ERR ("glfs_h_lookupat root", ret); - } - leaf = glfs_h_creat (fs2, root, filename, O_RDWR, 0644, &sb); - if (!leaf) { - ret = -1; - LOG_ERR ("glfs_h_lookupat leaf", ret); - } - fprintf (stderr, "glfs_h_create leaf - %p\n", leaf); - - while (cnt++ < 5 && !upcall_received) { - enum glfs_upcall_reason reason = 0; - struct glfs_upcall_inode *in_arg = NULL; - - ret = glfs_h_poll_upcall(fs, &cbk); - LOG_ERR ("glfs_h_poll_upcall", ret); - if (ret) - goto retry; - - reason = glfs_upcall_get_reason (cbk); - fprintf (stderr, "Upcall received(%d)\n", reason); - - if (reason == GLFS_UPCALL_INODE_INVALIDATE) { - struct glfs_object *object = NULL; - - in_arg = glfs_upcall_get_event (cbk); - object = glfs_upcall_inode_get_object (in_arg); - - ret = glfs_h_extract_handle (root, - globjhdl+GLAPI_UUID_LENGTH, - GFAPI_HANDLE_LENGTH); - LOG_ERR("glfs_h_extract_handle", (ret != 16)); - - ret = glfs_h_extract_handle (object, - globjhdl2+GLAPI_UUID_LENGTH, - GFAPI_HANDLE_LENGTH); - LOG_ERR("glfs_h_extract_handle", (ret != 16)); - - if (memcmp (globjhdl+GLAPI_UUID_LENGTH, - globjhdl2+GLAPI_UUID_LENGTH, 16)) { - fprintf (stderr, "Error: gfid mismatch\n"); - exit (1); - } - upcall_received = 1; - } - -retry: - if (!upcall_received) - sleep (1); /* glfs_h_poll_upcall() does not block */ - - glfs_free (cbk); - cbk = NULL; + if (!ret) { + glfs_free(cbk); + cbk = NULL; } + } - if (!upcall_received) { - fprintf (stderr, "Error: Upcall not received\n"); - exit (1); - } + if (!upcall_received) { + fprintf(stderr, "Error: Upcall not received\n"); + exit(1); + } - ret = glfs_fini(fs); - LOG_ERR("glfs_fini", ret); + ret = glfs_fini(fs); + LOG_ERR("glfs_fini", ret); - fprintf (stderr, "End of libgfapi_fini\n"); + fprintf(stderr, "End of libgfapi_fini\n"); - exit(0); + exit(0); } - - diff --git a/tests/basic/gfapi/bug1291259.t b/tests/basic/gfapi/bug1291259.t index bf217b34606..999cda2da3a 100755 --- a/tests/basic/gfapi/bug1291259.t +++ b/tests/basic/gfapi/bug1291259.t @@ -28,5 +28,5 @@ TEST $CLI volume stop $V0 TEST $CLI volume delete $V0 cleanup; -#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=1376390 -#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=1376390 +#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=1405301 +#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=1405301 diff --git a/tests/basic/gfapi/bug1613098.c b/tests/basic/gfapi/bug1613098.c new file mode 100644 index 00000000000..ee67e97a034 --- /dev/null +++ b/tests/basic/gfapi/bug1613098.c @@ -0,0 +1,96 @@ +#include <inttypes.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> + +#define ACL_TYPE_ACCESS (0x8000) + +#define VALIDATE_AND_GOTO_LABEL_ON_ERROR(func, ret, label) \ + do { \ + if (ret < 0) { \ + fprintf(stderr, "%s : returned error %d (%s)\n", func, ret, \ + strerror(errno)); \ + goto label; \ + } \ + } while (0) + +int +main(int argc, char *argv[]) +{ + int ret = -1; + int flags = O_RDWR | O_SYNC; + glfs_t *fs = NULL; + glfs_fd_t *fd = NULL; + char *volname = NULL; + char *logfile = NULL; + const char *filename = "file_tmp"; + struct glfs_object *object = NULL; + acl_t acl = NULL; + struct stat sb; + + if (argc != 3) { + fprintf(stderr, "Invalid argument\n"); + return 1; + } + + volname = argv[1]; + logfile = argv[2]; + + fs = glfs_new(volname); + if (!fs) + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_new", ret, out); + + ret = glfs_set_volfile_server(fs, "tcp", "localhost", 24007); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_volfile_server", ret, out); + + ret = glfs_set_logging(fs, logfile, 7); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_logging", ret, out); + + ret = glfs_init(fs); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_init", ret, out); + + fd = glfs_creat(fs, filename, flags, 0044); + if (fd == NULL) { + ret = -1; + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_creat", ret, out); + } + glfs_close(fd); + + object = glfs_h_lookupat(fs, NULL, filename, NULL, 0); + if (object == NULL) { + ret = -1; + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_h_lookupat", ret, out); + } + + ret = glfs_chown(fs, filename, 99, 99); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_chown", ret, out); + + ret = glfs_setfsuid(99); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_setfsuid", ret, out); + + ret = glfs_setfsgid(99); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_setfsgid", ret, out); + + acl = glfs_h_acl_get(fs, object, ACL_TYPE_ACCESS); + if (acl == NULL) { + ret = -1; + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_h_acl_get", ret, out); + } + + ret = glfs_h_acl_set(fs, object, ACL_TYPE_ACCESS, acl); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_h_acl_get", ret, out); +out: + glfs_setfsuid(0); + glfs_setfsgid(0); + + if (object) + glfs_h_close(object); + + if (fs) + glfs_fini(fs); + + return ret; +} diff --git a/tests/basic/gfapi/bug1613098.t b/tests/basic/gfapi/bug1613098.t new file mode 100755 index 00000000000..e4acc2b76bf --- /dev/null +++ b/tests/basic/gfapi/bug1613098.t @@ -0,0 +1,22 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +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'; + +logdir=`gluster --print-logdir` + +build_tester $(dirname $0)/bug1613098.c -lgfapi + +TEST ./$(dirname $0)/bug1613098 $V0 $logdir/bug1613098.log + +cleanup_tester $(dirname $0)/bug1613098 + +cleanup; diff --git a/tests/basic/gfapi/gfapi-async-calls-test.c b/tests/basic/gfapi/gfapi-async-calls-test.c index 277067bee2c..55835b14709 100644 --- a/tests/basic/gfapi/gfapi-async-calls-test.c +++ b/tests/basic/gfapi/gfapi-async-calls-test.c @@ -9,169 +9,486 @@ #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) +#define LOG_ERR(msg) \ + do { \ + fprintf(stderr, "%s : Error (%s)\n", msg, strerror(errno)); \ + } while (0) int cbk_complete = 0; int cbk_ret_val = -1; -int -fill_iov (struct iovec *iov, char fillchar, int count) +void +cbk_check() { - int ret = -1; + while (cbk_complete != 1) { + sleep(1); + } + if (cbk_ret_val < 0) { + fprintf(stderr, "cbk_ret_val is -ve\n"); + } +} - iov->iov_base = calloc (count + 1, sizeof(fillchar)); - if (iov->iov_base == NULL) { - return ret; - } else { - iov->iov_len = count; - ret = 0; - } - memset (iov->iov_base, fillchar, count); - memset (iov->iov_base + count, '\0', 1); +int +fill_iov(struct iovec *iov, char fillchar, int count) +{ + int ret = -1; + iov->iov_base = malloc(count + 1); + if (iov->iov_base == NULL) { return ret; + } else { + iov->iov_len = count; + ret = 0; + } + memset(iov->iov_base, fillchar, count); + memset(iov->iov_base + count, '\0', 1); + + return ret; } 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; - } +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; + } - ret = 0; + return fs; +} + +void +pwritev_async_cbk(glfs_fd_t *fd, ssize_t ret, struct stat *prestat, + struct stat *poststat, void *cookie) +{ + if (ret < 0) { + LOG_ERR("glfs_pwritev failed"); + } + cbk_ret_val = ret; + cbk_complete = 1; +} + +int +pwritev_async(glfs_t *fs, glfs_fd_t *glfd, int char_count) +{ + ssize_t ret = -1; + int flags = O_RDWR; + struct iovec iov = {0}; + void *write_cookie = NULL; + + ret = fill_iov(&iov, 'a', char_count); + if (ret) { + LOG_ERR("failed to create iov"); + goto out; + } + + write_cookie = strdup("write_cookie"); + ret = glfs_pwritev_async(glfd, &iov, 1, 0, flags, pwritev_async_cbk, + &write_cookie); out: - if (ret) { - glfs_fini (fs); - fs = NULL; - } + if (ret < 0) { + LOG_ERR("glfs_pwritev async failed"); + } + return ret; +} - return fs; +void +pwrite_async_cbk(glfs_fd_t *fd, ssize_t ret, struct stat *prestat, + struct stat *poststat, void *cookie) +{ + if (ret < 0) { + LOG_ERR("glfs_pwrite_cbk failed"); + } + cbk_ret_val = ret; + cbk_complete = 1; +} + +int +pwrite_async(glfs_fd_t *glfd) +{ + ssize_t ret = -1; + int flags = O_RDWR; + char buf1[10]; + char *buf2 = "ten bytes!"; + void *write_cookie = strdup("write_cookie"); + ret = glfs_pwrite_async(glfd, buf1, 10, 0, flags, pwrite_async_cbk, + &write_cookie); + + if (ret < 0) { + LOG_ERR("glfs_pwrite_async failed"); + } + return ret; } void -write_async_cbk (glfs_fd_t *fd, ssize_t ret, void *cookie) +writev_async_cbk(glfs_fd_t *fd, ssize_t ret, struct stat *prestat, + struct stat *poststat, void *cookie) +{ + if (ret < 0) { + LOG_ERR("glfs_writev_cbk failed"); + } + cbk_ret_val = ret; + cbk_complete = 1; +} + +int +writev_async(glfs_t *fs, glfs_fd_t *glfd, int char_count) { + ssize_t ret = -1; + int flags = O_RDWR; + struct iovec iov = {0}; + void *write_cookie = NULL; + + ret = fill_iov(&iov, 'a', char_count); + if (ret) { + LOG_ERR("failed to create iov"); + goto out; + } + + write_cookie = strdup("write_cookie"); + ret = glfs_writev_async(glfd, &iov, 1, flags, writev_async_cbk, + &write_cookie); +out: + if (ret < 0) { + LOG_ERR("glfs_writev_async failed"); + } + return ret; +} - if (ret < 0) { - LOG_ERR ("glfs_write failed"); - } - cbk_ret_val = ret; - cbk_complete = 1; +void +write_async_cbk(glfs_fd_t *fd, ssize_t ret, struct stat *prestat, + struct stat *poststat, void *cookie) +{ + if (ret < 0) { + LOG_ERR("glfs_write_cbk failed"); + } + cbk_ret_val = ret; + cbk_complete = 1; } int -write_async (glfs_t *fs, glfs_fd_t *glfd, int char_count) +write_async(glfs_fd_t *glfd) { - ssize_t ret = -1; - int flags = O_RDWR; - const char *buff = "This is from my prog\n"; - struct iovec iov = {0}; - void *write_cookie = NULL; - void *read_cookie = NULL; + ssize_t ret = -1; + int flags = O_RDWR; + char buf1[10]; + char *buf2 = "ten bytes!"; + void *write_cookie = strdup("write_cookie"); + ret = glfs_write_async(glfd, buf1, 10, flags, write_async_cbk, + &write_cookie); + + if (ret < 0) { + LOG_ERR("glfs_write_async failed"); + } + return ret; +} +void +preadv_async_cbk(glfs_fd_t *fd, ssize_t ret, struct stat *prestat, + struct stat *poststat, void *cookie) +{ + if (ret < 0) { + LOG_ERR("glfs_preadv_cbk failed"); + } + cbk_ret_val = ret; + cbk_complete = 1; +} +int +preadv_async(glfs_t *fs, glfs_fd_t *glfd, int char_count) +{ + ssize_t ret = -1; + int flags = O_RDWR; + struct iovec iov = {0}; + void *read_cookie = NULL; + + ret = fill_iov(&iov, 'a', char_count); + if (ret) { + LOG_ERR("failed to create iov"); + goto out; + } + + read_cookie = strdup("preadv_cookie"); + ret = glfs_preadv_async(glfd, &iov, 1, 0, flags, preadv_async_cbk, + &read_cookie); +out: + if (ret < 0) { + LOG_ERR("glfs_preadv async failed"); + } + return ret; +} + +void +pread_async_cbk(glfs_fd_t *fd, ssize_t ret, struct stat *prestat, + struct stat *poststat, void *cookie) +{ + if (ret < 0) { + LOG_ERR("glfs_pread_cbk failed"); + } + cbk_ret_val = ret; + cbk_complete = 1; +} + +int +pread_async(glfs_fd_t *glfd) +{ + ssize_t ret = -1; + int flags = O_RDWR; + char buf1[10]; + void *read_cookie = strdup("read_cookie"); + ret = glfs_pread_async(glfd, buf1, 10, 0, flags, pread_async_cbk, + &read_cookie); + if (ret < 0) { + LOG_ERR("glfs_pread_async failed"); + } + + return ret; +} - ret = fill_iov (&iov, 'a', char_count); - if (ret) { - LOG_ERR ("failed to create iov"); - goto out; - } +void +readv_async_cbk(glfs_fd_t *fd, ssize_t ret, struct stat *prestat, + struct stat *poststat, void *cookie) +{ + if (ret < 0) { + LOG_ERR("glfs_readv_cbk failed"); + } + cbk_ret_val = ret; + cbk_complete = 1; +} - write_cookie = strdup ("write_cookie"); - ret = glfs_pwritev_async (glfd, &iov, 1, 0, flags, write_async_cbk, - &write_cookie); +int +readv_async(glfs_t *fs, glfs_fd_t *glfd, int char_count) +{ + ssize_t ret = -1; + int flags = O_RDWR; + struct iovec iov = {0}; + void *read_cookie = NULL; + + ret = fill_iov(&iov, 'a', char_count); + if (ret) { + LOG_ERR("failed to create iov"); + goto out; + } + + read_cookie = strdup("read_cookie"); + ret = glfs_readv_async(glfd, &iov, 1, flags, readv_async_cbk, &read_cookie); out: - if (ret < 0) { - LOG_ERR ("glfs_pwritev async failed"); - } - return ret; + if (ret < 0) { + LOG_ERR("glfs_readv_async failed"); + } + return ret; +} +void +read_async_cbk(glfs_fd_t *fd, ssize_t ret, struct stat *prestat, + struct stat *poststat, void *cookie) +{ + if (ret < 0) { + LOG_ERR("glfs_read_cbk failed"); + } + cbk_ret_val = ret; + cbk_complete = 1; } int -main (int argc, char *argv[]) -{ - int ret = 0; - char *hostname = NULL; - char *volname = NULL; - char *logfile = NULL; - glfs_t *fs = NULL; - const char *filename = "glfs_test.txt"; - int flags = (O_RDWR|O_CREAT); - glfs_fd_t *glfd = NULL; - int count = 200; - - if (argc != 4) { - fprintf (stderr, "Invalid argument\n"); - exit(1); - } - - hostname = argv[1]; - volname = argv[2]; - logfile = argv[3]; - - 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"); - exit(1); - } - - ret = write_async (fs, glfd, count); - if (ret) { - LOG_ERR ("glfs_test_function failed"); - exit(1); - } - - while (cbk_complete != 1) { - sleep(1); - } - - ret = glfs_close (glfd); - if (ret < 0) { - LOG_ERR ("glfs close failed"); - } - - /* - * skipping fini - */ - - if (cbk_ret_val == count) - return 0; - else - return -1; +read_async(glfs_fd_t *glfd) +{ + ssize_t ret = -1; + int flags = O_RDWR; + char buf1[10]; + void *read_cookie = strdup("read_cookie"); + ret = glfs_read_async(glfd, buf1, 10, flags, read_async_cbk, &read_cookie); + + if (ret < 0) { + LOG_ERR("glfs_read_async failed"); + } + return ret; +} + +void +fsync_async_cbk(glfs_fd_t *fd, ssize_t ret, struct stat *prestat, + struct stat *poststat, void *cookie) +{ + if (ret < 0) { + LOG_ERR("glfs_fsync_async_cbk failed"); + } + cbk_ret_val = ret; + cbk_complete = 1; +} + +void +fdatasync_async_cbk(glfs_fd_t *fd, ssize_t ret, struct stat *prestat, + struct stat *poststat, void *cookie) +{ + if (ret < 0) { + LOG_ERR("glfs_fdatasync_async_cbk failed"); + } + cbk_ret_val = ret; + cbk_complete = 1; } +void +ftruncate_async_cbk(glfs_fd_t *fd, ssize_t ret, struct stat *prestat, + struct stat *poststat, void *cookie) +{ + if (ret < 0) { + LOG_ERR("glfs_ftruncate_async_cbk failed"); + } + cbk_ret_val = ret; + cbk_complete = 1; +} +int +main(int argc, char *argv[]) +{ + int ret = 0; + char *hostname = NULL; + char *volname = NULL; + char *logfile = NULL; + glfs_t *fs = NULL; + const char *filename = "glfs_test.txt"; + int flags = (O_RDWR | O_CREAT); + glfs_fd_t *glfd = NULL; + int count = 200; + void *data = strdup("Sample_text"); + + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + 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"); + exit(1); + } + + ret = pwritev_async(fs, glfd, count); + if (ret) { + LOG_ERR("glfs_pwritev_async_test failed"); + exit(1); + } + cbk_check(); + + ret = writev_async(fs, glfd, count); + if (ret) { + LOG_ERR("glfs_writev_async_test failed"); + exit(1); + } + cbk_check(); + + ret = write_async(glfd); + if (ret) { + LOG_ERR("glfs_write_async_test failed"); + exit(1); + } + cbk_check(); + + ret = preadv_async(fs, glfd, count); + if (ret) { + LOG_ERR("glfs_preadv_async_test failed"); + exit(1); + } + cbk_check(); + + ret = pread_async(glfd); + if (ret) { + LOG_ERR("glfs_pread_async_test failed"); + exit(1); + } + cbk_check(); + + ret = readv_async(fs, glfd, count); + if (ret) { + LOG_ERR("glfs_readv_async_test failed"); + exit(1); + } + cbk_check(); + + ret = read_async(glfd); + if (ret) { + LOG_ERR("glfs_read_async_test failed"); + exit(1); + } + cbk_check(); + + ret = glfs_fsync(glfd, NULL, NULL); + if (ret < 0) { + LOG_ERR("glfs_fsync failed"); + exit(1); + } + + ret = glfs_fdatasync(glfd, NULL, NULL); + if (ret < 0) { + LOG_ERR("glfs_fdatasync failed"); + exit(1); + } + + ret = glfs_fsync_async(glfd, fsync_async_cbk, data); + if (ret < 0) { + LOG_ERR("glfs_fsync_async failed"); + exit(1); + } + cbk_check(); + + ret = glfs_fdatasync_async(glfd, fdatasync_async_cbk, data); + if (ret < 0) { + LOG_ERR("glfs_fdatasync_async failed"); + exit(1); + } + cbk_check(); + + ret = glfs_ftruncate_async(glfd, 4, ftruncate_async_cbk, data); + if (ret < 0) { + LOG_ERR("glfs_ftruncate_async failed"); + exit(1); + } + + ret = glfs_close(glfd); + if (ret < 0) { + LOG_ERR("glfs close failed"); + } + + ret = glfs_fini(fs); + + return ret; +} diff --git a/tests/basic/gfapi/gfapi-copy-file-range.t b/tests/basic/gfapi/gfapi-copy-file-range.t new file mode 100644 index 00000000000..a56d3a58e07 --- /dev/null +++ b/tests/basic/gfapi/gfapi-copy-file-range.t @@ -0,0 +1,82 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +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 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 + +# Just a single brick volume. More test cases need to be +# added in future for distribute, replicate, +# distributed replicate and distributed replicated sharded +# volumes. +TEST $CLI volume create $V0 $H0:$B0/bricks/brick1; +EXPECT 'Created' volinfo_field $V0 'Status'; + +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; + +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 + +TEST dd if=/dev/urandom of=$M0/file bs=1M count=555; + +# check for the existence of the created file +TEST stat $M0/file; + +# grab the size of the file +SRC_SIZE=$(stat -c %s $M0/file); + +logdir=`gluster --print-logdir` + +# TODO: +# For now, do not call copy-file-range utility. This is because, +# the regression machines are centos-7 based which does not have +# copy_file_range API available. So, instead of this testcase +# causing regression failures, for now, this is just a dummy test +# case. Uncomment the below tests (until volume stop) when there +# is support for copy_file_range in the regression machines. +# + +TEST build_tester $(dirname $0)/glfs-copy-file-range.c -lgfapi + +TEST ./$(dirname $0)/glfs-copy-file-range $H0 $V0 $logdir/gfapi-copy-file-range.log /file /new + +# check whether the destination file is created or not +TEST stat $M0/new + +# check the size of the destination file +DST_SIZE=$(stat -c %s $M0/new); + +# The sizes of the source and destination should be same. +# Atleast it ensures that, copy_file_range API is working +# as expected. Whether the actual cloning happened via reflink +# or a read/write happened is different matter. +TEST [ $SRC_SIZE == $DST_SIZE ]; + +cleanup_tester $(dirname $0)/glfs-copy-file-range + +TEST $CLI volume stop $V0 +TEST $CLI volume delete $V0 + +UMOUNT_LOOP $B0/bricks; + +cleanup; diff --git a/tests/basic/gfapi/gfapi-dup.c b/tests/basic/gfapi/gfapi-dup.c index 96f133eae33..028108e4590 100644 --- a/tests/basic/gfapi/gfapi-dup.c +++ b/tests/basic/gfapi/gfapi-dup.c @@ -4,81 +4,81 @@ #include <glusterfs/api/glfs.h> #include <glusterfs/api/glfs-handles.h> -#define VALIDATE_AND_GOTO_LABEL_ON_ERROR(func, ret, label) do { \ - if (ret < 0) { \ - fprintf (stderr, "%s : returned error %d (%s)\n", \ - func, ret, strerror (errno)); \ - goto label; \ - } \ - } while (0) +#define VALIDATE_AND_GOTO_LABEL_ON_ERROR(func, ret, label) \ + do { \ + if (ret < 0) { \ + fprintf(stderr, "%s : returned error %d (%s)\n", func, ret, \ + strerror(errno)); \ + goto label; \ + } \ + } while (0) int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - int ret = -1; - int flags = O_RDWR|O_SYNC; - glfs_t *fs = NULL; - glfs_fd_t *fd1 = NULL; - glfs_fd_t *fd2 = NULL; - char *volname = NULL; - char *logfile = NULL; - char *hostname = NULL; - const char *filename = "file_tmp"; - const char *buff = "An opinion should be the result of thought, " - "not a substitute for it."; - - if (argc != 4) { - fprintf (stderr, "Invalid argument\n"); - return 1; - } - - hostname = argv[1]; - volname = argv[2]; - logfile = argv[3]; - - fs = glfs_new (volname); - if (!fs) - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_new", ret, out); - - ret = glfs_set_volfile_server (fs, "tcp", hostname, 24007); - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_set_volfile_server", ret, out); - - ret = glfs_set_logging (fs, logfile, 7); - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_set_logging", ret, out); - - ret = glfs_init (fs); - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_init", ret, out); - - fd1 = glfs_creat(fs, filename, flags, 0644); - if (fd1 == NULL) { - ret = -1; - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_creat", ret, out); - } - - ret = glfs_write (fd1, buff, strlen (buff), flags); - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_write", ret, out); - - fd2 = glfs_dup(fd1); - if (fd2 == NULL) { - ret = -1; - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_dup", ret, out); - } - - ret = glfs_lseek (fd2, 0, SEEK_SET); - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_lseek", ret, out); + int ret = -1; + int flags = O_RDWR | O_SYNC; + glfs_t *fs = NULL; + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + char *volname = NULL; + char *logfile = NULL; + char *hostname = NULL; + const char *filename = "file_tmp"; + const char *buff = + "An opinion should be the result of thought, " + "not a substitute for it."; + + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + return 1; + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + fs = glfs_new(volname); + if (!fs) + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_new", ret, out); + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_volfile_server", ret, out); + + ret = glfs_set_logging(fs, logfile, 7); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_logging", ret, out); + + ret = glfs_init(fs); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_init", ret, out); + + fd1 = glfs_creat(fs, filename, flags, 0644); + if (fd1 == NULL) { + ret = -1; + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_creat", ret, out); + } + + ret = glfs_write(fd1, buff, strlen(buff), flags); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_write", ret, out); + + fd2 = glfs_dup(fd1); + if (fd2 == NULL) { + ret = -1; + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_dup", ret, out); + } + + ret = glfs_lseek(fd2, 0, SEEK_SET); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_lseek", ret, out); out: - if (fd1 != NULL) - glfs_close(fd1); - if (fd2 != NULL) - glfs_close(fd2); - if (fs) { - ret = glfs_fini(fs); - if (ret) - fprintf (stderr, "glfs_fini(fs) returned %d\n", ret); - } - - return ret; + if (fd1 != NULL) + glfs_close(fd1); + if (fd2 != NULL) + glfs_close(fd2); + if (fs) { + ret = glfs_fini(fs); + if (ret) + fprintf(stderr, "glfs_fini(fs) returned %d\n", ret); + } + + return ret; } - - 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-load-volfile.c b/tests/basic/gfapi/gfapi-load-volfile.c new file mode 100644 index 00000000000..fbfc6045cd7 --- /dev/null +++ b/tests/basic/gfapi/gfapi-load-volfile.c @@ -0,0 +1,65 @@ +/* + * Create a glfs instance based on a .vol file + * + * This is used to measure memory leaks by initializing a graph through a .vol + * file and destroying it again. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <glusterfs/api/glfs.h> + +#define PROGNAME "gfapi-load-volfile" + +void +usage(FILE *output) +{ + fprintf(output, "Usage: " PROGNAME " <volfile>\n"); +} + +void +main(int argc, char **argv) +{ + int ret = 0; + glfs_t *fs = NULL; + + if (argc != 2) { + usage(stderr); + exit(EXIT_FAILURE); + } + + if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "-h")) { + usage(stdout); + exit(EXIT_SUCCESS); + } + + fs = glfs_new(PROGNAME); + if (!fs) { + perror("glfs_new failed"); + exit(EXIT_FAILURE); + } + + glfs_set_logging(fs, PROGNAME ".log", 9); + + ret = glfs_set_volfile(fs, argv[1]); + if (ret) { + perror("glfs_set_volfile failed"); + ret = EXIT_FAILURE; + goto out; + } + + ret = glfs_init(fs); + if (ret) { + perror("glfs_init failed"); + ret = EXIT_FAILURE; + goto out; + } + + ret = EXIT_SUCCESS; +out: + glfs_fini(fs); + + exit(ret); +} diff --git a/tests/basic/gfapi/gfapi-load-volfile.t b/tests/basic/gfapi/gfapi-load-volfile.t new file mode 100644 index 00000000000..d914cacd819 --- /dev/null +++ b/tests/basic/gfapi/gfapi-load-volfile.t @@ -0,0 +1,28 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup + +TEST glusterd + +TEST $CLI volume create ${V0} ${H0}:${B0}/brick0 +EXPECT 'Created' volinfo_field ${V0} 'Status' + +TEST $CLI volume start ${V0} +EXPECT 'Started' volinfo_field ${V0} 'Status' + +TEST build_tester $(dirname ${0})/gfapi-load-volfile.c -lgfapi + +sed -e "s,@@HOSTNAME@@,${H0},g" -e "s,@@BRICKPATH@@,${B0}/brick0,g" \ + $(dirname ${0})/protocol-client.vol.in \ + > $(dirname ${0})/protocol-client.vol + +TEST ./$(dirname ${0})/gfapi-load-volfile \ + $(dirname ${0})/protocol-client.vol + +cleanup_tester $(dirname ${0})/gfapi-load-volfile +cleanup_tester $(dirname ${0})/protocol-client.vol + +cleanup 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/gfapi-ssl-test.c b/tests/basic/gfapi/gfapi-ssl-test.c index 41126bdc6db..a27b5233702 100644 --- a/tests/basic/gfapi/gfapi-ssl-test.c +++ b/tests/basic/gfapi/gfapi-ssl-test.c @@ -9,118 +9,116 @@ #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) +#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) +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; + 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; - } + if (ret) { + glfs_fini(fs); + fs = NULL; + } - return fs; + return fs; } int -glfs_test_function (const char *hostname, const char *volname, - const char *logfile) +glfs_test_function(const char *hostname, const char *volname, + 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, 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; - } + 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, 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"); - } + ret = glfs_fini(fs); + if (ret) { + LOG_ERR("glfs_fini failed"); + } - return ret; + return ret; } int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - int ret = 0; - char *hostname = NULL; - char *volname = NULL; - char *logfile = NULL; - - if (argc != 4) { - fprintf (stderr, "Invalid argument\n"); - exit(1); - } - - hostname = argv[1]; - volname = argv[2]; - logfile = argv[3]; - - ret = glfs_test_function (hostname, volname, logfile); - if (ret) { - LOG_ERR ("glfs_test_function failed"); - } - - return ret; + int ret = 0; + char *hostname = NULL; + char *volname = NULL; + char *logfile = NULL; + + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + ret = glfs_test_function(hostname, volname, logfile); + if (ret) { + LOG_ERR("glfs_test_function failed"); + } + + return ret; } - - diff --git a/tests/basic/gfapi/gfapi-ssl-test.t b/tests/basic/gfapi/gfapi-ssl-test.t index 3236625357d..937fcc83a4c 100755 --- a/tests/basic/gfapi/gfapi-ssl-test.t +++ b/tests/basic/gfapi/gfapi-ssl-test.t @@ -55,7 +55,7 @@ TEST $CLI volume delete $V0 cleanup; -# NetBSD build scripts are not upto date therefore this test +# 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/gfapi-statx-basic.c b/tests/basic/gfapi/gfapi-statx-basic.c new file mode 100644 index 00000000000..a4943fa0fd1 --- /dev/null +++ b/tests/basic/gfapi/gfapi-statx-basic.c @@ -0,0 +1,184 @@ +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <glusterfs/api/glfs.h> + +#define VALIDATE_AND_GOTO_LABEL_ON_ERROR(func, ret, label) \ + do { \ + if (ret < 0) { \ + fprintf(stderr, "%s : returned error %d (%s)\n", func, ret, \ + strerror(errno)); \ + goto label; \ + } \ + } while (0) + +#define GOTO_LABEL_ON_FALSE(compstr, ret, label) \ + do { \ + if (ret == false) { \ + fprintf(stderr, "%s : comparison failed!\n", compstr); \ + goto label; \ + } \ + } while (0) + +#define WRITE_SIZE 513 +#define TRUNC_SIZE 4096 + +/* Using private function and hence providing a forward declation in sync with +code in glfs-internal.h */ +int +glfs_statx(struct glfs *fs, const char *path, unsigned int mask, + struct glfs_stat *statxbuf); + +int +main(int argc, char *argv[]) +{ + int ret = -1; + int flags = O_RDWR | O_SYNC; + glfs_t *fs = NULL; + glfs_fd_t *fd1 = NULL; + char *volname = NULL; + char *logfile = NULL; + const char *filename = "file_tmp"; + const char buff[WRITE_SIZE]; + struct stat sb; + unsigned int mask; + struct glfs_stat statx; + bool bret; + + if (argc != 3) { + fprintf(stderr, "Invalid argument\n"); + fprintf(stderr, "Usage: %s <volname> <logfile>\n", argv[0]); + return 1; + } + + volname = argv[1]; + logfile = argv[2]; + + fs = glfs_new(volname); + if (!fs) + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_new", ret, out); + + ret = glfs_set_volfile_server(fs, "tcp", "localhost", 24007); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_volfile_server", ret, out); + + ret = glfs_set_logging(fs, logfile, 7); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_logging", ret, out); + + ret = glfs_init(fs); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_init", ret, out); + + fd1 = glfs_creat(fs, filename, flags, 0644); + if (fd1 == NULL) { + ret = -1; + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_creat", ret, out); + } + + ret = glfs_truncate(fs, filename, TRUNC_SIZE); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_truncate", ret, out); + + ret = glfs_write(fd1, buff, WRITE_SIZE, flags); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_write", ret, out); + + ret = glfs_fstat(fd1, &sb); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_fstat", ret, out); + + if (sb.st_size != TRUNC_SIZE) { + fprintf(stderr, "wrong size %jd should be %jd\n", (intmax_t)sb.st_size, + (intmax_t)2048); + ret = -1; + goto out; + } + + glfs_close(fd1); + fd1 = NULL; + + /* TEST 1: Invalid mask to statx */ + mask = 0xfafadbdb; + ret = glfs_statx(fs, filename, mask, NULL); + if (ret == 0 || ((ret == -1) && (errno != EINVAL))) { + fprintf(stderr, + "Invalid args passed, but error returned is" + " incorrect (ret - %d, errno - %d)\n", + ret, errno); + ret = -1; + goto out; + } + ret = 0; + + /* TEST 2: Call statx and validate fields against prior fstat data */ + /* NOTE: This fails, as iatt->ia_flags are not carried through the stack, + * for example if mdc_to_iatt is invoked to serve cached stat, we will loose + * the flags. */ + mask = GLFS_STAT_ALL; + ret = glfs_statx(fs, filename, mask, &statx); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_statx", ret, out); + + if ((statx.glfs_st_mask & GLFS_STAT_BASIC_STATS) != GLFS_STAT_BASIC_STATS) { + fprintf(stderr, "Invalid glfs_st_mask, expecting 0x%x got 0x%x\n", + GLFS_STAT_ALL, statx.glfs_st_mask); + ret = -1; + goto out; + } + + bret = (sb.st_ino == statx.glfs_st_ino); + GOTO_LABEL_ON_FALSE("(sb.st_ino == statx.glfs_st_ino)", bret, out); + + bret = (sb.st_mode == statx.glfs_st_mode); + GOTO_LABEL_ON_FALSE("(sb.st_mode == statx.glfs_st_mode)", bret, out); + + bret = (sb.st_nlink == statx.glfs_st_nlink); + GOTO_LABEL_ON_FALSE("(sb.st_nlink == statx.glfs_st_nlink)", bret, out); + + bret = (sb.st_uid == statx.glfs_st_uid); + GOTO_LABEL_ON_FALSE("(sb.st_uid == statx.glfs_st_uid)", bret, out); + + bret = (sb.st_gid == statx.glfs_st_gid); + GOTO_LABEL_ON_FALSE("(sb.st_gid == statx.glfs_st_gid)", bret, out); + + bret = (sb.st_size == statx.glfs_st_size); + GOTO_LABEL_ON_FALSE("(sb.st_size == statx.glfs_st_size)", bret, out); + + bret = (sb.st_blksize == statx.glfs_st_blksize); + GOTO_LABEL_ON_FALSE("(sb.st_blksize == statx.glfs_st_blksize)", bret, out); + + bret = (sb.st_blocks == statx.glfs_st_blocks); + GOTO_LABEL_ON_FALSE("(sb.st_blocks == statx.glfs_st_blocks)", bret, out); + + bret = (!memcmp(&sb.st_atim, &statx.glfs_st_atime, + sizeof(struct timespec))); + GOTO_LABEL_ON_FALSE("(sb.st_atim == statx.glfs_st_atime)", bret, out); + + bret = (!memcmp(&sb.st_mtim, &statx.glfs_st_mtime, + sizeof(struct timespec))); + GOTO_LABEL_ON_FALSE("(sb.st_mtim == statx.glfs_st_mtime)", bret, out); + + bret = (!memcmp(&sb.st_ctim, &statx.glfs_st_ctime, + sizeof(struct timespec))); + GOTO_LABEL_ON_FALSE("(sb.st_ctim == statx.glfs_st_ctime)", bret, out); + + /* TEST 3: Check if partial masks are accepted */ + mask = GLFS_STAT_TYPE | GLFS_STAT_UID | GLFS_STAT_GID; + ret = glfs_statx(fs, filename, mask, &statx); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_statx", ret, out); + + /* We currently still return all stats, as is acceptable based on the API + * definition in the header (and in statx as well) */ + if ((statx.glfs_st_mask & GLFS_STAT_BASIC_STATS) != GLFS_STAT_BASIC_STATS) { + fprintf(stderr, "Invalid glfs_st_mask, expecting 0x%x got 0x%x\n", + GLFS_STAT_ALL, statx.glfs_st_mask); + ret = -1; + goto out; + } +out: + if (fd1 != NULL) + glfs_close(fd1); + if (fs) { + (void)glfs_fini(fs); + } + + return ret; +} diff --git a/tests/basic/gfapi/gfapi-statx-basic.t b/tests/basic/gfapi/gfapi-statx-basic.t new file mode 100755 index 00000000000..d9acbce2f99 --- /dev/null +++ b/tests/basic/gfapi/gfapi-statx-basic.t @@ -0,0 +1,30 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +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'; + +# NOTE: Test is passing due to very specific volume configuration +# Disable md-cache, as it does not save and return ia_flags from iatt +# This is possibly going to be true of other xlators as well (ec/afr), need to +# ensure these are fixed, or hack statx to return all basic attrs anyway. +TEST $CLI volume set $V0 performance.md-cache-timeout 0 + +logdir=`gluster --print-logdir` + +build_tester $(dirname $0)/gfapi-statx-basic.c -lgfapi + +TEST ./$(dirname $0)/gfapi-statx-basic $V0 $logdir/gfapi-statx-basic.log + +cleanup_tester $(dirname $0)/gfapi-statx-basic + +cleanup; diff --git a/tests/basic/gfapi/gfapi-trunc.c b/tests/basic/gfapi/gfapi-trunc.c index af187e50c78..769f6cfa1d9 100644 --- a/tests/basic/gfapi/gfapi-trunc.c +++ b/tests/basic/gfapi/gfapi-trunc.c @@ -5,86 +5,85 @@ #include <glusterfs/api/glfs.h> #include <glusterfs/api/glfs-handles.h> -#define VALIDATE_AND_GOTO_LABEL_ON_ERROR(func, ret, label) do { \ - if (ret < 0) { \ - fprintf (stderr, "%s : returned error %d (%s)\n", \ - func, ret, strerror (errno)); \ - goto label; \ - } \ - } while (0) - -#define WRITE_SIZE 4096 -#define TRUNC_SIZE 1234 +#define VALIDATE_AND_GOTO_LABEL_ON_ERROR(func, ret, label) \ + do { \ + if (ret < 0) { \ + fprintf(stderr, "%s : returned error %d (%s)\n", func, ret, \ + strerror(errno)); \ + goto label; \ + } \ + } while (0) + +#define WRITE_SIZE 4096 +#define TRUNC_SIZE 1234 /* Make sure TRUNC_SIZE is smaller than WRITE_SIZE at compile time. */ -typedef char _size_check[WRITE_SIZE-TRUNC_SIZE]; +typedef char _size_check[WRITE_SIZE - TRUNC_SIZE]; int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - int ret = -1; - int flags = O_RDWR|O_SYNC; - glfs_t *fs = NULL; - glfs_fd_t *fd1 = NULL; - char *volname = NULL; - char *logfile = NULL; - const char *filename = "file_tmp"; - const char buff[WRITE_SIZE]; - struct stat sb; - - if (argc != 3) { - fprintf (stderr, "Invalid argument\n"); - return 1; - } - - volname = argv[1]; - logfile = argv[2]; - - fs = glfs_new (volname); - if (!fs) - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_new", ret, out); - - ret = glfs_set_volfile_server (fs, "tcp", "localhost", 24007); - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_set_volfile_server", ret, out); - - ret = glfs_set_logging (fs, logfile, 7); - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_set_logging", ret, out); - - ret = glfs_init (fs); - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_init", ret, out); - - fd1 = glfs_creat(fs, filename, flags, 0644); - if (fd1 == NULL) { - ret = -1; - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_creat", ret, out); - } - - ret = glfs_write (fd1, buff, WRITE_SIZE, flags); - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_write", ret, out); - - ret = glfs_truncate (fs, filename, TRUNC_SIZE); - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_truncate", ret, out); - - ret = glfs_fstat (fd1, &sb); - VALIDATE_AND_GOTO_LABEL_ON_ERROR ("glfs_fstat", ret, out); - - if (sb.st_size != TRUNC_SIZE) { - fprintf (stderr, "wrong size %jd should be %jd\n", - (intmax_t)sb.st_size, (intmax_t)2048); - ret = -1; - } + int ret = -1; + int flags = O_RDWR | O_SYNC; + glfs_t *fs = NULL; + glfs_fd_t *fd1 = NULL; + char *volname = NULL; + char *logfile = NULL; + const char *filename = "file_tmp"; + const char buff[WRITE_SIZE]; + struct stat sb; + + if (argc != 3) { + fprintf(stderr, "Invalid argument\n"); + return 1; + } + + volname = argv[1]; + logfile = argv[2]; + + fs = glfs_new(volname); + if (!fs) + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_new", ret, out); + + ret = glfs_set_volfile_server(fs, "tcp", "localhost", 24007); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_volfile_server", ret, out); + + ret = glfs_set_logging(fs, logfile, 7); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_logging", ret, out); + + ret = glfs_init(fs); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_init", ret, out); + + fd1 = glfs_creat(fs, filename, flags, 0644); + if (fd1 == NULL) { + ret = -1; + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_creat", ret, out); + } + + ret = glfs_write(fd1, buff, WRITE_SIZE, flags); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_write", ret, out); + + ret = glfs_truncate(fs, filename, TRUNC_SIZE); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_truncate", ret, out); + + ret = glfs_fstat(fd1, &sb); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_fstat", ret, out); + + if (sb.st_size != TRUNC_SIZE) { + fprintf(stderr, "wrong size %jd should be %jd\n", (intmax_t)sb.st_size, + (intmax_t)2048); + ret = -1; + } out: - if (fd1 != NULL) - glfs_close(fd1); - if (fs) { - /* - * If this fails (as it does on Special Snowflake NetBSD for no - * good reason), it shouldn't affect the result of the test. - */ - (void) glfs_fini(fs); - } - - return ret; + if (fd1 != NULL) + glfs_close(fd1); + if (fs) { + /* + * If this fails (as it does on Special Snowflake NetBSD for no + * good reason), it shouldn't affect the result of the test. + */ + (void)glfs_fini(fs); + } + + return ret; } - - diff --git a/tests/basic/gfapi/gfapi-trunc.sh b/tests/basic/gfapi/gfapi-trunc.sh deleted file mode 100755 index ce604f4d098..00000000000 --- a/tests/basic/gfapi/gfapi-trunc.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc - -TEST glusterd - -TEST $CLI volume create $V0 localhost:$B0/brick1; -EXPECT 'Created' volinfo_field $V0 'Status'; - -TEST $CLI volume start $V0; -EXPECT 'Started' volinfo_field $V0 'Status'; - -logdir=`gluster --print-logdir` - -# Special Snowflake NetBSD isn't set up to run tests that involve building -# executables. Until that's fixed somewhere else, patch things up here. -if [ x"$OSTYPE" = x"NetBSD" ]; then - mkdir -p $logdir - extra_cflags="-I/build/install/include -L/build/install/lib" -fi - -build_tester $(dirname $0)/gfapi-trunc.c -lgfapi -o $(dirname $0)/gfapi-trunc - -TEST ./$(dirname $0)/gfapi-trunc $V0 $logdir/gfapi-trunc.log - -cleanup_tester $(dirname $0)/gfapi-trunc - -cleanup; diff --git a/tests/basic/gfapi/gfapi-trunc.t b/tests/basic/gfapi/gfapi-trunc.t new file mode 100644 index 00000000000..4943a6be898 --- /dev/null +++ b/tests/basic/gfapi/gfapi-trunc.t @@ -0,0 +1,22 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +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'; + +logdir=`gluster --print-logdir` + +build_tester $(dirname $0)/gfapi-trunc.c -lgfapi + +TEST ./$(dirname $0)/gfapi-trunc $V0 $logdir/gfapi-trunc.log + +cleanup_tester $(dirname $0)/gfapi-trunc + +cleanup; diff --git a/tests/basic/gfapi/glfd-lkowner.c b/tests/basic/gfapi/glfd-lkowner.c new file mode 100644 index 00000000000..ec0429dc3c4 --- /dev/null +++ b/tests/basic/gfapi/glfd-lkowner.c @@ -0,0 +1,214 @@ +#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> +#include <sys/wait.h> +#include <stdbool.h> + +int gfapi = 1; + +#define LOG_ERR(func, ret) \ + do { \ + if (ret != 0) { \ + fprintf(stderr, "%s : returned error %d (%s)\n", func, ret, \ + strerror(errno)); \ + goto out; \ + } else { \ + fprintf(stderr, "%s : returned %d\n", func, ret); \ + } \ + } while (0) + +char lownera[8] = "lownera", lownerb[8] = "lownerb"; +char lownerc[8] = "lownerc"; + +int +lock_test(glfs_fd_t *glfd1, glfs_fd_t *glfd2, bool should_fail, int l1_start, + int l1_len, char *l1_owner, int lo1_len, int l2_start, int l2_len, + char *l2_owner, int lo2_len) +{ + int ret = -1, f_ret = -1; + struct flock lock1 = + { + 0, + }, + lock2 = { + 0, + }; + +lock1: + if (!glfd1) + goto lock2; + + /* lock on glfd1 */ + lock1.l_type = F_WRLCK; + lock1.l_whence = SEEK_SET; + lock1.l_start = l1_start; + lock1.l_len = l1_len; + + ret = glfs_fd_set_lkowner(glfd1, l1_owner, lo1_len); + LOG_ERR("glfs_fd_set_lkowner on glfd1", ret); + + ret = glfs_posix_lock(glfd1, F_SETLK, &lock1); + LOG_ERR("glfs_posix_lock on glfd1", ret); + +lock2: + if (!glfd2) + goto out; + + /* lock on glfd2 */ + lock2.l_type = F_WRLCK; + lock2.l_whence = SEEK_SET; + lock2.l_start = l2_start; + lock2.l_len = l2_len; + + ret = glfs_fd_set_lkowner(glfd2, l2_owner, lo2_len); + LOG_ERR("glfs_fd_set_lkowner on glfd2", ret); + + ret = glfs_posix_lock(glfd2, F_SETLK, &lock2); + + if (should_fail && ret) { + f_ret = 0; + } else if (!ret && !should_fail) { + f_ret = 0; + } else { + f_ret = -1; + } +out: + fprintf(stderr, + "Lock test on glfd1 (start(%d), len(%d)," + " lk_owner(%s)) and glfd2 (start(%d), len(%d), " + "lk_owner(%s)) - expected(%s) - result(%s)\n", + l1_start, l1_len, l1_owner, l2_start, l2_len, l2_owner, + (should_fail ? "FAIL" : "SUCCESS"), (ret ? "FAIL" : "SUCCESS")); + return f_ret; +} + +int +main(int argc, char *argv[]) +{ + glfs_t *fs = NULL; + int ret = 0, i, status = 0; + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + glfs_fd_t *fd3 = NULL; + char *filename = "file_tmp"; + char *volname = NULL; + char *logfile = NULL; + char *hostname = NULL; + + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + fs = glfs_new(volname); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + return -1; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + LOG_ERR("glfs_set_volfile_server", ret); + + ret = glfs_set_logging(fs, logfile, 7); + LOG_ERR("glfs_set_logging", ret); + + ret = glfs_init(fs); + LOG_ERR("glfs_init", ret); + + fd1 = glfs_creat(fs, filename, O_RDWR | O_SYNC, 0644); + if (fd1 <= 0) { + ret = -1; + LOG_ERR("glfs_creat", ret); + } + fprintf(stderr, "glfs-create fd1 - %d\n", fd1); + + fd2 = glfs_dup(fd1); + fprintf(stderr, "glfs-dup fd2 - %d\n", fd2); + + fd3 = glfs_open(fs, filename, O_RDWR | O_SYNC); + if (fd2 <= 0) { + ret = -1; + LOG_ERR("glfs_open", ret); + } + fprintf(stderr, "glfs-open fd3 - %d\n", fd3); + + /* TEST 1: Conflicting ranges, same lk_owner + * lock1 (0, 10, lownera) + * lock2 (5, 10, lownera) + * Expected: should not fail but get merged + */ + ret = lock_test(fd1, fd2, false, 0, 10, lownera, 8, 5, 10, lownera, 8); + LOG_ERR("==== glfs_lock_test_1", ret); + + /* TEST 2: Conflicting ranges, different lk_owner + * lock1 (0, 10, lownera) - already taken + * lock2 (5, 10, lownerb) + * Expected: should fail and not get merged + */ + ret = lock_test(NULL, fd2, true, 0, 10, lownera, 8, 5, 10, lownerb, 8); + LOG_ERR("==== glfs_lock_test_2", ret); + + /* TEST 3: Different ranges, same lk_owner + * lock1 (0, 10, lownera) - already taken + * lock2 (30, 10, lownera) + * Expected: should not fail + */ + ret = lock_test(NULL, fd2, false, 0, 10, lownera, 8, 30, 10, lownera, 8); + LOG_ERR("==== glfs_lock_test_3", ret); + + /* TEST 4: Conflicting ranges, different lk_owner + * lock1 (0, 10, lownera) - already taken + * lock2 (50, 10, lownerb) + * Expected: should not fail + */ + ret = lock_test(NULL, fd2, false, 0, 10, lownera, 8, 50, 10, lownerb, 8); + LOG_ERR("==== glfs_lock_test_4", ret); + + /* TEST 5: Close fd1 & retry TEST2 + * lock1 (not applicable) + * lock2 (5, 10, lownerb) + * Expected: should succeed now + */ + ret = glfs_close(fd1); + LOG_ERR("glfs_close", ret); + + ret = lock_test(NULL, fd2, false, 0, 10, lownera, 8, 5, 10, lownerb, 8); + LOG_ERR("==== glfs_lock_test_5", ret); + + /* TEST 6: Check closing fd1 doesn't flush fd2 locks + * retry TEST 4 but with fd2 and fd3. + * lock1 (50, 10, lownerb) - already taken + * lock2 (55, 10, lownerc) + * Expected: should fail + */ + ret = lock_test(NULL, fd3, true, 50, 10, lownerb, 8, 55, 10, lownerc, 8); + LOG_ERR("==== glfs_lock_test_6", ret); + +err: + ret = glfs_close(fd2); + LOG_ERR("glfs_close", ret); + + ret = glfs_close(fd3); + LOG_ERR("glfs_close", ret); + +out: + if (fs) { + ret = glfs_fini(fs); + fprintf(stderr, "glfs_fini(fs) returned %d\n", ret); + } + + if (ret) + exit(1); + exit(0); +} diff --git a/tests/basic/gfapi/glfd-lkowner.t b/tests/basic/gfapi/glfd-lkowner.t new file mode 100755 index 00000000000..ad7b0260a14 --- /dev/null +++ b/tests/basic/gfapi/glfd-lkowner.t @@ -0,0 +1,27 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +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'; + +logdir=`gluster --print-logdir` + +TEST build_tester $(dirname $0)/glfd-lkowner.c -lgfapi + +TEST ./$(dirname $0)/glfd-lkowner $H0 $V0 $logdir/glfd-lkowner.log + +cleanup_tester $(dirname $0)/glfd-lkowner + +TEST $CLI volume stop $V0 +TEST $CLI volume delete $V0 + +cleanup; diff --git a/tests/basic/gfapi/glfs-copy-file-range.c b/tests/basic/gfapi/glfs-copy-file-range.c new file mode 100644 index 00000000000..1c5fd81fc87 --- /dev/null +++ b/tests/basic/gfapi/glfs-copy-file-range.c @@ -0,0 +1,180 @@ +/* + Copyright (c) 2018 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 <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> +#include <string.h> +#include <time.h> +#include <libgen.h> + +static void +cleanup(glfs_t *fs) +{ + if (!fs) + return; +#if 0 + /* glfs fini path is still racy and crashing the program. Since + * this program any way has to die, we are not going to call fini + * in the released versions. i.e. final builds. For all + * internal testing lets enable this so that glfs_fini code + * path becomes stable. */ + glfs_fini (fs); +#endif +} + +int +main(int argc, char **argv) +{ + glfs_t *fs = NULL; + int ret = -1; + char *volname = NULL; + char *logfilepath = NULL; + char *path_src = NULL; + char *path_dst = NULL; + glfs_fd_t *glfd_in = NULL; + glfs_fd_t *glfd_out = NULL; + char *volfile_server = NULL; + + struct stat stbuf = { + 0, + }; + struct glfs_stat stat_src = { + 0, + }; + struct glfs_stat prestat_dst = { + 0, + }; + struct glfs_stat poststat_dst = { + 0, + }; + size_t len; + + if (argc < 6) { + printf("%s <volume> <log file path> <source> <destination>", argv[0]); + ret = -1; + goto out; + } + + volfile_server = argv[1]; + volname = argv[2]; + logfilepath = argv[3]; + path_src = argv[4]; + path_dst = argv[5]; + + if (path_src[0] != '/') { + fprintf(stderr, "source path %s is not absolute", path_src); + errno = EINVAL; + goto out; + } + + if (path_dst[0] != '/') { + fprintf(stderr, "destination path %s is not absolute", path_dst); + errno = EINVAL; + goto out; + } + + fs = glfs_new(volname); + if (!fs) { + ret = -errno; + fprintf(stderr, "Not able to initialize volume '%s'", volname); + goto out; + } + + ret = glfs_set_volfile_server(fs, "tcp", volfile_server, 24007); + if (ret < 0) { + ret = -errno; + fprintf(stderr, + "Failed to set the volfile server, " + "%s", + strerror(errno)); + goto out; + } + + ret = glfs_set_logging(fs, logfilepath, 7); + if (ret < 0) { + ret = -errno; + fprintf(stderr, + "Failed to set the log file path, " + "%s", + strerror(errno)); + goto out; + } + + ret = glfs_init(fs); + if (ret < 0) { + ret = -errno; + if (errno == ENOENT) { + fprintf(stderr, "Volume %s does not exist", volname); + } else { + fprintf(stderr, + "%s: Not able to fetch " + "volfile from glusterd", + volname); + } + goto out; + } + + glfd_in = glfs_open(fs, path_src, O_RDONLY | O_NONBLOCK); + if (!glfd_in) { + ret = -errno; + goto out; + } else { + printf("OPEN_SRC: opening %s is success\n", path_src); + } + + glfd_out = glfs_creat(fs, path_dst, O_RDWR, 0644); + if (!glfd_out) { + fprintf(stderr, + "FAILED_DST_OPEN: failed to " + "open (create) %s (%s)\n", + path_dst, strerror(errno)); + ret = -errno; + goto out; + } else { + printf("OPEN_DST: opening %s is success\n", path_dst); + } + + ret = glfs_fstat(glfd_in, &stbuf); + if (ret < 0) { + ret = -errno; + goto out; + } else { + printf("FSTAT_SRC: fstat on %s is success\n", path_dst); + } + + len = stbuf.st_size; + + do { + ret = glfs_copy_file_range(glfd_in, NULL, glfd_out, NULL, len, 0, + &stat_src, &prestat_dst, &poststat_dst); + if (ret == -1) { + fprintf(stderr, "copy_file_range failed with %s\n", + strerror(errno)); + ret = -errno; + break; + } else { + printf("copy_file_range successful\n"); + len -= ret; + } + } while (len > 0); + +out: + if (glfd_in) + glfs_close(glfd_in); + if (glfd_out) + glfs_close(glfd_out); + + cleanup(fs); + + return ret; +} diff --git a/tests/basic/gfapi/glfs_h_creat_open.c b/tests/basic/gfapi/glfs_h_creat_open.c new file mode 100644 index 00000000000..7672561e73f --- /dev/null +++ b/tests/basic/gfapi/glfs_h_creat_open.c @@ -0,0 +1,118 @@ +#include <fcntl.h> +#include <unistd.h> +#include <time.h> +#include <limits.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> + +#define LOG_ERR(func, ret) \ + do { \ + if (ret != 0) { \ + fprintf(stderr, "%s : returned error ret(%d), errno(%d)\n", func, \ + ret, errno); \ + exit(1); \ + } else { \ + fprintf(stderr, "%s : returned %d\n", func, ret); \ + } \ + } while (0) +#define LOG_IF_NO_ERR(func, ret) \ + do { \ + if (ret == 0) { \ + fprintf(stderr, "%s : hasn't returned error %d\n", func, ret); \ + exit(1); \ + } else { \ + fprintf(stderr, "%s : returned %d\n", func, ret); \ + } \ + } while (0) +int +main(int argc, char *argv[]) +{ + glfs_t *fs = NULL; + int ret = 0; + struct glfs_object *root = NULL, *leaf = NULL; + glfs_fd_t *fd = NULL; + char *filename = "/ro-file"; + struct stat sb = { + 0, + }; + char *logfile = NULL; + char *volname = NULL; + char *hostname = NULL; + char buf[32] = "abcdefghijklmnopqrstuvwxyz012345"; + + fprintf(stderr, "Starting glfs_h_creat_open\n"); + + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + fs = glfs_new(volname); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + return 1; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + LOG_ERR("glfs_set_volfile_server", ret); + + ret = glfs_set_logging(fs, logfile, 7); + LOG_ERR("glfs_set_logging", ret); + + ret = glfs_init(fs); + LOG_ERR("glfs_init", ret); + + sleep(2); + root = glfs_h_lookupat(fs, NULL, "/", &sb, 0); + if (!root) { + ret = -1; + LOG_ERR("glfs_h_lookupat root", ret); + } + leaf = glfs_h_lookupat(fs, root, filename, &sb, 0); + if (!leaf) { + ret = -1; + LOG_IF_NO_ERR("glfs_h_lookupat leaf", ret); + } + + leaf = glfs_h_creat_open(fs, root, filename, O_RDONLY, 00444, &sb, &fd); + if (!leaf || !fd) { + ret = -1; + LOG_ERR("glfs_h_creat leaf", ret); + } + fprintf(stderr, "glfs_h_create_open leaf - %p\n", leaf); + + ret = glfs_write(fd, buf, 32, 0); + if (ret < 0) { + fprintf(stderr, "glfs_write: error writing to file %s, %s\n", filename, + strerror(errno)); + goto out; + } + + ret = glfs_h_getattrs(fs, leaf, &sb); + LOG_ERR("glfs_h_getattrs", ret); + + if (sb.st_size != 32) { + fprintf(stderr, "glfs_write: post size mismatch\n"); + goto out; + } + + fprintf(stderr, "Successfully opened and written to a read-only file \n"); +out: + if (fd) + glfs_close(fd); + + ret = glfs_fini(fs); + LOG_ERR("glfs_fini", ret); + + fprintf(stderr, "End of libgfapi_fini\n"); + + exit(0); +} diff --git a/tests/basic/gfapi/glfs_h_creat_open.t b/tests/basic/gfapi/glfs_h_creat_open.t new file mode 100755 index 00000000000..f24ae7395be --- /dev/null +++ b/tests/basic/gfapi/glfs_h_creat_open.t @@ -0,0 +1,27 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +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'; + +logdir=`gluster --print-logdir` + +TEST build_tester $(dirname $0)/glfs_h_creat_open.c -lgfapi + +TEST ./$(dirname $0)/glfs_h_creat_open $H0 $V0 $logdir/glfs.log + +cleanup_tester $(dirname $0)/glfs_h_creat_open + +TEST $CLI volume stop $V0 +TEST $CLI volume delete $V0 + +cleanup; diff --git a/tests/basic/gfapi/glfs_sysrq.c b/tests/basic/gfapi/glfs_sysrq.c new file mode 100644 index 00000000000..13e06be6df2 --- /dev/null +++ b/tests/basic/gfapi/glfs_sysrq.c @@ -0,0 +1,60 @@ +/** glfs_sysrq.c + * + * Simple test application to run all glfs_syqrq() debugging calls. + * + * Usage: ./glfs_sysrq <host> <volume> <logfile> + */ +#include <errno.h> +#include <stdio.h> + +#include <glusterfs/api/glfs.h> + +int +main(int argc, char *argv[]) +{ + /* cmdline arguments */ + char *host = NULL; + char *volume = NULL; + char *logfile = NULL; + + /* other variables */ + glfs_t *fs = NULL; + int ret = 0; + + if (argc != 4) { + fprintf(stderr, "Usage: %s <host> <volume> <logfile>\n", argv[0]); + return -1; + } + + host = argv[1]; + volume = argv[2]; + logfile = argv[3]; + + fs = glfs_new(volume); + if (!fs) { + return -1; + } + + ret = glfs_set_logging(fs, logfile, 7); + if (ret < 0) { + return -1; + } + + ret = glfs_set_volfile_server(fs, "tcp", host, 24007); + if (ret < 0) { + return -1; + } + + ret = glfs_init(fs); + if (ret < 0) { + return -1; + } + + /* checking of the results is easier in the script running this test */ + glfs_sysrq(fs, GLFS_SYSRQ_HELP); + glfs_sysrq(fs, GLFS_SYSRQ_STATEDUMP); + + glfs_fini(fs); + + return 0; +} diff --git a/tests/basic/gfapi/glfs_sysrq.t b/tests/basic/gfapi/glfs_sysrq.t new file mode 100755 index 00000000000..d1a0e9bc248 --- /dev/null +++ b/tests/basic/gfapi/glfs_sysrq.t @@ -0,0 +1,39 @@ +#!/bin/bash +# +# Run glfs_sysrq, a gfapi applications calling all glfs_sysrq() commands. +# Each command generates a specific log message, or something else that can be +# tested for existance. +# + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup + +TEST glusterd +TEST pidof 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' + +logdir=$(gluster --print-logdir) + +# clear all statedumps +cleanup_statedump +TEST ! test -e $statedumpdir/*.dump.* +# vim friendly command */ + +build_tester $(dirname $0)/glfs_sysrq.c -lgfapi +TEST $(dirname $0)/glfs_sysrq $H0 $V0 $logdir/glfs_sysrq.log + +# check for the help message in the log +TEST grep -q '"(H)elp"' $logdir/glfs_sysrq.log + +# see if there is a statedump +TEST test -e $statedumpdir/*.dump.* +# vim friendly command */ + +cleanup_tester $(dirname $0)/glfs_sysrq +cleanup diff --git a/tests/basic/gfapi/glfs_xreaddirplus_r.c b/tests/basic/gfapi/glfs_xreaddirplus_r.c new file mode 100644 index 00000000000..0c4c79123eb --- /dev/null +++ b/tests/basic/gfapi/glfs_xreaddirplus_r.c @@ -0,0 +1,242 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> +#include <time.h> + +#define VALIDATE_AND_GOTO_LABEL_ON_ERROR(func, ret, label) \ + do { \ + if (ret < 0) { \ + fprintf(stderr, "%s : returned error %d (%s)\n", func, ret, \ + strerror(errno)); \ + goto label; \ + } \ + } while (0) + +#define VALIDATE_BOOL_AND_GOTO_LABEL_ON_ERROR(func, bool_var, ret, label) \ + do { \ + if (!bool_var) { \ + fprintf(stderr, "%s : returned error (%s)\n", func, \ + strerror(errno)); \ + ret = -1; \ + goto label; \ + } \ + } while (0) + +#define MAX_FILES_CREATE 10 +#define MAXPATHNAME 512 + +void +assimilatetime(struct timespec *ts, struct timespec ts_st, + struct timespec ts_ed) +{ + if ((ts_ed.tv_nsec - ts_st.tv_nsec) < 0) { + ts->tv_sec += ts_ed.tv_sec - ts_st.tv_sec - 1; + ts->tv_nsec += 1000000000 + ts_ed.tv_nsec - ts_st.tv_nsec; + } else { + ts->tv_sec += ts_ed.tv_sec - ts_st.tv_sec; + ts->tv_nsec += ts_ed.tv_nsec - ts_st.tv_nsec; + } + + if (ts->tv_nsec > 1000000000) { + ts->tv_nsec = ts->tv_nsec - 1000000000; + ts->tv_sec += 1; + } + + return; +} + +/* + * Returns '%' difference between ts1 & ts2 + */ +int +comparetime(struct timespec ts1, struct timespec ts2) +{ + uint64_t ts1_n, ts2_n; + int pct = 0; + + ts1_n = (ts1.tv_sec * 1000000000) + ts1.tv_nsec; + ts2_n = (ts2.tv_sec * 1000000000) + ts2.tv_nsec; + + pct = ((ts1_n - ts2_n) * 100) / ts1_n; + + return pct; +} + +int +old_readdir(glfs_t *fs) +{ + struct glfs_object *root = NULL; + struct glfs_fd *fd = NULL; + struct stat *sb = NULL; + char buf[512]; + struct dirent *entry = NULL; + int ret = -1; + struct glfs_object *glhandle = NULL; + + if (!fs) + return -1; + + root = glfs_h_lookupat(fs, NULL, "/", sb, 0); + VALIDATE_BOOL_AND_GOTO_LABEL_ON_ERROR("glfs_h_lookupat", !!root, ret, out); + + fd = glfs_opendir(fs, "/"); + VALIDATE_BOOL_AND_GOTO_LABEL_ON_ERROR("glfs_opendir", !!fd, ret, out); + + while (glfs_readdir_r(fd, (struct dirent *)buf, &entry), entry) { + if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) { + glhandle = glfs_h_lookupat(fs, root, "/", sb, 0); + VALIDATE_BOOL_AND_GOTO_LABEL_ON_ERROR("glfs_h_lookupat", !!glhandle, + ret, out); + } + } + + glfs_closedir(fd); + + ret = 0; +out: + return ret; +} + +int +new_xreaddirplus(glfs_t *fs) +{ + struct glfs_fd *fd = NULL; + struct stat *sb = NULL; + int ret = -1; + uint32_t rflags = (GFAPI_XREADDIRP_STAT | GFAPI_XREADDIRP_HANDLE); + struct glfs_xreaddirp_stat *xstat = NULL; + struct dirent de; + struct dirent *pde = NULL; + struct glfs_object *glhandle = NULL; + + if (!fs) + return -1; + + fd = glfs_opendir(fs, "/"); + VALIDATE_BOOL_AND_GOTO_LABEL_ON_ERROR("glfs_opendir", !!fd, ret, out); + + ret = glfs_xreaddirplus_r(fd, rflags, &xstat, &de, &pde); + while (ret > 0 && pde != NULL) { + if (xstat) { + sb = glfs_xreaddirplus_get_stat(xstat); + VALIDATE_BOOL_AND_GOTO_LABEL_ON_ERROR("glfs_xreaddirplus_get_stat", + !!sb, ret, out); + + if (strcmp(de.d_name, ".") && strcmp(de.d_name, "..")) { + glhandle = glfs_xreaddirplus_get_object(xstat); + VALIDATE_BOOL_AND_GOTO_LABEL_ON_ERROR( + "glfs_xreaddirplus_get_object", !!glhandle, ret, out); + } + } + + if (xstat) { + glfs_free(xstat); + xstat = NULL; + } + + ret = glfs_xreaddirplus_r(fd, rflags, &xstat, &de, &pde); + + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_xreaddirp_r", ret, out); + } + + if (xstat) + glfs_free(xstat); + + ret = 0; +out: + return ret; +} + +int +main(int argc, char *argv[]) +{ + int ret = -1; + glfs_t *fs = NULL; + char *volname = NULL; + char *logfile = NULL; + char *hostname = NULL; + char *my_file = "file_"; + char my_file_name[MAXPATHNAME]; + uint32_t flags = O_RDWR | O_SYNC; + struct glfs_fd *fd = NULL; + int i = 0; + int pct = 0; + struct timespec timestamp = {0, 0}, st_timestamp, ed_timestamp; + struct timespec otimestamp = {0, 0}, ost_timestamp, oed_timestamp; + + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + return 1; + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + fs = glfs_new(volname); + VALIDATE_BOOL_AND_GOTO_LABEL_ON_ERROR("glfs_new", !!fs, ret, out); + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_volfile_server", ret, out); + + ret = glfs_set_logging(fs, logfile, 7); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_logging", ret, out); + + ret = glfs_init(fs); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_init", ret, out); + + for (i = 0; i < MAX_FILES_CREATE; i++) { + sprintf(my_file_name, "%s%d", my_file, i); + + fd = glfs_creat(fs, my_file_name, flags, 0644); + VALIDATE_BOOL_AND_GOTO_LABEL_ON_ERROR("glfs_creat", !!fd, ret, out); + + glfs_close(fd); + } + + /* measure performance using old readdir call and new xreaddirplus call and + * compare */ + ret = clock_gettime(CLOCK_REALTIME, &ost_timestamp); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("clock_gettime", ret, out); + + ret = old_readdir(fs); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("old_readdir", ret, out); + + ret = clock_gettime(CLOCK_REALTIME, &oed_timestamp); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("clock_gettime", ret, out); + + assimilatetime(&otimestamp, ost_timestamp, oed_timestamp); + + printf("\tOverall time using readdir:\n\t\tSecs:%ld\n\t\tnSecs:%ld\n", + otimestamp.tv_sec, otimestamp.tv_nsec); + + ret = clock_gettime(CLOCK_REALTIME, &st_timestamp); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("clock_gettime", ret, out); + + ret = new_xreaddirplus(fs); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("new_xreaddirplus", ret, out); + + ret = clock_gettime(CLOCK_REALTIME, &ed_timestamp); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("clock_gettime", ret, out); + + assimilatetime(×tamp, st_timestamp, ed_timestamp); + + printf("\tOverall time using xreaddirplus:\n\t\tSecs:%ld\n\t\tnSecs:%ld\n", + timestamp.tv_sec, timestamp.tv_nsec); + + pct = comparetime(otimestamp, timestamp); + printf("There is improvement by %d%%\n", pct); + + ret = 0; +out: + if (fs) { + ret = glfs_fini(fs); + if (ret) + fprintf(stderr, "glfs_fini(fs) returned %d\n", ret); + } + + return ret; +} diff --git a/tests/basic/gfapi/glfs_xreaddirplus_r.t b/tests/basic/gfapi/glfs_xreaddirplus_r.t new file mode 100755 index 00000000000..d21a00c66f2 --- /dev/null +++ b/tests/basic/gfapi/glfs_xreaddirplus_r.t @@ -0,0 +1,28 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +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'; + +logdir=`gluster --print-logdir` + +TEST build_tester $(dirname $0)/glfs_xreaddirplus_r.c -lgfapi + +TEST $(dirname $0)/glfs_xreaddirplus_r $H0 $V0 $logdir/glfs_xreaddirplus_r.log + +cleanup_tester $(dirname $0)/glfs_xreaddirplus_r + +TEST $CLI volume stop $V0 +TEST $CLI volume delete $V0 + +cleanup; +#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=000000 diff --git a/tests/basic/gfapi/glfsxmp-coverage.c b/tests/basic/gfapi/glfsxmp-coverage.c new file mode 100644 index 00000000000..51650023efd --- /dev/null +++ b/tests/basic/gfapi/glfsxmp-coverage.c @@ -0,0 +1,1900 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> +#include <string.h> +#include <time.h> + +#define TEST_STR_LEN 2048 + +int +test_dirops(glfs_t *fs) +{ + glfs_fd_t *fd = NULL; + char buf[2048]; + struct dirent *entry = NULL; + + fd = glfs_opendir(fs, "/"); + if (!fd) { + fprintf(stderr, "/: %s\n", strerror(errno)); + return -1; + } + + fprintf(stderr, "Entries:\n"); + while (glfs_readdir_r(fd, (struct dirent *)buf, &entry), entry) { + fprintf(stderr, "%s: %lu\n", entry->d_name, glfs_telldir(fd)); + } + + /* Should internally call fsyncdir(), hopefully */ + glfs_fsync(fd, NULL, NULL); + + glfs_closedir(fd); + return 0; +} + +int +test_xattr(glfs_t *fs) +{ + char *filename = "/filename2"; + char *linkfile = "/linkfile"; + glfs_fd_t *fd = NULL; + char buf[512]; + char *ptr; + int ret; + + ret = glfs_setxattr(fs, filename, "user.testkey", "testval", 8, 0); + fprintf(stderr, "setxattr(%s): %d (%s)\n", filename, ret, strerror(errno)); + + ret = glfs_setxattr(fs, filename, "user.testkey2", "testval", 8, 0); + fprintf(stderr, "setxattr(%s): %d (%s)\n", filename, ret, strerror(errno)); + + ret = glfs_getxattr(fs, filename, "user.testkey", buf, 512); + fprintf(stderr, "getxattr(%s): %d (%s)\n", filename, ret, strerror(errno)); + if (ret < 0) + return -1; + + ret = glfs_listxattr(fs, filename, buf, 512); + fprintf(stderr, "listxattr(%s): %d (%s)\n", filename, ret, strerror(errno)); + if (ret < 0) + return -1; + + ret = glfs_symlink(fs, "filename", linkfile); + fprintf(stderr, "symlink(%s %s): %s\n", filename, linkfile, + strerror(errno)); + if (ret < 0) + return -1; + + ret = glfs_readlink(fs, linkfile, buf, 512); + fprintf(stderr, "readlink(%s) : %d (%s)\n", filename, ret, strerror(errno)); + if (ret < 0) + return -1; + + ret = glfs_lsetxattr(fs, filename, "user.testkey3", "testval", 8, 0); + fprintf(stderr, "lsetxattr(%s) : %d (%s)\n", linkfile, ret, + strerror(errno)); + if (ret < 0) + return -1; + + ret = glfs_llistxattr(fs, linkfile, buf, 512); + fprintf(stderr, "llistxattr(%s): %d (%s)\n", filename, ret, + strerror(errno)); + if (ret < 0) + return -1; + + ret = glfs_lgetxattr(fs, filename, "user.testkey3", buf, 512); + fprintf(stderr, "lgetxattr(%s): %d (%s)\n", linkfile, ret, strerror(errno)); + if (ret < 0) + return -1; + + for (ptr = buf; ptr < buf + ret; ptr++) { + printf("key=%s\n", ptr); + ptr += strlen(ptr); + } + + ret = glfs_removexattr(fs, filename, "user.testkey2"); + fprintf(stderr, "removexattr(%s): %d (%s)\n", filename, ret, + strerror(errno)); + + fd = glfs_open(fs, filename, O_RDWR); + fprintf(stderr, "open(%s): (%p) %s\n", filename, fd, strerror(errno)); + + ret = glfs_fsetxattr(fd, "user.testkey2", "testval", 8, 0); + fprintf(stderr, "fsetxattr(%s): %d (%s)\n", filename, ret, strerror(errno)); + + ret = glfs_fgetxattr(fd, "user.testkey2", buf, 512); + fprintf(stderr, "fgetxattr(%s): %d (%s)\n", filename, ret, strerror(errno)); + + ret = glfs_flistxattr(fd, buf, 512); + fprintf(stderr, "flistxattr(%s): %d (%s)\n", filename, ret, + strerror(errno)); + if (ret < 0) + return -1; + + for (ptr = buf; ptr < buf + ret; ptr++) { + printf("key=%s\n", ptr); + ptr += strlen(ptr); + } + + ret = glfs_fremovexattr(fd, "user.testkey2"); + fprintf(stderr, "fremovexattr(%s): %d (%s)\n", filename, ret, + strerror(errno)); + + glfs_close(fd); + + return 0; +} + +int +test_chdir(glfs_t *fs) +{ + int ret = -1; + char *dir = "/dir"; + char *topdir = "/topdir"; + char *linkdir = "/linkdir"; + char *linkdir2 = "/linkdir2"; + char *subdir = "./subdir"; + char *respath = NULL; + char pathbuf[4096]; + + ret = glfs_mkdir(fs, topdir, 0755); + fprintf(stderr, "mkdir(%s): %s\n", topdir, strerror(errno)); + if (ret) + return -1; + + ret = glfs_mkdir(fs, dir, 0755); + fprintf(stderr, "mkdir(%s): %s\n", dir, strerror(errno)); + if (ret) + return -1; + + respath = glfs_getcwd(fs, pathbuf, 4096); + fprintf(stdout, "getcwd() = %s\n", respath); + + ret = glfs_symlink(fs, "topdir", linkdir); + if (ret) { + fprintf(stderr, "symlink(%s, %s): %s\n", topdir, linkdir, + strerror(errno)); + return -1; + } + + ret = glfs_chdir(fs, linkdir); + if (ret) { + fprintf(stderr, "chdir(%s): %s\n", linkdir, strerror(errno)); + return -1; + } + + respath = glfs_getcwd(fs, pathbuf, 4096); + fprintf(stdout, "getcwd() = %s\n", respath); + + respath = glfs_realpath(fs, subdir, pathbuf); + if (respath) { + fprintf(stderr, "realpath(%s) worked unexpectedly: %s\n", subdir, + respath); + return -1; + } + + ret = glfs_mkdir(fs, subdir, 0755); + if (ret) { + fprintf(stderr, "mkdir(%s): %s\n", subdir, strerror(errno)); + return -1; + } + + respath = glfs_realpath(fs, subdir, pathbuf); + if (!respath) { + fprintf(stderr, "realpath(%s): %s\n", subdir, strerror(errno)); + } else { + fprintf(stdout, "realpath(%s) = %s\n", subdir, respath); + } + + ret = glfs_chdir(fs, subdir); + if (ret) { + fprintf(stderr, "chdir(%s): %s\n", subdir, strerror(errno)); + return -1; + } + + respath = glfs_getcwd(fs, pathbuf, 4096); + fprintf(stdout, "getcwd() = %s\n", respath); + + respath = glfs_realpath(fs, "/linkdir/subdir", pathbuf); + if (!respath) { + fprintf(stderr, "realpath(/linkdir/subdir): %s\n", strerror(errno)); + } else { + fprintf(stdout, "realpath(/linkdir/subdir) = %s\n", respath); + } + + return 0; +} + +#ifdef DEBUG +static void +peek_stat(struct stat *sb) +{ + printf("Dumping stat information:\n"); + printf("File type: "); + + switch (sb->st_mode & S_IFMT) { + case S_IFBLK: + printf("block device\n"); + break; + case S_IFCHR: + printf("character device\n"); + break; + case S_IFDIR: + printf("directory\n"); + break; + case S_IFIFO: + printf("FIFO/pipe\n"); + break; + case S_IFLNK: + printf("symlink\n"); + break; + case S_IFREG: + printf("regular file\n"); + break; + case S_IFSOCK: + printf("socket\n"); + break; + default: + printf("unknown?\n"); + break; + } + + printf("I-node number: %ld\n", (long)sb->st_ino); + + printf("Mode: %lo (octal)\n", + (unsigned long)sb->st_mode); + + printf("Link count: %ld\n", (long)sb->st_nlink); + printf("Ownership: UID=%ld GID=%ld\n", (long)sb->st_uid, + (long)sb->st_gid); + + printf("Preferred I/O block size: %ld bytes\n", (long)sb->st_blksize); + printf("File size: %lld bytes\n", (long long)sb->st_size); + printf("Blocks allocated: %lld\n", (long long)sb->st_blocks); + + printf("Last status change: %s", ctime(&sb->st_ctime)); + printf("Last file access: %s", ctime(&sb->st_atime)); + printf("Last file modification: %s", ctime(&sb->st_mtime)); + + return; +} + +static void +peek_handle(unsigned char *glid) +{ + int i; + + for (i = 0; i < GFAPI_HANDLE_LENGTH; i++) { + printf(":%02x:", glid[i]); + } + printf("\n"); +} +#else /* DEBUG */ +static void +peek_stat(struct stat *sb) +{ + return; +} + +static void +peek_handle(unsigned char *id) +{ + return; +} +#endif /* DEBUG */ + +glfs_t *fs = NULL; +char *full_parent_name = "/testdir", *parent_name = "testdir"; + +void +test_h_unlink(void) +{ + char *my_dir = "unlinkdir"; + char *my_file = "file.txt"; + char *my_subdir = "dir1"; + struct glfs_object *parent = NULL, *leaf = NULL, *dir = NULL, + *subdir = NULL, *subleaf = NULL; + struct stat sb; + int ret; + + printf("glfs_h_unlink tests: In Progress\n"); + + /* Prepare tests */ + parent = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0); + if (parent == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + full_parent_name, NULL, strerror(errno)); + printf("glfs_h_lookupat tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + dir = glfs_h_mkdir(fs, parent, my_dir, 0755, &sb); + if (dir == NULL) { + fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n", + my_dir, parent, strerror(errno)); + printf("glfs_h_unlink tests: FAILED\n"); + goto out; + } + + leaf = glfs_h_creat(fs, dir, my_file, O_CREAT, 0644, &sb); + if (leaf == NULL) { + fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n", + my_file, dir, strerror(errno)); + printf("glfs_h_unlink tests: FAILED\n"); + goto out; + } + + subdir = glfs_h_mkdir(fs, dir, my_subdir, 0755, &sb); + if (subdir == NULL) { + fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n", + my_subdir, dir, strerror(errno)); + printf("glfs_h_unlink tests: FAILED\n"); + goto out; + } + + subleaf = glfs_h_creat(fs, subdir, my_file, O_CREAT, 0644, &sb); + if (subleaf == NULL) { + fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n", + my_file, subdir, strerror(errno)); + printf("glfs_h_unlink tests: FAILED\n"); + goto out; + } + + /* unlink non empty directory */ + ret = glfs_h_unlink(fs, dir, my_subdir); + if ((ret && errno != ENOTEMPTY) || (ret == 0)) { + fprintf(stderr, + "glfs_h_unlink: error unlinking %s: it is non empty: %s\n", + my_subdir, strerror(errno)); + printf("glfs_h_unlink tests: FAILED\n"); + goto out; + } + + /* unlink regular file */ + ret = glfs_h_unlink(fs, subdir, my_file); + if (ret) { + fprintf(stderr, "glfs_h_unlink: error unlinking %s: from (%p),%s\n", + my_file, subdir, strerror(errno)); + printf("glfs_h_unlink tests: FAILED\n"); + goto out; + } + + /* unlink directory */ + ret = glfs_h_unlink(fs, dir, my_subdir); + if (ret) { + fprintf(stderr, "glfs_h_unlink: error unlinking %s: from (%p),%s\n", + my_subdir, dir, strerror(errno)); + printf("glfs_h_unlink tests: FAILED\n"); + goto out; + } + + /* unlink regular file */ + ret = glfs_h_unlink(fs, dir, my_file); + if (ret) { + fprintf(stderr, "glfs_h_unlink: error unlinking %s: from (%p),%s\n", + my_file, dir, strerror(errno)); + printf("glfs_h_unlink tests: FAILED\n"); + goto out; + } + + /* unlink non-existent regular file */ + ret = glfs_h_unlink(fs, dir, my_file); + if ((ret && errno != ENOENT) || (ret == 0)) { + fprintf(stderr, + "glfs_h_unlink: error unlinking non-existent %s: invalid errno " + ",%d, %s\n", + my_file, ret, strerror(errno)); + printf("glfs_h_unlink tests: FAILED\n"); + goto out; + } + + /* unlink non-existent directory */ + ret = glfs_h_unlink(fs, dir, my_subdir); + if ((ret && errno != ENOENT) || (ret == 0)) { + fprintf(stderr, + "glfs_h_unlink: error unlinking non-existent %s: invalid " + "errno ,%d, %s\n", + my_subdir, ret, strerror(errno)); + printf("glfs_h_unlink tests: FAILED\n"); + goto out; + } + + /* unlink directory */ + ret = glfs_h_unlink(fs, parent, my_dir); + if (ret) { + fprintf(stderr, "glfs_h_unlink: error unlinking %s: from (%p),%s\n", + my_dir, dir, strerror(errno)); + printf("glfs_h_unlink tests: FAILED\n"); + goto out; + } + + printf("glfs_h_unlink tests: PASSED\n"); + +out: + if (dir) + glfs_h_close(dir); + if (leaf) + glfs_h_close(leaf); + if (subdir) + glfs_h_close(subdir); + if (subleaf) + glfs_h_close(subleaf); + if (parent) + glfs_h_close(parent); + + return; +} + +void +test_h_getsetattrs(void) +{ + char *my_dir = "attrdir"; + char *my_file = "attrfile.txt"; + struct glfs_object *parent = NULL, *leaf = NULL, *dir = NULL; + struct stat sb, retsb; + int ret, valid; + struct timespec timestamp; + + printf("glfs_h_getattrs and setattrs tests: In Progress\n"); + + /* Prepare tests */ + parent = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0); + if (parent == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + full_parent_name, NULL, strerror(errno)); + printf("glfs_h_lookupat tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + dir = glfs_h_mkdir(fs, parent, my_dir, 0755, &sb); + if (dir == NULL) { + fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n", + my_dir, parent, strerror(errno)); + printf("glfs_h_unlink tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + leaf = glfs_h_creat(fs, dir, my_file, O_CREAT, 0644, &sb); + if (leaf == NULL) { + fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n", + my_file, dir, strerror(errno)); + printf("glfs_h_unlink tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + ret = glfs_h_getattrs(fs, dir, &retsb); + if (ret != 0) { + fprintf(stderr, "glfs_h_getattrs: error %s: from (%p),%s\n", my_dir, + dir, strerror(errno)); + printf("glfs_h_getattrs and setattrs tests: FAILED\n"); + goto out; + } + peek_stat(&retsb); + /* TODO: Compare stat information */ + + retsb.st_mode = 00666; + retsb.st_uid = 1000; + retsb.st_gid = 1001; + ret = clock_gettime(CLOCK_REALTIME, ×tamp); + if (ret != 0) { + fprintf(stderr, "clock_gettime: error %s\n", strerror(errno)); + printf("glfs_h_getattrs and setattrs tests: FAILED\n"); + goto out; + } + retsb.st_atim = timestamp; + retsb.st_mtim = timestamp; + valid = GFAPI_SET_ATTR_MODE | GFAPI_SET_ATTR_UID | GFAPI_SET_ATTR_GID | + GFAPI_SET_ATTR_ATIME | GFAPI_SET_ATTR_MTIME; + peek_stat(&retsb); + + ret = glfs_h_setattrs(fs, dir, &retsb, valid); + if (ret != 0) { + fprintf(stderr, "glfs_h_setattrs: error %s: from (%p),%s\n", my_dir, + dir, strerror(errno)); + printf("glfs_h_getattrs and setattrs tests: FAILED\n"); + goto out; + } + + memset(&retsb, 0, sizeof(struct stat)); + ret = glfs_h_stat(fs, dir, &retsb); + if (ret != 0) { + fprintf(stderr, "glfs_h_stat: error %s: from (%p),%s\n", my_dir, dir, + strerror(errno)); + printf("glfs_h_getattrs and setattrs tests: FAILED\n"); + goto out; + } + peek_stat(&retsb); + + printf("glfs_h_getattrs and setattrs tests: PASSED\n"); +out: + if (parent) + glfs_h_close(parent); + if (leaf) + glfs_h_close(leaf); + if (dir) + glfs_h_close(dir); + + return; +} + +void +test_h_truncate(void) +{ + char *my_dir = "truncatedir"; + char *my_file = "file.txt"; + struct glfs_object *root = NULL, *parent = NULL, *leaf = NULL; + struct stat sb; + glfs_fd_t *fd = NULL; + char buf[32]; + off_t offset = 0; + int ret = 0; + + printf("glfs_h_truncate tests: In Progress\n"); + + /* Prepare tests */ + root = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0); + if (root == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + full_parent_name, NULL, strerror(errno)); + printf("glfs_h_truncate tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + parent = glfs_h_mkdir(fs, root, my_dir, 0755, &sb); + if (parent == NULL) { + fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n", + my_dir, root, strerror(errno)); + printf("glfs_h_truncate tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + leaf = glfs_h_creat(fs, parent, my_file, O_CREAT, 0644, &sb); + if (leaf == NULL) { + fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n", + my_file, parent, strerror(errno)); + printf("glfs_h_truncate tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + fd = glfs_h_open(fs, leaf, O_RDWR); + if (fd == NULL) { + fprintf(stderr, "glfs_h_open: error on open of %s: %s\n", my_file, + strerror(errno)); + printf("glfs_h_truncate tests: FAILED\n"); + goto out; + } + + memcpy(buf, "abcdefghijklmnopqrstuvwxyz012345", 32); + ret = glfs_write(fd, buf, 32, 0); + + /* run tests */ + /* truncate lower */ + offset = 30; + ret = glfs_h_truncate(fs, leaf, offset); + if (ret != 0) { + fprintf(stderr, "glfs_h_truncate: error creating %s: from (%p),%s\n", + my_file, parent, strerror(errno)); + printf("glfs_h_truncate tests: FAILED\n"); + goto out; + } + ret = glfs_h_getattrs(fs, leaf, &sb); + if (ret != 0) { + fprintf(stderr, "glfs_h_getattrs: error for %s (%p),%s\n", my_file, + leaf, strerror(errno)); + printf("glfs_h_truncate tests: FAILED\n"); + goto out; + } + if (sb.st_size != offset) { + fprintf(stderr, "glfs_h_truncate: post size mismatch\n"); + printf("glfs_h_truncate tests: FAILED\n"); + goto out; + } + + /* truncate higher */ + offset = 32; + ret = glfs_h_truncate(fs, leaf, offset); + if (ret != 0) { + fprintf(stderr, "glfs_h_truncate: error creating %s: from (%p),%s\n", + my_file, parent, strerror(errno)); + printf("glfs_h_truncate tests: FAILED\n"); + goto out; + } + ret = glfs_h_getattrs(fs, leaf, &sb); + if (ret != 0) { + fprintf(stderr, "glfs_h_getattrs: error for %s (%p),%s\n", my_file, + leaf, strerror(errno)); + printf("glfs_h_truncate tests: FAILED\n"); + goto out; + } + if (sb.st_size != offset) { + fprintf(stderr, "glfs_h_truncate: post size mismatch\n"); + printf("glfs_h_truncate tests: FAILED\n"); + goto out; + } + + /* truncate equal */ + offset = 30; + ret = glfs_h_truncate(fs, leaf, offset); + if (ret != 0) { + fprintf(stderr, "glfs_h_truncate: error creating %s: from (%p),%s\n", + my_file, parent, strerror(errno)); + printf("glfs_h_truncate tests: FAILED\n"); + goto out; + } + ret = glfs_h_getattrs(fs, leaf, &sb); + if (ret != 0) { + fprintf(stderr, "glfs_h_getattrs: error for %s (%p),%s\n", my_file, + leaf, strerror(errno)); + printf("glfs_h_truncate tests: FAILED\n"); + goto out; + } + if (sb.st_size != offset) { + fprintf(stderr, "glfs_h_truncate: post size mismatch\n"); + printf("glfs_h_truncate tests: FAILED\n"); + goto out; + } + + printf("glfs_h_truncate tests: PASSED\n"); +out: + if (fd) + glfs_close(fd); + if (root) + glfs_h_close(root); + if (parent) + glfs_h_close(parent); + if (leaf) + glfs_h_close(leaf); + + return; +} + +void +test_h_links(void) +{ + char *my_dir = "linkdir"; + char *my_file = "file.txt"; + char *my_symlnk = "slnk.txt"; + char *my_lnk = "lnk.txt"; + char *linksrc_dir = "dir1"; + char *linktgt_dir = "dir2"; + struct glfs_object *root = NULL, *parent = NULL, *leaf = NULL, + *dirsrc = NULL, *dirtgt = NULL, *dleaf = NULL; + struct glfs_object *ln1 = NULL; + struct stat sb; + int ret; + char *buf = NULL; + + printf("glfs_h_link(s) tests: In Progress\n"); + + /* Prepare tests */ + root = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0); + if (root == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + full_parent_name, NULL, strerror(errno)); + printf("glfs_h_link(s) tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + parent = glfs_h_mkdir(fs, root, my_dir, 0755, &sb); + if (parent == NULL) { + fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n", + my_dir, root, strerror(errno)); + printf("glfs_h_link(s) tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + leaf = glfs_h_creat(fs, parent, my_file, O_CREAT, 0644, &sb); + if (leaf == NULL) { + fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n", + my_file, parent, strerror(errno)); + printf("glfs_h_link(s) tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + dirsrc = glfs_h_mkdir(fs, parent, linksrc_dir, 0755, &sb); + if (dirsrc == NULL) { + fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n", + linksrc_dir, parent, strerror(errno)); + printf("glfs_h_link(s) tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + dirtgt = glfs_h_mkdir(fs, parent, linktgt_dir, 0755, &sb); + if (dirtgt == NULL) { + fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n", + linktgt_dir, parent, strerror(errno)); + printf("glfs_h_link(s) tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + dleaf = glfs_h_creat(fs, dirsrc, my_file, O_CREAT, 0644, &sb); + if (dleaf == NULL) { + fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n", + my_file, dirsrc, strerror(errno)); + printf("glfs_h_link(s) tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + /* run tests */ + /* sym link: /testdir/linkdir/file.txt to ./slnk.txt */ + ln1 = glfs_h_symlink(fs, parent, my_symlnk, "./file.txt", &sb); + if (ln1 == NULL) { + fprintf(stderr, "glfs_h_symlink: error creating %s: from (%p),%s\n", + my_symlnk, parent, strerror(errno)); + printf("glfs_h_link(s) tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + buf = calloc(1024, sizeof(char)); + if (buf == NULL) { + fprintf(stderr, "Error allocating memory\n"); + printf("glfs_h_link(s) tests: FAILED\n"); + goto out; + } + + ret = glfs_h_readlink(fs, ln1, buf, 1024); + if (ret <= 0) { + fprintf(stderr, "glfs_h_readlink: error reading %s: from (%p),%s\n", + my_symlnk, ln1, strerror(errno)); + printf("glfs_h_link(s) tests: FAILED\n"); + goto out; + } + if (!(strncmp(buf, my_symlnk, strlen(my_symlnk)))) { + fprintf(stderr, + "glfs_h_readlink: error mismatch in link name: actual %s: " + "retrieved %s\n", + my_symlnk, buf); + printf("glfs_h_link(s) tests: FAILED\n"); + goto out; + } + + /* link: /testdir/linkdir/file.txt to ./lnk.txt */ + ret = glfs_h_link(fs, leaf, parent, my_lnk); + if (ret != 0) { + fprintf(stderr, "glfs_h_link: error creating %s: from (%p),%s\n", + my_lnk, parent, strerror(errno)); + printf("glfs_h_link(s) tests: FAILED\n"); + goto out; + } + /* TODO: Should write content to a file and read from the link */ + + /* link: /testdir/linkdir/dir1/file.txt to ../dir2/slnk.txt */ + ret = glfs_h_link(fs, dleaf, dirtgt, my_lnk); + if (ret != 0) { + fprintf(stderr, "glfs_h_link: error creating %s: from (%p),%s\n", + my_lnk, dirtgt, strerror(errno)); + printf("glfs_h_link(s) tests: FAILED\n"); + goto out; + } + /* TODO: Should write content to a file and read from the link */ + + printf("glfs_h_link(s) tests: PASSED\n"); + +out: + if (root) + glfs_h_close(root); + if (parent) + glfs_h_close(parent); + if (leaf) + glfs_h_close(leaf); + if (dirsrc) + glfs_h_close(dirsrc); + if (dirtgt) + glfs_h_close(dirtgt); + if (dleaf) + glfs_h_close(dleaf); + if (ln1) + glfs_h_close(ln1); + if (buf) + free(buf); + + return; +} + +void +test_h_rename(void) +{ + char *my_dir = "renamedir"; + char *my_file = "file.txt"; + char *src_dir = "dir1"; + char *tgt_dir = "dir2"; + struct glfs_object *root = NULL, *parent = NULL, *leaf = NULL, + *dirsrc = NULL, *dirtgt = NULL, *dleaf = NULL; + struct stat sb; + int ret; + + printf("glfs_h_rename tests: In Progress\n"); + + /* Prepare tests */ + root = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0); + if (root == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + full_parent_name, NULL, strerror(errno)); + printf("glfs_h_rename tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + parent = glfs_h_mkdir(fs, root, my_dir, 0755, &sb); + if (parent == NULL) { + fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n", + my_dir, root, strerror(errno)); + printf("glfs_h_rename tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + leaf = glfs_h_creat(fs, parent, my_file, O_CREAT, 0644, &sb); + if (leaf == NULL) { + fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n", + my_file, parent, strerror(errno)); + printf("glfs_h_rename tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + dirsrc = glfs_h_mkdir(fs, parent, src_dir, 0755, &sb); + if (dirsrc == NULL) { + fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n", + src_dir, parent, strerror(errno)); + printf("glfs_h_rename tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + dirtgt = glfs_h_mkdir(fs, parent, tgt_dir, 0755, &sb); + if (dirtgt == NULL) { + fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n", + tgt_dir, parent, strerror(errno)); + printf("glfs_h_rename tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + dleaf = glfs_h_creat(fs, dirsrc, my_file, O_CREAT, 0644, &sb); + if (dleaf == NULL) { + fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n", + my_file, dirsrc, strerror(errno)); + printf("glfs_h_rename tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + /* run tests */ + /* Rename file.txt -> file1.txt */ + ret = glfs_h_rename(fs, parent, "file.txt", parent, "file1.txt"); + if (ret != 0) { + fprintf(stderr, "glfs_h_rename: error renaming %s to %s (%s)\n", + "file.txt", "file1.txt", strerror(errno)); + printf("glfs_h_rename tests: FAILED\n"); + goto out; + } + + /* rename dir1/file.txt -> file.txt */ + ret = glfs_h_rename(fs, dirsrc, "file.txt", parent, "file.txt"); + if (ret != 0) { + fprintf(stderr, "glfs_h_rename: error renaming %s/%s to %s (%s)\n", + src_dir, "file.txt", "file.txt", strerror(errno)); + printf("glfs_h_rename tests: FAILED\n"); + goto out; + } + + /* rename file1.txt -> file.txt (exists) */ + ret = glfs_h_rename(fs, parent, "file1.txt", parent, "file.txt"); + if (ret != 0) { + fprintf(stderr, "glfs_h_rename: error renaming %s to %s (%s)\n", + "file.txt", "file.txt", strerror(errno)); + printf("glfs_h_rename tests: FAILED\n"); + goto out; + } + + /* rename dir1 -> dir3 */ + ret = glfs_h_rename(fs, parent, "dir1", parent, "dir3"); + if (ret != 0) { + fprintf(stderr, "glfs_h_rename: error renaming %s to %s (%s)\n", "dir1", + "dir3", strerror(errno)); + printf("glfs_h_rename tests: FAILED\n"); + goto out; + } + + /* rename dir2 ->dir3 (exists) */ + ret = glfs_h_rename(fs, parent, "dir2", parent, "dir3"); + if (ret != 0) { + fprintf(stderr, "glfs_h_rename: error renaming %s to %s (%s)\n", "dir2", + "dir3", strerror(errno)); + printf("glfs_h_rename tests: FAILED\n"); + goto out; + } + + /* rename file.txt -> dir3 (fail) */ + ret = glfs_h_rename(fs, parent, "file.txt", parent, "dir3"); + if (ret == 0) { + fprintf(stderr, "glfs_h_rename: NO error renaming %s to %s (%s)\n", + "file.txt", "dir3", strerror(errno)); + printf("glfs_h_rename tests: FAILED\n"); + goto out; + } + + /* rename dir3 -> file.txt (fail) */ + ret = glfs_h_rename(fs, parent, "dir3", parent, "file.txt"); + if (ret == 0) { + fprintf(stderr, "glfs_h_rename: NO error renaming %s to %s (%s)\n", + "dir3", "file.txt", strerror(errno)); + printf("glfs_h_rename tests: FAILED\n"); + goto out; + } + + printf("glfs_h_rename tests: PASSED\n"); + +out: + if (root) + glfs_h_close(root); + if (parent) + glfs_h_close(parent); + if (leaf) + glfs_h_close(leaf); + if (dirsrc) + glfs_h_close(dirsrc); + if (dirtgt) + glfs_h_close(dirtgt); + if (dleaf) + glfs_h_close(dleaf); + + return; +} + +void +assimilatetime(struct timespec *ts, struct timespec ts_st, + struct timespec ts_ed) +{ + if ((ts_ed.tv_nsec - ts_st.tv_nsec) < 0) { + ts->tv_sec += ts_ed.tv_sec - ts_st.tv_sec - 1; + ts->tv_nsec += 1000000000 + ts_ed.tv_nsec - ts_st.tv_nsec; + } else { + ts->tv_sec += ts_ed.tv_sec - ts_st.tv_sec; + ts->tv_nsec += ts_ed.tv_nsec - ts_st.tv_nsec; + } + + if (ts->tv_nsec > 1000000000) { + ts->tv_nsec = ts->tv_nsec - 1000000000; + ts->tv_sec += 1; + } + + return; +} + +#define MAX_FILES_CREATE 10 +#define MAXPATHNAME 512 +void +test_h_performance(void) +{ + char *my_dir = "perftest", *full_dir_path = "/testdir/perftest"; + char *my_file = "file_", my_file_name[MAXPATHNAME]; + struct glfs_object *parent = NULL, *leaf = NULL, *dir = NULL; + struct stat sb; + int ret, i; + struct glfs_fd *fd; + struct timespec c_ts = {0, 0}, c_ts_st, c_ts_ed; + struct timespec o_ts = {0, 0}, o_ts_st, o_ts_ed; + + printf("glfs_h_performance tests: In Progress\n"); + + /* Prepare tests */ + parent = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0); + if (parent == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + full_parent_name, NULL, strerror(errno)); + printf("glfs_h_performance tests: FAILED\n"); + goto out; + } + + dir = glfs_h_mkdir(fs, parent, my_dir, 0755, &sb); + if (dir == NULL) { + fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n", + my_dir, parent, strerror(errno)); + printf("glfs_h_performance tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + /* create performance */ + ret = clock_gettime(CLOCK_REALTIME, &o_ts_st); + if (ret != 0) { + fprintf(stderr, "clock_gettime: error %s\n", strerror(errno)); + printf("glfs_h_getattrs and setattrs tests: FAILED\n"); + goto out; + } + + for (i = 0; i < MAX_FILES_CREATE; i++) { + sprintf(my_file_name, "%s%d", my_file, i); + + ret = clock_gettime(CLOCK_REALTIME, &c_ts_st); + if (ret != 0) { + fprintf(stderr, "clock_gettime: error %s\n", strerror(errno)); + printf("glfs_h_getattrs and setattrs tests: FAILED\n"); + goto out; + } + + leaf = glfs_h_lookupat(fs, dir, my_file_name, &sb, 0); + if (leaf != NULL) { + fprintf(stderr, "glfs_h_lookup: exists %s\n", my_file_name); + printf("glfs_h_performance tests: FAILED\n"); + goto out; + } + + leaf = glfs_h_creat(fs, dir, my_file_name, O_CREAT, 0644, &sb); + if (leaf == NULL) { + fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n", + my_file, dir, strerror(errno)); + printf("glfs_h_performance tests: FAILED\n"); + goto out; + } + + ret = clock_gettime(CLOCK_REALTIME, &c_ts_ed); + if (ret != 0) { + fprintf(stderr, "clock_gettime: error %s\n", strerror(errno)); + printf("glfs_h_getattrs and setattrs tests: FAILED\n"); + goto out; + } + + assimilatetime(&c_ts, c_ts_st, c_ts_ed); + glfs_h_close(leaf); + leaf = NULL; + } + + ret = clock_gettime(CLOCK_REALTIME, &o_ts_ed); + if (ret != 0) { + fprintf(stderr, "clock_gettime: error %s\n", strerror(errno)); + printf("glfs_h_getattrs and setattrs tests: FAILED\n"); + goto out; + } + + assimilatetime(&o_ts, o_ts_st, o_ts_ed); + + printf("Creation performance (handle based):\n\t# empty files:%d\n", + MAX_FILES_CREATE); + printf("\tOverall time:\n\t\tSecs:%ld\n\t\tnSecs:%ld\n", o_ts.tv_sec, + o_ts.tv_nsec); + printf("\tcreate call time time:\n\t\tSecs:%ld\n\t\tnSecs:%ld\n", + c_ts.tv_sec, c_ts.tv_nsec); + + /* create using path */ + c_ts.tv_sec = o_ts.tv_sec = 0; + c_ts.tv_nsec = o_ts.tv_nsec = 0; + + sprintf(my_file_name, "%s1", full_dir_path); + ret = glfs_mkdir(fs, my_file_name, 0755); + if (ret != 0) { + fprintf(stderr, "glfs_mkdir: error creating %s: from (%p),%s\n", my_dir, + parent, strerror(errno)); + printf("glfs_h_performance tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + ret = clock_gettime(CLOCK_REALTIME, &o_ts_st); + if (ret != 0) { + fprintf(stderr, "clock_gettime: error %s\n", strerror(errno)); + printf("glfs_h_getattrs and setattrs tests: FAILED\n"); + goto out; + } + + for (i = 0; i < MAX_FILES_CREATE; i++) { + sprintf(my_file_name, "%s1/%sn%d", full_dir_path, my_file, i); + + ret = clock_gettime(CLOCK_REALTIME, &c_ts_st); + if (ret != 0) { + fprintf(stderr, "clock_gettime: error %s\n", strerror(errno)); + printf("glfs_h_getattrs and setattrs tests: FAILED\n"); + goto out; + } + + ret = glfs_stat(fs, my_file_name, &sb); + if (ret == 0) { + fprintf(stderr, "glfs_stat: exists %s\n", my_file_name); + printf("glfs_h_performance tests: FAILED\n"); + goto out; + } + + fd = glfs_creat(fs, my_file_name, O_CREAT, 0644); + if (fd == NULL) { + fprintf(stderr, "glfs_creat: error creating %s: from (%p),%s\n", + my_file, dir, strerror(errno)); + printf("glfs_h_performance tests: FAILED\n"); + goto out; + } + + ret = clock_gettime(CLOCK_REALTIME, &c_ts_ed); + if (ret != 0) { + fprintf(stderr, "clock_gettime: error %s\n", strerror(errno)); + printf("glfs_h_getattrs and setattrs tests: FAILED\n"); + goto out; + } + + assimilatetime(&c_ts, c_ts_st, c_ts_ed); + glfs_close(fd); + } + + ret = clock_gettime(CLOCK_REALTIME, &o_ts_ed); + if (ret != 0) { + fprintf(stderr, "clock_gettime: error %s\n", strerror(errno)); + printf("glfs_h_getattrs and setattrs tests: FAILED\n"); + goto out; + } + + assimilatetime(&o_ts, o_ts_st, o_ts_ed); + + printf("Creation performance (path based):\n\t# empty files:%d\n", + MAX_FILES_CREATE); + printf("\tOverall time:\n\t\tSecs:%ld\n\t\tnSecs:%ld\n", o_ts.tv_sec, + o_ts.tv_nsec); + printf("\tcreate call time time:\n\t\tSecs:%ld\n\t\tnSecs:%ld\n", + c_ts.tv_sec, c_ts.tv_nsec); +out: + return; +} + +int +test_handleops(int argc, char *argv[]) +{ + int ret = 0; + glfs_fd_t *fd = NULL; + struct stat sb = { + 0, + }; + struct glfs_object *root = NULL, *parent = NULL, *leaf = NULL, *tmp = NULL; + char readbuf[32], writebuf[32]; + unsigned char leaf_handle[GFAPI_HANDLE_LENGTH]; + + char *full_leaf_name = "/testdir/testfile.txt", *leaf_name = "testfile.txt", + *relative_leaf_name = "testdir/testfile.txt"; + char *leaf_name1 = "testfile1.txt"; + char *full_newparent_name = "/testdir/dir1", *newparent_name = "dir1"; + char *full_newnod_name = "/testdir/nod1", *newnod_name = "nod1"; + + /* Initialize test area */ + ret = glfs_mkdir(fs, full_parent_name, 0755); + if (ret != 0 && errno != EEXIST) { + fprintf(stderr, "%s: (%p) %s\n", full_parent_name, fd, strerror(errno)); + printf("Test initialization failed on volume %s\n", argv[1]); + goto out; + } else if (ret != 0) { + printf("Found test directory %s to be existing\n", full_parent_name); + printf("Cleanup test directory and restart tests\n"); + goto out; + } + + fd = glfs_creat(fs, full_leaf_name, O_CREAT, 0644); + if (fd == NULL) { + fprintf(stderr, "%s: (%p) %s\n", full_leaf_name, fd, strerror(errno)); + printf("Test initialization failed on volume %s\n", argv[1]); + goto out; + } + glfs_close(fd); + + printf("Initialized the test area, within volume %s\n", argv[1]); + + /* Handle based APIs test area */ + + /* glfs_lookupat test */ + printf("glfs_h_lookupat tests: In Progress\n"); + /* start at root of the volume */ + root = glfs_h_lookupat(fs, NULL, "/", &sb, 0); + if (root == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", "/", + NULL, strerror(errno)); + printf("glfs_h_lookupat tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + /* lookup a parent within root */ + parent = glfs_h_lookupat(fs, root, parent_name, &sb, 0); + if (parent == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + parent_name, root, strerror(errno)); + printf("glfs_h_lookupat tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + /* lookup a leaf/child within the parent */ + leaf = glfs_h_lookupat(fs, parent, leaf_name, &sb, 0); + if (leaf == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + leaf_name, parent, strerror(errno)); + printf("glfs_h_lookupat tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + /* reset */ + glfs_h_close(root); + root = NULL; + glfs_h_close(leaf); + leaf = NULL; + glfs_h_close(parent); + parent = NULL; + + /* check absolute paths */ + root = glfs_h_lookupat(fs, NULL, "/", &sb, 0); + if (root == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", "/", + NULL, strerror(errno)); + printf("glfs_h_lookupat tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + parent = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0); + if (parent == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + full_parent_name, root, strerror(errno)); + printf("glfs_h_lookupat tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + leaf = glfs_h_lookupat(fs, NULL, full_leaf_name, &sb, 0); + if (leaf == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + full_leaf_name, parent, strerror(errno)); + printf("glfs_h_lookupat tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + /* reset */ + glfs_h_close(leaf); + leaf = NULL; + + /* check multiple component paths */ + leaf = glfs_h_lookupat(fs, root, relative_leaf_name, &sb, 0); + if (leaf == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + relative_leaf_name, parent, strerror(errno)); + goto out; + } + peek_stat(&sb); + + /* reset */ + glfs_h_close(root); + root = NULL; + glfs_h_close(parent); + parent = NULL; + + /* check symlinks in path */ + + /* TODO: -ve test cases */ + /* parent invalid + * path invalid + * path does not exist after some components + * no parent, but relative path + * parent and full path? -ve? + */ + + printf("glfs_h_lookupat tests: PASSED\n"); + + /* glfs_openat test */ + printf("glfs_h_open tests: In Progress\n"); + fd = glfs_h_open(fs, leaf, O_RDWR); + if (fd == NULL) { + fprintf(stderr, "glfs_h_open: error on open of %s: %s\n", + full_leaf_name, strerror(errno)); + printf("glfs_h_open tests: FAILED\n"); + goto out; + } + + /* test read/write based on fd */ + memcpy(writebuf, "abcdefghijklmnopqrstuvwxyz012345", 32); + ret = glfs_write(fd, writebuf, 32, 0); + + glfs_lseek(fd, 10, SEEK_SET); + + ret = glfs_read(fd, readbuf, 32, 0); + if (memcmp(readbuf, writebuf, 32)) { + printf("Failed to read what I wrote: %s %s\n", readbuf, writebuf); + glfs_close(fd); + printf("glfs_h_open tests: FAILED\n"); + goto out; + } + + glfs_h_close(leaf); + leaf = NULL; + glfs_close(fd); + + printf("glfs_h_open tests: PASSED\n"); + + /* Create tests */ + printf("glfs_h_creat tests: In Progress\n"); + parent = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0); + if (parent == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + full_parent_name, root, strerror(errno)); + printf("glfs_h_creat tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + leaf = glfs_h_creat(fs, parent, leaf_name1, O_CREAT, 0644, &sb); + if (leaf == NULL) { + fprintf(stderr, "glfs_h_creat: error on create of %s: from (%p),%s\n", + leaf_name1, parent, strerror(errno)); + printf("glfs_h_creat tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + glfs_h_close(leaf); + leaf = NULL; + + leaf = glfs_h_creat(fs, parent, leaf_name1, O_CREAT | O_EXCL, 0644, &sb); + if (leaf != NULL || errno != EEXIST) { + fprintf(stderr, + "glfs_h_creat: existing file, leaf = (%p), errno = %s\n", leaf, + strerror(errno)); + printf("glfs_h_creat tests: FAILED\n"); + if (leaf != NULL) { + glfs_h_close(leaf); + leaf = NULL; + } + } + + tmp = glfs_h_creat(fs, root, parent_name, O_CREAT, 0644, &sb); + if (tmp != NULL || !(errno == EISDIR || errno == EINVAL)) { + fprintf(stderr, "glfs_h_creat: dir create, tmp = (%p), errno = %s\n", + leaf, strerror(errno)); + printf("glfs_h_creat tests: FAILED\n"); + if (tmp != NULL) { + glfs_h_close(tmp); + tmp = NULL; + } + } + + /* TODO: Other combinations and -ve cases as applicable */ + printf("glfs_h_creat tests: PASSED\n"); + + /* extract handle and create from handle test */ + printf( + "glfs_h_extract_handle and glfs_h_create_from_handle tests: In " + "Progress\n"); + /* TODO: Change the lookup to create below for a GIFD recovery failure, + * that needs to be fixed */ + leaf = glfs_h_lookupat(fs, parent, leaf_name1, &sb, 0); + if (leaf == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + leaf_name1, parent, strerror(errno)); + printf("glfs_h_extract_handle tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + ret = glfs_h_extract_handle(leaf, leaf_handle, GFAPI_HANDLE_LENGTH); + if (ret < 0) { + fprintf(stderr, + "glfs_h_extract_handle: error extracting handle of %s: %s\n", + full_leaf_name, strerror(errno)); + printf("glfs_h_extract_handle tests: FAILED\n"); + goto out; + } + peek_handle(leaf_handle); + + glfs_h_close(leaf); + leaf = NULL; + + leaf = glfs_h_create_from_handle(fs, leaf_handle, GFAPI_HANDLE_LENGTH, &sb); + if (leaf == NULL) { + fprintf( + stderr, + "glfs_h_create_from_handle: error on create of %s: from (%p),%s\n", + leaf_name1, leaf_handle, strerror(errno)); + printf("glfs_h_create_from_handle tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + fd = glfs_h_open(fs, leaf, O_RDWR); + if (fd == NULL) { + fprintf(stderr, "glfs_h_open: error on open of %s: %s\n", + full_leaf_name, strerror(errno)); + printf("glfs_h_create_from_handle tests: FAILED\n"); + goto out; + } + + /* test read/write based on fd */ + memcpy(writebuf, "abcdefghijklmnopqrstuvwxyz012345", 32); + ret = glfs_write(fd, writebuf, 32, 0); + + glfs_lseek(fd, 0, SEEK_SET); + + ret = glfs_read(fd, readbuf, 32, 0); + if (memcmp(readbuf, writebuf, 32)) { + printf("Failed to read what I wrote: %s %s\n", writebuf, writebuf); + printf("glfs_h_create_from_handle tests: FAILED\n"); + glfs_close(fd); + goto out; + } + + glfs_close(fd); + glfs_h_close(leaf); + leaf = NULL; + glfs_h_close(parent); + parent = NULL; + + printf( + "glfs_h_extract_handle and glfs_h_create_from_handle tests: PASSED\n"); + + /* Mkdir tests */ + printf("glfs_h_mkdir tests: In Progress\n"); + + ret = glfs_rmdir(fs, full_newparent_name); + if (ret && errno != ENOENT) { + fprintf(stderr, "glfs_rmdir: Failed for %s: %s\n", full_newparent_name, + strerror(errno)); + printf("glfs_h_mkdir tests: FAILED\n"); + goto out; + } + + parent = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0); + if (parent == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + full_parent_name, root, strerror(errno)); + printf("glfs_h_mkdir tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + leaf = glfs_h_mkdir(fs, parent, newparent_name, 0755, &sb); + if (leaf == NULL) { + fprintf(stderr, "glfs_h_mkdir: error on mkdir of %s: from (%p),%s\n", + newparent_name, parent, strerror(errno)); + printf("glfs_h_mkdir tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + glfs_h_close(leaf); + leaf = NULL; + + leaf = glfs_h_mkdir(fs, parent, newparent_name, 0755, &sb); + if (leaf != NULL || errno != EEXIST) { + fprintf(stderr, + "glfs_h_mkdir: existing directory, leaf = (%p), errno = %s\n", + leaf, strerror(errno)); + printf("glfs_h_mkdir tests: FAILED\n"); + if (leaf != NULL) { + glfs_h_close(leaf); + leaf = NULL; + } + } + + glfs_h_close(parent); + parent = NULL; + + printf("glfs_h_mkdir tests: PASSED\n"); + + /* Mknod tests */ + printf("glfs_h_mknod tests: In Progress\n"); + ret = glfs_unlink(fs, full_newnod_name); + if (ret && errno != ENOENT) { + fprintf(stderr, "glfs_unlink: Failed for %s: %s\n", full_newnod_name, + strerror(errno)); + printf("glfs_h_mknod tests: FAILED\n"); + goto out; + } + + parent = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0); + if (parent == NULL) { + fprintf(stderr, + "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", + full_parent_name, root, strerror(errno)); + printf("glfs_h_mknod tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + leaf = glfs_h_mknod(fs, parent, newnod_name, S_IFIFO, 0, &sb); + if (leaf == NULL) { + fprintf(stderr, "glfs_h_mkdir: error on mkdir of %s: from (%p),%s\n", + newnod_name, parent, strerror(errno)); + printf("glfs_h_mknod tests: FAILED\n"); + goto out; + } + peek_stat(&sb); + + /* TODO: create op on a FIFO node hangs, need to check and fix + tmp = glfs_h_creat (fs, parent, newnod_name, O_CREAT, 0644, &sb); + if (tmp != NULL || errno != EINVAL) { + fprintf (stderr, "glfs_h_creat: node create, tmp = (%p), errno = + %s\n", tmp, strerror (errno)); printf ("glfs_h_creat/mknod tests: + FAILED\n"); if (tmp != NULL) { glfs_h_close(tmp); tmp = NULL; + } + } */ + + glfs_h_close(leaf); + leaf = NULL; + + leaf = glfs_h_mknod(fs, parent, newnod_name, 0644, 0, &sb); + if (leaf != NULL || errno != EEXIST) { + fprintf(stderr, + "glfs_h_mknod: existing node, leaf = (%p), errno = %s\n", leaf, + strerror(errno)); + printf("glfs_h_mknod tests: FAILED\n"); + if (leaf != NULL) { + glfs_h_close(leaf); + leaf = NULL; + } + } + + glfs_h_close(parent); + parent = NULL; + + printf("glfs_h_mknod tests: PASSED\n"); + + /* unlink tests */ + test_h_unlink(); + + /* TODO: opendir tests */ + + /* getattr tests */ + test_h_getsetattrs(); + + /* TODO: setattr tests */ + + /* truncate tests */ + test_h_truncate(); + + /* link tests */ + test_h_links(); + + /* rename tests */ + test_h_rename(); + + /* performance tests */ + test_h_performance(); + + /* END: New APIs test area */ + +out: + /* Cleanup glfs handles */ + if (root) + glfs_h_close(root); + if (parent) + glfs_h_close(parent); + if (leaf) + glfs_h_close(leaf); + + return ret; +} + +int +test_write_apis(glfs_t *fs) +{ + /* Add more content here */ + /* Some apis we can get are */ + /* + 0. glfs_set_xlator_option() + + Read/Write combinations: + . glfs_{p,}readv/{p,}writev + . glfs_pread/pwrite + + tests/basic/gfapi/gfapi-async-calls-test.c + . glfs_read_async/write_async + . glfs_pread_async/pwrite_async + . glfs_readv_async/writev_async + . glfs_preadv_async/pwritev_async + + . ftruncate/ftruncate_async + . fsync/fsync_async + . fdatasync/fdatasync_async + + */ + + glfs_fd_t *fd = NULL; + char *filename = "/filename2"; + int flags = O_RDWR; + char *buf = "some bytes!"; + char writestr[TEST_STR_LEN]; + struct iovec iov = {&writestr, TEST_STR_LEN}; + int ret, i; + + for (i = 0; i < TEST_STR_LEN; i++) + writestr[i] = 0x11; + + fd = glfs_open(fs, filename, flags); + if (!fd) + fprintf(stderr, "open(%s): (%p) %s\n", filename, fd, strerror(errno)); + + ret = glfs_writev(fd, &iov, 1, flags); + if (ret < 0) { + fprintf(stderr, "writev(%s): %d (%s)\n", filename, ret, + strerror(errno)); + } + + ret = glfs_pwrite(fd, buf, 10, 4, flags, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "pwrite(%s): %d (%s)\n", filename, ret, + strerror(errno)); + } + + ret = glfs_pwritev(fd, &iov, 1, 4, flags); + if (ret < 0) { + fprintf(stderr, "pwritev(%s): %d (%s)\n", filename, ret, + strerror(errno)); + } + + ret = glfs_fsync(fd, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "fsync(%s): %d (%s)\n", filename, ret, strerror(errno)); + } + + glfs_close(fd); + + return 0; +} + +int +test_metadata_ops(glfs_t *fs, glfs_t *fs2) +{ + glfs_fd_t *fd = NULL; + glfs_fd_t *fd2 = NULL; + struct stat sb = { + 0, + }; + struct glfs_stat gsb = { + 0, + }; + struct statvfs sfs; + char readbuf[32]; + char writebuf[11] = "helloworld"; + + char *filename = "/filename2"; + int ret; + + ret = glfs_lstat(fs, filename, &sb); + fprintf(stderr, "lstat(%s): (%d) %s\n", filename, ret, strerror(errno)); + + fd = glfs_creat(fs, filename, O_RDWR, 0644); + if (!fd) + fprintf(stderr, "creat(%s): (%p) %s\n", filename, fd, strerror(errno)); + + fd2 = glfs_open(fs2, filename, O_RDWR); + if (!fd2) + fprintf(stderr, "open(%s): (%p) %s\n", filename, fd, strerror(errno)); + + ret = glfs_lstat(fs, filename, &sb); + if (ret) + fprintf(stderr, "lstat(%s): (%d) %s\n", filename, ret, strerror(errno)); + + ret = glfs_write(fd, writebuf, 11, 0); + if (ret < 0) { + fprintf(stderr, "writev(%s): %d (%s)\n", filename, ret, + strerror(errno)); + } + + glfs_fsync(fd, NULL, NULL); + + glfs_lseek(fd2, 5, SEEK_SET); + + ret = glfs_read(fd2, readbuf, 32, 0); + + printf("read %d, %s", ret, readbuf); + + /* get stat */ + ret = glfs_fstat(fd2, &sb); + if (ret) + fprintf(stderr, "fstat(%s): %d (%s)\n", filename, ret, strerror(errno)); + + ret = glfs_access(fs, filename, R_OK); + if (ret) + fprintf(stderr, "access(%s): %d (%s)\n", filename, ret, + strerror(errno)); + + ret = glfs_fallocate(fd2, 1024, 1024, 1024); + if (ret) + fprintf(stderr, "fallocate(%s): %d (%s)\n", filename, ret, + strerror(errno)); + + ret = glfs_discard(fd2, 1024, 512); + if (ret) + fprintf(stderr, "discard(%s): %d (%s)\n", filename, ret, + strerror(errno)); + + ret = glfs_zerofill(fd2, 2048, 1024); + if (ret) + fprintf(stderr, "zerofill(%s): %d (%s)\n", filename, ret, + strerror(errno)); + + /* set stat */ + /* TODO: got some errors, need to fix */ + ret = glfs_fsetattr(fd2, &gsb); + + glfs_close(fd); + glfs_close(fd2); + + filename = "/filename3"; + ret = glfs_mknod(fs, filename, S_IFIFO, 0); + if (ret) + fprintf(stderr, "%s: (%d) %s\n", filename, ret, strerror(errno)); + + ret = glfs_lstat(fs, filename, &sb); + if (ret) + fprintf(stderr, "%s: (%d) %s\n", filename, ret, strerror(errno)); + + ret = glfs_rename(fs, filename, "/filename4"); + if (ret) + fprintf(stderr, "rename(%s): (%d) %s\n", filename, ret, + strerror(errno)); + + ret = glfs_unlink(fs, "/filename4"); + if (ret) + fprintf(stderr, "unlink(%s): (%d) %s\n", "/filename4", ret, + strerror(errno)); + + filename = "/dirname2"; + ret = glfs_mkdir(fs, filename, 0); + if (ret) + fprintf(stderr, "%s: (%d) %s\n", filename, ret, strerror(errno)); + + ret = glfs_lstat(fs, filename, &sb); + if (ret) + fprintf(stderr, "lstat(%s): (%d) %s\n", filename, ret, strerror(errno)); + + ret = glfs_rmdir(fs, filename); + if (ret) + fprintf(stderr, "rmdir(%s): (%d) %s\n", filename, ret, strerror(errno)); +} +int +main(int argc, char *argv[]) +{ + glfs_t *fs2 = NULL; + int ret = 0; + glfs_fd_t *fd = NULL; + glfs_fd_t *fd2 = NULL; + struct stat sb = { + 0, + }; + struct glfs_stat gsb = { + 0, + }; + struct statvfs sfs; + char readbuf[32]; + char writebuf[32]; + char volumeid[64]; + + char *filename = "/filename2"; + + if ((argc < 2) || (argc > 3)) { + printf("Usage:\n\t%s <volname> <hostname>\n\t%s <volfile-path>", + argv[0], argv[0]); + return -1; + } + + if (argc == 2) { + /* Generally glfs_new() requires volume name as an argument */ + fs = glfs_new("test-only"); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + return 1; + } + ret = glfs_set_volfile(fs, argv[1]); + if (ret) + fprintf(stderr, "glfs_set_volfile failed\n"); + } else { + fs = glfs_new(argv[1]); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + return 1; + } + // ret = glfs_set_volfile_server (fs, "unix", "/tmp/gluster.sock", 0); + ret = glfs_set_volfile_server(fs, "tcp", argv[2], 24007); + if (ret) + fprintf(stderr, "glfs_set_volfile_server failed\n"); + } + + /* Change this to relevant file when running locally */ + ret = glfs_set_logging(fs, "/dev/stderr", 5); + if (ret) + fprintf(stderr, "glfs_set_logging failed\n"); + + ret = glfs_init(fs); + if (ret) + fprintf(stderr, "glfs_init: returned %d\n", ret); + + if (ret) + goto out; + + /* no major use for getting the volume id in this test, done for coverage */ + ret = glfs_get_volumeid(fs, volumeid, 64); + if (ret) { + fprintf(stderr, "glfs_get_volumeid: returned %d\n", ret); + } + + sleep(2); + + if (argc == 2) { + /* Generally glfs_new() requires volume name as an argument */ + fs2 = glfs_new("test_only_volume"); + if (!fs2) { + fprintf(stderr, "glfs_new(fs2): returned NULL\n"); + return 1; + } + ret = glfs_set_volfile(fs2, argv[1]); + if (ret) + fprintf(stderr, "glfs_set_volfile failed(fs2)\n"); + } else { + fs2 = glfs_new(argv[1]); + if (!fs2) { + fprintf(stderr, "glfs_new(fs2): returned NULL\n"); + return 1; + } + ret = glfs_set_volfile_server(fs2, "tcp", argv[2], 24007); + if (ret) + fprintf(stderr, "glfs_set_volfile_server failed(fs2)\n"); + } + + ret = glfs_set_statedump_path(fs2, "/tmp"); + if (ret) { + fprintf(stderr, "glfs_set_statedump_path: %s\n", strerror(errno)); + } + + ret = glfs_init(fs2); + if (ret) + fprintf(stderr, "glfs_init: returned %d\n", ret); + + test_metadata_ops(fs, fs2); + + test_dirops(fs); + + test_xattr(fs); + + test_chdir(fs); + + test_handleops(argc, argv); + // done + + /* Test some extra apis */ + test_write_apis(fs); + + glfs_statvfs(fs, "/", &sfs); + + glfs_unset_volfile_server(fs, "tcp", argv[2], 24007); + + glfs_fini(fs); + glfs_fini(fs2); + + ret = 0; +out: + return ret; +} diff --git a/tests/basic/gfapi/glfsxmp.t b/tests/basic/gfapi/glfsxmp.t new file mode 100644 index 00000000000..b3e6645c0f5 --- /dev/null +++ b/tests/basic/gfapi/glfsxmp.t @@ -0,0 +1,30 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup + +TEST glusterd + +TEST $CLI volume create $V0 replica 3 $H0:$B0/brick{0,1,2} +EXPECT 'Created' volinfo_field $V0 'Status' + +TEST $CLI volume start $V0 +EXPECT 'Started' volinfo_field $V0 'Status' + +$CLI system getspec $V0 > fubar.vol + +TEST cp $(dirname $0)/glfsxmp-coverage.c ./glfsxmp.c +TEST build_tester ./glfsxmp.c -lgfapi +TEST ./glfsxmp $V0 $H0 + +TEST ./glfsxmp fubar.vol + +TEST cleanup_tester ./glfsxmp +TEST rm ./glfsxmp.c + +TEST $CLI volume stop $V0 +TEST $CLI volume delete $V0 + +cleanup diff --git a/tests/basic/gfapi/libgfapi-fini-hang.c b/tests/basic/gfapi/libgfapi-fini-hang.c index e192751f295..37800e3188b 100644 --- a/tests/basic/gfapi/libgfapi-fini-hang.c +++ b/tests/basic/gfapi/libgfapi-fini-hang.c @@ -8,56 +8,55 @@ #include <glusterfs/api/glfs.h> #include <glusterfs/api/glfs-handles.h> -#define LOG_ERR(func, ret) do { \ - if (ret != 0) { \ - fprintf (stderr, "%s : returned error %d\n", func, ret); \ - exit(1); \ - } else { \ - fprintf (stderr, "%s : returned %d\n", func, ret); \ - } \ -} while (0) +#define LOG_ERR(func, ret) \ + do { \ + if (ret != 0) { \ + fprintf(stderr, "%s : returned error %d\n", func, ret); \ + exit(1); \ + } else { \ + fprintf(stderr, "%s : returned %d\n", func, ret); \ + } \ + } while (0) int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - glfs_t *fs = NULL; - int ret = 0, i; - glfs_fd_t *fd = NULL; - char readbuf[32]; - char *logname = NULL; - char *hostname = NULL; - char *volname = NULL; - - fprintf (stderr, "Starting libgfapi_fini\n"); - - if (argc < 4) { - fprintf (stderr, "Invalid argument\n"); - exit(1); - } - - hostname = argv[1]; - volname = argv[2]; - logname = argv[3]; - - fs = glfs_new (volname); - if (!fs) { - fprintf (stderr, "glfs_new: returned NULL\n"); - exit(1); - } - - ret = glfs_set_volfile_server (fs, "tcp", hostname, 0); - LOG_ERR("glfs_set_volfile_server", ret); - - ret = glfs_set_logging (fs, logname, 7); - LOG_ERR("glfs_set_logging", ret); - - /* Do not call glfs_init. - * glfs_fini() shouldn't hang in that case*/ - ret = glfs_fini(fs); - LOG_ERR("glfs_fini", ret); - fprintf (stderr, "End of libgfapi_fini\n"); - - exit(0); + glfs_t *fs = NULL; + int ret = 0, i; + glfs_fd_t *fd = NULL; + char readbuf[32]; + char *logname = NULL; + char *hostname = NULL; + char *volname = NULL; + + fprintf(stderr, "Starting libgfapi_fini\n"); + + if (argc < 4) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logname = argv[3]; + + fs = glfs_new(volname); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + exit(1); + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 0); + LOG_ERR("glfs_set_volfile_server", ret); + + ret = glfs_set_logging(fs, logname, 7); + LOG_ERR("glfs_set_logging", ret); + + /* Do not call glfs_init. + * glfs_fini() shouldn't hang in that case*/ + ret = glfs_fini(fs); + LOG_ERR("glfs_fini", ret); + fprintf(stderr, "End of libgfapi_fini\n"); + + exit(0); } - - diff --git a/tests/basic/gfapi/mandatory-lock-optimal.c b/tests/basic/gfapi/mandatory-lock-optimal.c new file mode 100644 index 00000000000..34fef8d0b80 --- /dev/null +++ b/tests/basic/gfapi/mandatory-lock-optimal.c @@ -0,0 +1,532 @@ +/* Pre-requisites:- + * + * 1. Make sure that performance translators are switched off while running this + * test. + * 2. Perform the following volume set operation: + * # gluster volume set <VOLNAME> locks.mandatory-locking optimal + * 3. For installation under non-standard paths, export LD_LIBRARY_PATH to + * automatically load exact libgfapi.so and compile this C file as follows: + * $ gcc mandatory-lock-optimal.c -lgfapi -I <include path for api/glfs.h> -L + * <include path for libgfapi shared library> + */ + +#include <errno.h> +#include <stdio.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <glusterfs/api/glfs.h> + +#define TOTAL_TEST_COUNT 8 + +/* C1 = Client 1 : C2 = Client 2 : C3 = Client 3 : + * fs1, fd1 are associated with C1. Similarly fs2, fd2 for C2 + * and fs3, fd3 for C3 */ + +FILE *fp; +glfs_t *fs1, *fs2, *fs3; +glfs_fd_t *fd, *fd1, *fd2, *fd3; +struct flock lock; +char buf1[10], *buf2 = "ten bytes!", *fname = "/mand.lock"; +int ret, test_count; +off_t offset; + +/* run_test_1 () : C1 takes byte range mandatory read lock. + C2 attempts to read from a conflicting range. + Expected result : Read from C2 should pass. + + * run_test_2 () : C1 takes byte range mandatory read lock. + C2 attempts write to a conflicting range. + Expected result : Write from C2 should fail with EAGAIN. + + * run_test_3 () : C1 takes byte range advisory write lock. + C2 attempts to read from a conflicting range. + Expected result : Read from C2 should pass. + + * run_test_4 () : C1 takes byte range advisory write lock. + C2 attempts write to a conflicting range. + Expected result : Write from C2 should pass. + + * run_test_5 () : C1 takes byte range advisory read lock. + C2 attempts to open the same file with O_TRUNC. + Expected result : Open from C2 should pass. + + * run_test_6 () : C1 takes byte range mandatory read lock. + C2 attempts to open the same file with O_TRUNC. + Expected result : Open from C2 should fail with EAGAIN. + + * run_test_7 () : C1 takes byte range mandatory read lock. + C2 attempts ftruncate on a conflicting range. + Expected result : Write from C2 should fail with EAGAIN. + + * run_test_8 () : C1 takes byte range advisory read lock. + C2 takes byte range mandatory read lock + within the byte range for which C1 already + holds an advisory lock so as to perform a + basic split/merge. C3 repositions fd3 to + start of C2's byte range mandatory lock + offset and attempts a write. Then it again + repositions fd3 to one byte past C2's byte + range mandatoy lock and again attempts a write. + Expected result : First write should fail with EAGAIN. + Second write should pass. */ + +#define LOG_ERR(func, err) \ + do { \ + if (!fp) \ + fprintf(stderr, "\n%s : returned error (%s)\n", func, \ + strerror(err)); \ + else \ + fprintf(fp, "\n%s : returned error (%s)\n", func, strerror(err)); \ + cleanup_and_exit(err); \ + } while (0) + +void +cleanup_and_exit(int exit_status) +{ + if (exit_status || test_count != TOTAL_TEST_COUNT) { + fprintf(fp, "\nAborting due to some test failures.\n"); + exit_status = 1; + } else + fprintf(fp, "\nAll tests ran successfully.\n"); + if (fp) + fclose(fp); + if (fd) + glfs_close(fd); + if (fd1) + glfs_close(fd1); + if (fd2) + glfs_close(fd2); + + glfs_unlink(fs1, fname); + + if (fs1) + glfs_fini(fs1); + if (fs2) + glfs_fini(fs2); + + exit(exit_status); +} + +glfs_t * +new_client_create(char *hostname, char *volname, char *logfile_name) +{ + glfs_t *fs = NULL; + + fs = glfs_new(volname); + if (!fs) + LOG_ERR("glfs_new", errno); + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + if (ret) + LOG_ERR("glfs_set_volfile_server", errno); + + ret = glfs_set_logging(fs, logfile_name, 7); + if (ret) + LOG_ERR("glfs_set_logging", errno); + + ret = glfs_init(fs); + if (ret) + LOG_ERR("glfs_init", errno); + + return fs; +} + +void +run_test_1(int i) +{ + fprintf(fp, "\nRunning Test-%d . . . ", i); + + fd1 = glfs_open(fs1, fname, O_RDONLY | O_NONBLOCK); + if (!fd1) + LOG_ERR("glfs_open", errno); + + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0L; + lock.l_len = 5L; + + ret = glfs_file_lock(fd1, F_SETLK, &lock, GLFS_LK_MANDATORY); + if (ret) + LOG_ERR("glfs_file_lock", errno); + + fd2 = glfs_open(fs2, fname, O_RDONLY | O_NONBLOCK); + if (!fd2) + LOG_ERR("glfs_open", errno); + + /* On successful read, 0 is returned as there is no content inside the + * file + */ + ret = glfs_read(fd2, buf1, 10, 0); + if (ret) + LOG_ERR("glfs_read", errno); + + ret = glfs_close(fd1); + if (ret) + LOG_ERR("glfs_close", errno); + fd1 = NULL; + + ret = glfs_close(fd2); + if (ret) + LOG_ERR("glfs_close", errno); + fd2 = NULL; + + test_count++; + fprintf(fp, "OK\n", i); +} + +void +run_test_2(int i) +{ + fprintf(fp, "\nRunning Test-%d . . . ", i); + + fd1 = glfs_open(fs1, fname, O_RDONLY | O_NONBLOCK); + if (!fd1) + LOG_ERR("glfs_open", errno); + + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0L; + lock.l_len = 5L; + + ret = glfs_file_lock(fd1, F_SETLK, &lock, GLFS_LK_MANDATORY); + if (ret) + LOG_ERR("glfs_file_lock", errno); + + fd2 = glfs_open(fs2, fname, O_WRONLY | O_NONBLOCK); + if (!fd2) + LOG_ERR("glfs_open", errno); + + ret = glfs_write(fd2, buf2, 10, 0); + if (ret == 10 || errno != EAGAIN) + LOG_ERR("glfs_write", errno); + + ret = glfs_close(fd1); + if (ret) + LOG_ERR("glfs_close", errno); + fd1 = NULL; + + ret = glfs_close(fd2); + if (ret) + LOG_ERR("glfs_close", errno); + fd2 = NULL; + + test_count++; + fprintf(fp, "OK\n", i); +} + +void +run_test_3(int i) +{ + fprintf(fp, "\nRunning Test-%d . . . ", i); + + fd1 = glfs_open(fs1, fname, O_WRONLY | O_NONBLOCK); + if (!fd1) + LOG_ERR("glfs_open", errno); + + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0L; + lock.l_len = 5L; + + ret = glfs_file_lock(fd1, F_SETLK, &lock, GLFS_LK_ADVISORY); + if (ret) + LOG_ERR("glfs_file_lock", errno); + + fd2 = glfs_open(fs2, fname, O_RDONLY | O_NONBLOCK); + if (!fd2) + LOG_ERR("glfs_open", errno); + + /* Still there is no content inside file. So following read should + * return 0 + */ + ret = glfs_read(fd2, buf1, 10, 0); + if (ret) + LOG_ERR("glfs_read", errno); + + ret = glfs_close(fd1); + if (ret) + LOG_ERR("glfs_close", errno); + fd1 = NULL; + + ret = glfs_close(fd2); + if (ret) + LOG_ERR("glfs_close", errno); + fd2 = NULL; + + test_count++; + fprintf(fp, "OK\n", i); +} + +void +run_test_4(int i) +{ + fprintf(fp, "\nRunning Test-%d . . . ", i); + + fd1 = glfs_open(fs1, fname, O_WRONLY | O_NONBLOCK); + if (!fd1) + LOG_ERR("glfs_open", errno); + + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0L; + lock.l_len = 5L; + + ret = glfs_file_lock(fd1, F_SETLK, &lock, GLFS_LK_ADVISORY); + if (ret) + LOG_ERR("glfs_file_lock", errno); + + fd2 = glfs_open(fs2, fname, O_WRONLY | O_NONBLOCK); + if (!fd2) + LOG_ERR("glfs_open", errno); + + ret = glfs_write(fd2, buf2, 10, 0); + if (ret != 10) + LOG_ERR("glfs_write", errno); + + ret = glfs_close(fd1); + if (ret) + LOG_ERR("glfs_close", errno); + fd1 = NULL; + + ret = glfs_close(fd2); + if (ret) + LOG_ERR("glfs_close", errno); + fd2 = NULL; + + test_count++; + fprintf(fp, "OK\n", i); +} + +void +run_test_5(int i) +{ + fprintf(fp, "\nRunning Test-%d . . . ", i); + + fd1 = glfs_open(fs1, fname, O_RDONLY | O_NONBLOCK); + if (!fd1) + LOG_ERR("glfs_open", errno); + + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0L; + lock.l_len = 5L; + + ret = glfs_file_lock(fd1, F_SETLK, &lock, GLFS_LK_ADVISORY); + if (ret) + LOG_ERR("glfs_file_lock", errno); + + fd2 = glfs_open(fs2, fname, O_RDONLY | O_NONBLOCK | O_TRUNC); + if (!fd2) + LOG_ERR("glfs_open", errno); + + ret = glfs_close(fd1); + if (ret) + LOG_ERR("glfs_close", errno); + fd1 = NULL; + + ret = glfs_close(fd2); + if (ret) + LOG_ERR("glfs_close", errno); + fd2 = NULL; + + test_count++; + fprintf(fp, "OK\n", i); +} + +void +run_test_6(int i) +{ + fprintf(fp, "\nRunning Test-%d . . . ", i); + + fd1 = glfs_open(fs1, fname, O_RDONLY | O_NONBLOCK); + if (!fd1) + LOG_ERR("glfs_open", errno); + + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0L; + lock.l_len = 5L; + + ret = glfs_file_lock(fd1, F_SETLK, &lock, GLFS_LK_MANDATORY); + if (ret) + LOG_ERR("glfs_file_lock", errno); + + fd2 = glfs_open(fs2, fname, O_RDONLY | O_NONBLOCK | O_TRUNC); + if (fd2) + LOG_ERR("glfs_open", errno); + + ret = glfs_close(fd1); + if (ret) + LOG_ERR("glfs_close", errno); + fd1 = NULL; + + test_count++; + fprintf(fp, "OK\n", i); +} + +void +run_test_7(int i) +{ + fprintf(fp, "\nRunning Test-%d . . . ", i); + + fd1 = glfs_open(fs1, fname, O_RDONLY | O_NONBLOCK); + if (!fd1) + LOG_ERR("glfs_open", errno); + + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0L; + lock.l_len = 5L; + + ret = glfs_file_lock(fd1, F_SETLK, &lock, GLFS_LK_MANDATORY); + if (ret) + LOG_ERR("glfs_file_lock", errno); + + fd2 = glfs_open(fs2, fname, O_RDWR | O_NONBLOCK); + if (!fd2) + LOG_ERR("glfs_open", errno); + + ret = glfs_ftruncate(fd2, 4, NULL, NULL); + if (ret == 0 || errno != EAGAIN) + LOG_ERR("glfs_ftruncate", errno); + + ret = glfs_close(fd1); + if (ret) + LOG_ERR("glfs_close", errno); + fd1 = NULL; + + ret = glfs_close(fd2); + if (ret) + LOG_ERR("glfs_close", errno); + fd2 = NULL; + + test_count++; + fprintf(fp, "OK\n", i); +} + +void +run_test_8(int i) +{ + fprintf(fp, "\nRunning Test-%d . . . ", i); + + fd1 = glfs_open(fs1, fname, O_RDONLY | O_NONBLOCK); + if (!fd1) + LOG_ERR("glfs_open", errno); + + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0L; + lock.l_len = 10L; + + ret = glfs_file_lock(fd1, F_SETLK, &lock, GLFS_LK_ADVISORY); + if (ret) + LOG_ERR("glfs_file_lock", errno); + + fd2 = glfs_open(fs2, fname, O_RDONLY | O_NONBLOCK); + if (!fd2) + LOG_ERR("glfs_open", errno); + + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 5L; + lock.l_len = 2L; + + ret = glfs_file_lock(fd2, F_SETLK, &lock, GLFS_LK_MANDATORY); + if (ret) + LOG_ERR("glfs_file_lock", errno); + + fd3 = glfs_open(fs3, fname, O_RDWR | O_NONBLOCK); + if (!fd3) + LOG_ERR("glfs_open", errno); + + offset = glfs_lseek(fd3, 5L, SEEK_SET); + if (offset != 5) + LOG_ERR("glfs_lseek", errno); + + ret = glfs_write(fd3, buf2, 10, 0); + if (ret == 10 || errno != EAGAIN) + LOG_ERR("glfs_write", errno); + + offset = glfs_lseek(fd3, 8L, SEEK_SET); + if (offset != 8) + LOG_ERR("glfs_lseek", errno); + + ret = glfs_write(fd3, buf2, 10, 0); + if (ret != 10) + LOG_ERR("glfs_write", errno); + + ret = glfs_close(fd1); + if (ret) + LOG_ERR("glfs_close", errno); + fd1 = NULL; + + ret = glfs_close(fd2); + if (ret) + LOG_ERR("glfs_close", errno); + fd2 = NULL; + + ret = glfs_close(fd3); + if (ret) + LOG_ERR("glfs_close", errno); + fd3 = NULL; + + test_count++; + fprintf(fp, "OK\n", i); +} + +int +main(int argc, char *argv[]) +{ + char logfile[50]; + + if (argc != 4) { + fprintf(stderr, + "Usage: %s <server ip/hostname> <volume name> <test log " + "directory>\n", + argv[0]); + return 0; + } + + sprintf(logfile, "%s/%s", argv[3], "mandatory-lock-optimal-test.log"); + fp = fopen(logfile, "w"); + if (!fp) { + fprintf(stderr, "\n%s\n", logfile); + LOG_ERR("Log file creation", errno); + } + + sprintf(logfile, "%s/%s", argv[3], "glfs-client-1.log"); + fs1 = new_client_create(argv[1], argv[2], logfile); + if (!fs1) + LOG_ERR("client-1 creation", EINVAL); + + sprintf(logfile, "%s/%s", argv[3], "glfs-client-2.log"); + fs2 = new_client_create(argv[1], argv[2], logfile); + if (!fs2) + LOG_ERR("client-2 creation", EINVAL); + + sprintf(logfile, "%s/%s", argv[3], "glfs-client-3.log"); + fs3 = new_client_create(argv[1], argv[2], logfile); + if (!fs3) + LOG_ERR("client-3 creation", EINVAL); + + fd = glfs_creat(fs1, fname, O_RDWR, 0644); + if (!fd) + LOG_ERR("glfs_creat", errno); + + test_count = 0; + + run_test_1(1); + run_test_2(2); + run_test_3(3); + run_test_4(4); + run_test_5(5); + run_test_6(6); + run_test_7(7); + run_test_8(8); + + cleanup_and_exit(0); + + return 0; +} diff --git a/tests/basic/gfapi/mandatory-lock-optimal.t b/tests/basic/gfapi/mandatory-lock-optimal.t new file mode 100644 index 00000000000..27062e1f6c2 --- /dev/null +++ b/tests/basic/gfapi/mandatory-lock-optimal.t @@ -0,0 +1,38 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup + +TEST glusterd + +# Create and start the volume +TEST $CLI volume create $V0 $H0:$B0/${V0}1 +TEST $CLI volume start $V0 + +logdir=`gluster --print-logdir` + +# Switch off performance translators +TEST $CLI volume set $V0 performance.open-behind off +TEST $CLI volume set $V0 performance.write-behind off +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.readdir-ahead off + +# Enable optimal mandatory-locking mode and restart the volume +TEST $CLI volume set $V0 locks.mandatory-locking optimal +TEST $CLI volume stop $V0 +TEST $CLI volume start $V0 + +# Compile and run the test program +TEST build_tester $(dirname $0)/mandatory-lock-optimal.c -lgfapi +TEST ./$(dirname $0)/mandatory-lock-optimal $H0 $V0 $logdir + +# Cleanup the environment +cleanup_tester $(dirname $0)/mandatory-lock-optimal +TEST $CLI volume stop $V0 +TEST $CLI volume delete $V0 + +cleanup 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/gfapi/protocol-client.vol.in b/tests/basic/gfapi/protocol-client.vol.in new file mode 100644 index 00000000000..ef35001e29f --- /dev/null +++ b/tests/basic/gfapi/protocol-client.vol.in @@ -0,0 +1,14 @@ +# +# 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 +end-volume + diff --git a/tests/basic/gfapi/seek.c b/tests/basic/gfapi/seek.c index fb2f6361bf3..85ea9b88141 100644 --- a/tests/basic/gfapi/seek.c +++ b/tests/basic/gfapi/seek.c @@ -18,80 +18,82 @@ #include <glusterfs/api/glfs-handles.h> int -main (int argc, char **argv) +main(int argc, char **argv) { - glfs_t *fs = NULL; - int ret = 0; - glfs_fd_t *fd = NULL; - char *filename = NULL; - char *volname = NULL; - char *hostname = NULL; - struct stat st = { 0, }; - off_t hole_start = 0; - off_t hole_end = 0; - - if (argc != 4) { - fprintf (stderr, "Invalid argument, use %s <hostname> <vol> <file>\n", - argv[0]); - exit (1); + glfs_t *fs = NULL; + int ret = 0; + glfs_fd_t *fd = NULL; + char *filename = NULL; + char *volname = NULL; + char *hostname = NULL; + struct stat st = { + 0, + }; + off_t hole_start = 0; + off_t hole_end = 0; + + if (argc != 4) { + fprintf(stderr, "Invalid argument, use %s <hostname> <vol> <file>\n", + argv[0]); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + filename = argv[3]; + + fs = glfs_new(volname); + if (!fs) { + perror("glfs_new() returned NULL"); + return 1; + } + + if (glfs_set_volfile_server(fs, "tcp", hostname, 24007)) { + perror("glfs_set_volfile_server"); + return 1; + } + + if (glfs_init(fs)) { + perror("glfs_init"); + return 1; + } + + fd = glfs_open(fs, filename, O_RDONLY); + if (fd <= 0) { + perror("glfs_open"); + return 1; + } + + if (glfs_fstat(fd, &st)) { + perror("glfs_fstat"); + return 1; + } + + while (hole_end < st.st_size) { + hole_start = glfs_lseek(fd, hole_end, SEEK_HOLE); + if (hole_start == -1 && errno == ENXIO) + /* no more holes */ + break; + if (hole_start == -1) { + perror("no more holes"); + break; } - hostname = argv[1]; - volname = argv[2]; - filename = argv[3]; - - fs = glfs_new (volname); - if (!fs) { - perror ("glfs_new() returned NULL"); - return 1; - } - - if (glfs_set_volfile_server (fs, "tcp", hostname, 24007)) { - perror ("glfs_set_volfile_server"); - return 1; + hole_end = glfs_lseek(fd, hole_start, SEEK_DATA); + if (hole_end == -1 && errno == ENXIO) { + /* no more data */ + break; } - if (glfs_init (fs)) { - perror ("glfs_init"); - return 1; - } + printf("HOLE found: %ld - %ld%s\n", hole_start, hole_end, + (hole_end == st.st_size) ? " (EOF)" : ""); + } - fd = glfs_open (fs, filename, O_RDONLY); - if (fd <= 0) { - perror ("glfs_open"); - return 1; - } + glfs_close(fd); - if (glfs_fstat (fd, &st)) { - perror ("glfs_fstat"); - return 1; - } - - while (hole_end < st.st_size) { - hole_start = glfs_lseek (fd, hole_end, SEEK_HOLE); - if (hole_start == -1 && errno == ENXIO) - /* no more holes */ - break; - if (hole_start == -1) { - perror ("no more holes"); - break; - } - - hole_end = glfs_lseek (fd, hole_start, SEEK_DATA); - if (hole_end == -1 && errno == ENXIO) { - /* no more data */ - break; - } - - printf ("HOLE found: %ld - %ld%s\n", hole_start, hole_end, - (hole_end == st.st_size) ? " (EOF)" : ""); - } - - glfs_close (fd); - - if (fs) { - glfs_fini (fs); - } + if (fs) { + glfs_fini(fs); + } - return ret; + return ret; } diff --git a/tests/basic/gfapi/sink.t b/tests/basic/gfapi/sink.t new file mode 100644 index 00000000000..53af2ecf62d --- /dev/null +++ b/tests/basic/gfapi/sink.t @@ -0,0 +1,13 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup + +TEST build_tester $(dirname ${0})/gfapi-load-volfile.c -lgfapi +TEST ./$(dirname ${0})/gfapi-load-volfile $(dirname $0)/sink.vol + +cleanup_tester $(dirname ${0})/gfapi-load-volfile + +cleanup diff --git a/tests/basic/gfapi/sink.vol b/tests/basic/gfapi/sink.vol new file mode 100644 index 00000000000..d1c92261448 --- /dev/null +++ b/tests/basic/gfapi/sink.vol @@ -0,0 +1,24 @@ +# +# The sink xlator does not do any memory allocations. It only passes the FOPs +# through to the next xlator. +# +# For testing, there is no next xlator needed, we are only interested in the +# resource usage of the Gluster core when gfapi is used. +# +# Note: The sink xlator does not handle any calls. Mounting is possible, but +# any I/O needs additional functionality in the sink xlator. +# +volume sink + type debug/sink + # an option is required, otherwise the graph parsing fails + option an-option-is-required yes +end-volume + +# +# It is possible to test the resource usage of other xlators by adding them in +# the graph before the "sink". +# +#volume mdcache-sink +# type performance/md-cache +# subvolumes sink +#end-volume diff --git a/tests/basic/gfapi/upcall-cache-invalidate.c b/tests/basic/gfapi/upcall-cache-invalidate.c index 9add3381278..078286a8956 100644 --- a/tests/basic/gfapi/upcall-cache-invalidate.c +++ b/tests/basic/gfapi/upcall-cache-invalidate.c @@ -9,204 +9,201 @@ #include <glusterfs/api/glfs.h> #include <glusterfs/api/glfs-handles.h> -#define LOG_ERR(func, ret) do { \ - if (ret != 0) { \ - fprintf (stderr, "%s : returned error %d (%s)\n", \ - func, ret, strerror (errno)); \ - goto out; \ - } else { \ - fprintf (stderr, "%s : returned %d\n", func, ret); \ - } \ - } while (0) +#define LOG_ERR(func, ret) \ + do { \ + if (ret != 0) { \ + fprintf(stderr, "%s : returned error %d (%s)\n", func, ret, \ + strerror(errno)); \ + goto out; \ + } else { \ + fprintf(stderr, "%s : returned %d\n", func, ret); \ + } \ + } while (0) int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - glfs_t *fs = NULL; - glfs_t *fs2 = NULL; - glfs_t *fs_tmp = NULL; - glfs_t *fs_tmp2 = NULL; - int ret = 0, i; - glfs_fd_t *fd = NULL; - glfs_fd_t *fd2 = NULL; - glfs_fd_t *fd_tmp = NULL; - glfs_fd_t *fd_tmp2 = NULL; - char readbuf[32]; - char *filename = "file_tmp"; - char *writebuf = NULL; - char *vol_id = NULL; - unsigned int cnt = 1; - struct glfs_upcall *cbk = NULL; - char *logfile = NULL; - char *volname = NULL; - char *hostname = NULL; - - if (argc != 4) { - fprintf (stderr, "Invalid argument\n"); - exit(1); + glfs_t *fs = NULL; + glfs_t *fs2 = NULL; + glfs_t *fs_tmp = NULL; + glfs_t *fs_tmp2 = NULL; + int ret = 0, i; + glfs_fd_t *fd = NULL; + glfs_fd_t *fd2 = NULL; + glfs_fd_t *fd_tmp = NULL; + glfs_fd_t *fd_tmp2 = NULL; + char readbuf[32]; + char *filename = "file_tmp"; + char *writebuf = NULL; + char *vol_id = NULL; + unsigned int cnt = 1; + struct glfs_upcall *cbk = NULL; + char *logfile = NULL; + char *volname = NULL; + char *hostname = NULL; + + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + fs = glfs_new(volname); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + return -1; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + LOG_ERR("glfs_set_volfile_server", ret); + + ret = glfs_set_logging(fs, logfile, 7); + LOG_ERR("glfs_set_logging", ret); + + ret = glfs_init(fs); + LOG_ERR("glfs_init", ret); + + /* This does not block, but enables caching of events. Real + * applications like NFS-Ganesha run this in a thread before activity + * on the fs (through this instance) happens. */ + ret = glfs_h_poll_upcall(fs_tmp, &cbk); + LOG_ERR("glfs_h_poll_upcall", ret); + + fs2 = glfs_new(volname); + if (!fs2) { + fprintf(stderr, "glfs_new fs2: returned NULL\n"); + return 1; + } + + ret = glfs_set_volfile_server(fs2, "tcp", hostname, 24007); + LOG_ERR("glfs_set_volfile_server-fs2", ret); + + ret = glfs_set_logging(fs2, logfile, 7); + LOG_ERR("glfs_set_logging-fs2", ret); + + ret = glfs_init(fs2); + LOG_ERR("glfs_init-fs2", ret); + + fd = glfs_creat(fs, filename, O_RDWR | O_SYNC, 0644); + if (fd <= 0) { + ret = -1; + LOG_ERR("glfs_creat", ret); + } + fprintf(stderr, "glfs-create fd - %d\n", fd); + + fd2 = glfs_open(fs2, filename, O_SYNC | O_RDWR | O_CREAT); + if (fd2 <= 0) { + ret = -1; + LOG_ERR("glfs_open-fs2", ret); + } + fprintf(stderr, "glfs-open fd2 - %d\n", fd2); + + do { + if (cnt % 2) { + fd_tmp = fd; + fs_tmp = fs; + fd_tmp2 = fd2; + fs_tmp2 = fs2; + } else { + fd_tmp = fd2; + fs_tmp = fs2; + fd_tmp2 = fd; + fs_tmp2 = fs; } - hostname = argv[1]; - volname = argv[2]; - logfile = argv[3]; - - fs = glfs_new (volname); - if (!fs) { - fprintf (stderr, "glfs_new: returned NULL\n"); - return -1; + /* WRITE on fd_tmp */ + writebuf = malloc(10); + if (writebuf) { + memcpy(writebuf, "abcd", 4); + ret = glfs_write(fd_tmp, writebuf, 4, 0); + if (ret <= 0) { + ret = -1; + LOG_ERR("glfs_write", ret); + } else { + fprintf(stderr, "glfs_write succeeded\n"); + } + free(writebuf); + } else { + fprintf(stderr, "Could not allocate writebuf\n"); + return -1; } - ret = glfs_set_volfile_server (fs, "tcp", hostname, 24007); - LOG_ERR("glfs_set_volfile_server", ret); - - ret = glfs_set_logging (fs, logfile, 7); - LOG_ERR("glfs_set_logging", ret); - - ret = glfs_init (fs); - LOG_ERR("glfs_init", ret); + /* READ on fd_tmp2 */ + ret = glfs_lseek(fd_tmp2, 0, SEEK_SET); + LOG_ERR("glfs_lseek", ret); - /* This does not block, but enables caching of events. Real - * applications like NFS-Ganesha run this in a thread before activity - * on the fs (through this instance) happens. */ - ret = glfs_h_poll_upcall(fs_tmp, &cbk); - LOG_ERR ("glfs_h_poll_upcall", ret); + memset(readbuf, 0, sizeof(readbuf)); + ret = glfs_pread(fd_tmp2, readbuf, 4, 0, 0, NULL); - fs2 = glfs_new (volname); - if (!fs2) { - fprintf (stderr, "glfs_new fs2: returned NULL\n"); - return 1; + if (ret <= 0) { + ret = -1; + LOG_ERR("glfs_pread", ret); + } else { + fprintf(stderr, "glfs_read: %s\n", readbuf); } - ret = glfs_set_volfile_server (fs2, "tcp", hostname, 24007); - LOG_ERR("glfs_set_volfile_server-fs2", ret); - - ret = glfs_set_logging (fs2, logfile, 7); - LOG_ERR("glfs_set_logging-fs2", ret); - - ret = glfs_init (fs2); - LOG_ERR("glfs_init-fs2", ret); - - fd = glfs_creat(fs, filename, O_RDWR|O_SYNC, 0644); - if (fd <= 0) { + /* Open() fops seem to be not performed on server side until + * there are I/Os on that fd + */ + if (cnt > 2) { + struct glfs_upcall_inode *in_arg = NULL; + enum glfs_upcall_reason reason = 0; + struct glfs_object *object = NULL; + uint64_t flags = 0; + uint64_t expire = 0; + + ret = glfs_h_poll_upcall(fs_tmp, &cbk); + LOG_ERR("glfs_h_poll_upcall", ret); + + reason = glfs_upcall_get_reason(cbk); + + /* Expect 'GLFS_INODE_INVALIDATE' upcall event. */ + if (reason == GLFS_UPCALL_INODE_INVALIDATE) { + in_arg = glfs_upcall_get_event(cbk); + + object = glfs_upcall_inode_get_object(in_arg); + flags = glfs_upcall_inode_get_flags(in_arg); + expire = glfs_upcall_inode_get_expire(in_arg); + + fprintf(stderr, + " upcall event type - %d," + " object(%p), flags(%d), " + " expire_time_attr(%d)\n", + reason, object, flags, expire); + } else { + fprintf(stderr, "Didn't receive upcall notify event"); ret = -1; - LOG_ERR ("glfs_creat", ret); - } - fprintf (stderr, "glfs-create fd - %d\n", fd); + goto err; + } - fd2 = glfs_open(fs2, filename, O_SYNC|O_RDWR|O_CREAT); - if (fd2 <= 0) { - ret = -1; - LOG_ERR ("glfs_open-fs2", ret); + glfs_free(cbk); } - fprintf (stderr, "glfs-open fd2 - %d\n", fd2); - - do { - if (cnt%2) { - fd_tmp = fd; - fs_tmp = fs; - fd_tmp2 = fd2; - fs_tmp2 = fs2; - } else { - fd_tmp = fd2; - fs_tmp = fs2; - fd_tmp2 = fd; - fs_tmp2 = fs; - } - - /* WRITE on fd_tmp */ - writebuf = malloc(10); - if (writebuf) { - memcpy (writebuf, "abcd", 4); - ret = glfs_write (fd_tmp, writebuf, 4, 0); - if (ret <= 0) { - ret = -1; - LOG_ERR ("glfs_write", ret); - } else { - fprintf (stderr, - "glfs_write suceeded\n"); - } - free(writebuf); - } else { - fprintf (stderr, - "Could not allocate writebuf\n"); - return -1; - } - - /* READ on fd_tmp2 */ - ret = glfs_lseek (fd_tmp2, 0, SEEK_SET); - LOG_ERR ("glfs_lseek", ret); - - memset (readbuf, 0, sizeof(readbuf)); - ret = glfs_pread (fd_tmp2, readbuf, 4, 0, 0); - - if (ret <= 0) { - ret = -1; - LOG_ERR ("glfs_pread", ret); - } else { - fprintf (stderr, "glfs_read: %s\n", readbuf); - } - - /* Open() fops seem to be not performed on server side until - * there are I/Os on that fd - */ - if (cnt > 2) { - struct glfs_upcall_inode *in_arg = NULL; - enum glfs_upcall_reason reason = 0; - struct glfs_object *object = NULL; - uint64_t flags = 0; - uint64_t expire = 0; - - ret = glfs_h_poll_upcall(fs_tmp, &cbk); - LOG_ERR ("glfs_h_poll_upcall", ret); - - reason = glfs_upcall_get_reason (cbk); - - /* Expect 'GLFS_INODE_INVALIDATE' upcall event. */ - if (reason == GLFS_UPCALL_INODE_INVALIDATE) { - in_arg = glfs_upcall_get_event (cbk); - - object = glfs_upcall_inode_get_object (in_arg); - flags = glfs_upcall_inode_get_flags (in_arg); - expire = glfs_upcall_inode_get_expire (in_arg); - - fprintf (stderr, " upcall event type - %d," - " object(%p), flags(%d), " - " expire_time_attr(%d)\n" , - reason, object, flags, expire); - } else { - fprintf (stderr, - "Didnt receive upcall notify event"); - ret = -1; - goto err; - } - - glfs_free (cbk); - } - - sleep(5); - } while (++cnt < 5); + + sleep(5); + } while (++cnt < 5); err: - glfs_close(fd); - LOG_ERR ("glfs_close", ret); + glfs_close(fd); + LOG_ERR("glfs_close", ret); - glfs_close(fd2); - LOG_ERR ("glfs_close-fd2", ret); + glfs_close(fd2); + LOG_ERR("glfs_close-fd2", ret); out: - if (fs) { - ret = glfs_fini(fs); - fprintf (stderr, "glfs_fini(fs) returned %d \n", ret); - } - - if (fs2) { - ret = glfs_fini(fs2); - fprintf (stderr, "glfs_fini(fs2) returned %d \n", ret); - } - - if (ret) - exit(1); - exit(0); + if (fs) { + ret = glfs_fini(fs); + fprintf(stderr, "glfs_fini(fs) returned %d \n", ret); + } + + if (fs2) { + ret = glfs_fini(fs2); + fprintf(stderr, "glfs_fini(fs2) returned %d \n", ret); + } + + if (ret) + exit(1); + exit(0); } - - diff --git a/tests/basic/gfapi/upcall-register-api.c b/tests/basic/gfapi/upcall-register-api.c new file mode 100644 index 00000000000..53ce0ecdb68 --- /dev/null +++ b/tests/basic/gfapi/upcall-register-api.c @@ -0,0 +1,286 @@ +#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(func, ret) \ + do { \ + if (ret != 0) { \ + fprintf(stderr, "%s : returned error %d (%s)\n", func, ret, \ + strerror(errno)); \ + goto out; \ + } else { \ + fprintf(stderr, "%s : returned %d\n", func, ret); \ + } \ + } while (0) + +int upcall_recv = 0; + +void +up_async_invalidate(struct glfs_upcall *up_arg, void *data) +{ + struct glfs_upcall_inode *in_arg = NULL; + enum glfs_upcall_reason reason = 0; + struct glfs_object *object = NULL; + uint64_t flags = 0; + uint64_t expire = 0; + + if (!up_arg) + return; + + reason = glfs_upcall_get_reason(up_arg); + + /* Expect 'GLFS_INODE_INVALIDATE' upcall event. */ + + if (reason == GLFS_UPCALL_INODE_INVALIDATE) { + in_arg = glfs_upcall_get_event(up_arg); + + object = glfs_upcall_inode_get_object(in_arg); + flags = glfs_upcall_inode_get_flags(in_arg); + expire = glfs_upcall_inode_get_expire(in_arg); + + fprintf(stderr, + " upcall event type - %d," + " object(%p), flags(%d), " + " expire_time_attr(%d)\n", + reason, object, flags, expire); + upcall_recv++; + } + + glfs_free(up_arg); + return; +} + +int +perform_io(glfs_t *fs, glfs_t *fs2, int cnt) +{ + glfs_t *fs_tmp = NULL; + glfs_t *fs_tmp2 = NULL; + glfs_fd_t *fd_tmp = NULL; + glfs_fd_t *fd_tmp2 = NULL; + char readbuf[32]; + char *writebuf = NULL; + glfs_fd_t *fd = NULL; + glfs_fd_t *fd2 = NULL; + char *filename = "file_tmp"; + int ret = -1; + + if (!fs || !fs2) + return -1; + + /* Create file from fs and open it from fs2 */ + fd = glfs_creat(fs, filename, O_RDWR | O_SYNC, 0644); + if (fd <= 0) { + ret = -1; + LOG_ERR("glfs_creat", ret); + } + + fd2 = glfs_open(fs2, filename, O_SYNC | O_RDWR | O_CREAT); + if (fd2 <= 0) { + ret = -1; + LOG_ERR("glfs_open-fs2", ret); + } + + do { + if (cnt % 2) { + fd_tmp = fd; + fs_tmp = fs; + fd_tmp2 = fd2; + fs_tmp2 = fs2; + } else { + fd_tmp = fd2; + fs_tmp = fs2; + fd_tmp2 = fd; + fs_tmp2 = fs; + } + + /* WRITE on fd_tmp */ + writebuf = malloc(10); + if (writebuf) { + memcpy(writebuf, "abcd", 4); + ret = glfs_write(fd_tmp, writebuf, 4, 0); + if (ret <= 0) { + ret = -1; + LOG_ERR("glfs_write", ret); + } + free(writebuf); + } else { + fprintf(stderr, "Could not allocate writebuf\n"); + return -1; + } + + /* READ on fd_tmp2 */ + ret = glfs_lseek(fd_tmp2, 0, SEEK_SET); + LOG_ERR("glfs_lseek", ret); + + memset(readbuf, 0, sizeof(readbuf)); + ret = glfs_pread(fd_tmp2, readbuf, 4, 0, 0, NULL); + + if (ret <= 0) { + ret = -1; + LOG_ERR("glfs_pread", ret); + } + + sleep(2); + } while (--cnt > 0); + + sleep(2); + + ret = 0; +err: + glfs_close(fd); + + glfs_close(fd2); + +out: + return ret; +} + +int +main(int argc, char *argv[]) +{ + glfs_t *fs = NULL; + glfs_t *fs2 = NULL; + int ret = 0, i; + char *vol_id = NULL; + unsigned int cnt = 5; + struct glfs_upcall *cbk = NULL; + char *logfile = NULL; + char *volname = NULL; + char *hostname = NULL; + int up_events = GLFS_EVENT_ANY; + + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + /* Initialize fs */ + fs = glfs_new(volname); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + return -1; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + LOG_ERR("glfs_set_volfile_server", ret); + + ret = glfs_set_logging(fs, logfile, 7); + LOG_ERR("glfs_set_logging", ret); + + ret = glfs_init(fs); + LOG_ERR("glfs_init", ret); + + /* Initialize fs2 */ + fs2 = glfs_new(volname); + if (!fs2) { + fprintf(stderr, "glfs_new fs2: returned NULL\n"); + return 1; + } + + ret = glfs_set_volfile_server(fs2, "tcp", hostname, 24007); + LOG_ERR("glfs_set_volfile_server-fs2", ret); + + ret = glfs_set_logging(fs2, logfile, 7); + LOG_ERR("glfs_set_logging-fs2", ret); + + ret = glfs_init(fs2); + LOG_ERR("glfs_init-fs2", ret); + + /* Register Upcalls */ + ret = glfs_upcall_register(fs, up_events, up_async_invalidate, NULL); + + /* Check if the return mask contains the event */ + if (!(ret & GLFS_EVENT_INODE_INVALIDATE)) { + fprintf(stderr, + "glfs_upcall_register return doesn't contain" + " upcall event\n"); + return -1; + } + + ret = glfs_upcall_register(fs2, up_events, up_async_invalidate, NULL); + + /* Check if the return mask contains the event */ + if ((ret < 0) || !(ret & GLFS_EVENT_INODE_INVALIDATE)) { + fprintf(stderr, + "glfs_upcall_register return doesn't contain" + " upcall event\n"); + return -1; + } + + /* Perform I/O */ + ret = perform_io(fs, fs2, cnt); + LOG_ERR("perform_io", ret); + + if (upcall_recv == 0) { + fprintf(stderr, "Upcalls are not received.\n"); + ret = -1; + } else { + fprintf(stderr, "Received %d upcalls as expected\n", upcall_recv); + ret = 0; + } + + sleep(5); /* to flush out previous upcalls if any */ + + /* Now unregister and check there are no upcall events received */ + ret = glfs_upcall_unregister(fs, up_events); + + /* Check if the return mask contains the event */ + if ((ret < 0) || !(ret & GLFS_EVENT_INODE_INVALIDATE)) { + fprintf(stderr, + "glfs_upcall_unregister return doesn't contain" + " upcall event\n"); + return -1; + } + + ret = glfs_upcall_unregister(fs2, up_events); + + /* Check if the return mask contains the event */ + if ((ret < 0) || !(ret & GLFS_EVENT_INODE_INVALIDATE)) { + fprintf(stderr, + "glfs_upcall_unregister return doesn't contain" + " upcall event\n"); + return -1; + } + + upcall_recv = 0; + + ret = perform_io(fs, fs2, cnt); + LOG_ERR("perform_io", ret); + + if (upcall_recv != 0) { + fprintf(stderr, "%d upcalls received even after unregister.\n", + upcall_recv); + ret = -1; + } else { + fprintf(stderr, + "Post unregister, no upcalls received as" + " expected\n"); + ret = 0; + } + +out: + if (fs) { + ret = glfs_fini(fs); + fprintf(stderr, "glfs_fini(fs) returned %d\n", ret); + } + + if (fs2) { + ret = glfs_fini(fs2); + fprintf(stderr, "glfs_fini(fs2) returned %d\n", ret); + } + + if (ret) + exit(1); + exit(0); +} diff --git a/tests/basic/gfapi/upcall-register-api.t b/tests/basic/gfapi/upcall-register-api.t new file mode 100755 index 00000000000..a46234ed7af --- /dev/null +++ b/tests/basic/gfapi/upcall-register-api.t @@ -0,0 +1,30 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +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'; + +logdir=`gluster --print-logdir` + +## Enable Upcall cache-invalidation feature +TEST $CLI volume set $V0 features.cache-invalidation on; + +TEST build_tester $(dirname $0)/upcall-register-api.c -lgfapi + +TEST ./$(dirname $0)/upcall-register-api $H0 $V0 $logdir/upcall-register-api.log + +cleanup_tester $(dirname $0)/upcall-register-api + +TEST $CLI volume stop $V0 +TEST $CLI volume delete $V0 + +cleanup; diff --git a/tests/basic/gfproxy.t b/tests/basic/gfproxy.t new file mode 100755 index 00000000000..7aa8b70b793 --- /dev/null +++ b/tests/basic/gfproxy.t @@ -0,0 +1,71 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../nfs.rc + +function file_exists +{ + if [ -f $1 ]; then echo "Y"; else echo "N"; fi +} + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2} +TEST $CLI volume set $V0 config.gfproxyd enable +TEST $CLI volume set $V0 failover-hosts "127.0.0.1,192.168.122.215,192.168.122.90" +TEST $CLI volume set $V0 client-log-level TRACE +TEST $CLI volume start $V0 + +sleep 2 + +REGULAR_CLIENT_VOLFILE="/var/lib/glusterd/vols/${V0}/trusted-${V0}.tcp-fuse.vol" +GFPROXY_CLIENT_VOLFILE="/var/lib/glusterd/vols/${V0}/trusted-${V0}.tcp-gfproxy-fuse.vol" +GFPROXYD_VOLFILE="/var/lib/glusterd/vols/${V0}/${V0}.gfproxyd.vol" + +# Client volfile must exist +TEST [ -f $GFPROXY_CLIENT_VOLFILE ] + +# write-behind translators must exist +TEST grep "performance/write-behind" $GFPROXY_CLIENT_VOLFILE + +# Make sure we didn't screw up the existing client +TEST grep "performance/write-behind" $REGULAR_CLIENT_VOLFILE +TEST grep "cluster/replicate" $REGULAR_CLIENT_VOLFILE +TEST grep "cluster/distribute" $REGULAR_CLIENT_VOLFILE + +TEST [ -f $GFPROXYD_VOLFILE ] + +TEST grep "cluster/replicate" $GFPROXYD_VOLFILE +TEST grep "cluster/distribute" $GFPROXYD_VOLFILE + +# write-behind must *not* exist +TEST ! grep "performance/write-behind" $GFPROXYD_VOLFILE + +# Test that we can start the server and the client +TEST glusterfs --thin-client --volfile-id=patchy --volfile-server=$H0 -l /var/log/glusterfs/${V0}-gfproxy-client.log $M0 +sleep 2 +TEST grep gfproxy-client/${V0} /proc/mounts + +# Write data to the mount and checksum it +TEST dd if=/dev/urandom bs=1M count=10 of=/tmp/testfile1 +md5=$(md5sum /tmp/testfile1 | awk '{print $1}') +TEST cp -v /tmp/testfile1 $M0/testfile1 +TEST [ "$(md5sum $M0/testfile1 | awk '{print $1}')" == "$md5" ] + +rm /tmp/testfile1 + +dd if=/dev/zero of=$M0/bigfile bs=1K count=10240 & +BG_STRESS_PID=$! + +TEST wait $BG_STRESS_PID + +# Perform graph change and make sure the gfproxyd restarts +TEST $CLI volume set $V0 stat-prefetch off + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" file_exists $M0/bigfile + +cleanup; +#G_TESTDEF_TEST_STATUS_NETBSD7=1501392 diff --git a/tests/basic/global-threading.t b/tests/basic/global-threading.t new file mode 100644 index 00000000000..f7d34044b09 --- /dev/null +++ b/tests/basic/global-threading.t @@ -0,0 +1,104 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +# Test if the given process has a number of threads of a given type between +# min and max. +function check_threads() { + local pid="${1}" + local pattern="${2}" + local min="${3}" + local max="${4-}" + local count + + count="$(ps hH -o comm ${pid} | grep "${pattern}" | wc -l)" + if [[ ${min} -gt ${count} ]]; then + return 1 + fi + if [[ ! -z "${max}" && ${max} -lt ${count} ]]; then + return 1 + fi + + return 0 +} + +cleanup + +TEST glusterd + +# Glusterd shouldn't use any thread +TEST check_threads $(get_glusterd_pid) glfs_tpw 0 0 +TEST check_threads $(get_glusterd_pid) glfs_iotwr 0 0 + +TEST pkill -9 glusterd + +TEST glusterd --global-threading + +# Glusterd shouldn't use global threads, even if enabled +TEST check_threads $(get_glusterd_pid) glfs_tpw 0 0 +TEST check_threads $(get_glusterd_pid) glfs_iotwr 0 0 + +TEST $CLI volume create $V0 replica 2 $H0:$B0/b{0,1} + +# Normal configuration using io-threads on bricks +TEST $CLI volume set $V0 config.global-threading off +TEST $CLI volume set $V0 performance.iot-pass-through off +TEST $CLI volume set $V0 performance.client-io-threads off +TEST $CLI volume start $V0 + +# There shouldn't be global threads +TEST check_threads $(get_brick_pid $V0 $H0 $B0/b0) glfs_tpw 0 0 +TEST check_threads $(get_brick_pid $V0 $H0 $B0/b1) glfs_tpw 0 0 + +# There should be at least 1 io-thread +TEST check_threads $(get_brick_pid $V0 $H0 $B0/b0) glfs_iotwr 1 +TEST check_threads $(get_brick_pid $V0 $H0 $B0/b1) glfs_iotwr 1 + +# Self-heal should be using global threads +TEST check_threads $(get_shd_process_pid) glfs_tpw 1 +TEST check_threads $(get_shd_process_pid) glfs_iotwr 0 0 + +TEST $CLI volume stop $V0 + +# Configuration with global threads on bricks +TEST $CLI volume set $V0 config.global-threading on +TEST $CLI volume set $V0 performance.iot-pass-through on +TEST $CLI volume start $V0 + +# There should be at least 1 global thread +TEST check_threads $(get_brick_pid $V0 $H0 $B0/b0) glfs_tpw 1 +TEST check_threads $(get_brick_pid $V0 $H0 $B0/b1) glfs_tpw 1 + +# There shouldn't be any io-thread worker threads +TEST check_threads $(get_brick_pid $V0 $H0 $B0/b0) glfs_iotwr 0 0 +TEST check_threads $(get_brick_pid $V0 $H0 $B0/b1) glfs_iotwr 0 0 + +# Normal configuration using io-threads on clients +TEST $CLI volume set $V0 performance.iot-pass-through off +TEST $CLI volume set $V0 performance.client-io-threads on +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 + +# There shouldn't be global threads +TEST check_threads $(get_mount_process_pid $V0 $M0) glfs_tpw 0 0 + +# There should be at least 1 io-thread +TEST check_threads $(get_mount_process_pid $V0 $M0) glfs_iotwr 1 + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +# Configuration with global threads on clients +TEST $CLI volume set $V0 performance.client-io-threads off +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 --global-threading $M0 + +# There should be at least 1 global thread +TEST check_threads $(get_mount_process_pid $V0 $M0) glfs_tpw 1 + +# There shouldn't be io-threads +TEST check_threads $(get_mount_process_pid $V0 $M0) glfs_iotwr 0 0 + +# Some basic volume access checks with global-threading enabled everywhere +TEST mkdir ${M0}/dir +TEST dd if=/dev/zero of=${M0}/dir/file bs=128k count=8 + +cleanup diff --git a/tests/basic/glusterd-restart-shd-mux.t b/tests/basic/glusterd-restart-shd-mux.t new file mode 100644 index 00000000000..46d0dac2fce --- /dev/null +++ b/tests/basic/glusterd-restart-shd-mux.t @@ -0,0 +1,96 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +TESTS_EXPECTED_IN_LOOP=20 + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2,3,4,5} +TEST $CLI volume set $V0 cluster.background-self-heal-count 0 +TEST $CLI volume set $V0 cluster.eager-lock off +TEST $CLI volume set $V0 performance.flush-behind off +TEST $CLI volume start $V0 + +for i in $(seq 1 3); do + TEST $CLI volume create ${V0}_afr$i replica 3 $H0:$B0/${V0}_afr${i}{0,1,2,3,4,5} + TEST $CLI volume start ${V0}_afr$i + TEST $CLI volume create ${V0}_ec$i disperse 6 redundancy 2 $H0:$B0/${V0}_ec${i}{0,1,2,3,4,5} + TEST $CLI volume start ${V0}_ec$i +done + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" shd_count + +#Stop the glusterd +TEST pkill glusterd +#Only stopping glusterd, so there will be one shd +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^1$" shd_count +TEST glusterd +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" shd_count +#Check the thread count become to number of volumes*number of ec subvolume (3*6=18) +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^18$" number_healer_threads_shd $V0 "ec_shd_index_healer" +#Check the thread count become to number of volumes*number of afr subvolume (4*6=24) +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^24$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +shd_pid=$(get_shd_mux_pid $V0) +for i in $(seq 1 3); do + afr_path="/var/run/gluster/shd/${V0}_afr$i/${V0}_afr$i-shd.pid" + EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^${shd_pid}$" cat $afr_path + ec_path="/var/run/gluster/shd/${V0}_ec$i/${V0}_ec${i}-shd.pid" + EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^${shd_pid}$" cat $ec_path +done + +#Reboot a node scenario +TEST pkill gluster +#Only stopped glusterd, so there will be one shd +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^0$" shd_count + +TEST glusterd +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" shd_count + +#Check the thread count become to number of volumes*number of ec subvolume (3*6=18) +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^18$" number_healer_threads_shd $V0 "ec_shd_index_healer" +#Check the thread count become to number of volumes*number of afr subvolume (4*6=24) +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^24$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +shd_pid=$(get_shd_mux_pid $V0) +for i in $(seq 1 3); do + afr_path="/var/run/gluster/shd/${V0}_afr$i/${V0}_afr$i-shd.pid" + EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^${shd_pid}$" cat $afr_path + ec_path="/var/run/gluster/shd/${V0}_ec$i/${V0}_ec${i}-shd.pid" + EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^${shd_pid}$" cat $ec_path +done + +for i in $(seq 1 3); do + TEST $CLI volume stop ${V0}_afr$i + TEST $CLI volume stop ${V0}_ec$i +done + +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^6$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 + +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}3 + +TEST touch $M0/foo{1..100} + +EXPECT_WITHIN $HEAL_TIMEOUT "^204$" get_pending_heal_count $V0 + +TEST $CLI volume start ${V0} force + +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +TEST rm -rf $M0/* +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + + +TEST $CLI volume stop ${V0} +TEST $CLI volume delete ${V0} + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^0$" shd_count + +cleanup diff --git a/tests/basic/glusterd/arbiter-volume.t b/tests/basic/glusterd/arbiter-volume.t deleted file mode 100644 index 03f9aca2daf..00000000000 --- a/tests/basic/glusterd/arbiter-volume.t +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc - -# This command tests the volume create command validation for arbiter volumes. - -cleanup; -TEST glusterd -TEST pidof glusterd - -TEST $CLI volume create $V0 replica 3 arbiter 1 $H0:$B0/b1 $H0:$B0/b2 $H0:$B0/b3 -EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks" - -TEST $CLI volume delete $V0 -TEST $CLI volume create $V0 replica 3 arbiter 1 $H0:$B0/b{4..9} -EXPECT "2 x \(2 \+ 1\) = 6" volinfo_field $V0 "Number of Bricks" - -TEST $CLI volume delete $V0 -TEST $CLI volume create $V0 stripe 2 replica 3 arbiter 1 $H0:$B0/b{10..15} -EXPECT "1 x 2 x \(2 \+ 1\) = 6" volinfo_field $V0 "Number of Bricks" - -TEST $CLI volume delete $V0 -TEST rm -rf $B0/b{1..3} -TEST $CLI volume create $V0 replica 3 arbiter 1 $H0:$B0/b1 $H0:$B0/b2 $H0:$B0/b3 -EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks" -TEST killall -15 glusterd -TEST glusterd -TEST pidof glusterd -EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks" - -#cleanup diff --git a/tests/basic/glusterd/check-cloudsync-ancestry.t b/tests/basic/glusterd/check-cloudsync-ancestry.t new file mode 100644 index 00000000000..ff6ffee8db7 --- /dev/null +++ b/tests/basic/glusterd/check-cloudsync-ancestry.t @@ -0,0 +1,48 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +# When shard and cloudsync xlators enabled on a volume, shard xlator +# should be an ancestor of cloudsync. This testcase is to check this condition. + +cleanup; +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 $H0:$B0/b1 $H0:$B0/b2 $H0:$B0/b3 + +volfile=$(gluster system:: getwd)"/vols/$V0/trusted-$V0.tcp-fuse.vol" + +#Test that both shard and cloudsync are not loaded +EXPECT "N" volgen_volume_exists $volfile $V0-shard features shard +EXPECT "N" volgen_volume_exists $volfile $V0-cloudsync features cloudsync + +#Enable shard and cloudsync in that order and check if volfile is correct +TEST $CLI volume set $V0 shard on +TEST $CLI volume set $V0 cloudsync on + +#Test that both shard and cloudsync are loaded +EXPECT "Y" volgen_volume_exists $volfile $V0-shard features shard +EXPECT "Y" volgen_volume_exists $volfile $V0-cloudsync features cloudsync + +EXPECT "Y" volgen_check_ancestry $volfile features shard features cloudsync + +#Disable shard and cloudsync +TEST $CLI volume set $V0 shard off +TEST $CLI volume set $V0 cloudsync off + +#Test that both shard and cloudsync are not loaded +EXPECT "N" volgen_volume_exists $volfile $V0-shard features shard +EXPECT "N" volgen_volume_exists $volfile $V0-cloudsync features cloudsync + +#Enable cloudsync and shard in that order and check if volfile is correct +TEST $CLI volume set $V0 cloudsync on +TEST $CLI volume set $V0 shard on + +#Test that both shard and cloudsync are loaded +EXPECT "Y" volgen_volume_exists $volfile $V0-shard features shard +EXPECT "Y" volgen_volume_exists $volfile $V0-cloudsync features cloudsync + +EXPECT "Y" volgen_check_ancestry $volfile features shard features cloudsync + +cleanup; diff --git a/tests/basic/glusterd/disperse-create.t b/tests/basic/glusterd/disperse-create.t index e5ce74c12b2..db8a621d48e 100644 --- a/tests/basic/glusterd/disperse-create.t +++ b/tests/basic/glusterd/disperse-create.t @@ -20,6 +20,10 @@ TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/b7 $H0:$B0/b8 $H0:$B EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks" TEST $CLI volume delete $V0 +TEST $CLI volume create $V0 disperse-data 2 $H0:$B0/b10 $H0:$B0/b11 $H0:$B0/b12 +EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks" + +TEST $CLI volume delete $V0 TEST $CLI volume create $V0 redundancy 1 $H0:$B0/b10 $H0:$B0/b11 $H0:$B0/b12 EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks" @@ -48,6 +52,7 @@ TEST ! $CLI volume create $V0 redundancy 1 redundancy 1 $H0:$B0/b20 $H0:$B0/b21 #Minimum counts test TEST ! $CLI volume create $V0 disperse 2 $H0:$B0/b20 $H0:$B0/b22 TEST ! $CLI volume create $V0 disperse-data 1 redundancy 0 $H0:$B0/b20 $H0:$B0/b22 +TEST ! $CLI volume create $V0 disperse 4 disperse-data 4 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b23 $H0:$B0/b24 TEST ! $CLI volume create $V0 redundancy 0 $H0:$B0/b20 $H0:$B0/b22 #Wrong count n != k+m @@ -64,18 +69,5 @@ TEST ! $CLI volume create $V0 redundancy 2 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0 TEST ! $CLI volume create $V0 replica 2 disperse 4 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 TEST ! $CLI volume create $V0 replica 2 disperse-data 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 $H0:$B0/b23 TEST ! $CLI volume create $V0 replica 2 redundancy 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 -#Stripe + Disperse -TEST ! $CLI volume create $V0 disperse 4 stripe 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 -TEST ! $CLI volume create $V0 disperse-data 2 stripe 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 $H0:$B0/b23 -TEST ! $CLI volume create $V0 redundancy 2 stripe 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 -TEST ! $CLI volume create $V0 stripe 2 disperse 4 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 -TEST ! $CLI volume create $V0 stripe 2 disperse-data 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 $H0:$B0/b23 -TEST ! $CLI volume create $V0 stripe 2 redundancy 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 -#Stripe + Replicate + Disperse, It is failing with striped-dispersed volume. -TEST ! $CLI volume create $V0 disperse 4 stripe 2 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 -TEST ! $CLI volume create $V0 disperse-data 2 stripe 2 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 $H0:$B0/b23 -TEST ! $CLI volume create $V0 redundancy 2 stripe 2 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 -TEST ! $CLI volume create $V0 stripe 2 disperse 4 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 -TEST ! $CLI volume create $V0 stripe 2 disperse-data 2 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 $H0:$B0/b23 -TEST ! $CLI volume create $V0 stripe 2 redundancy 2 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 + cleanup diff --git a/tests/basic/glusterd/heald.t b/tests/basic/glusterd/heald.t index bdfda8ff0d6..7dae3c3f0fb 100644 --- a/tests/basic/glusterd/heald.t +++ b/tests/basic/glusterd/heald.t @@ -7,70 +7,73 @@ # Covers enable/disable at the moment. Will be enhanced later to include # the other commands as well. +function is_pid_running { + local pid=$1 + num=`ps auxww | grep glustershd | grep $pid | grep -v grep | wc -l` + echo $num +} + cleanup; TEST glusterd TEST pidof glusterd -volfile=$(gluster system:: getwd)"/glustershd/glustershd-server.vol" #Commands should fail when volume doesn't exist TEST ! $CLI volume heal non-existent-volume enable TEST ! $CLI volume heal non-existent-volume disable -# Commands should fail when volume is of distribute/stripe type. # Glustershd shouldn't be running as long as there are no replicate/disperse # volumes TEST $CLI volume create dist $H0:$B0/dist TEST $CLI volume start dist -TEST "[ -z $(get_shd_process_pid)]" +TEST "[ -z $(get_shd_process_pid dist)]" TEST ! $CLI volume heal dist enable TEST ! $CLI volume heal dist disable -TEST $CLI volume create st stripe 3 $H0:$B0/st1 $H0:$B0/st2 $H0:$B0/st3 -TEST $CLI volume start st -TEST "[ -z $(get_shd_process_pid)]" -TEST ! $CLI volume heal st -TEST ! $CLI volume heal st disable # Commands should work on replicate/disperse volume. TEST $CLI volume create r2 replica 2 $H0:$B0/r2_0 $H0:$B0/r2_1 -TEST "[ -z $(get_shd_process_pid)]" +TEST "[ -z $(get_shd_process_pid r2)]" TEST $CLI volume start r2 -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid r2 TEST $CLI volume heal r2 enable EXPECT "enable" volume_option r2 "cluster.self-heal-daemon" -EXPECT "enable" volgen_volume_option $volfile r2-replicate-0 cluster replicate self-heal-daemon -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid +volfiler2=$(gluster system:: getwd)"/vols/r2/r2-shd.vol" +EXPECT "enable" volgen_volume_option $volfiler2 r2-replicate-0 cluster replicate self-heal-daemon +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid r2 +pid=$( get_shd_process_pid r2 ) TEST $CLI volume heal r2 disable EXPECT "disable" volume_option r2 "cluster.self-heal-daemon" -EXPECT "disable" volgen_volume_option $volfile r2-replicate-0 cluster replicate self-heal-daemon -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid +EXPECT "disable" volgen_volume_option $volfiler2 r2-replicate-0 cluster replicate self-heal-daemon +EXPECT "1" is_pid_running $pid # Commands should work on disperse volume. TEST $CLI volume create ec2 disperse 3 redundancy 1 $H0:$B0/ec2_0 $H0:$B0/ec2_1 $H0:$B0/ec2_2 TEST $CLI volume start ec2 -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid ec2 TEST $CLI volume heal ec2 enable EXPECT "enable" volume_option ec2 "cluster.disperse-self-heal-daemon" -EXPECT "enable" volgen_volume_option $volfile ec2-disperse-0 cluster disperse self-heal-daemon -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid +volfileec2=$(gluster system:: getwd)"/vols/ec2/ec2-shd.vol" +EXPECT "enable" volgen_volume_option $volfileec2 ec2-disperse-0 cluster disperse self-heal-daemon +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid ec2 +pid=$(get_shd_process_pid ec2) TEST $CLI volume heal ec2 disable EXPECT "disable" volume_option ec2 "cluster.disperse-self-heal-daemon" -EXPECT "disable" volgen_volume_option $volfile ec2-disperse-0 cluster disperse self-heal-daemon -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid +EXPECT "disable" volgen_volume_option $volfileec2 ec2-disperse-0 cluster disperse self-heal-daemon +EXPECT "1" is_pid_running $pid #Check that shd graph is rewritten correctly on volume stop/start -EXPECT "Y" volgen_volume_exists $volfile ec2-disperse-0 cluster disperse -EXPECT "Y" volgen_volume_exists $volfile r2-replicate-0 cluster replicate +EXPECT "Y" volgen_volume_exists $volfileec2 ec2-disperse-0 cluster disperse + +EXPECT "Y" volgen_volume_exists $volfiler2 r2-replicate-0 cluster replicate TEST $CLI volume stop r2 -EXPECT "Y" volgen_volume_exists $volfile ec2-disperse-0 cluster disperse -EXPECT "N" volgen_volume_exists $volfile r2-replicate-0 cluster replicate +EXPECT "Y" volgen_volume_exists $volfileec2 ec2-disperse-0 cluster disperse TEST $CLI volume stop ec2 # When both the volumes are stopped glustershd volfile is not modified just the # process is stopped -TEST "[ -z $(get_shd_process_pid) ]" +TEST "[ -z $(get_shd_process_pid dist) ]" +TEST "[ -z $(get_shd_process_pid ec2) ]" TEST $CLI volume start r2 -EXPECT "N" volgen_volume_exists $volfile ec2-disperse-0 cluster disperse -EXPECT "Y" volgen_volume_exists $volfile r2-replicate-0 cluster replicate +EXPECT "Y" volgen_volume_exists $volfiler2 r2-replicate-0 cluster replicate TEST $CLI volume set r2 self-heal-daemon on TEST $CLI volume set r2 cluster.self-heal-daemon off diff --git a/tests/basic/glusterd/thin-arbiter-volume-probe.t b/tests/basic/glusterd/thin-arbiter-volume-probe.t new file mode 100644 index 00000000000..acc6943806d --- /dev/null +++ b/tests/basic/glusterd/thin-arbiter-volume-probe.t @@ -0,0 +1,25 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../cluster.rc + +#This tests if the thin-arbiter-count is transferred to the other peer. +function check_peers { + $CLI_1 peer status | grep 'Peer in Cluster (Connected)' | wc -l +} + +cleanup; + +TEST launch_cluster 2; +TEST $CLI_1 peer probe $H2; + +EXPECT_WITHIN $PROBE_TIMEOUT 1 check_peers + +kill_glusterd 2 +$CLI_1 volume create $V0 replica 2 thin-arbiter 1 $H0:$B0/b{1..3} +TEST $glusterd_2 +EXPECT_WITHIN $PROBE_TIMEOUT 1 check_peers +EXPECT "1 x 2 = 2" volinfo_field_1 $V0 "Number of Bricks" +EXPECT "1 x 2 = 2" volinfo_field_2 $V0 "Number of Bricks" + +cleanup; diff --git a/tests/basic/glusterd/thin-arbiter-volume.t b/tests/basic/glusterd/thin-arbiter-volume.t new file mode 100644 index 00000000000..4e813890a45 --- /dev/null +++ b/tests/basic/glusterd/thin-arbiter-volume.t @@ -0,0 +1,45 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../ volume.rc +. $(dirname $0)/../../thin-arbiter.rc + +#This command tests the volume create command validation for thin-arbiter volumes. + +cleanup; + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 replica 2 thin-arbiter 1 $H0:$B0/b1 $H0:$B0/b2 $H0:$B0/b3 +EXPECT "1 x 2 = 2" volinfo_field $V0 "Number of Bricks" +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; + +TEST touch $M0/a.txt +TEST ls $B0/b1/a.txt +TEST ls $B0/b2/a.txt +TEST ! ls $B0/b3/a.txt + +TEST umount $M0 +TEST $CLI volume stop $V0 +TEST $CLI volume delete $V0 + +TEST $CLI volume create $V0 replica 2 thin-arbiter 1 $H0:$B0/b{4..8} +EXPECT "2 x 2 = 4" volinfo_field $V0 "Number of Bricks" + +TEST $CLI volume delete $V0 + +TEST rm -rf $B0/b{1..3} + +TEST $CLI volume create $V0 replica 2 thin-arbiter 1 $H0:$B0/b1 $H0:$B0/b2 $H0:$B0/b3 +EXPECT "1 x 2 = 2" volinfo_field $V0 "Number of Bricks" + +TEST killall -15 glusterd +TEST glusterd +TEST pidof glusterd +EXPECT "1 x 2 = 2" volinfo_field $V0 "Number of Bricks" + +cleanup + diff --git a/tests/basic/glusterd/volfile_server_switch.t b/tests/basic/glusterd/volfile_server_switch.t index 0b0e6470244..e11cfed509a 100644 --- a/tests/basic/glusterd/volfile_server_switch.t +++ b/tests/basic/glusterd/volfile_server_switch.t @@ -18,12 +18,10 @@ cleanup; TEST launch_cluster 3; -TEST $CLI_1 peer probe $H1; - TEST $CLI_1 peer probe $H2; +EXPECT_WITHIN $PROBE_TIMEOUT 1 peer_count TEST $CLI_1 peer probe $H3; - EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count TEST $CLI_1 volume create $V0 $H1:$B1/$V0 $H2:$B2/$V0 $H3:$B3/$V0 @@ -36,7 +34,7 @@ TEST glusterfs --volfile-id=/$V0 --volfile-server=$H1 --volfile-server=$H2 --vol TEST kill_glusterd 1 -TEST $CLI_2 volume set $V0 performance.io-cache off +TEST $CLI_2 volume set $V0 performance.write-behind off # make sure by this time directory will be created # TODO: suggest ideal time to wait diff --git a/tests/basic/glusterd/volume-brick-count.t b/tests/basic/glusterd/volume-brick-count.t new file mode 100644 index 00000000000..dc1a5278f4f --- /dev/null +++ b/tests/basic/glusterd/volume-brick-count.t @@ -0,0 +1,61 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +function test_volume_config() +{ + volname=$1 + type_string=$2 + brickCount=$3 + distCount=$4 + replicaCount=$5 + arbiterCount=$6 + disperseCount=$7 + redundancyCount=$8 + + EXPECT "$type_string" volinfo_field $volname "Number of Bricks" + EXPECT "$brickCount" get-xml "volume info $volname" "brickCount" + EXPECT "$distCount" get-xml "volume info $volname" "distCount" + EXPECT "$replicaCount" get-xml "volume info $volname" "replicaCount" + EXPECT "$arbiterCount" get-xml "volume info $volname" "arbiterCount" + EXPECT "$disperseCount" get-xml "volume info $volname" "disperseCount" + EXPECT "$redundancyCount" get-xml "volume info $volname" "redundancyCount" +} + +# This command tests the volume create command and number of bricks for different volume types. +cleanup; +TESTS_EXPECTED_IN_LOOP=56 +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create ${V0}_1 replica 3 arbiter 1 $H0:$B0/b1 $H0:$B0/b2 $H0:$B0/b3 +test_volume_config "${V0}_1" "1 x \(2 \+ 1\) = 3" "3" "1" "3" "1" "0" "0" + +TEST $CLI volume create ${V0}_2 replica 3 arbiter 1 $H0:$B0/b{4..9} +test_volume_config "${V0}_2" "2 x \(2 \+ 1\) = 6" "6" "2" "3" "1" "0" "0" + + +TEST $CLI volume create ${V0}_3 replica 3 arbiter 1 $H0:$B0/b{10..12} +test_volume_config "${V0}_3" "1 x \(2 \+ 1\) = 3" "3" "1" "3" "1" "0" "0" +TEST killall -15 glusterd +TEST glusterd +TEST pidof glusterd +test_volume_config "${V0}_3" "1 x \(2 \+ 1\) = 3" "3" "1" "3" "1" "0" "0" + +TEST $CLI volume create ${V0}_4 replica 3 $H0:$B0/b{13..15} +test_volume_config "${V0}_4" "1 x 3 = 3" "3" "1" "3" "0" "0" "0" + +TEST $CLI volume create ${V0}_5 replica 3 $H0:$B0/b{16..21} +test_volume_config "${V0}_5" "2 x 3 = 6" "6" "2" "3" "0" "0" "0" + +TEST $CLI volume create ${V0}_6 disperse 3 redundancy 1 $H0:$B0/b{22..24} +test_volume_config "${V0}_6" "1 x \(2 \+ 1\) = 3" "3" "1" "1" "0" "3" "1" + +TEST $CLI volume create ${V0}_7 disperse 3 redundancy 1 $H0:$B0/b{25..30} +test_volume_config "${V0}_7" "2 x \(2 \+ 1\) = 6" "6" "2" "1" "0" "3" "1" + +TEST $CLI volume create ${V0}_8 $H0:$B0/b{31..33} +test_volume_config "${V0}_8" "3" "3" "3" "1" "0" "0" "0" + +cleanup diff --git a/tests/basic/glusterfsd-args.t b/tests/basic/glusterfsd-args.t new file mode 100644 index 00000000000..2dd84b8c29e --- /dev/null +++ b/tests/basic/glusterfsd-args.t @@ -0,0 +1,5 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc + +EXPECT $GLUSTER_LIBEXECDIR glusterfsd --print-libexecdir diff --git a/tests/basic/graph-cleanup-brick-down-shd-mux.t b/tests/basic/graph-cleanup-brick-down-shd-mux.t new file mode 100644 index 00000000000..3c621cdcc26 --- /dev/null +++ b/tests/basic/graph-cleanup-brick-down-shd-mux.t @@ -0,0 +1,64 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +TESTS_EXPECTED_IN_LOOP=4 + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2,3,4,5} +TEST $CLI volume set $V0 cluster.background-self-heal-count 0 +TEST $CLI volume set $V0 cluster.eager-lock off +TEST $CLI volume set $V0 performance.flush-behind off +TEST $CLI volume start $V0 + +for i in $(seq 1 2); do + TEST $CLI volume create ${V0}_afr$i replica 3 $H0:$B0/${V0}_afr${i}{0,1,2,3,4,5} + TEST $CLI volume start ${V0}_afr$i + TEST $CLI volume create ${V0}_ec$i disperse 6 redundancy 2 $H0:$B0/${V0}_ec${i}{0,1,2,3,4,5} + TEST $CLI volume start ${V0}_ec$i +done + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" shd_count +#Check the thread count become to number of volumes*number of ec subvolume (2*6=12) +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^12$" number_healer_threads_shd $V0 "ec_shd_index_healer" +#Check the thread count become to number of volumes*number of afr subvolume (3*6=18) +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^18$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +#kill one brick and test cleanup +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST $CLI volume stop $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^12$" number_healer_threads_shd ${V0}_afr1 "afr_shd_index_healer" +TEST $CLI volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^18$" number_healer_threads_shd ${V0}_afr1 "afr_shd_index_healer" + +#kill an entire subvol and test cleanup +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST kill_brick $V0 $H0 $B0/${V0}2 +#wait for some time to create a race sceanrio +sleep 1 +TEST $CLI volume stop $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^12$" number_healer_threads_shd ${V0}_afr1 "afr_shd_index_healer" +TEST $CLI volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^18$" number_healer_threads_shd ${V0}_afr1 "afr_shd_index_healer" + +#kill all bricks and test cleanup +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}1 +TEST kill_brick $V0 $H0 $B0/${V0}2 +TEST kill_brick $V0 $H0 $B0/${V0}3 +TEST kill_brick $V0 $H0 $B0/${V0}4 +TEST kill_brick $V0 $H0 $B0/${V0}5 +#wait for some time to create a race sceanrio +sleep 2 + +TEST $CLI volume stop $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^12$" number_healer_threads_shd ${V0}_afr1 "afr_shd_index_healer" +TEST $CLI volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^18$" number_healer_threads_shd ${V0}_afr1 "afr_shd_index_healer" + +cleanup diff --git a/tests/basic/hardlink-limit.t b/tests/basic/hardlink-limit.t new file mode 100644 index 00000000000..ee65c650b59 --- /dev/null +++ b/tests/basic/hardlink-limit.t @@ -0,0 +1,44 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../dht.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +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 + +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; +TEST $CLI volume set $V0 storage.max-hardlinks 3 +TEST glusterfs -s $H0 --volfile-id $V0 $M0; + +TEST dd if=/dev/zero of=$M0/testfile count=1 + +# max-hardlinks is 3, should be able to create 2 links. +TEST link $M0/testfile $M0/testfile.link1 +TEST link $M0/testfile $M0/testfile.link2 + +# But not 3. +TEST ! link $M0/testfile $M0/testfile.link3 +# If we remove one... +TEST rm $M0/testfile.link1 +# Now we can add one. +TEST link $M0/testfile $M0/testfile.link3 + +# But not another +TEST ! link $M0/testfile $M0/testfile.link4 + +# Unless we disable the limit... +TEST $CLI volume set $V0 storage.max-hardlinks 0 +TEST link $M0/testfile $M0/testfile.link4 + +cleanup; diff --git a/tests/basic/inode-leak.t b/tests/basic/inode-leak.t new file mode 100644 index 00000000000..e112fdddf8a --- /dev/null +++ b/tests/basic/inode-leak.t @@ -0,0 +1,31 @@ +#!/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/${V0}{0,1,2,3} +TEST $CLI volume start $V0 +TEST glusterfs -s $H0 --volfile-id $V0 $M0 + +EXPECT "1" get_mount_active_size_value $V0 $M0 +EXPECT "0" get_mount_lru_size_value $V0 $M0 + +TEST cp -rf /etc $M0 +TEST find $M0 +TEST rm -rf $M0/* + +EXPECT "1" get_mount_active_size_value $V0 $M0 +EXPECT "0" get_mount_lru_size_value $V0 $M0 + +cleanup + +# Mainly marking it as known-issue as it is taking a *lot* of time. +# Revert back if we are below an hour in regression runs. +# Or consider running only in nightly regressions. + +#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 +#G_TESTDEF_TEST_STATUS_CENTOS6=KNOWN_ISSUE,BUG=000000 diff --git a/tests/basic/inode-quota-enforcing.t b/tests/basic/inode-quota-enforcing.t index d2067b2807c..d666395dab1 100644 --- a/tests/basic/inode-quota-enforcing.t +++ b/tests/basic/inode-quota-enforcing.t @@ -98,4 +98,3 @@ EXPECT_WITHIN $MARKER_UPDATE_TIMEOUT "0" quota_object_list_field "/test_dir" 4 rm -f $QDD cleanup; #G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=1332021 -#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=1332021 diff --git a/tests/basic/ios-dump.t b/tests/basic/ios-dump.t new file mode 100644 index 00000000000..0cfbdc6ae7c --- /dev/null +++ b/tests/basic/ios-dump.t @@ -0,0 +1,43 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +function check_brick_inter_stats() { + local counter="$1" + local inter_cnt="" + + inter_cnt=$(grep -h "\".*inter.*$counter\"" \ + /var/lib/glusterd/stats/glusterfsd*.dump 2>/dev/null | + grep -v '\"0.0000\"' | wc -l) + if (( $inter_cnt == 3 )); then + echo "Y" + else + echo "N" + fi +} + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2} +TEST $CLI volume set $V0 diagnostics.stats-dump-interval 5 +TEST $CLI volume set $V0 diagnostics.count-fop-hits on +TEST $CLI volume set $V0 diagnostics.latency-measurement on +TEST $CLI volume start $V0 +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 + +# Generate some FOPs +cd $M0 +for i in {1..10}; do + mkdir a + cd a + for g in {1..10}; do + dd if=/dev/zero of=test$g bs=128k count=1 + done +done + +EXPECT_WITHIN 30 "Y" check_brick_inter_stats fop.weighted_latency_ave_usec + +cleanup diff --git a/tests/basic/jbr/jbr-volgen.t b/tests/basic/jbr/jbr-volgen.t new file mode 100644 index 00000000000..f368710c158 --- /dev/null +++ b/tests/basic/jbr/jbr-volgen.t @@ -0,0 +1,39 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +volfiles=${GLUSTERD_WORKDIR}/vols/${V0}/ +check_brick_volfiles () { + for vf in ${volfiles}${V0}.$(hostname).*.vol; do + grep -qs experimental/jbr $vf || return + # At least for now, nothing else would put a client translator + # in a brick volfile. + grep -qs protocol/client $vf || return + done + echo "OK" +} + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{1,2} +TEST $CLI volume set $V0 cluster.jbr on + +# Check that the client volfile got modified properly. +TEST grep -qs experimental/jbrc ${volfiles}${V0}.tcp-fuse.vol + +# Check that the brick volfiles got modified as well. +EXPECT "OK" check_brick_volfiles + +# Put things back and make sure the "undo" worked. +TEST $CLI volume set $V0 cluster.jbr off +TEST $CLI volume start $V0 +TEST $GFS -s $H0 --volfile-id $V0 $M0 +echo hello > $M0/probe +EXPECT hello cat ${B0}/${V0}1/probe +EXPECT hello cat ${B0}/${V0}2/probe + +cleanup +#G_TESTDEF_TEST_STATUS_CENTOS6=KNOWN_ISSUE,BUG=1385758 +#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=1385758 diff --git a/tests/basic/jbr/jbr.t b/tests/basic/jbr/jbr.t new file mode 100755 index 00000000000..605344b5a7e --- /dev/null +++ b/tests/basic/jbr/jbr.t @@ -0,0 +1,38 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../cluster.rc +. $(dirname $0)/../../snapshot.rc +. $(dirname $0)/../../fdl.rc + +cleanup; + +TEST verify_lvm_version; +#Create cluster with 3 nodes +TEST launch_cluster 3; +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 $H2:$L2 $H3:$L3 +TEST $CLI_1 volume set $V0 cluster.jbr on +TEST $CLI_1 volume set $V0 cluster.jbr.quorum-percent 100 +TEST $CLI_1 volume set $V0 features.fdl on +#TEST $CLI_1 volume set $V0 diagnostics.brick-log-level DEBUG +TEST $CLI_1 volume start $V0 + +TEST glusterfs --volfile-id=$V0 --volfile-server=$H1 --entry-timeout=0 $M0; + +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" jbrc_child_up_status $V0 0 + +echo "file" > $M0/file1 +TEST stat $L1/file1 +TEST stat $L2/file1 +TEST stat $L3/file1 + +cleanup; +#G_TESTDEF_TEST_STATUS_CENTOS6=KNOWN_ISSUE,BUG=1385758 +#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=1385758 diff --git a/tests/basic/logchecks-messages.h b/tests/basic/logchecks-messages.h index 6344037b44a..bf364848ec7 100644 --- a/tests/basic/logchecks-messages.h +++ b/tests/basic/logchecks-messages.h @@ -11,7 +11,7 @@ #ifndef _LOGCHECKS_MESSAGES_H_ #define _LOGCHECKS_MESSAGES_H_ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* NOTE: Rules for message additions * 1) Each instance of a message is _better_ left with a unique message ID, even @@ -35,44 +35,70 @@ * holes. */ -#define GLFS_COMP_BASE 1000 -#define GLFS_NUM_MESSAGES 19 -#define GLFS_MSGID_END (GLFS_COMP_BASE + GLFS_NUM_MESSAGES + 1) +#define GLFS_COMP_BASE 1000 +#define GLFS_NUM_MESSAGES 19 +#define GLFS_MSGID_END (GLFS_COMP_BASE + GLFS_NUM_MESSAGES + 1) /* Messaged with message IDs */ #define glfs_msg_start_x GLFS_COMP_BASE, "Invalid: Start of messages" /*------------*/ -#define logchecks_msg_1 (GLFS_COMP_BASE + 1), "Informational: Testing logging" \ - " in gluster" -#define logchecks_msg_2 (GLFS_COMP_BASE + 2), "Informational: Format testing:" \ - " %d:%s:%x" -#define logchecks_msg_3 (GLFS_COMP_BASE + 3), "Critical: Testing logging" \ - " in gluster" -#define logchecks_msg_4 (GLFS_COMP_BASE + 4), "Critical: Format testing:" \ - " %d:%s:%x" +#define logchecks_msg_1 \ + (GLFS_COMP_BASE + 1), \ + "Informational: Testing logging" \ + " in gluster" +#define logchecks_msg_2 \ + (GLFS_COMP_BASE + 2), \ + "Informational: Format testing:" \ + " %d:%s:%x" +#define logchecks_msg_3 \ + (GLFS_COMP_BASE + 3), \ + "Critical: Testing logging" \ + " in gluster" +#define logchecks_msg_4 \ + (GLFS_COMP_BASE + 4), \ + "Critical: Format testing:" \ + " %d:%s:%x" #define logchecks_msg_5 (GLFS_COMP_BASE + 5), "Critical: Rotated the log" #define logchecks_msg_6 (GLFS_COMP_BASE + 6), "Critical: Flushed the log" #define logchecks_msg_7 (GLFS_COMP_BASE + 7), "Informational: gf_msg_callingfn" -#define logchecks_msg_8 (GLFS_COMP_BASE + 8), "Informational: " \ - "gf_msg_callingfn: Format testing: %d:%s:%x" +#define logchecks_msg_8 \ + (GLFS_COMP_BASE + 8), \ + "Informational: " \ + "gf_msg_callingfn: Format testing: %d:%s:%x" #define logchecks_msg_9 (GLFS_COMP_BASE + 9), "Critical: gf_msg_callingfn" -#define logchecks_msg_10 (GLFS_COMP_BASE + 10), "Critical: " \ - "gf_msg_callingfn: Format testing: %d:%s:%x" +#define logchecks_msg_10 \ + (GLFS_COMP_BASE + 10), \ + "Critical: " \ + "gf_msg_callingfn: Format testing: %d:%s:%x" #define logchecks_msg_11 (GLFS_COMP_BASE + 11), "==========================" -#define logchecks_msg_12 (GLFS_COMP_BASE + 12), "Test 1: Only stderr and" \ - " partial syslog" -#define logchecks_msg_13 (GLFS_COMP_BASE + 13), "Test 2: Only checklog and" \ - " partial syslog" -#define logchecks_msg_14 (GLFS_COMP_BASE + 14), "Test 5: Changing to" \ - " traditional format" -#define logchecks_msg_15 (GLFS_COMP_BASE + 15), "Test 6: Changing log level" \ - " to critical and above" +#define logchecks_msg_12 \ + (GLFS_COMP_BASE + 12), \ + "Test 1: Only stderr and" \ + " partial syslog" +#define logchecks_msg_13 \ + (GLFS_COMP_BASE + 13), \ + "Test 2: Only checklog and" \ + " partial syslog" +#define logchecks_msg_14 \ + (GLFS_COMP_BASE + 14), \ + "Test 5: Changing to" \ + " traditional format" +#define logchecks_msg_15 \ + (GLFS_COMP_BASE + 15), \ + "Test 6: Changing log level" \ + " to critical and above" #define logchecks_msg_16 (GLFS_COMP_BASE + 16), "Test 7: Only to syslog" -#define logchecks_msg_17 (GLFS_COMP_BASE + 17), "Test 8: Only to syslog," \ - " traditional format" -#define logchecks_msg_18 (GLFS_COMP_BASE + 18), "Test 9: Only to syslog," \ - " only critical and above" -#define logchecks_msg_19 (GLFS_COMP_BASE + 19), "Pre init message, not to be" \ - " seen in logs" +#define logchecks_msg_17 \ + (GLFS_COMP_BASE + 17), \ + "Test 8: Only to syslog," \ + " traditional format" +#define logchecks_msg_18 \ + (GLFS_COMP_BASE + 18), \ + "Test 9: Only to syslog," \ + " only critical and above" +#define logchecks_msg_19 \ + (GLFS_COMP_BASE + 19), \ + "Pre init message, not to be" \ + " seen in logs" /*------------*/ #define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages" diff --git a/tests/basic/logchecks.c b/tests/basic/logchecks.c index 58b57003640..df0be28ace0 100644 --- a/tests/basic/logchecks.c +++ b/tests/basic/logchecks.c @@ -11,198 +11,204 @@ #include <stdio.h> #include <unistd.h> -#include "glusterfs.h" -#include "globals.h" -#include "logging.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/globals.h> +#include <glusterfs/logging.h> #include "logchecks-messages.h" #include "../../libglusterfs/src/logging.h" -glusterfs_ctx_t *ctx = NULL; +glusterfs_ctx_t *ctx = NULL; -#define TEST_FILENAME "/tmp/logchecks.log" -#define GF_LOG_CONTROL_FILE "/etc/glusterfs/logger.conf" +#define TEST_FILENAME "/tmp/logchecks.log" +#define GF_LOG_CONTROL_FILE "/etc/glusterfs/logger.conf" int go_log_vargs(gf_loglevel_t level, const char *fmt, ...) { - va_list ap; + va_list ap; - va_start (ap, fmt); - gf_msg_vplain (level, fmt, ap); - va_end (ap); + va_start(ap, fmt); + gf_msg_vplain(level, fmt, ap); + va_end(ap); - return 0; + return 0; } int -go_log (void) +go_log(void) { - /*** gf_msg ***/ - gf_msg ("logchecks", GF_LOG_INFO, 0, logchecks_msg_1); - gf_msg ("logchecks", GF_LOG_INFO, 22, logchecks_msg_2, 42, "Forty-Two", - 42); - /* change criticality */ - gf_msg ("logchecks", GF_LOG_CRITICAL, 0, logchecks_msg_3); - gf_msg ("logchecks", GF_LOG_CRITICAL, 22, logchecks_msg_4, 42, - "Forty-Two", 42); - - /*** msg_nomem ***/ - gf_msg_nomem ("logchecks", GF_LOG_ALERT, 555); - gf_msg_nomem ("logchecks", GF_LOG_INFO, 555); - - /*** msg_plain ***/ - gf_msg_plain (GF_LOG_INFO, "Informational: gf_msg_plain with" - " args %d:%s:%x", 42, "Forty-Two", 42); - gf_msg_plain (GF_LOG_ALERT, "Alert: gf_msg_plain with" - " args %d:%s:%x", 42, "Forty-Two", 42); - - /*** msg_vplain ***/ - go_log_vargs (GF_LOG_INFO, "Informational: gf_msg_vplain: No args!!!"); - go_log_vargs (GF_LOG_INFO, "Informational: gf_msg_vplain: Some" - " args %d:%s:%x", 42, "Forty-Two", 42); - go_log_vargs (GF_LOG_INFO, "Critical: gf_msg_vplain: No args!!!"); - go_log_vargs (GF_LOG_INFO, "Critical: gf_msg_vplain: Some" - " args %d:%s:%x", 42, "Forty-Two", 42); - - /*** msg_plain_nomem ***/ - gf_msg_plain_nomem (GF_LOG_INFO, "Informational: gf_msg_plain_nomem"); - gf_msg_plain_nomem (GF_LOG_ALERT, "Alert: gf_msg_plain_nomem"); - - /*** msg_backtrace_nomem ***/ - // TODO: Need to create a stack depth and then call - gf_msg_backtrace_nomem (GF_LOG_INFO, 5); - gf_msg_backtrace_nomem (GF_LOG_ALERT, 5); - - /*** gf_msg_callingfn ***/ - // TODO: Need to create a stack depth and then call - gf_msg_callingfn ("logchecks", GF_LOG_INFO, 0, logchecks_msg_7); - gf_msg_callingfn ("logchecks", GF_LOG_INFO, 0, logchecks_msg_8, 42, - "Forty-Two", 42); - gf_msg_callingfn ("logchecks", GF_LOG_CRITICAL, 0, logchecks_msg_9); - gf_msg_callingfn ("logchecks", GF_LOG_CRITICAL, 0, logchecks_msg_10, 42, - "Forty-Two", 42); - - /*** gf_msg_debug ***/ - gf_msg_debug ("logchecks", 0, "Debug: Hello World!!!"); - gf_msg_debug ("logchecks", 22, "Debug: With args %d:%s:%x", 42, - "Forty-Two", 42); - - /*** gf_msg_trace ***/ - gf_msg_trace ("logchecks", 0, "Trace: Hello World!!!"); - gf_msg_trace ("logchecks", 22, "Trace: With args %d:%s:%x", 42, - "Forty-Two", 42); - - /*** gf_msg_backtrace ***/ - // TODO: Test with lower callstr values to check truncation - - return 0; + /*** gf_msg ***/ + gf_msg("logchecks", GF_LOG_INFO, 0, logchecks_msg_1); + gf_msg("logchecks", GF_LOG_INFO, 22, logchecks_msg_2, 42, "Forty-Two", 42); + /* change criticality */ + gf_msg("logchecks", GF_LOG_CRITICAL, 0, logchecks_msg_3); + gf_msg("logchecks", GF_LOG_CRITICAL, 22, logchecks_msg_4, 42, "Forty-Two", + 42); + + /*** msg_nomem ***/ + gf_msg_nomem("logchecks", GF_LOG_ALERT, 555); + gf_msg_nomem("logchecks", GF_LOG_INFO, 555); + + /*** msg_plain ***/ + gf_msg_plain(GF_LOG_INFO, + "Informational: gf_msg_plain with" + " args %d:%s:%x", + 42, "Forty-Two", 42); + gf_msg_plain(GF_LOG_ALERT, + "Alert: gf_msg_plain with" + " args %d:%s:%x", + 42, "Forty-Two", 42); + + /*** msg_vplain ***/ + go_log_vargs(GF_LOG_INFO, "Informational: gf_msg_vplain: No args!!!"); + go_log_vargs(GF_LOG_INFO, + "Informational: gf_msg_vplain: Some" + " args %d:%s:%x", + 42, "Forty-Two", 42); + go_log_vargs(GF_LOG_INFO, "Critical: gf_msg_vplain: No args!!!"); + go_log_vargs(GF_LOG_INFO, + "Critical: gf_msg_vplain: Some" + " args %d:%s:%x", + 42, "Forty-Two", 42); + + /*** msg_plain_nomem ***/ + gf_msg_plain_nomem(GF_LOG_INFO, "Informational: gf_msg_plain_nomem"); + gf_msg_plain_nomem(GF_LOG_ALERT, "Alert: gf_msg_plain_nomem"); + + /*** msg_backtrace_nomem ***/ + // TODO: Need to create a stack depth and then call + gf_msg_backtrace_nomem(GF_LOG_INFO, 5); + gf_msg_backtrace_nomem(GF_LOG_ALERT, 5); + + /*** gf_msg_callingfn ***/ + // TODO: Need to create a stack depth and then call + gf_msg_callingfn("logchecks", GF_LOG_INFO, 0, logchecks_msg_7); + gf_msg_callingfn("logchecks", GF_LOG_INFO, 0, logchecks_msg_8, 42, + "Forty-Two", 42); + gf_msg_callingfn("logchecks", GF_LOG_CRITICAL, 0, logchecks_msg_9); + gf_msg_callingfn("logchecks", GF_LOG_CRITICAL, 0, logchecks_msg_10, 42, + "Forty-Two", 42); + + /*** gf_msg_debug ***/ + gf_msg_debug("logchecks", 0, "Debug: Hello World!!!"); + gf_msg_debug("logchecks", 22, "Debug: With args %d:%s:%x", 42, "Forty-Two", + 42); + + /*** gf_msg_trace ***/ + gf_msg_trace("logchecks", 0, "Trace: Hello World!!!"); + gf_msg_trace("logchecks", 22, "Trace: With args %d:%s:%x", 42, "Forty-Two", + 42); + + /*** gf_msg_backtrace ***/ + // TODO: Test with lower callstr values to check truncation + + return 0; } int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - int ret = -1; - - unlink (GF_LOG_CONTROL_FILE); - creat (GF_LOG_CONTROL_FILE, O_RDONLY); - ctx = glusterfs_ctx_new (); - if (!ctx) - return -1; - - ret = glusterfs_globals_init (ctx); - if (ret) { - printf ("Error from glusterfs_globals_init [%s]\n", - strerror (errno)); - return ret; - } - - /* Pre init test, message should not be printed */ - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_19); - - THIS->ctx = ctx; - - /* TEST 1: messages before initializing the log, goes to stderr - * and syslog based on criticality */ - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_12); - go_log (); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - - /* TEST 2: messages post initialization, goes to glusterlog and - * syslog based on severity */ - ret = gf_log_init(ctx, TEST_FILENAME, "logchecks"); - if (ret != 0) { - printf ("Error from gf_log_init [%s]\n", strerror (errno)); - return -1; - } - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_13); - go_log (); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - - /* TEST 3: Test rotation */ - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - gf_log_logrotate (0); - gf_msg ("logchecks", GF_LOG_CRITICAL, 0, logchecks_msg_5); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - - /* TEST 4: Check flush, nothing noticeable should occur :) */ - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - gf_log_flush (); - gf_msg ("logchecks", GF_LOG_CRITICAL, 0, logchecks_msg_6); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - - /* TEST 5: Change format */ - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - gf_log_set_logformat (gf_logformat_traditional); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_14); - go_log (); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - - /* TEST 6: Change level */ - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - gf_log_set_loglevel (GF_LOG_CRITICAL); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_15); - go_log (); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - - /* Reset to run with syslog */ - gf_log_set_logformat (gf_logformat_withmsgid); - gf_log_set_loglevel (GF_LOG_INFO); - - /* Run tests with logger changed to syslog */ - /* TEST 7: No more gluster logs */ - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - gf_log_set_logger (gf_logger_syslog); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_16); - go_log (); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - - /* TEST 8: Change format */ - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - gf_log_set_logformat (gf_logformat_traditional); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_14); - go_log (); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - - /* TEST 9: Change level */ - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - gf_log_set_loglevel (GF_LOG_CRITICAL); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_15); - go_log (); - gf_msg ("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); - - // TODO: signal crash prints, but not yet feasible here - // TODO: Graph printing - // TODO: Multi threaded logging - - /* Close out the logging */ - gf_log_fini (ctx); - gf_log_globals_fini (); - - unlink (GF_LOG_CONTROL_FILE); - unlink (TEST_FILENAME); - - return 0; + int ret = -1; + + unlink(GF_LOG_CONTROL_FILE); + creat(GF_LOG_CONTROL_FILE, O_RDONLY); + ctx = glusterfs_ctx_new(); + if (!ctx) + return -1; + + ret = glusterfs_globals_init(ctx); + if (ret) { + printf("Error from glusterfs_globals_init [%s]\n", strerror(errno)); + return ret; + } + + /* Pre init test, message should not be printed */ + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_19); + + THIS->ctx = ctx; + + /* TEST 1: messages before initializing the log, goes to stderr + * and syslog based on criticality */ + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_12); + go_log(); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + + /* TEST 2: messages post initialization, goes to glusterlog and + * syslog based on severity */ + ret = gf_log_init(ctx, TEST_FILENAME, "logchecks"); + if (ret != 0) { + printf("Error from gf_log_init [%s]\n", strerror(errno)); + return -1; + } + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_13); + go_log(); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + + /* TEST 3: Test rotation */ + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + gf_log_logrotate(0); + gf_msg("logchecks", GF_LOG_CRITICAL, 0, logchecks_msg_5); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + + /* TEST 4: Check flush, nothing noticeable should occur :) */ + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + gf_log_flush(); + gf_msg("logchecks", GF_LOG_CRITICAL, 0, logchecks_msg_6); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + + /* TEST 5: Change format */ + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + gf_log_set_logformat(gf_logformat_traditional); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_14); + go_log(); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + + /* TEST 6: Change level */ + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + gf_log_set_loglevel(ctx, GF_LOG_CRITICAL); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_15); + go_log(); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + + /* Reset to run with syslog */ + gf_log_set_logformat(gf_logformat_withmsgid); + gf_log_set_loglevel(ctx, GF_LOG_INFO); + + /* Run tests with logger changed to syslog */ + /* TEST 7: No more gluster logs */ + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + gf_log_set_logger(gf_logger_syslog); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_16); + go_log(); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + + /* TEST 8: Change format */ + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + gf_log_set_logformat(gf_logformat_traditional); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_14); + go_log(); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + + /* TEST 9: Change level */ + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + gf_log_set_loglevel(ctx, GF_LOG_CRITICAL); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_15); + go_log(); + gf_msg("logchecks", GF_LOG_ALERT, 0, logchecks_msg_11); + + // TODO: signal crash prints, but not yet feasible here + // TODO: Graph printing + // TODO: Multi threaded logging + + /* Close out the logging */ + gf_log_fini(ctx); + gf_log_globals_fini(); + + unlink(GF_LOG_CONTROL_FILE); + unlink(TEST_FILENAME); + + return 0; } diff --git a/tests/basic/md-cache/bug-1317785.t b/tests/basic/md-cache/bug-1317785.t new file mode 100644 index 00000000000..5076e3612ac --- /dev/null +++ b/tests/basic/md-cache/bug-1317785.t @@ -0,0 +1,34 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd + +TEST $CLI volume create $V0 $H0:$B0/$V0 +TEST $CLI volume start $V0 + +TEST $CLI volume set $V0 cache-swift-metadata on +EXPECT 'on' volinfo_field $V0 'performance.cache-swift-metadata' + +TEST $CLI volume set $V0 cache-swift-metadata off +EXPECT 'off' volinfo_field $V0 'performance.cache-swift-metadata' + +TEST $CLI volume set $V0 performance.cache-capability-xattrs off +EXPECT 'off' volinfo_field $V0 'performance.cache-capability-xattrs' + +TEST $CLI volume set $V0 performance.cache-capability-xattrs on +EXPECT 'on' volinfo_field $V0 'performance.cache-capability-xattrs' + +TEST $CLI volume set $V0 performance.cache-ima-xattrs off +EXPECT 'off' volinfo_field $V0 'performance.cache-ima-xattrs' + +TEST $CLI volume set $V0 performance.cache-ima-xattrs on +EXPECT 'on' volinfo_field $V0 'performance.cache-ima-xattrs' + +TEST $CLI volume stop $V0 +TEST $CLI volume delete $V0 + +cleanup; diff --git a/tests/basic/md-cache/bug-1418249.t b/tests/basic/md-cache/bug-1418249.t new file mode 100755 index 00000000000..85a4f58ec10 --- /dev/null +++ b/tests/basic/md-cache/bug-1418249.t @@ -0,0 +1,20 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd + +TEST $CLI volume create $V0 $H0:$B0/$V0 +TEST $CLI volume start $V0 + +TEST $CLI volume set $V0 group metadata-cache +EXPECT 'on' volinfo_field $V0 'performance.cache-invalidation' +EXPECT '600' volinfo_field $V0 'performance.md-cache-timeout' +EXPECT 'on' volinfo_field $V0 'performance.stat-prefetch' +EXPECT '600' volinfo_field $V0 'features.cache-invalidation-timeout' +EXPECT 'on' volinfo_field $V0 'features.cache-invalidation' +EXPECT '200000' volinfo_field $V0 'network.inode-lru-limit' +cleanup; diff --git a/tests/basic/meta.t b/tests/basic/meta.t index 55ca005824b..0bac3c6797d 100755 --- a/tests/basic/meta.t +++ b/tests/basic/meta.t @@ -9,7 +9,7 @@ TEST glusterd TEST pidof glusterd TEST $CLI volume info; -TEST $CLI volume create $V0 replica 2 stripe 4 $H0:$B0/${V0}{1..16}; +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{1..9}; EXPECT "$V0" volinfo_field $V0 'Volume Name'; EXPECT 'Created' volinfo_field $V0 'Status'; 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/mount-nfs-auth.t b/tests/basic/mount-nfs-auth.t deleted file mode 100755 index 9df5cb45c3b..00000000000 --- a/tests/basic/mount-nfs-auth.t +++ /dev/null @@ -1,328 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../include.rc -. $(dirname $0)/../nfs.rc - -# Our mount timeout must be as long as the time for a regular configuration -# change to be acted upon *plus* AUTH_REFRESH_TIMEOUT, not one replacing the -# other. Otherwise this process races vs. the one making the change we're -# trying to test, which leads to spurious failures. -MY_MOUNT_TIMEOUT=$((CONFIG_UPDATE_TIMEOUT+AUTH_REFRESH_INTERVAL)) - -cleanup; -## Check whether glusterd is running -TEST glusterd -TEST pidof glusterd -TEST $CLI volume info - -# Export variables for allow & deny -EXPORT_ALLOW="/$V0 $H0(sec=sys,rw,anonuid=0) @ngtop(sec=sys,rw,anonuid=0)" -EXPORT_ALLOW_SLASH="/$V0/ $H0(sec=sys,rw,anonuid=0) @ngtop(sec=sys,rw,anonuid=0)" -EXPORT_DENY="/$V0 1.2.3.4(sec=sys,rw,anonuid=0) @ngtop(sec=sys,rw,anonuid=0)" - -# Netgroup variables for allow & deny -NETGROUP_ALLOW="ngtop ng1000\nng1000 ng999\nng999 ng1\nng1 ng2\nng2 ($H0,,)" -NETGROUP_DENY="ngtop ng1000\nng1000 ng999\nng999 ng1\nng1 ng2\nng2 (1.2.3.4,,)" - -V0L1="$V0/L1" -V0L2="$V0L1/L2" -V0L3="$V0L2/L3" - -# Other variations for allow & deny -EXPORT_ALLOW_RO="/$V0 $H0(sec=sys,ro,anonuid=0) @ngtop(sec=sys,ro,anonuid=0)" -EXPORT_ALLOW_L1="/$V0L1 $H0(sec=sys,rw,anonuid=0) @ngtop(sec=sys,rw,anonuid=0)" -EXPORT_WILDCARD="/$V0 *(sec=sys,rw,anonuid=0) @ngtop(sec=sys,rw,anonuid=0)" - -function build_dirs () { - mkdir -p $B0/b{0,1,2}/L1/L2/L3 -} - -function export_allow_this_host () { - printf "$EXPORT_ALLOW\n" > ${NFSDIR}/exports -} - -function export_allow_this_host_with_slash () { - printf "$EXPORT_ALLOW_SLASH\n" > ${NFSDIR}/exports -} - -function export_deny_this_host () { - printf "$EXPORT_DENY\n" > ${NFSDIR}/exports -} - -function export_allow_this_host_l1 () { - printf "$EXPORT_ALLOW_L1\n" >> ${NFSDIR}/exports -} - -function export_allow_wildcard () { - printf "$EXPORT_WILDCARD\n" > ${NFSDIR}/exports -} - -function export_allow_this_host_ro () { - printf "$EXPORT_ALLOW_RO\n" > ${NFSDIR}/exports -} - -function netgroup_allow_this_host () { - printf "$NETGROUP_ALLOW\n" > ${NFSDIR}/netgroups -} - -function netgroup_deny_this_host () { - printf "$NETGROUP_DENY\n" > ${NFSDIR}/netgroups -} - -function create_vol () { - $CLI vol create $V0 $H0:$B0/b0 -} - -function setup_cluster() { - build_dirs # Build directories - export_allow_this_host # Allow this host in the exports file - netgroup_allow_this_host # Allow this host in the netgroups file - - glusterd - create_vol # Create the volume -} - -function check_mount_success { - mount_nfs $H0:/$1 $N0 nolock - if [ $? -eq 0 ]; then - echo "Y" - else - echo "N" - fi -} - -function check_mount_failure { - mount_nfs $H0:/$1 $N0 nolock - if [ $? -ne 0 ]; then - echo "Y" - else - local timeout=$UMOUNT_TIMEOUT - while ! umount_nfs $N0 && [$timeout -ne 0] ; do - timeout=$(( $timeout - 1 )) - sleep 1 - done - fi -} - -function small_write () { - dd if=/dev/zero of=$N0/test-small-write count=1 bs=1k 2>&1 - if [ $? -ne 0 ]; then - echo "N" - else - echo "Y" - fi -} - -function bg_write () { - dd if=/dev/zero of=$N0/test-bg-write count=1 bs=1k & - BG_WRITE_PID=$! -} - -function big_write() { - dd if=/dev/zero of=$N0/test-big-write count=500 bs=1024k -} - -function create () { - touch $N0/create-test -} - -function stat_nfs () { - ls $N0/ -} - -# Restarts the NFS server -function restart_nfs () { - local NFS_PID=$(cat ${GLUSTERD_WORKDIR}/nfs/run/nfs.pid) - - # kill the NFS-server if it is running - while ps -q ${NFS_PID} 2>&1 > /dev/null; do - kill ${NFS_PID} - sleep 0.5 - done - - # start-force starts the NFS-server again - $CLI vol start patchy force -} - -setup_cluster - -# run preliminary tests -TEST $CLI vol set $V0 nfs.disable off -TEST $CLI vol start $V0 - -# Get NFS state directory -NFSDIR=$( $CLI volume get patchy nfs.mount-rmtab | \ - awk '/^nfs.mount-rmtab/{print $2}' | \ - xargs dirname ) - -## Wait for volume to register with rpc.mountd -EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "1" is_nfs_export_available - -## NFS server starts with auth disabled -## Do some tests to verify that. - -EXPECT "Y" check_mount_success $V0 -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - -## Disallow host -TEST export_deny_this_host -TEST netgroup_deny_this_host - -## Technically deauthorized this host, but since auth is disabled we should be -## able to do mounts, writes, etc. -EXPECT_WITHIN $MY_MOUNT_TIMEOUT "Y" check_mount_success $V0 -EXPECT "Y" small_write -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - -## Reauthorize this host -export_allow_this_host -netgroup_allow_this_host - -## Restart NFS with auth enabled -$CLI vol stop $V0 -TEST $CLI vol set $V0 nfs.exports-auth-enable on -$CLI vol start $V0 -EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "1" is_nfs_export_available - -## Mount NFS -EXPECT "Y" check_mount_success $V0 - -## Disallow host -TEST export_deny_this_host -TEST netgroup_deny_this_host - -## Writes should not be allowed, host is not authorized -EXPECT_WITHIN $AUTH_REFRESH_INTERVAL "N" small_write - -## Unmount so we can test mount -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - -## Subsequent ounts should not be allowed, host is not authorized -EXPECT "Y" check_mount_failure $V0 - -## Reauthorize host -TEST export_allow_this_host -TEST netgroup_allow_this_host - -EXPECT_WITHIN $MY_MOUNT_TIMEOUT "Y" check_mount_success $V0 -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - -## Allow host in netgroups but not in exports, host should be allowed -TEST export_deny_this_host -TEST netgroup_allow_this_host - -# wait for the mount authentication to rebuild -sleep $[$AUTH_REFRESH_INTERVAL + 1] - -EXPECT_WITHIN $MY_MOUNT_TIMEOUT "Y" check_mount_success $V0 -EXPECT "Y" small_write -TEST big_write -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - -## Allow host in exports but not in netgroups, host should be allowed -TEST export_allow_this_host -TEST netgroup_deny_this_host - -EXPECT_WITHIN $MY_MOUNT_TIMEOUT "Y" check_mount_success $V0 -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - -## Finally, reauth the host in export and netgroup, test mount & write -TEST export_allow_this_host_l1 -TEST netgroup_allow_this_host - -EXPECT_WITHIN $MY_MOUNT_TIMEOUT "Y" check_mount_success $V0L1 -EXPECT "Y" small_write - -## Failover test: Restarting NFS and then doing a write should pass -bg_write -TEST restart_nfs -EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "1" is_nfs_export_available - -TEST wait $BG_WRITE_PID -EXPECT "Y" small_write -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - -## Test deep mounts -EXPECT "Y" check_mount_success $V0L1 -EXPECT "Y" small_write -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - -TEST export_allow_this_host_ro -TEST netgroup_deny_this_host - -## Restart the nfs server to avoid spurious failure(BZ1256352) -restart_nfs -EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "1" is_nfs_export_available - -EXPECT_WITHIN $MY_MOUNT_TIMEOUT "Y" check_mount_success $V0 -EXPECT "N" small_write # Writes should not be allowed -TEST ! create # Create should not be allowed -TEST stat_nfs # Stat should be allowed -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - -TEST export_deny_this_host -TEST netgroup_deny_this_host -TEST export_allow_this_host_l1 # Allow this host at L1 - -EXPECT_WITHIN $MY_MOUNT_TIMEOUT "Y" check_mount_failure $V0 #V0 shouldnt be allowed -EXPECT_WITHIN $MY_MOUNT_TIMEOUT "Y" check_mount_success $V0L1 #V0L1 should be -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - -## Test wildcard hosts -TEST export_allow_wildcard - -# the $MY_MOUNT_TIMEOUT might not be long enough? restart should do -restart_nfs -EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "1" is_nfs_export_available - -EXPECT_WITHIN $MY_MOUNT_TIMEOUT "Y" check_mount_success $V0 -EXPECT_WITHIN $AUTH_REFRESH_INTERVAL "Y" small_write -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - -## Test if path is parsed correctly -## by mounting host:vol/ instead of host:vol -EXPECT "Y" check_mount_success $V0/ -EXPECT "Y" small_write -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - -TEST export_allow_this_host_with_slash - -EXPECT_WITHIN $MY_MOUNT_TIMEOUT "Y" check_mount_success $V0 -EXPECT "Y" small_write -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - -EXPECT "Y" check_mount_success $V0/ -EXPECT "Y" small_write -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - - -## Turn off exports authentication -$CLI vol stop $V0 -TEST $CLI vol set $V0 nfs.exports-auth-enable off -$CLI vol start $V0 -EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "1" is_nfs_export_available - -TEST export_deny_this_host # Deny the host -TEST netgroup_deny_this_host - -EXPECT_WITHIN $MY_MOUNT_TIMEOUT "Y" check_mount_success $V0 # Do a mount & test -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 - -## Turn back on the exports authentication -$CLI vol stop $V0 -TEST $CLI vol set $V0 nfs.exports-auth-enable on -$CLI vol start $V0 -EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "1" is_nfs_export_available - -## Do a simple test to set the refresh time to 20 seconds -TEST $CLI vol set $V0 nfs.auth-refresh-interval-sec 20 - -## Do a simple test to see if the volume option exists -TEST $CLI vol set $V0 nfs.auth-cache-ttl-sec 400 - -## Finish up -TEST $CLI volume stop $V0 -TEST $CLI volume delete $V0; -TEST ! $CLI volume info $V0; - -cleanup diff --git a/tests/basic/mount-options.disabled b/tests/basic/mount-options.disabled index 2373e4461ce..a04c8686276 100644 --- a/tests/basic/mount-options.disabled +++ b/tests/basic/mount-options.disabled @@ -127,6 +127,9 @@ EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --volfile-server-transport=ib-verbs EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --auto-invalidation=off +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + TEST ! glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --volfile-server-port=socket TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --volume-name=$V0 diff --git a/tests/basic/mount.t b/tests/basic/mount.t index 52e760d048d..3a3d7cc9d8d 100755 --- a/tests/basic/mount.t +++ b/tests/basic/mount.t @@ -3,15 +3,16 @@ . $(dirname $0)/../include.rc . $(dirname $0)/../nfs.rc -cleanup; +#G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST +cleanup; ## Start and create a volume TEST glusterd TEST pidof glusterd TEST $CLI volume info; -TEST $CLI volume create $V0 replica 2 stripe 2 $H0:$B0/${V0}{1,2,3,4,5,6,7,8}; +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{1,2,3,4,5,6,7,8,9}; TEST $CLI volume set $V0 nfs.disable false function volinfo_field() @@ -68,6 +69,9 @@ TEST rm -f $N0/newfile; TEST ! stat $M0/newfile; TEST ! stat $M1/newfile; +# No need to check for status here right now +$(dirname $0)/rpc-coverage.sh $N0 >/dev/null + ## Before killing daemon to avoid deadlocks EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 diff --git a/tests/basic/mpx-compat.t b/tests/basic/mpx-compat.t new file mode 100644 index 00000000000..baf629dbf9b --- /dev/null +++ b/tests/basic/mpx-compat.t @@ -0,0 +1,53 @@ +#!/bin/bash +#This test tests that self-heals don't perform fsync when durability is turned +#off + +. $(dirname $0)/../include.rc +. $(dirname $0)/../traps.rc +. $(dirname $0)/../volume.rc + +function count_processes { + # It would generally be a good idea to use "pgrep -x" to ensure an + # exact match, but the version of pgrep we have on NetBSD (a.k.a. + # the worst operating system ever) doesn't support that option. + # Fortunately, "glusterfsd" isn't the prefix of any other name, + # so this works anyway. For now. + pgrep glusterfsd | wc -w +} + +function count_brick_pids { + $CLI --xml volume status all | sed -n '/.*<pid>\([^<]*\).*/s//\1/p' \ + | grep -v "N/A" | sort | uniq | wc -l +} + +cleanup +TEST glusterd +TEST $CLI volume set all cluster.brick-multiplex yes + +# Create two vanilla volumes. +TEST $CLI volume create $V0 $H0:$B0/brick-${V0}-{0,1} +TEST $CLI volume create $V1 $H0:$B0/brick-${V1}-{0,1} + +# Enable brick log-level to DEBUG +gluster v set $V0 diagnostics.brick-log-level DEBUG + +# Start both. +TEST $CLI volume start $V0 +TEST $CLI volume start $V1 + +# There should be only one process for compatible volumes. We can't use +# EXPECT_WITHIN here because it could transiently see one process as two are +# coming up, and yield a false positive. +sleep $PROCESS_UP_TIMEOUT +EXPECT "1" count_processes +EXPECT 1 count_brick_pids + +# Make the second volume incompatible with the first. +TEST $CLI volume stop $V1 +TEST $CLI volume set $V1 server.manage-gids no +TEST $CLI volume start $V1 + +# There should be two processes this time (can't share protocol/server). +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" count_processes + +cleanup;
\ No newline at end of file diff --git a/tests/basic/multiple-volume-shd-mux.t b/tests/basic/multiple-volume-shd-mux.t new file mode 100644 index 00000000000..d7cfbaec85f --- /dev/null +++ b/tests/basic/multiple-volume-shd-mux.t @@ -0,0 +1,46 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +TESTS_EXPECTED_IN_LOOP=16 + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2,3,4,5} +TEST $CLI volume start $V0 + +shd_pid=$(get_shd_mux_pid $V0) +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^6$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +for i in $(seq 1 3); do + TEST $CLI volume create ${V0}_afr$i replica 3 $H0:$B0/${V0}_afr${i}{0,1,2,3,4,5} + TEST $CLI volume start ${V0}_afr$i + TEST $CLI volume create ${V0}_ec$i disperse 6 redundancy 2 $H0:$B0/${V0}_ec${i}{0,1,2,3,4,5} + TEST $CLI volume start ${V0}_ec$i +done + +#Check the thread count become to number of volumes*number of ec subvolume (3*6=18) +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^18$" number_healer_threads_shd $V0 "ec_shd_index_healer" +#Check the thread count become to number of volumes*number of afr subvolume (4*6=24) +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^24$" number_healer_threads_shd $V0 "afr_shd_index_healer" +#Delete the volumes +for i in $(seq 1 3); do + TEST $CLI volume stop ${V0}_afr$i + TEST $CLI volume stop ${V0}_ec$i + TEST $CLI volume delete ${V0}_afr$i + TEST $CLI volume delete ${V0}_ec$i +done + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^${shd_pid}$" get_shd_mux_pid $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" shd_count + +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^6$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +TEST $CLI volume stop ${V0} +TEST $CLI volume delete ${V0} +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^0$" shd_count + +cleanup diff --git a/tests/basic/multiplex.t b/tests/basic/multiplex.t new file mode 100644 index 00000000000..2f558a6824b --- /dev/null +++ b/tests/basic/multiplex.t @@ -0,0 +1,78 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../traps.rc +. $(dirname $0)/../volume.rc + +function count_up_bricks { + $CLI --xml volume status $V0 | grep '<status>1' | wc -l +} + +function count_brick_processes { + pgrep glusterfsd | wc -l +} + +function count_brick_pids { + $CLI --xml volume status $V0 | sed -n '/.*<pid>\([^<]*\).*/s//\1/p' \ + | grep -v "N/A" | sort | uniq | wc -l +} + +cleanup + +TEST glusterd +TEST $CLI volume set all cluster.brick-multiplex on + +TEST $CLI volume create $V0 $H0:$B0/brick{0,1} +TEST $CLI volume set $V0 features.trash enable + +TEST $CLI volume start $V0 +# Without multiplexing, there would be two. +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 2 count_up_bricks +EXPECT 1 count_brick_processes + +TEST $CLI volume stop $V0 +#Testing the volume set command introduced for protocol/server +TEST $CLI volume set $V0 transport.listen-backlog 1024 +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT 0 count_brick_processes +TEST $CLI volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 2 count_up_bricks +EXPECT 1 count_brick_processes + +TEST kill_brick $V0 $H0 $B0/brick1 +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT 1 count_up_bricks +# Make sure the whole process didn't go away. +EXPECT 1 count_brick_processes + +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 2 count_up_bricks +EXPECT 1 count_brick_processes + +# Killing the first brick is a bit more of a challenge due to socket-path +# issues. +TEST kill_brick $V0 $H0 $B0/brick0 +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT 1 count_up_bricks +EXPECT 1 count_brick_processes +TEST $CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 2 count_up_bricks +EXPECT 1 count_brick_processes + +# Make sure that the two bricks show the same PID. +EXPECT 1 count_brick_pids + +# Do a quick test to make sure that the bricks are acting as separate bricks +# even though they're in the same process. +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0 +for i in $(seq 10 99); do + echo hello > $M0/file$i +done +nbrick0=$(ls $B0/brick0/file?? | wc -l) +nbrick1=$(ls $B0/brick1/file?? | wc -l) +TEST [ $((nbrick0 + nbrick1)) -eq 90 ] +TEST [ $((nbrick0 * nbrick1)) -ne 0 ] + +pkill gluster +TEST glusterd +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT 1 count_brick_pids +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT 1 count_brick_processes + +cleanup;
\ No newline at end of file diff --git a/tests/basic/namespace.t b/tests/basic/namespace.t new file mode 100644 index 00000000000..d1bbe7eea29 --- /dev/null +++ b/tests/basic/namespace.t @@ -0,0 +1,131 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../nfs.rc + +#G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST + +# These hashes are a result of calling SuperFastHash +# on the corresponding folder names. +NAMESPACE_HASH=28153613 +NAMESPACE2_HASH=3926991974 +NAMESPACE3_HASH=3493960770 + +function check_brick_multiplex() { + local ret=$($CLI volume info|grep "cluster.brick-multiplex"|cut -d" " -f2) + local cnt="$(ls /var/log/glusterfs/bricks|wc -l)" + local bcnt="$(brick_count)" + + if [ $bcnt -ne 1 ]; then + if [ -z $ret ]; then + ret="no" + fi + + if [ $ret = "on" ] || [ $cnt -eq 1 ]; then + echo "Y" + else + echo "N" + fi + else + echo "N" + fi +} + +function check_samples() { + local FOP_TYPE=$1 + local NS_HASH=$2 + local FILE=$3 + local BRICK=$4 + local GFID="$(getfattr -n trusted.gfid -e text --only-values $B0/$BRICK$FILE | xxd -p)" + local val="$(check_brick_multiplex)" + + if [ $val = "Y" ]; then + BRICK="${V0}0" + fi + + grep -i "ns_$OP" /var/log/glusterfs/bricks/d-backends-$BRICK.log | + grep -- $NS_HASH | sed 's/\-//g' | grep -- $GFID + if [ $? -eq 0 ]; then + echo "Y" + else + echo "N" + fi +} + +cleanup; + +TEST mkdir -p $B0/${V0}{0,1,2,3,4,5,6,7,8,9} + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2,3,4,5,6,7,8} +TEST $CLI volume set $V0 nfs.disable off +TEST $CLI volume set $V0 performance.stat-prefetch off +TEST $CLI volume set $V0 performance.nfs.stat-prefetch off +TEST $CLI volume set $V0 cluster.read-subvolume-index 0 +TEST $CLI volume set $V0 diagnostics.brick-log-level DEBUG +TEST $CLI volume set $V0 features.tag-namespaces on +TEST $CLI volume set $V0 storage.build-pgfid on +TEST $CLI volume start $V0 + +sleep 2 + +TEST mount_nfs $H0:/$V0 $N0 nolock; + +################################ +# Paths in the samples # +################################ + +mkdir -p $N0/namespace + +# subvol_1 = bar, subvol_2 = foo, subvol_3 = hey +# Test create, write (tagged by loc, fd respectively). +touch $N0/namespace/{bar,foo,hey} +echo "garbage" > $N0/namespace/bar +echo "garbage" > $N0/namespace/foo +echo "garbage" > $N0/namespace/hey +EXPECT_WITHIN 10 "Y" check_samples CREATE $NAMESPACE_HASH /namespace/bar patchy0 +EXPECT_WITHIN 10 "Y" check_samples CREATE $NAMESPACE_HASH /namespace/foo patchy3 +EXPECT_WITHIN 10 "Y" check_samples CREATE $NAMESPACE_HASH /namespace/hey patchy6 +EXPECT_WITHIN 10 "Y" check_samples WRITEV $NAMESPACE_HASH /namespace/bar patchy0 +EXPECT_WITHIN 10 "Y" check_samples WRITEV $NAMESPACE_HASH /namespace/foo patchy3 +EXPECT_WITHIN 10 "Y" check_samples WRITEV $NAMESPACE_HASH /namespace/hey patchy6 + +# Test stat (tagged by loc) +stat $N0/namespace/bar &> /dev/null +stat $N0/namespace/foo &> /dev/null +stat $N0/namespace/hey &> /dev/null +EXPECT_WITHIN 10 "Y" check_samples STAT $NAMESPACE_HASH /namespace/bar patchy0 +EXPECT_WITHIN 10 "Y" check_samples STAT $NAMESPACE_HASH /namespace/foo patchy3 +EXPECT_WITHIN 10 "Y" check_samples STAT $NAMESPACE_HASH /namespace/hey patchy6 + +EXPECT_WITHIN 10 "Y" umount_nfs $N0; +sleep 1 +TEST mount_nfs $H0:/$V0 $N0 nolock; + +cat $N0/namespace/bar &> /dev/null +EXPECT_WITHIN 10 "Y" check_samples READ $NAMESPACE_HASH /namespace/bar patchy0 + +dir $N0/namespace &> /dev/null +EXPECT_WITHIN 10 "Y" check_samples LOOKUP $NAMESPACE_HASH /namespace patchy0 + +mkdir -p $N0/namespace{2,3} +EXPECT_WITHIN 10 "Y" check_samples MKDIR $NAMESPACE2_HASH /namespace2 patchy0 +EXPECT_WITHIN 10 "Y" check_samples MKDIR $NAMESPACE3_HASH /namespace3 patchy0 + +touch $N0/namespace2/file +touch $N0/namespace3/file +EXPECT_WITHIN 10 "Y" check_samples CREATE $NAMESPACE2_HASH /namespace2/file patchy0 +EXPECT_WITHIN 10 "Y" check_samples CREATE $NAMESPACE3_HASH /namespace3/file patchy0 + +truncate -s 0 $N0/namespace/bar +EXPECT_WITHIN 10 "Y" check_samples TRUNCATE $NAMESPACE_HASH /namespace/bar patchy0 + +ln -s $N0/namespace/foo $N0/namespace/foo_link +EXPECT_WITHIN 10 "Y" check_samples SYMLINK $NAMESPACE_HASH /namespace/foo patchy3 + +open $N0/namespace/hey +EXPECT_WITHIN 10 "Y" check_samples OPEN $NAMESPACE_HASH /namespace/hey patchy6 + +cleanup; diff --git a/tests/basic/nl-cache.t b/tests/basic/nl-cache.t new file mode 100755 index 00000000000..90c778c8a88 --- /dev/null +++ b/tests/basic/nl-cache.t @@ -0,0 +1,98 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +TEST glusterd + +TEST $CLI volume create $V0 $H0:$B0/${V0}{0..4} +EXPECT 'Created' volinfo_field $V0 'Status' + +TEST $CLI volume set $V0 group nl-cache +EXPECT '600' volinfo_field $V0 'performance.nl-cache-timeout' +EXPECT 'on' volinfo_field $V0 'performance.nl-cache' +EXPECT '600' volinfo_field $V0 'features.cache-invalidation-timeout' +EXPECT 'on' volinfo_field $V0 'features.cache-invalidation' +EXPECT '200000' volinfo_field $V0 'network.inode-lru-limit' +TEST $CLI volume set $V0 nl-cache-positive-entry on + +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; + +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M1 + +TEST ! ls $M0/file2 +TEST touch $M0/file1 +TEST ! ls $M0/file2 +TEST touch $M0/file2 +TEST ls $M0/file2 +TEST rm $M0/file2 +TEST rm $M0/file1 + +TEST mkdir $M0/dir1 +TEST ! ls -l $M0/dir1/file +TEST mkdir $M0/dir1/dir2 +TEST ! ls -l $M0/dir1/file +TEST ! ls -l $M0/dir1/dir2/file +TEST ls -l $M0/dir1/dir2 +TEST rmdir $M0/dir1/dir2 +TEST rmdir $M0/dir1 + +TEST ! ls -l $M0/file2 +TEST touch $M1/file2 +TEST ls -l $M0/file2 +TEST rm $M1/file2 + +TEST ! ls -l $M0/dir1 +TEST mkdir $M1/dir1 +TEST ls -l $M0/dir1 +TEST ! ls -l $M0/dir1/file1 +TEST mkdir $M1/dir1/dir2 +TEST ! ls -l $M0/dir1/file1 +TEST ls -l $M0/dir1/dir2 +TEST ! ls -l $M1/dir1/file1 + +TEST touch $M0/dir1/file +TEST ln $M0/dir1/file $M0/dir1/file_link +TEST ls -l $M1/dir1/file +TEST ls -l $M1/dir1/file_link +TEST rm $M0/dir1/file +TEST rm $M0/dir1/file_link +TEST rmdir $M0/dir1/dir2 +TEST rmdir $M0/dir1 + +#Check mknod +TEST ! ls -l $M0/dir +TEST mkdir $M0/dir +TEST mknod -m 0666 $M0/dir/block b 4 5 +TEST mknod -m 0666 $M0/dir/char c 1 5 +TEST mknod -m 0666 $M0/dir/fifo p +TEST rm $M0/dir/block +TEST rm $M0/dir/char +TEST rm $M0/dir/fifo + +#Check getxattr +TEST touch $M0/file1 +TEST getfattr -d -m. -e hex $M0/file1 +TEST getfattr -n "glusterfs.get_real_filename:file1" $M0; +TEST getfattr -n "glusterfs.get_real_filename:FILE1" $M0; +TEST ! getfattr -n "glusterfs.get_real_filename:FILE2" $M0; + +#Check statedump +TEST generate_mount_statedump $V0 $M0 +TEST cleanup_mount_statedump $V0 + +#Check reconfigure +TEST $CLI volume reset $V0 nl-cache-timeout +TEST $CLI volume reset $V0 nl-cache-positive-entry +TEST $CLI volume reset $V0 nl-cache-limit +TEST $CLI volume reset $V0 nl-cache-pass-through + +TEST $CLI volume stop $V0 +TEST $CLI volume delete $V0 + +cleanup; +#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=000000 diff --git a/tests/basic/nufa.t b/tests/basic/nufa.t index 1d74d376b7d..cb09fc5bbbf 100644 --- a/tests/basic/nufa.t +++ b/tests/basic/nufa.t @@ -4,18 +4,20 @@ . $(dirname $0)/../volume.rc . $(dirname $0)/../nfs.rc +#G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST + cleanup; TEST glusterd TEST pidof glusterd TEST $CLI volume info; -TEST $CLI volume create $V0 replica 2 stripe 2 $H0:$B0/${V0}{1,2,3,4,5,6,7,8}; +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{1,2,3,4,5,6}; TEST $CLI volume set $V0 nfs.disable false EXPECT "$V0" volinfo_field $V0 'Volume Name'; EXPECT 'Created' volinfo_field $V0 'Status'; -EXPECT '8' brick_count $V0 +EXPECT '6' brick_count $V0 TEST $CLI volume set $V0 nufa on; diff --git a/tests/basic/op_errnos.t b/tests/basic/op_errnos.t index 8b16267cb50..9c48d7a02ad 100755 --- a/tests/basic/op_errnos.t +++ b/tests/basic/op_errnos.t @@ -17,8 +17,6 @@ TEST setup_lvm 1 TEST $CLI volume create $V0 $H0:$L1 TEST $CLI volume start $V0 -TEST $CLI volume create $V1 replica 2 stripe 2 $H0:$B0/${V0}{1,2,3,4,5,6,7,8}; -TEST $CLI volume start $V1 EXPECT 0 get-op_errno-xml "snapshot create snap1 $V0 no-timestamp" EXPECT 30806 get-op_errno-xml "snapshot create snap1 imaginary_volume" @@ -29,10 +27,8 @@ EXPECT 30810 get-op_errno-xml "snapshot create snap1 $V0" TEST $CLI volume start $V0 EXPECT 30811 get-op_errno-xml "snapshot clone $V0 snap1" EXPECT 30812 get-op_errno-xml "snapshot create snap1 $V0 no-timestamp" -EXPECT 30815 get-op_errno-xml "snapshot create snap2 $V1 no-timestamp" EXPECT 0 get-op_errno-xml "snapshot delete snap1" TEST $CLI volume stop $V0 -TEST $CLI volume stop $V1 cleanup; 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/open-fd-snap-delete.t b/tests/basic/open-fd-snap-delete.t new file mode 100644 index 00000000000..a9f47cac19d --- /dev/null +++ b/tests/basic/open-fd-snap-delete.t @@ -0,0 +1,74 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../snapshot.rc +. $(dirname $0)/../fileio.rc + +cleanup; + +TEST init_n_bricks 3; +TEST setup_lvm 3; + +# start glusterd +TEST glusterd; + +TEST pidof glusterd; + +TEST $CLI volume create $V0 $H0:$L1 $H0:$L2 $H0:$L3; +TEST $CLI volume set $V0 nfs.disable false + + +TEST $CLI volume start $V0; + +TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0; + +for i in {1..10} ; do echo "file" > $M0/file$i ; done + +# Create file and directory +TEST touch $M0/f1 +TEST mkdir $M0/dir + +TEST $CLI snapshot config activate-on-create enable +TEST $CLI volume set $V0 features.uss enable; + +for i in {1..10} ; do echo "file" > $M0/dir/file$i ; done + +TEST $CLI snapshot create snap1 $V0 no-timestamp; + +for i in {11..20} ; do echo "file" > $M0/file$i ; done +for i in {11..20} ; do echo "file" > $M0/dir/file$i ; done + +TEST $CLI snapshot create snap2 $V0 no-timestamp; + +TEST fd1=`fd_available` +TEST fd_open $fd1 'r' $M0/.snaps/snap2/dir/file11; +TEST fd_cat $fd1 + +TEST $CLI snapshot delete snap2; + +TEST ! fd_cat $fd1; + +# the return value of this command (i.e. fd_close) depetends +# mainly on how the release operation on a file descriptor is +# handled in snapview-server process. As of now snapview-server +# returns 0 for the release operation. And it is similar to how +# posix xlator does. So, as of now the expectation is to receive +# success for the close operation. +TEST fd_close $fd1; + +# This check is mainly to ensure that the snapshot daemon +# (snapd) is up and running. If it is not running, the following +# stat would receive ENOTCONN. + +TEST stat $M0/.snaps/snap1/dir/file1 + +TEST $CLI snapshot delete snap1; + +TEST rm -rf $M0/*; + +TEST $CLI volume stop $V0; + +TEST $CLI volume delete $V0; + +cleanup diff --git a/tests/basic/peer-parsing.t b/tests/basic/peer-parsing.t new file mode 100644 index 00000000000..813b65e2ae1 --- /dev/null +++ b/tests/basic/peer-parsing.t @@ -0,0 +1,52 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc + +PEER_DIR="$GLUSTERD_WORKDIR"/peers +TEST mkdir -p $PEER_DIR + +declare -i HOST_NUM=100 + +create_random_peer_files() { + for i in $(seq 0 9); do + local peer_uuid=$(uuidgen) + # The rules for quoting and variable substitution in + # here documents would force this to be even less + # readable that way. + ( + echo "state=1" + echo "uuid=$peer_uuid" + echo "hostname=127.0.0.$HOST_NUM" + ) > $PEER_DIR/$peer_uuid + HOST_NUM+=1 + done +} + +create_non_peer_file() { + echo "random stuff" > $PEER_DIR/not_a_peer_file +} + +create_malformed_peer_file() { + echo "more random stuff" > $PEER_DIR/$(uuidgen) +} + +# We create lots of files, in batches, to ensure that our bogus ones are +# properly interspersed with the valid ones. + +TEST create_random_peer_files +TEST create_non_peer_file +TEST create_random_peer_files +TEST create_malformed_peer_file +TEST create_random_peer_files + +# There should be 30 peers, not counting the two bogus files. +TEST glusterd +N_PEERS=$($CLI peer status | grep ^Uuid: | wc -l) +TEST [ "$N_PEERS" = "30" ] + +# For extra credit, check the logs for messages about bogus files. + +cleanup + + + diff --git a/tests/basic/playground/template-xlator-sanity.t b/tests/basic/playground/template-xlator-sanity.t new file mode 100755 index 00000000000..1c665502bfe --- /dev/null +++ b/tests/basic/playground/template-xlator-sanity.t @@ -0,0 +1,43 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST mkdir -p $B0/single-brick +cat > $B0/template.vol <<EOF +volume posix + type storage/posix + option directory $B0/single-brick +end-volume + +volume template + type playground/template + subvolumes posix + option dummy 13 +end-volume +EOF + +TEST glusterfs -f $B0/template.vol $M0 + +TEST $(dirname $0)/../rpc-coverage.sh --no-locks $M0 + +# Take statedump to get maximum code coverage +pid=$(ps auxww | grep glusterfs | grep -E "template.vol" | awk '{print $2}' | head -1) + +TEST generate_statedump $pid + +# For monitor output +kill -USR2 $pid + +# Handle SIGHUP and reconfigure +sed -i -e '/s/dummy 13/dummy 42/g' $B0/template.vol +kill -HUP $pid + +# for calling 'fini()' +kill -TERM $pid + +force_umount $M0 + +cleanup; diff --git a/tests/basic/posix/shared-statfs.t b/tests/basic/posix/shared-statfs.t new file mode 100644 index 00000000000..0e4a1bb409f --- /dev/null +++ b/tests/basic/posix/shared-statfs.t @@ -0,0 +1,58 @@ +#!/bin/bash +#Test that statfs is not served from posix backend FS. + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; +TEST glusterd + +#Create brick partitions +TEST truncate -s 100M $B0/brick1 +TEST truncate -s 100M $B0/brick2 +LO1=`SETUP_LOOP $B0/brick1` +TEST [ $? -eq 0 ] +TEST MKFS_LOOP $LO1 +LO2=`SETUP_LOOP $B0/brick2` +TEST [ $? -eq 0 ] +TEST MKFS_LOOP $LO2 +TEST mkdir -p $B0/${V0}1 $B0/${V0}2 +TEST MOUNT_LOOP $LO1 $B0/${V0}1 +TEST MOUNT_LOOP $LO2 $B0/${V0}2 + +total_brick_blocks=$(df -P $B0/${V0}1 $B0/${V0}2 | tail -2 | awk '{sum = sum+$2}END{print sum}') +#Account for rounding error +brick_blocks_two_percent_less=$((total_brick_blocks*98/100)) +# Create a subdir in mountpoint and use that for volume. +TEST $CLI volume create $V0 $H0:$B0/${V0}1/1 $H0:$B0/${V0}2/1; +TEST $CLI volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" online_brick_count +TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0 +total_mount_blocks=$(df -P $M0 | tail -1 | awk '{ print $2}') +# Keeping the size less than 200M mainly because XFS will use +# some storage in brick to keep its own metadata. +TEST [ $total_mount_blocks -gt $brick_blocks_two_percent_less -a $total_mount_blocks -lt 200000 ] + + +TEST force_umount $M0 +TEST $CLI volume stop $V0 +EXPECT 'Stopped' volinfo_field $V0 'Status'; + +# From the same mount point, share another 2 bricks with the volume +TEST $CLI volume add-brick $V0 $H0:$B0/${V0}1/2 $H0:$B0/${V0}2/2 $H0:$B0/${V0}1/3 $H0:$B0/${V0}2/3 + +TEST $CLI volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "6" online_brick_count +TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0 +total_mount_blocks=$(df -P $M0 | tail -1 | awk '{ print $2}') +TEST [ $total_mount_blocks -gt $brick_blocks_two_percent_less -a $total_mount_blocks -lt 200000 ] + +TEST force_umount $M0 +TEST $CLI volume stop $V0 +EXPECT 'Stopped' volinfo_field $V0 'Status'; + +TEST $CLI volume delete $V0; + +UMOUNT_LOOP ${B0}/${V0}{1,2} +rm -f ${B0}/brick{1,2} +cleanup; diff --git a/tests/basic/posix/zero-fill-enospace.c b/tests/basic/posix/zero-fill-enospace.c new file mode 100644 index 00000000000..b1f142c6be9 --- /dev/null +++ b/tests/basic/posix/zero-fill-enospace.c @@ -0,0 +1,67 @@ +#include <stdio.h> +#include <stdlib.h> +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> + +int +main(int argc, char *argv[]) +{ + glfs_t *fs = NULL; + glfs_fd_t *fd = NULL; + int ret = 1; + off_t size = 0; + + if (argc != 6) { + fprintf(stderr, + "Syntax: %s <host> <volname> <file-path> <log-file> <size>\n", + argv[0]); + return 1; + } + + fs = glfs_new(argv[2]); + if (!fs) { + fprintf(stderr, "glfs_new: returned NULL\n"); + return 1; + } + + ret = glfs_set_volfile_server(fs, "tcp", argv[1], 24007); + if (ret != 0) { + fprintf(stderr, "glfs_set_volfile_server: returned %d\n", ret); + goto out; + } + ret = glfs_set_logging(fs, argv[4], 7); + if (ret != 0) { + fprintf(stderr, "glfs_set_logging: returned %d\n", ret); + goto out; + } + ret = glfs_init(fs); + if (ret != 0) { + fprintf(stderr, "glfs_init: returned %d\n", ret); + goto out; + } + + fd = glfs_open(fs, argv[3], O_RDWR); + if (fd == NULL) { + fprintf(stderr, "glfs_open: returned NULL\n"); + goto out; + } + + size = strtol(argv[5], NULL, 10); + if (size < 0) { + fprintf(stderr, "Wrong size %s", argv[5]); + goto out; + } + ret = glfs_zerofill(fd, 0, size); + if (ret <= 0) { + fprintf(stderr, "glfs_zerofill: returned %d\n", ret); + goto out; + } + + ret = 0; + +out: + if (fd) + glfs_close(fd); + glfs_fini(fs); + return ret; +} diff --git a/tests/basic/posix/zero-fill-enospace.t b/tests/basic/posix/zero-fill-enospace.t new file mode 100644 index 00000000000..ac2e61b10cf --- /dev/null +++ b/tests/basic/posix/zero-fill-enospace.t @@ -0,0 +1,35 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../dht.rc + +cleanup; + +TEST glusterd; +TEST pidof glusterd; + +TEST truncate -s 100M $B0/brick1 + +TEST L1=`SETUP_LOOP $B0/brick1` +TEST MKFS_LOOP $L1 + +TEST mkdir -p $B0/${V0}1 + +TEST MOUNT_LOOP $L1 $B0/${V0}1 + +TEST $CLI volume create $V0 $H0:$B0/${V0}1 + +TEST $CLI volume start $V0; + +TEST glusterfs -s $H0 --volfile-id=$V0 $M0 +TEST touch $M0/foo +TEST build_tester $(dirname $0)/zero-fill-enospace.c -lgfapi -Wall -O2 +TEST ! $(dirname $0)/zero-fill-enospace $H0 $V0 /foo `gluster --print-logdir`/glfs-$V0.log 104857600 + +TEST force_umount $M0 +TEST $CLI volume stop $V0 +UMOUNT_LOOP ${B0}/${V0}1 +rm -f ${B0}/brick1 + +cleanup diff --git a/tests/basic/pump.t b/tests/basic/pump.t deleted file mode 100644 index ab62f77224f..00000000000 --- a/tests/basic/pump.t +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../include.rc -. $(dirname $0)/../volume.rc - -cleanup; -START_TIMESTAMP=`date +%s` - -TEST glusterd -TEST pidof glusterd -TEST $CLI volume create $V0 $H0:$B0/${V0}0 -TEST $CLI volume start $V0 -TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; -cd $M0 -for i in {1..3} -do - for j in {1..10} - do - dd if=/dev/urandom of=file$j bs=128K count=10 2>/dev/null 1>/dev/null - done - mkdir dir$i && cd dir$i -done -cd -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 -TEST $CLI volume replace-brick $V0 $H0:$B0/${V0}0 $H0:$B0/${V0}1 commit force -TEST $CLI volume stop $V0 - -files="" - -cd $B0/${V0}0 -for f in `find . -path ./.glusterfs -prune -o -print`; -do - if [ -d $f ]; then continue; fi - cmp $f $B0/${V0}1/$f - if [ $? -ne 0 ]; then - files="$files $f" - fi -done - -EXPECT "" echo $files - -# Check for non Linux systems that we did not mess with directory offsets -TEST ! log_newer $START_TIMESTAMP "offset reused from another DIR" - -cleanup diff --git a/tests/basic/quick-read-with-upcall.t b/tests/basic/quick-read-with-upcall.t new file mode 100644 index 00000000000..dfb751dfcdb --- /dev/null +++ b/tests/basic/quick-read-with-upcall.t @@ -0,0 +1,72 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc + #. $(dirname $0)/../volume.rc + +cleanup; + +#Basic checks +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info + +#Create a distributed volume +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 --direct-io-mode=enable $M0; +TEST glusterfs -s $H0 --volfile-id $V0 --direct-io-mode=enable $M1; + +D0="test-message0"; +D1="test-message1"; + +function write_to() +{ + local file="$1"; + local data="$2"; + echo "$data" > "$file"; +} + + +TEST write_to "$M0/test.txt" "$D0" +EXPECT "$D0" cat $M0/test.txt +EXPECT "$D0" cat $M1/test.txt + +TEST write_to "$M0/test.txt" "$D1" +EXPECT "$D1" cat $M0/test.txt +EXPECT "$D0" cat $M1/test.txt + +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.quick-read-cache-timeout 15 +TEST $CLI volume set $V0 performance.md-cache-timeout 15 + +TEST write_to "$M0/test1.txt" "$D0" +EXPECT "$D0" cat $M0/test1.txt +EXPECT "$D0" cat $M1/test1.txt + +TEST write_to "$M0/test1.txt" "$D1" +EXPECT "$D1" cat $M0/test1.txt +EXPECT "$D0" cat $M1/test1.txt + +sleep 1 +EXPECT "$D0" cat $M1/test1.txt + +sleep 30 +EXPECT "$D1" cat $M1/test1.txt + +TEST $CLI volume set $V0 performance.quick-read-cache-invalidation on +TEST $CLI volume set $V0 performance.cache-invalidation on + +TEST write_to "$M0/test2.txt" "$D0" +EXPECT "$D0" cat $M0/test2.txt +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 diff --git a/tests/basic/quota-ancestry-building.t b/tests/basic/quota-ancestry-building.t index 99c971859e8..fcb39ee31f5 100755 --- a/tests/basic/quota-ancestry-building.t +++ b/tests/basic/quota-ancestry-building.t @@ -65,9 +65,7 @@ exec 5>&- exec 6>&- TEST $CLI volume stop $V0 -EXPECT "1" get_aux rm -f $QDD cleanup; #G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=1332020 -#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=1332020 diff --git a/tests/basic/quota-anon-fd-nfs.t b/tests/basic/quota-anon-fd-nfs.t index c6b01553b02..9e6675af6ec 100755 --- a/tests/basic/quota-anon-fd-nfs.t +++ b/tests/basic/quota-anon-fd-nfs.t @@ -5,6 +5,8 @@ . $(dirname $0)/../nfs.rc . $(dirname $0)/../fileio.rc +#G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST + cleanup; QDD=$(dirname $0)/quota @@ -50,6 +52,7 @@ TEST $CLI volume quota $V0 limit-usage / 1 TEST $CLI volume quota $V0 soft-timeout 0 TEST $CLI volume quota $V0 hard-timeout 0 +EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "1" is_nfs_export_available; TEST mount_nfs $H0:/$V0 $N0 noac,soft,nolock,vers=3; deep=/0/1/2/3/4/5/6/7/8/9 TEST mkdir -p $N0/$deep @@ -97,8 +100,16 @@ $CLI volume statedump $V0 all EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $N0 +# This is ugly, but there seems to be a latent race between other actions and +# stopping the volume. The visible symptom is that "umount -l" (run from +# gf_umount_lazy in glusterd) hangs. This happens pretty consistently with the +# new mem-pool code, though it's not really anything to do with memory pools - +# just with changed timing. Adding the sleep here makes it work consistently. +# +# If anyone else wants to debug the race condition, feel free. +sleep 3 + TEST $CLI volume stop $V0 -EXPECT "1" get_aux rm -f $QDD diff --git a/tests/basic/quota-nfs.t b/tests/basic/quota-nfs.t index 74fde400bd1..de94a950a7f 100755 --- a/tests/basic/quota-nfs.t +++ b/tests/basic/quota-nfs.t @@ -4,6 +4,8 @@ . $(dirname $0)/../volume.rc . $(dirname $0)/../nfs.rc +#G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST + cleanup; QDD=$(dirname $0)/quota # compile the test write program and run it @@ -58,7 +60,6 @@ TEST rm -f $N0/$deep/newfile_2 EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 TEST $CLI volume stop $V0 -EXPECT "1" get_aux rm -f $QDD cleanup; diff --git a/tests/basic/quota.c b/tests/basic/quota.c index f69b0ea9bc5..809ceb8e54c 100644 --- a/tests/basic/quota.c +++ b/tests/basic/quota.c @@ -8,83 +8,82 @@ #include <unistd.h> ssize_t -nwrite (int fd, const void *buf, size_t count) +nwrite(int fd, const void *buf, size_t count) { - ssize_t ret = 0; - ssize_t written = 0; + ssize_t ret = 0; + ssize_t written = 0; - for (written = 0; written != count; written += ret) { - ret = write (fd, buf + written, count - written); - if (ret < 0) { - if (errno == EINTR) - ret = 0; - else - goto out; - } + for (written = 0; written != count; written += ret) { + ret = write(fd, buf + written, count - written); + if (ret < 0) { + if (errno == EINTR) + ret = 0; + else + goto out; } + } - ret = written; + ret = written; out: - return ret; + return ret; } int -file_write (char *filename, int bs, int count) +file_write(char *filename, int bs, int count) { - int fd = 0; - int ret = -1; - int i = 0; - char *buf = NULL; + int fd = 0; + int ret = -1; + int i = 0; + char *buf = NULL; - bs = bs * 1024; + bs = bs * 1024; - buf = (char *) malloc (bs); - if (buf == NULL) - goto out; + buf = (char *)malloc(bs); + if (buf == NULL) + goto out; - memset (buf, 0, bs); + memset(buf, 0, bs); - fd = open (filename, O_RDWR|O_CREAT|O_SYNC, 0600); - while (i < count) { - ret = nwrite(fd, buf, bs); - if (ret == -1) { - close (fd); - goto out; - } - i++; + fd = open(filename, O_RDWR | O_CREAT | O_SYNC, 0600); + while (i < count) { + ret = nwrite(fd, buf, bs); + if (ret == -1) { + close(fd); + goto out; } + i++; + } - ret = fdatasync(fd); - if (ret) { - close (fd); - goto out; - } + ret = fdatasync(fd); + if (ret) { + close(fd); + goto out; + } - ret = close(fd); - if (ret) - goto out; + ret = close(fd); + if (ret) + goto out; - ret = 0; + ret = 0; out: - if (buf) - free (buf); - return ret; + if (buf) + free(buf); + return ret; } int -main (int argc, char **argv) +main(int argc, char **argv) { - if (argc != 4) { - printf("Usage: %s <filename> <block size in k> <count>\n", - argv[0]); - return EXIT_FAILURE; - } + if (argc != 4) { + printf("Usage: %s <filename> <block size in k> <count>\n", argv[0]); + return EXIT_FAILURE; + } - if (file_write (argv[1], atoi(argv[2]), atoi(argv[3])) < 0) { - perror ("write failed"); - return EXIT_FAILURE; - } + if (file_write(argv[1], atoi(argv[2]), atoi(argv[3])) < 0) { + perror("write failed"); + return EXIT_FAILURE; + } - return EXIT_SUCCESS; + return EXIT_SUCCESS; } diff --git a/tests/basic/quota.t b/tests/basic/quota.t index 17d571060e1..46d1bafff84 100755 --- a/tests/basic/quota.t +++ b/tests/basic/quota.t @@ -6,6 +6,8 @@ . $(dirname $0)/../dht.rc . $(dirname $0)/../nfs.rc +#G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST + cleanup; QDD=$(dirname $0)/quota @@ -40,12 +42,8 @@ EXPECT 'on' volinfo_field $V0 'features.quota' EXPECT 'on' volinfo_field $V0 'features.inode-quota' EXPECT 'on' volinfo_field $V0 'features.quota-deem-statfs' -#Wait for the auxiliarymount to come up -sleep 3 TEST $CLI volume quota $V0 limit-usage /test_dir 100MB -# Checking for auxiliary mount -EXPECT "0" get_aux TEST $CLI volume quota $V0 limit-usage /test_dir/in_test_dir 150MB @@ -231,9 +229,7 @@ EXPECT 'off' volinfo_field $V0 'features.quota' EXPECT 'off' volinfo_field $V0 'features.inode-quota' EXPECT '' volinfo_field $V0 'features.quota-deem-statfs' -# aux mount should be removed TEST $CLI volume stop $V0; -EXPECT "1" get_aux rm -f $QDD cleanup; diff --git a/tests/basic/quota_aux_mount.t b/tests/basic/quota_aux_mount.t new file mode 100755 index 00000000000..78d7f47e373 --- /dev/null +++ b/tests/basic/quota_aux_mount.t @@ -0,0 +1,53 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +##------------------------------------------------------------- +## Tests to verify that aux mount is unmounted after each quota +## command executes. +##------------------------------------------------------------- + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info; + +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{1,2,3,4}; + +EXPECT "$V0" volinfo_field $V0 'Volume Name'; +EXPECT 'Created' volinfo_field $V0 'Status'; +EXPECT '4' brick_count $V0 + +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; + +TEST $GFS -s $H0 --volfile-id $V0 $M0; + +TEST mkdir -p $M0/test_dir/ + +TEST $CLI volume quota $V0 enable +EXPECT 'on' volinfo_field $V0 'features.quota' +EXPECT 'on' volinfo_field $V0 'features.inode-quota' + +TEST $CLI volume quota $V0 limit-usage /test_dir 150MB +EXPECT "1" get_limit_aux +TEST $CLI volume quota $V0 limit-objects /test_dir 10 +EXPECT "1" get_limit_aux +EXPECT "150.0MB" quota_hard_limit "/test_dir"; +EXPECT "1" get_list_aux +EXPECT "10" quota_object_hard_limit "/test_dir"; +EXPECT "1" get_list_aux + +TEST $CLI volume quota $V0 remove /test_dir/ +EXPECT "1" get_limit_aux +TEST $CLI volume quota $V0 remove-objects /test_dir +EXPECT "1" get_limit_aux + +TEST $CLI volume quota $V0 disable + +TEST $CLI volume stop $V0; + +cleanup; +#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=1447344 diff --git a/tests/basic/rpc-coverage.sh b/tests/basic/rpc-coverage.sh index 11d3be66dcb..6203f0ac7cb 100755 --- a/tests/basic/rpc-coverage.sh +++ b/tests/basic/rpc-coverage.sh @@ -419,9 +419,15 @@ function test_rmdir() rm -rf $PFX || fail "rm -rf" } +function test_statvfs() +{ + df $DIR 2>&1 || fail "df" +} + function run_tests() { + test_statvfs; test_mkdir; test_create; test_statfs; @@ -436,13 +442,15 @@ function run_tests() test_rename; test_chmod; test_chown; - test_utimes; - test_locks; test_readdir; test_setxattr; test_listxattr; test_getxattr; test_removexattr; + if [ "$run_lock_tests" = "1" ]; then + test_locks; + fi + test_utimes; test_unlink; test_rmdir; } @@ -453,14 +461,19 @@ function _init() DIR=$(pwd); } - +run_lock_tests=1 function parse_cmdline() { if [ "x$1" == "x" ] ; then - echo "Usage: $0 /path/mount" + echo "Usage: $0 [--no-locks] /path/mount" exit 1 fi + if [ "$1" == "--no-locks" ] ; then + run_lock_tests=0 + shift + fi + DIR=$1; if [ ! -d "$DIR" ] ; then diff --git a/tests/basic/rpc-coverage.t b/tests/basic/rpc-coverage.t index a76ba7084eb..2c1bcd5a63a 100755 --- a/tests/basic/rpc-coverage.t +++ b/tests/basic/rpc-coverage.t @@ -9,11 +9,11 @@ TEST glusterd TEST pidof glusterd TEST $CLI volume info; -TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{1,2,3,4,5,6,7,8}; +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{1,2,3,4,5,6,7,8,9}; EXPECT "$V0" volinfo_field $V0 'Volume Name'; EXPECT 'Created' volinfo_field $V0 'Status'; -EXPECT '8' brick_count $V0 +EXPECT '9' brick_count $V0 TEST $CLI volume start $V0; EXPECT 'Started' volinfo_field $V0 'Status'; diff --git a/tests/basic/rpm.t b/tests/basic/rpm.t deleted file mode 100755 index e5da49bb7e0..00000000000 --- a/tests/basic/rpm.t +++ /dev/null @@ -1,145 +0,0 @@ -#!/bin/bash -# -# This test will run mock and rebuild the srpm for the latest two EPEL version. -# By default, the results and the chroots are deleted. -# -# When debugging is needed, make sure to set DEBUG=1 in the environment or this -# script. When debugging is enabled, the resulting log files and chroots are -# kept. With debugging enabled, this test will fail the regression test, and -# all output is saved to rpmbuild-mock.log. Tests are run in parallel, so the -# logfile may be difficult to read. -# -# chroots are configured in /etc/mock/*.cfg, with site-defaults.cfg as main -# configuration file. The default for chroots is /var/lib/mock, but this -# depends on the 'basedir' configuration option set in the mentioned files. -# - -. $(dirname $0)/../include.rc - -case $OSTYPE in -Linux) - ;; -*) - echo "Skip test using mock, which requires Linux" >&2 - SKIP_TESTS - exit 0 - ;; -esac - -# enable some extra debugging -if [ -n "${DEBUG}" -a "${DEBUG}" != "0" ] -then - exec &> rpmbuild-mock.log - set -x - MOCK_CLEANUP='--no-cleanup-after' -else - MOCK_CLEANUP='--cleanup-after' -fi - -# detect the branch we're based off -if [ -n "${BRANCH}" ] ; then - # $BRANCH is set in the environment (by Jenkins or other) - GIT_PARENT="origin/${BRANCH}" -else - # get a reference to the latest clean tree - GIT_PARENT=$(git describe --abbrev=0) -fi - -# Filter out everything and what remains needs to be built -BUILD_FILES=$(git diff --name-status ${GIT_PARENT} | grep -Ev '^M.*\.(c|h|py)' | awk {'print $2'}) -SELFTEST=$(grep -e 'tests/basic/rpm.t' <<< "${BUILD_FILES}") -BUILD_FILES=$(grep -Ev '^tests/' <<< "${BUILD_FILES}") -if [ -z "${BUILD_FILES}" -a -z "${SELFTEST}" ] -then - # nothing affecting packaging changed, no need to retest rpmbuild - SKIP_TESTS - cleanup - exit 0 -fi - -# checkout the sources to a new directory to execute ./configure and all -REPO=${PWD} -COMMIT=$(git describe) - -# make sure to cleanup in case DEBUG was enabled in a previous run -[ -d rpmbuild-mock.d ] && rm -rf rpmbuild-mock.d -mkdir rpmbuild-mock.d -pushd rpmbuild-mock.d 2>/dev/null - -function git_quiet() { - git ${@} 2>&1 > /dev/null -} - -TEST git_quiet clone -s file://${REPO} . -TEST git_quiet checkout -b rpm-test ${COMMIT} - -# build the glusterfs-*.tar.gz -function build_srpm_from_tgz() { - rpmbuild -ts $1 \ - --define "_srcrpmdir ${PWD}" \ - --define '_source_payload w9.gzdio' \ - --define '_source_filedigest_algorithm 1' -} - -TEST ./autogen.sh -TEST ./configure -TEST make dist - -# build the glusterfs src.rpm -TEST build_srpm_from_tgz ${PWD}/*.tar.gz - -# even though the last two Fedora EPEL releases are x86_64 only, we allow other arches to build -for MOCK_CONF in $(ls -x1 /etc/mock/*.cfg | egrep -e 'epel-[0-9]+-'`uname -i`'.cfg$' | tail -n2) -do - EPEL_RELEASE=$(basename ${MOCK_CONF} .cfg) - mkdir -p "${PWD}/mock.d/${EPEL_RELEASE}" - chgrp mock "${PWD}/mock.d/${EPEL_RELEASE}" - chmod 0775 "${PWD}/mock.d/${EPEL_RELEASE}" - MOCK_RESULTDIR="--resultdir ${PWD}/mock.d/${EPEL_RELEASE}" - # expand the mock command line - MOCK_CMD="/usr/bin/mock ${MOCK_CLEANUP} \ - ${MOCK_RESULTDIR} \ - -r ${EPEL_RELEASE} --rebuild ${PWD}/*.src.rpm" - - # write the mock command to a file, so that its easier to execute - cat << EOF > mock-${EPEL_RELEASE}.sh -#!/bin/sh -${MOCK_CMD} -EOF - chmod +x mock-${EPEL_RELEASE}.sh - - # root can not run 'mock', it needs to drop privileges - if (groups | grep -q mock) - then - # the current user is in group 'mock' - ${PWD}/mock-${EPEL_RELEASE}.sh & - else - # "su" might not work, using sudo instead - sudo -u mock -E ${PWD}/mock-${EPEL_RELEASE}.sh & - fi - sleep 5 -done - -# TAP and Prove aren't smart about loops -TESTS_EXPECTED_IN_LOOP=2 -for mockjob in $(jobs -p) -do - TEST_IN_LOOP wait ${mockjob} -done - -# we could build for the last two Fedora releases too, but that is not -# possible on EPEL-5/6 installations, Fedora 17 and newer have unmet -# dependencies on the build-server :-/ - -# logs are archived by Jenkins -if [ -d '/build/install/var' ] -then - LOGS=$(find mock.d -type f -name '*.log') - [ -n "${LOGS}" ] && xargs cp --parents ${LOGS} /build/install/var/ -fi - -popd 2>/dev/null -# only remove rpmbuild-mock.d if we're not debugging -[ "${DEBUG}" = "0" ] && rm -rf rpmbuild-mock.d - -cleanup diff --git a/tests/basic/sdfs-sanity.t b/tests/basic/sdfs-sanity.t new file mode 100644 index 00000000000..16d0bed866f --- /dev/null +++ b/tests/basic/sdfs-sanity.t @@ -0,0 +1,28 @@ +#!/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}{1,2,3,4,5,6,7,8,9}; +TEST $CLI volume set $V0 features.sdfs enable; +TEST $CLI volume start $V0; + +## Mount FUSE +TEST $GFS -s $H0 --volfile-id $V0 $M1; + +# This test covers lookup, mkdir, mknod, symlink, link, rename, +# create operations +TEST $(dirname $0)/rpc-coverage.sh $M1 + +TEST cp $(dirname ${0})/gfapi/glfsxmp-coverage.c glfsxmp.c +TEST build_tester ./glfsxmp.c -lgfapi +TEST ./glfsxmp $V0 $H0 +TEST cleanup_tester ./glfsxmp +TEST rm ./glfsxmp.c + +cleanup; diff --git a/tests/basic/seek.c b/tests/basic/seek.c new file mode 100644 index 00000000000..54fa6f463af --- /dev/null +++ b/tests/basic/seek.c @@ -0,0 +1,182 @@ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> + +static char buffer[65536]; + +static int +parse_int(const char *text, size_t *value) +{ + char *ptr; + size_t val; + + val = strtoul(text, &ptr, 0); + if (*ptr != 0) { + return 0; + } + + *value = val; + + return 1; +} + +static int +fill_area(int fd, off_t offset, size_t size) +{ + size_t len; + ssize_t res; + + while (size > 0) { + len = sizeof(buffer); + if (len > size) { + len = size; + } + res = pwrite(fd, buffer, len, offset); + if (res < 0) { + fprintf(stderr, "pwrite(%d, %p, %lu, %lu) failed: %d\n", fd, buffer, + size, offset, errno); + return 0; + } + if (res != len) { + fprintf(stderr, + "pwrite(%d, %p, %lu, %lu) didn't wrote all " + "data: %lu/%lu\n", + fd, buffer, size, offset, res, len); + return 0; + } + offset += len; + size -= len; + } + + return 1; +} + +static void +syntax(void) +{ + fprintf(stderr, "Syntax: seek create <path> <offset> <size> [...]\n"); + fprintf(stderr, " seek scan <path> data|hole <offset>\n"); +} + +static int +seek_create(const char *path, int argc, char *argv[]) +{ + size_t off, size; + int fd; + int ret = 1; + + fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644); + if (fd < 0) { + fprintf(stderr, "Failed to create the file\n"); + goto out; + } + + while (argc > 0) { + if (!parse_int(argv[0], &off) || !parse_int(argv[1], &size)) { + syntax(); + goto out_close; + } + if (!fill_area(fd, off, size)) { + goto out_close; + } + argv += 2; + argc -= 2; + } + + ret = 0; + +out_close: + close(fd); +out: + return ret; +} + +static int +seek_scan(const char *path, const char *type, const char *pos) +{ + size_t off, res; + int fd, whence; + int ret = 1; + + if (strcmp(type, "data") == 0) { + whence = SEEK_DATA; + } else if (strcmp(type, "hole") == 0) { + whence = SEEK_HOLE; + } else { + syntax(); + goto out; + } + + if (!parse_int(pos, &off)) { + syntax(); + goto out; + } + + fd = open(path, O_RDWR); + if (fd < 0) { + fprintf(stderr, "Failed to open the file\n"); + goto out; + } + + res = lseek(fd, off, whence); + if (res == (off_t)-1) { + if (errno != ENXIO) { + fprintf(stderr, "seek(%d, %lu, %d) failed: %d\n", fd, off, whence, + errno); + goto out_close; + } + fprintf(stdout, "ENXIO\n"); + } else { + fprintf(stdout, "%lu\n", res); + } + + ret = 0; + +out_close: + close(fd); +out: + return ret; +} + +int +main(int argc, char *argv[]) +{ + int ret = 1; + + memset(buffer, 0x55, sizeof(buffer)); + + if (argc < 3) { + syntax(); + goto out; + } + + if (strcmp(argv[1], "create") == 0) { + if (((argc - 3) & 1) != 0) { + syntax(); + goto out; + } + ret = seek_create(argv[2], argc - 3, argv + 3); + } else if (strcmp(argv[1], "scan") == 0) { + if (argc != 5) { + syntax(); + goto out; + } + ret = seek_scan(argv[2], argv[3], argv[4]); + } else { + syntax(); + goto out; + } + + ret = 0; + +out: + return ret; +} diff --git a/tests/basic/shd-mux-afr.t b/tests/basic/shd-mux-afr.t new file mode 100644 index 00000000000..cf300c148bb --- /dev/null +++ b/tests/basic/shd-mux-afr.t @@ -0,0 +1,70 @@ +#!/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,3,4,5} +TEST $CLI volume set $V0 cluster.background-self-heal-count 0 +TEST $CLI volume set $V0 cluster.eager-lock off +TEST $CLI volume set $V0 performance.flush-behind off +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 + +shd_pid=$(get_shd_mux_pid $V0) +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^6$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +#Create a one more volume +TEST $CLI volume create ${V0}_1 replica 3 $H0:$B0/${V0}_1{0,1,2,3,4,5} +TEST $CLI volume start ${V0}_1 + +#Check whether the shd has multiplexed or not +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" shd_count +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^${shd_pid}$" get_shd_mux_pid ${V0}_1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^${shd_pid}$" get_shd_mux_pid ${V0} + +TEST $CLI volume set ${V0}_1 cluster.background-self-heal-count 0 +TEST $CLI volume set ${V0}_1 cluster.eager-lock off +TEST $CLI volume set ${V0}_1 performance.flush-behind off +TEST $GFS --volfile-id=/${V0}_1 --volfile-server=$H0 $M1 + +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}4 +TEST kill_brick ${V0}_1 $H0 $B0/${V0}_10 +TEST kill_brick ${V0}_1 $H0 $B0/${V0}_14 + +TEST touch $M0/foo{1..100} +TEST touch $M1/foo{1..100} + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^204$" get_pending_heal_count $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^204$" get_pending_heal_count ${V0}_1 + +TEST $CLI volume start ${V0} force +TEST $CLI volume start ${V0}_1 force + +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count ${V0}_1 + +TEST rm -rf $M0/* +TEST rm -rf $M1/* +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M1 + +#Stop the volume +TEST $CLI volume stop ${V0}_1 +TEST $CLI volume delete ${V0}_1 + +#Check the stop succeeded and detached the volume with out restarting it +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" shd_count + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^${shd_pid}$" get_shd_mux_pid $V0 + +#Check the thread count become to earlier number after stopping +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^6$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +TEST $CLI volume stop ${V0} +TEST $CLI volume delete ${V0} +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^0$" shd_count +cleanup diff --git a/tests/basic/shd-mux-ec.t b/tests/basic/shd-mux-ec.t new file mode 100644 index 00000000000..ef4d65018d3 --- /dev/null +++ b/tests/basic/shd-mux-ec.t @@ -0,0 +1,75 @@ +#!/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,3,4,5} +TEST $CLI volume set $V0 cluster.background-self-heal-count 0 +TEST $CLI volume set $V0 cluster.eager-lock off +TEST $CLI volume set $V0 performance.flush-behind off +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 + +shd_pid=$(get_shd_mux_pid $V0) +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^6$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +#Now create a ec volume and check mux works +TEST $CLI volume create ${V0}_2 disperse 6 redundancy 2 $H0:$B0/${V0}_2{0,1,2,3,4,5} +TEST $CLI volume start ${V0}_2 + +#Check whether the shd has multiplexed or not +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" shd_count +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^${shd_pid}$" get_shd_mux_pid ${V0}_2 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^${shd_pid}$" get_shd_mux_pid ${V0} + +TEST $CLI volume set ${V0}_2 cluster.background-self-heal-count 0 +TEST $CLI volume set ${V0}_2 cluster.eager-lock off +TEST $CLI volume set ${V0}_2 performance.flush-behind off +TEST $GFS --volfile-id=/${V0}_2 --volfile-server=$H0 $M1 + +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}4 +TEST kill_brick ${V0}_2 $H0 $B0/${V0}_20 +TEST kill_brick ${V0}_2 $H0 $B0/${V0}_22 + +TEST touch $M0/foo{1..100} +TEST touch $M1/foo{1..100} + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^204$" get_pending_heal_count $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^404$" get_pending_heal_count ${V0}_2 + +TEST $CLI volume start ${V0} force +TEST $CLI volume start ${V0}_2 force + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^6$" number_healer_threads_shd $V0 "ec_shd_index_healer" + +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count ${V0}_2 + +TEST rm -rf $M0/* +TEST rm -rf $M1/* + + +#Stop the volume +TEST $CLI volume stop ${V0}_2 +TEST $CLI volume delete ${V0}_2 + +#Check the stop succeeded and detached the volume with out restarting it +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" shd_count + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^${shd_pid}$" get_shd_mux_pid $V0 + +#Check the thread count become to zero for ec related threads +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^0$" number_healer_threads_shd $V0 "ec_shd_index_healer" +#Check the thread count become to earlier number after stopping +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^6$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +TEST $CLI volume stop ${V0} +TEST $CLI volume delete ${V0} +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^0$" shd_count + +cleanup diff --git a/tests/basic/stats-dump.t b/tests/basic/stats-dump.t index 7da6e0605a4..ed73fd1d14a 100644 --- a/tests/basic/stats-dump.t +++ b/tests/basic/stats-dump.t @@ -4,6 +4,8 @@ . $(dirname $0)/../volume.rc . $(dirname $0)/../nfs.rc +#G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST + cleanup; TEST glusterd @@ -12,6 +14,7 @@ TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2} TEST $CLI volume set $V0 diagnostics.latency-measurement on TEST $CLI volume set $V0 diagnostics.count-fop-hits on TEST $CLI volume set $V0 diagnostics.stats-dump-interval 1 +TEST $CLI volume set $V0 performance.nfs.io-threads on TEST $CLI volume set $V0 nfs.disable off TEST $CLI volume start $V0 EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "1" is_nfs_export_available @@ -25,19 +28,28 @@ done for i in {1..10};do dd if=/dev/zero of=$N0/nfs_testfile$i bs=4k count=100 done + +# Wait for one dump interval to be done, some seconds past 1 that is the dump +# interval set sleep 2 +# Change the dump interval to 0, so that when reading the file contents we +# do not get them truncated by the next interval that is overwriting the latest +# stats data +TEST $CLI volume set $V0 diagnostics.stats-dump-interval 0 + # Verify we have non-zero write counts from the bricks, gNFSd -# and the FUSE mount -BRICK_OUTPUT="$(grep 'aggr.fop.write.count": "0"' ${GLUSTERD_WORKDIR}/stats/glusterfsd__d_backends_patchy?.dump)" -BRICK_RET="$?" -NFSD_OUTPUT="$(grep 'aggr.fop.write.count": "0"' ${GLUSTERD_WORKDIR}/stats/glusterfs_nfsd.dump)" -NFSD_RET="$?" -FUSE_OUTPUT="$(grep 'aggr.fop.write.count": "0"' ${GLUSTERD_WORKDIR}/stats/glusterfs_patchy.dump)" -FUSE_RET="$?" - -TEST [ 0 -ne "$BRICK_RET" ] -TEST [ 0 -ne "$NFSD_RET" ] -TEST [ 0 -ne "$FUSE_RET" ] +# and the FUSE mount. +TEST [ $(grep 'aggr.fop.write.count' ${GLUSTERD_WORKDIR}/stats/glusterfs_nfsd.dump|tail -1|cut -d: -f2) != "0," ] +TEST [ $(grep 'aggr.fop.write.count' ${GLUSTERD_WORKDIR}/stats/glusterfs_patchy.dump|tail -1|cut -d: -f2) != "0," ] +TEST [ $(grep 'aggr.fop.write.count' ${GLUSTERD_WORKDIR}/stats/glusterfsd__d_backends_patchy0.dump|tail -1|cut -d: -f2) != "0," ] +TEST [ $(grep 'aggr.fop.write.count' ${GLUSTERD_WORKDIR}/stats/glusterfsd__d_backends_patchy1.dump|tail -1|cut -d: -f2) != "0," ] +TEST [ $(grep 'aggr.fop.write.count' ${GLUSTERD_WORKDIR}/stats/glusterfsd__d_backends_patchy2.dump|tail -1|cut -d: -f2) != "0," ] + +# Test that io-stats is getting queue sizes from io-threads +TEST grep '.queue_size' ${GLUSTERD_WORKDIR}/stats/glusterfs_nfsd.dump +TEST grep '.queue_size' ${GLUSTERD_WORKDIR}/stats/glusterfsd__d_backends_patchy0.dump +TEST grep '.queue_size' ${GLUSTERD_WORKDIR}/stats/glusterfsd__d_backends_patchy1.dump +TEST grep '.queue_size' ${GLUSTERD_WORKDIR}/stats/glusterfsd__d_backends_patchy2.dump cleanup; diff --git a/tests/basic/symbol-check.sh b/tests/basic/symbol-check.sh index f84d591facb..0f8243ca731 100755 --- a/tests/basic/symbol-check.sh +++ b/tests/basic/symbol-check.sh @@ -13,6 +13,8 @@ syscalls32=$'creat\nfallocate\nftruncate\n__fxstat\n__fxstatat\n\ lseek\n__lxstat\nopenat\nreaddir\nstatvfs\ntruncate\nstat\n\ preadv\npwritev\npread\npwrite' +glibccalls=$'tmpfile' + exclude_files=$'/libglusterfs/src/.libs/libglusterfs_la-syscall.o\n\ /libglusterfs/src/.libs/libglusterfs_la-gen_uuid.o\n\ /contrib/fuse-util/fusermount.o\n\ @@ -33,13 +35,14 @@ function main() done local retval=0 - local t=$(nm ${1} | grep " U " | sed -e "s/ //g" -e "s/ U //g") + local t + t=$(nm "${1}" | grep " U " | sed -e "s/ //g" -e "s/ U //g") for symy in ${t}; do for symx in ${syscalls}; do - if [[ ${symx} = ${symy} ]]; then + if [[ ${symx} = "${symy}" ]]; then case ${symx} in "creat64") sym="creat";; @@ -70,12 +73,36 @@ function main() for symx in ${syscalls32}; do - if [[ ${symx} = ${symy} ]]; then + if [[ ${symx} = "${symy}" ]]; then echo "${1} was not compiled with -D_FILE_OFFSET_BITS=64" >&2 retval=1 fi done + + symy_glibc=$(echo "${symy}" | sed -e "s/@@GLIBC.*//g") + # Eliminate false positives, check if we have a GLIBC symbol in 'y' + if [[ ${symy} != "${symy_glibc}" ]]; then + for symx in ${glibccalls}; do + + if [[ ${symx} = "${symy_glibc}" ]]; then + + case ${symx} in + "tmpfile") alt="mkstemp";; + *) alt="none";; + esac + + if [[ ${alt} = "none" ]]; then + echo "${1} should not call ${symy_glibc}"; + else + echo "${1} should use ${alt} instead of ${symy_glibc}" >&2; + fi + + retval=1 + fi + done + fi + done if [ ${retval} = 1 ]; then diff --git a/tests/basic/tier/bug-1214222-directories_missing_after_attach_tier.t b/tests/basic/tier/bug-1214222-directories_missing_after_attach_tier.t deleted file mode 100755 index 754e8033f61..00000000000 --- a/tests/basic/tier/bug-1214222-directories_missing_after_attach_tier.t +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc - -LAST_BRICK=3 -CACHE_BRICK_FIRST=4 -CACHE_BRICK_LAST=5 -DEMOTE_TIMEOUT=12 -PROMOTE_TIMEOUT=5 - - -LAST_BRICK=1 -CACHE_BRICK=2 -DEMOTE_TIMEOUT=12 -PROMOTE_TIMEOUT=5 -MIGRATION_TIMEOUT=10 -cleanup - - -TEST glusterd -TEST pidof glusterd - -TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0..$LAST_BRICK} -TEST $CLI volume start $V0 -TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; - -# Basic operations. -cd $M0 -TEST stat . -TEST mkdir d1 -TEST [ -d d1 ] -TEST touch file1 -TEST [ -e file1 ] - -TEST $CLI volume attach-tier $V0 replica 2 $H0:$B0/${V0}$CACHE_BRICK_FIRST $H0:$B0/${V0}$CACHE_BRICK_LAST -TEST $CLI volume set $V0 features.ctr-enabled on - -#check whether the directory's and files are present on mount or not. -TEST [ -d d1 ] -TEST [ -e file1 ] - -cd -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0; - -TEST $CLI volume detach-tier $V0 start -TEST $CLI volume detach-tier $V0 commit - -EXPECT "0" confirm_tier_removed ${V0}${CACHE_BRICK_FIRST} - -EXPECT_WITHIN $REBALANCE_TIMEOUT "0" confirm_vol_stopped $V0 - - -cleanup -#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=000000 -#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=000000 diff --git a/tests/basic/tier/ctr-rename-overwrite.t b/tests/basic/tier/ctr-rename-overwrite.t deleted file mode 100755 index 8bccd3b3489..00000000000 --- a/tests/basic/tier/ctr-rename-overwrite.t +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc - -LAST_BRICK=1 -CACHE_BRICK_FIRST=4 -CACHE_BRICK_LAST=5 - -DEMOTE_FREQ=5 -PROMOTE_FREQ=5 - -cleanup - -# Start glusterd -TEST glusterd -TEST pidof glusterd - -# Set-up tier cluster -TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0..$LAST_BRICK} -TEST $CLI volume start $V0 -TEST $CLI volume attach-tier $V0 replica 2 $H0:$B0/${V0}$CACHE_BRICK_FIRST $H0:$B0/${V0}$CACHE_BRICK_LAST - -TEST $CLI volume set $V0 cluster.tier-demote-frequency $DEMOTE_FREQ -TEST $CLI volume set $V0 cluster.tier-promote-frequency $PROMOTE_FREQ - -# Start and mount the volume after enabling CTR -TEST $CLI volume set $V0 features.ctr-enabled on -TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; - -# create two files -echo "hello world" > $M0/file1 -echo "hello world" > $M0/file2 - -# db in hot brick shows 4 record. 2 for file1 and 2 for file2 -ENTRY_COUNT=$(echo "select * from gf_file_tb; select * from gf_flink_tb;" | \ - sqlite3 $B0/${V0}5/.glusterfs/${V0}5.db | wc -l ) -TEST [ $ENTRY_COUNT -eq 4 ] - -#overwrite file2 with file1 -mv -f $M0/file1 $M0/file2 - -# Now the db in hot tier should have only 2 records for file1. -ENTRY_COUNT=$(echo "select * from gf_file_tb; select * from gf_flink_tb;" | \ - sqlite3 $B0/${V0}5/.glusterfs/${V0}5.db | wc -l ) -TEST [ $ENTRY_COUNT -eq 2 ] - -cleanup -#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 diff --git a/tests/basic/tier/file_lock.c b/tests/basic/tier/file_lock.c deleted file mode 100644 index 730cca92e42..00000000000 --- a/tests/basic/tier/file_lock.c +++ /dev/null @@ -1,75 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> - - -void usage (void) -{ - - printf ("Usage: testlock <filepath> [R|W]\n"); - return; -} - - -int main (int argc, char *argv[]) -{ - char *file_path = NULL; - int fd = -1; - struct flock lock = {0}; - int ret = -1; - int c = 0; - - if (argc != 3) { - usage (); - exit (1); - } - - file_path = argv[1]; - fd = open (file_path, O_RDWR); - - if (-1 == fd) { - printf ("Failed to open file %s. %m\n", file_path); - exit (1); - } - - /* TODO: Check for invalid input*/ - - if (!strcmp (argv[2], "W")) { - lock.l_type = F_WRLCK; - printf("Taking write lock\n"); - - } else { - lock.l_type = F_RDLCK; - printf("Taking read lock\n"); - } - - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - lock.l_pid = getpid (); - - - printf ("Acquiring lock on %s\n", file_path); - ret = fcntl (fd, F_SETLK, &lock); - if (ret) { - printf ("Failed to acquire lock on %s (%m)\n", file_path); - close (fd); - exit (1); - } - - sleep(10); - - /*Unlock*/ - - printf ("Releasing lock on %s\n", file_path); - lock.l_type = F_UNLCK; - ret = fcntl (fd, F_SETLK, &lock); - if (ret) { - printf ("Failed to release lock on %s (%m)\n", file_path); - } - - close (fd); - return ret; - -} diff --git a/tests/basic/tier/file_with_spaces.t b/tests/basic/tier/file_with_spaces.t deleted file mode 100755 index bd99e71ffe5..00000000000 --- a/tests/basic/tier/file_with_spaces.t +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc - -NUM_BRICKS=3 -DEMOTE_FREQ=5 -DEMOTE_TIMEOUT=10 -PROMOTE_FREQ=5 - -FILE_SPACE="Testing filenames with spaces.log" - - -# Creates a tiered volume with pure distribute hot and cold tiers -# Both hot and cold tiers will have an equal number of bricks. - -function create_dist_tier_vol () { - mkdir $B0/cold - mkdir $B0/hot - TEST $CLI volume create $V0 $H0:$B0/cold/${V0}{0..$1} - TEST $CLI volume set $V0 performance.quick-read off - TEST $CLI volume set $V0 performance.io-cache off - TEST $CLI volume set $V0 features.ctr-enabled on - TEST $CLI volume start $V0 - TEST $CLI volume attach-tier $V0 $H0:$B0/hot/${V0}{0..$1} - TEST $CLI volume set $V0 cluster.tier-demote-frequency $DEMOTE_FREQ - TEST $CLI volume set $V0 cluster.tier-promote-frequency $PROMOTE_FREQ - TEST $CLI volume set $V0 cluster.read-freq-threshold 0 - TEST $CLI volume set $V0 cluster.write-freq-threshold 0 - TEST $CLI volume set $V0 cluster.tier-mode test -} - - -cleanup; - -#Basic checks -TEST glusterd -TEST pidof glusterd -TEST $CLI volume info - - -#Create and start a tiered volume -create_dist_tier_vol $NUM_BRICKS - -# Mount FUSE -TEST glusterfs -s $H0 --volfile-id $V0 $M0 - - -# The file will be created on the hot tier - -touch "$M0/$FILE_SPACE" - -# Get the path of the file on the hot tier -HPATH=`find $B0/hot/ -name "$FILE_SPACE"` -echo "File path on hot tier: "$HPATH - -EXPECT "yes" exists_and_regular_file $HPATH - -# Wait for the tier process to demote the file -sleep $DEMOTE_TIMEOUT - -# Get the path of the file on the cold tier -CPATH=`find $B0/cold/ -name "$FILE_SPACE"` -echo "File path on cold tier: "$CPATH - -EXPECT "yes" exists_and_regular_file $CPATH - -cleanup; - -#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 diff --git a/tests/basic/tier/fops-during-migration-pause.t b/tests/basic/tier/fops-during-migration-pause.t deleted file mode 100755 index 10bd3f4667a..00000000000 --- a/tests/basic/tier/fops-during-migration-pause.t +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc - -NUM_BRICKS=3 -DEMOTE_FREQ=10 -PROMOTE_FREQ=10 - -TEST_STR="Testing write and truncate fops on tier migration" - -function is_sticky_set () { - echo $1 - if [ -k $1 ]; - then - echo "yes" - else - echo "no" - fi -} - - -# Creates a tiered volume with pure distribute hot and cold tiers -# Both hot and cold tiers will have an equal number of bricks. - -function create_dist_tier_vol () { - mkdir $B0/cold - mkdir $B0/hot - TEST $CLI volume create $V0 $H0:$B0/cold/${V0}{0..$1} - TEST $CLI volume set $V0 performance.quick-read off - TEST $CLI volume set $V0 performance.io-cache off - TEST $CLI volume set $V0 features.ctr-enabled on - TEST $CLI volume start $V0 - TEST $CLI volume attach-tier $V0 $H0:$B0/hot/${V0}{0..$1} - TEST $CLI volume set $V0 cluster.tier-demote-frequency $DEMOTE_FREQ - TEST $CLI volume set $V0 cluster.tier-promote-frequency $PROMOTE_FREQ - TEST $CLI volume set $V0 cluster.read-freq-threshold 0 - TEST $CLI volume set $V0 cluster.write-freq-threshold 0 - TEST $CLI volume set $V0 cluster.tier-mode test -} - - -cleanup; - -#Basic checks -TEST glusterd -TEST pidof glusterd -TEST $CLI volume info - - -#Create and start a tiered volume -create_dist_tier_vol $NUM_BRICKS - -# Mount FUSE -TEST glusterfs -s $H0 --volfile-id $V0 $M0 - -TEST mkdir $M0/dir1 - -# Create a large file (800MB), so that rebalance takes time -# The file will be created on the hot tier -sleep_until_mid_cycle $DEMOTE_FREQ -dd if=/dev/zero of=$M0/dir1/FILE1 bs=256k count=5120 - -# Get the path of the file on the hot tier -HPATH=`find $B0/hot/ -name FILE1` -echo "File path on hot tier: "$HPATH - - -# Wait for the tier process to demote the file -EXPECT_WITHIN $REBALANCE_TIMEOUT "yes" is_sticky_set $HPATH - -TEST $CLI volume set $V0 cluster.tier-pause on - -# Wait for the tier process to finish migrating the file -EXPECT_WITHIN $REBALANCE_TIMEOUT "no" is_sticky_set $HPATH - -# Get the path of the file on the cold tier -CPATH=`find $B0/cold/ -name FILE1` - -# make sure destination is empty -TEST ! test -s $CPATH - -# make sure source exists and not empty -TEST test -s $HPATH - -cleanup; - -#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 diff --git a/tests/basic/tier/fops-during-migration.t b/tests/basic/tier/fops-during-migration.t deleted file mode 100755 index 4be05acb357..00000000000 --- a/tests/basic/tier/fops-during-migration.t +++ /dev/null @@ -1,107 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc - - -NUM_BRICKS=3 -DEMOTE_FREQ=5 -PROMOTE_FREQ=5 - -TEST_STR="Testing write and truncate fops on tier migration" - - -# Creates a tiered volume with pure distribute hot and cold tiers -# Both hot and cold tiers will have an equal number of bricks. - -function create_dist_tier_vol () { - mkdir $B0/cold - mkdir $B0/hot - TEST $CLI volume create $V0 $H0:$B0/cold/${V0}{0..$1} - TEST $CLI volume set $V0 performance.quick-read off - TEST $CLI volume set $V0 performance.io-cache off - TEST $CLI volume set $V0 features.ctr-enabled on - TEST $CLI volume start $V0 - TEST $CLI volume attach-tier $V0 $H0:$B0/hot/${V0}{0..$1} - TEST $CLI volume set $V0 cluster.tier-demote-frequency $DEMOTE_FREQ - TEST $CLI volume set $V0 cluster.tier-promote-frequency $PROMOTE_FREQ - TEST $CLI volume set $V0 cluster.read-freq-threshold 0 - TEST $CLI volume set $V0 cluster.write-freq-threshold 0 - TEST $CLI volume set $V0 cluster.tier-mode test -} - - -# Checks that the contents of the file matches the input string -#$1 : file_path -#$2 : comparison string - -function check_file_content () { - contents=`cat $1` - echo $contents - if [ "$contents" = "$2" ]; then - echo "1" - else - echo "0" - fi -} - - -cleanup; - -#Basic checks -TEST glusterd -TEST pidof glusterd -TEST $CLI volume info - - -#Create and start a tiered volume -create_dist_tier_vol $NUM_BRICKS - -# Mount FUSE -TEST glusterfs -s $H0 --volfile-id $V0 $M0 - -$CLI volume set $V0 diagnostics.client-log-level DEBUG - -TEST mkdir $M0/dir1 - -# Create a large file (320MB), so that rebalance takes time -# The file will be created on the hot tier - -dd if=/dev/zero of=$M0/dir1/FILE1 bs=64k count=5120 - -# Get the path of the file on the hot tier -HPATH=`find $B0/hot/ -name FILE1` -echo "File path on hot tier: "$HPATH - - -# Wait for the tier process to demote the file -EXPECT_WITHIN $REBALANCE_TIMEOUT "yes" is_sticky_set $HPATH - -# Get the path of the file on the cold tier -CPATH=`find $B0/cold/ -name FILE1` -echo "File path on cold tier: "$CPATH - -# Test setxattr -TEST setfattr -n "user.test_xattr" -v "qwerty" $M0/dir1/FILE1 - -# Change the file contents while it is being migrated -echo $TEST_STR > $M0/dir1/FILE1 - -# The file contents should have changed even if the file -# is not done migrating -EXPECT "1" check_file_content $M0/dir1/FILE1 "$TEST_STR" - - -# Wait for the tier process to finish migrating the file -EXPECT_WITHIN $REBALANCE_TIMEOUT "no" is_sticky_set $CPATH - -# The file contents should have changed -EXPECT "1" check_file_content $M0/dir1/FILE1 "$TEST_STR" - - -TEST getfattr -n "user.test_xattr" $M0/dir1/FILE1 - -cleanup; -#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=000000 -#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=000000 diff --git a/tests/basic/tier/frequency-counters.t b/tests/basic/tier/frequency-counters.t deleted file mode 100644 index c335c02c563..00000000000 --- a/tests/basic/tier/frequency-counters.t +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc - - -NUM_BRICKS=3 -DEMOTE_FREQ=10 -PROMOTE_FREQ=10 -NUM_FILES=5 -TEST_DIR=test -# Creates a tiered volume with pure distribute hot and cold tiers -# Both hot and cold tiers will have an equal number of bricks. - -function create_dist_vol () { - mkdir $B0/cold - mkdir $B0/hot - TEST $CLI volume create $V0 $H0:$B0/cold/${V0}{0..$1} - TEST $CLI volume set $V0 performance.quick-read off - TEST $CLI volume set $V0 performance.io-cache off - TEST $CLI volume start $V0 -} - -function create_dist_tier_vol () { - TEST $CLI volume attach-tier $V0 $H0:$B0/hot/${V0}{0..$1} - TEST $CLI volume set $V0 cluster.tier-mode test - TEST $CLI volume set $V0 cluster.tier-demote-frequency $DEMOTE_FREQ - TEST $CLI volume set $V0 cluster.tier-promote-frequency $PROMOTE_FREQ - TEST $CLI volume set $V0 features.record-counters on - TEST $CLI volume set $V0 cluster.read-freq-threshold 2 - TEST $CLI volume set $V0 cluster.write-freq-threshold 2 -} - -cleanup; - - -TEST glusterd - -#Create and start a tiered volume -create_dist_vol $NUM_BRICKS - -# Mount FUSE -TEST glusterfs -s $H0 --volfile-id $V0 $M0 - -# create some files -mkdir $M0/$TEST_DIR -cd $M0/${TEST_DIR} - -date > file1 -touch file2 - -# attach tier -create_dist_tier_vol $NUM_BRICKS - -sleep_until_mid_cycle $PROMOTE_FREQ - -# check if promotion on single hit, should fail -date >> file2 -cat file1 -drop_cache $M0 -sleep $PROMOTE_FREQ -EXPECT "0" check_counters 0 0 - -# check if promotion on double hit, should suceed -sleep_until_mid_cycle $PROMOTE_FREQ -date >> file2 -drop_cache $M0 -cat file1 -date >> file2 -drop_cache $M0 -cat file1 - -EXPECT_WITHIN $PROMOTE_FREQ "0" check_counters 2 0 - -TEST ! $CLI volume set $V0 features.record-counters off - -cd / - -cleanup - -#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 diff --git a/tests/basic/tier/legacy-many.t b/tests/basic/tier/legacy-many.t deleted file mode 100644 index a9fcba85209..00000000000 --- a/tests/basic/tier/legacy-many.t +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc - - -LAST_BRICK=3 -CACHE_BRICK_FIRST=4 -CACHE_BRICK_LAST=5 -DEMOTE_TIMEOUT=12 -PROMOTE_TIMEOUT=12 -MIGRATION_TIMEOUT=10 -DEMOTE_FREQ=60 -PROMOTE_FREQ=10 -TEST_DIR="test_files" -NUM_FILES=15 - -function read_all { - for file in * - do - cat $file - done -} - -cleanup - -TEST glusterd -TEST pidof glusterd - -# Create distributed replica volume -TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0..$LAST_BRICK} -TEST $CLI volume start $V0 - -TEST $CLI volume set $V0 performance.quick-read off -TEST $CLI volume set $V0 performance.io-cache off -TEST $CLI volume set $V0 features.ctr-enabled on - - -TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; - -# Create a number of "legacy" files before attaching tier -mkdir $M0/${TEST_DIR} -cd $M0/${TEST_DIR} -TEST create_many_files file $NUM_FILES -wait - -# Attach tier -TEST $CLI volume attach-tier $V0 replica 2 $H0:$B0/${V0}$CACHE_BRICK_FIRST $H0:$B0/${V0}$CACHE_BRICK_LAST -TEST $CLI volume rebalance $V0 tier status - -TEST $CLI volume set $V0 cluster.tier-mode test -TEST $CLI volume set $V0 cluster.tier-demote-frequency $DEMOTE_FREQ -TEST $CLI volume set $V0 cluster.tier-promote-frequency $PROMOTE_FREQ -TEST $CLI volume set $V0 cluster.read-freq-threshold 0 -TEST $CLI volume set $V0 cluster.write-freq-threshold 0 - -# wait a little for lookup heal to finish -sleep 10 - -# make sure fix layout completed -CPATH=$B0/${V0}0 -echo $CPATH > /tmp/out -TEST getfattr -n "trusted.tier.fix.layout.complete" $CPATH - -# Read "legacy" files -drop_cache $M0 - -sleep_until_mid_cycle $DEMOTE_FREQ - -TEST read_all - -# Test to make sure files were promoted as expected -sleep $PROMOTE_TIMEOUT -EXPECT_WITHIN $PROMOTE_TIMEOUT "0" check_counters $NUM_FILES 0 - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "0" detach_start $V0 -EXPECT_WITHIN $REBALANCE_TIMEOUT "completed" remove_brick_status_completed_field "$V0 $H0:$B0/${V0}${CACHE_BRICK_FIRST}" - -TEST $CLI volume tier $V0 detach commit - -# fix layout flag should be cleared -TEST ! getfattr -n "trusted.tier.fix.layout.complete" $CPATH - -cd; -cleanup -#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 diff --git a/tests/basic/tier/locked_file_migration.t b/tests/basic/tier/locked_file_migration.t deleted file mode 100755 index 1a7e3f53c8e..00000000000 --- a/tests/basic/tier/locked_file_migration.t +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc - - -NUM_BRICKS=3 -DEMOTE_FREQ=7 -PROMOTE_FREQ=30 -DEMOTE_TIMEOUT=15 - -TEST_STR="Testing write and truncate fops on tier migration" - - -# Creates a tiered volume with pure distribute hot and cold tiers -# Both hot and cold tiers will have an equal number of bricks. - -function create_dist_tier_vol () { - mkdir $B0/cold - mkdir $B0/hot - TEST $CLI volume create $V0 $H0:$B0/cold/${V0}{0..$1} - TEST $CLI volume set $V0 performance.quick-read off - TEST $CLI volume set $V0 performance.io-cache off - TEST $CLI volume set $V0 features.ctr-enabled on - TEST $CLI volume start $V0 - TEST $CLI volume attach-tier $V0 $H0:$B0/hot/${V0}{0..$1} - TEST $CLI volume set $V0 cluster.tier-demote-frequency $DEMOTE_FREQ - TEST $CLI volume set $V0 cluster.tier-promote-frequency $PROMOTE_FREQ - -#We don't want promotes to happen in this test - TEST $CLI volume set $V0 cluster.read-freq-threshold 10 - TEST $CLI volume set $V0 cluster.write-freq-threshold 10 - TEST $CLI volume set $V0 cluster.tier-mode test -} - - -cleanup; - -#Basic checks -TEST glusterd -TEST pidof glusterd -TEST $CLI volume info - - -# Create and start a tiered volume -create_dist_tier_vol $NUM_BRICKS - -# Mount FUSE -TEST glusterfs -s $H0 --volfile-id $V0 $M0 - -TEST mkdir $M0/dir1 -build_tester $(dirname $0)/file_lock.c -o file_lock -cp $(dirname $0)/file_lock $M0/file_lock - -# The files will be created on the hot tier -touch $M0/dir1/FILE1 -touch $M0/dir1/FILE2 - -# For FILE1, take a POSIX write lock on the entire file. -# Don't take a lock on FILE2 - -./file_lock $M0/dir1/FILE1 W & - -sleep $DEMOTE_FREQ - -# Wait for the tier process to demote the file -# Only FILE2 and file_lock should be demoted -# FILE1 should be skipped because of the lock held -# on it - -EXPECT_WITHIN $DEMOTE_TIMEOUT "0" check_counters 0 2 - -sleep 10 - -rm $(dirname $0)/file_lock - -cleanup; - -#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 diff --git a/tests/basic/tier/new-tier-cmds.t b/tests/basic/tier/new-tier-cmds.t deleted file mode 100644 index dbfac54938e..00000000000 --- a/tests/basic/tier/new-tier-cmds.t +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc -. $(dirname $0)/../../cluster.rc - - -# Creates a tiered volume with pure distribute hot and cold tiers -# Both hot and cold tiers will have an equal number of bricks. - -function check_peers { - $CLI_1 peer status | grep 'Peer in Cluster (Connected)' | wc -l -} - -function create_dist_tier_vol () { - TEST $CLI_1 volume create $V0 $H1:$B1/${V0} $H2:$B2/${V0} $H3:$B3/${V0} - TEST $CLI_1 volume start $V0 - TEST $CLI_1 volume attach-tier $V0 $H1:$B1/${V0}_h1 $H2:$B2/${V0}_h2 $H3:$B3/${V0}_h3 -} - -cleanup; - -#setup cluster and test volume -TEST launch_cluster 3; # start 3-node virtual cluster -TEST $CLI_1 peer probe $H2; # peer probe server 2 from server 1 cli -TEST $CLI_1 peer probe $H3; # peer probe server 3 from server 1 cli - -EXPECT_WITHIN $PROBE_TIMEOUT 2 check_peers; - -#Create and start a tiered volume -create_dist_tier_vol - -#Issue detach tier on the tiered volume -#Will throw error saying detach tier not started - -EXPECT "Tier command failed" $CLI_1 volume tier $V0 detach status - -#after starting detach tier the detach tier status should display the status - -TEST $CLI_1 volume tier $V0 detach start - -TEST $CLI_1 volume tier $V0 detach status - -#kill a node -TEST kill_node 2 - -#check if we have the rest of the node available printed in the output of detach status -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" tier_detach_status_node_down - -#check if we have the rest of the node available printed in the output of tier status -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" tier_status_node_down - -TEST $glusterd_2; - -EXPECT_WITHIN $PROBE_TIMEOUT 2 check_peers; - -TEST $CLI_1 volume tier $V0 detach status - -TEST $CLI_1 volume tier $V0 detach stop - -#If detach tier is stopped the detach tier command will fail - -EXPECT "Tier command failed" $CLI_1 volume tier $V0 detach status - -TEST $CLI_1 volume tier $V0 detach start - -#wait for the detach to complete -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" tier_detach_commit - -#If detach tier is committed then the detach status should fail throwing an error -#saying its not a tiered volume - -EXPECT "Tier command failed" $CLI_1 volume tier $V0 detach status - -cleanup; - -#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 diff --git a/tests/basic/tier/readdir-during-migration.t b/tests/basic/tier/readdir-during-migration.t deleted file mode 100644 index e2a43c93572..00000000000 --- a/tests/basic/tier/readdir-during-migration.t +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc - - -NUM_BRICKS=3 -DEMOTE_FREQ=5 -PROMOTE_FREQ=5 -NUM_FILES=30 -TEST_DIR=test -# Creates a tiered volume with pure distribute hot and cold tiers -# Both hot and cold tiers will have an equal number of bricks. - -function create_dist_tier_vol () { - mkdir $B0/cold - mkdir $B0/hot - TEST $CLI volume create $V0 $H0:$B0/cold/${V0}{0..$1} - TEST $CLI volume set $V0 performance.quick-read off - TEST $CLI volume set $V0 performance.io-cache off - TEST $CLI volume start $V0 - TEST $CLI volume attach-tier $V0 $H0:$B0/hot/${V0}{0..$1} - TEST $CLI volume set $V0 cluster.tier-mode test - TEST $CLI volume set $V0 cluster.tier-demote-frequency $DEMOTE_FREQ - TEST $CLI volume set $V0 cluster.tier-promote-frequency $PROMOTE_FREQ - TEST $CLI volume set $V0 cluster.read-freq-threshold 0 - TEST $CLI volume set $V0 cluster.write-freq-threshold 0 -} - -function check_file_count() { - if [ $(ls -1 | wc -l) == $1 ]; then - echo "1" - else - echo "0" - fi -} - -cleanup; - - -TEST glusterd - -#Create and start a tiered volume -create_dist_tier_vol $NUM_BRICKS - -# Mount FUSE -TEST glusterfs -s $H0 --volfile-id $V0 $M0 - -# Create a number of "legacy" files before attaching tier -mkdir $M0/${TEST_DIR} -cd $M0/${TEST_DIR} -TEST create_many_files tfile $NUM_FILES - -EXPECT "1" check_file_count $NUM_FILES - -sleep $DEMOTE_FREQ - -EXPECT "1" check_file_count $NUM_FILES - -cd / - -cleanup; - -#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 diff --git a/tests/basic/tier/record-metadata-heat.t b/tests/basic/tier/record-metadata-heat.t deleted file mode 100755 index d4481371f68..00000000000 --- a/tests/basic/tier/record-metadata-heat.t +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc - -NUM_BRICKS=3 -DEMOTE_FREQ=5 -DEMOTE_TIMEOUT=10 -PROMOTE_FREQ=5 - -FILE="file1.txt" -FILE_LINK="file2.txt" - -# Creates a tiered volume with pure distribute hot and cold tiers -# Both hot and cold tiers will have an equal number of bricks. - -function create_dist_tier_vol () { - mkdir $B0/cold - mkdir $B0/hot - TEST $CLI volume create $V0 $H0:$B0/cold/${V0}{0..$1} - TEST $CLI volume set $V0 performance.quick-read off - TEST $CLI volume set $V0 performance.io-cache off - TEST $CLI volume set $V0 features.ctr-enabled on - TEST $CLI volume start $V0 - TEST $CLI volume attach-tier $V0 $H0:$B0/hot/${V0}{0..$1} - TEST $CLI volume set $V0 cluster.tier-demote-frequency $DEMOTE_FREQ - TEST $CLI volume set $V0 cluster.tier-promote-frequency $PROMOTE_FREQ - TEST $CLI volume set $V0 cluster.read-freq-threshold 4 - TEST $CLI volume set $V0 cluster.write-freq-threshold 4 -} - - -cleanup; - -#Basic checks -TEST glusterd -TEST pidof glusterd -TEST $CLI volume info - - -#Create and start a tiered volume -create_dist_tier_vol $NUM_BRICKS - -# Mount FUSE -TEST glusterfs -s $H0 --volfile-id $V0 $M0 - - -# The file will be created on the hot tier -touch "$M0/$FILE" - -# Get the path of the file on the hot tier -HPATH=`find $B0/hot/ -name "$FILE"` -echo "File path on hot tier: "$HPATH - -# Expecting the file to be on the hot tier -EXPECT "yes" exists_and_regular_file $HPATH - -sleep_until_mid_cycle $DEMOTE_FREQ - -# Try to heat the file using 5 metadata operations -# WITHOUT setting ctr-record-metadata-heat on -touch "$M0/$FILE" -chmod +x "$M0/$FILE" -chown root "$M0/$FILE" -ln "$M0/$FILE" "$M0/$FILE_LINK" -rm -rf "$M0/$FILE_LINK" - -# Wait for the tier process to demote the file -sleep $DEMOTE_TIMEOUT - -# Get the path of the file on the cold tier -CPATH=`find $B0/cold/ -name "$FILE"` -echo "File path on cold tier: "$CPATH - -# Expecting the file to be on cold tier -EXPECT "yes" exists_and_regular_file $CPATH - -#Set ctr-record-metadata-heat on -TEST $CLI volume set $V0 ctr-record-metadata-heat on - -sleep_until_mid_cycle $DEMOTE_FREQ - -# Heating the file using 5 metadata operations -touch "$M0/$FILE" -chmod +x "$M0/$FILE" -chown root "$M0/$FILE" -ln "$M0/$FILE" "$M0/$FILE_LINK" -rm -rf "$M0/$FILE_LINK" - -# Wait for the tier process to demote the file -sleep $DEMOTE_TIMEOUT - -# Get the path of the file on the hot tier -echo "File path on hot tier: "$HPATH - -# Expecting the file to be on the hot tier -EXPECT "yes" exists_and_regular_file $HPATH - -cleanup; -#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=000000 -#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=000000 diff --git a/tests/basic/tier/tier-file-create.t b/tests/basic/tier/tier-file-create.t deleted file mode 100644 index 06f0e241502..00000000000 --- a/tests/basic/tier/tier-file-create.t +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc - - -NUM_BRICKS=3 -DEMOTE_FREQ=5 -PROMOTE_FREQ=5 - - - -# Creates a tiered volume with pure distribute hot and cold tiers -# Both hot and cold tiers will have an equal number of bricks. - -function create_dist_tier_vol () { - mkdir $B0/cold - mkdir $B0/hot - TEST $CLI volume create $V0 disperse 6 disperse-data 4 $H0:$B0/cold/${V0}{1..12} - TEST $CLI volume set $V0 performance.quick-read off - TEST $CLI volume set $V0 performance.io-cache off - TEST $CLI volume set $V0 features.ctr-enabled on - TEST $CLI volume start $V0 - TEST $CLI volume attach-tier $V0 replica 2 $H0:$B0/hot/${V0}{0..$1} - TEST $CLI volume set $V0 cluster.tier-demote-frequency $DEMOTE_FREQ - TEST $CLI volume set $V0 cluster.tier-promote-frequency $PROMOTE_FREQ - TEST $CLI volume set $V0 cluster.read-freq-threshold 0 - TEST $CLI volume set $V0 cluster.write-freq-threshold 0 - TEST $CLI volume set $V0 cluster.tier-mode test -} - - -cleanup; - -#Basic checks -TEST glusterd -TEST pidof glusterd -TEST $CLI volume info - - -#Create and start a tiered volume -create_dist_tier_vol $NUM_BRICKS - -# Mount FUSE -TEST glusterfs -s $H0 --volfile-id $V0 $M0 - -cd $M0 - -touch FILE1 - -HPATH=`find $B0/hot/ -name FILE1 | cut -d " " -f1` -echo $HPATH - -TEST ! getfattr -n "trusted.ec.size" $HPATH -cd - -cleanup; - -#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 -#G_TESTDEF_TEST_STATUS_CENTOS6=KNOWN_ISSUE,BUG=1315560 diff --git a/tests/basic/tier/tier-heald.t b/tests/basic/tier/tier-heald.t deleted file mode 100644 index 8dcdd39c619..00000000000 --- a/tests/basic/tier/tier-heald.t +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc - -# This test contains volume heal commands handled by glusterd. -# Covers enable/disable at the moment. Will be enhanced later to include -# the other commands as well. - -cleanup; -TEST glusterd -TEST pidof glusterd - -volfile=$(gluster system:: getwd)"/glustershd/glustershd-server.vol" - -# Commands should fail when both tiers are not of distribute type. -# Glustershd shouldn't be running as long as there are no replicate/disperse -# volumes -TEST $CLI volume create dist_tier $H0:$B0/cold -TEST $CLI volume start dist_tier -TEST $CLI volume attach-tier dist_tier $H0:$B0/hot - -TEST "[ -z $(get_shd_process_pid)]" -TEST ! $CLI volume heal dist_tier enable -TEST ! $CLI volume heal dist_tier disable - -# Commands should work on replicate/disperse volume. -TEST $CLI volume create r2 replica 2 $H0:$B0/r2_0 $H0:$B0/r2_1 -TEST "[ -z $(get_shd_process_pid)]" -TEST $CLI volume start r2 - -TEST $CLI volume attach-tier r2 $H0:$B0/r2_hot - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid -TEST $CLI volume heal r2 enable -EXPECT "enable" volume_option r2 "cluster.self-heal-daemon" -EXPECT "enable" volgen_volume_option $volfile r2-replicate-0 cluster replicate self-heal-daemon -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid -TEST $CLI volume heal r2 disable -EXPECT "disable" volume_option r2 "cluster.self-heal-daemon" -EXPECT "disable" volgen_volume_option $volfile r2-replicate-0 cluster replicate self-heal-daemon -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid -# Commands should work on disperse volume. -TEST $CLI volume create ec2 disperse 3 redundancy 1 $H0:$B0/ec2_0 $H0:$B0/ec2_1 $H0:$B0/ec2_2 -TEST $CLI volume start ec2 - -TEST $CLI volume attach-tier ec2 replica 2 $H0:$B0/ec2_hot{1..4} -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid -TEST $CLI volume heal ec2 enable -EXPECT "enable" volume_option ec2 "cluster.disperse-self-heal-daemon" -EXPECT "enable" volgen_volume_option $volfile ec2-disperse-0 cluster disperse self-heal-daemon -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid -TEST $CLI volume heal ec2 disable -EXPECT "disable" volume_option ec2 "cluster.disperse-self-heal-daemon" -EXPECT "disable" volgen_volume_option $volfile ec2-disperse-0 cluster disperse self-heal-daemon -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "[0-9][0-9]*" get_shd_process_pid - -#Check that shd graph is rewritten correctly on volume stop/start -EXPECT "Y" volgen_volume_exists $volfile ec2-disperse-0 cluster disperse -EXPECT "Y" volgen_volume_exists $volfile r2-replicate-0 cluster replicate -TEST $CLI volume stop r2 -EXPECT "Y" volgen_volume_exists $volfile ec2-disperse-0 cluster disperse -EXPECT "N" volgen_volume_exists $volfile r2-replicate-0 cluster replicate -TEST $CLI volume stop ec2 -# When both the volumes are stopped glustershd volfile is not modified just the -# process is stopped -TEST "[ -z $(get_shd_process_pid) ]" - -TEST $CLI volume start r2 -EXPECT "N" volgen_volume_exists $volfile ec2-disperse-0 cluster disperse -EXPECT "Y" volgen_volume_exists $volfile r2-replicate-0 cluster replicate - -TEST $CLI volume start ec2 - -EXPECT "Y" volgen_volume_exists $volfile ec2-disperse-0 cluster disperse -EXPECT "Y" volgen_volume_exists $volfile ec2-replicate-0 cluster replicate - -TEST $CLI volume detach-tier ec2 force - -EXPECT "Y" volgen_volume_exists $volfile ec2-disperse-0 cluster disperse -EXPECT "N" volgen_volume_exists $volfile ec2-replicate-0 cluster replicate - -TEST $CLI volume set r2 self-heal-daemon on -TEST $CLI volume set r2 cluster.self-heal-daemon off -TEST ! $CLI volume set ec2 self-heal-daemon off -TEST ! $CLI volume set ec2 cluster.self-heal-daemon on -TEST ! $CLI volume set dist self-heal-daemon off -TEST ! $CLI volume set dist cluster.self-heal-daemon on - -TEST $CLI volume set ec2 disperse-self-heal-daemon off -TEST $CLI volume set ec2 cluster.disperse-self-heal-daemon on -TEST ! $CLI volume set r2 disperse-self-heal-daemon on -TEST ! $CLI volume set r2 cluster.disperse-self-heal-daemon off -TEST ! $CLI volume set dist disperse-self-heal-daemon off -TEST ! $CLI volume set dist cluster.disperse-self-heal-daemon on - -cleanup -#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 diff --git a/tests/basic/tier/tier-snapshot.t b/tests/basic/tier/tier-snapshot.t deleted file mode 100644 index 6e7951d1963..00000000000 --- a/tests/basic/tier/tier-snapshot.t +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../snapshot.rc - -cleanup; - -TEST init_n_bricks 4; -TEST setup_lvm 4; - -TEST glusterd; - -TEST pidof glusterd; - -TEST $CLI volume create $V0 replica 2 $H0:$L1 $H0:$L2 ; - -TEST $CLI volume start $V0; - -TEST $CLI volume attach-tier $V0 replica 2 $H0:$L3 $H0:$L4 ; - -TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0; - -for i in {1..10} ; do echo "file" > $M0/file$i ; done - -TEST $CLI snapshot config activate-on-create enable - -TEST $CLI snapshot create snap1 $V0 no-timestamp; - -for i in {11..20} ; do echo "file" > $M0/file$i ; done - -TEST $CLI snapshot create snap2 $V0 no-timestamp; - -mkdir $M0/dir1; -mkdir $M0/dir2; - -for i in {1..10} ; do echo "foo" > $M0/dir1/foo$i ; done -for i in {1..10} ; do echo "foo" > $M0/dir2/foo$i ; done - -TEST $CLI snapshot create snap3 $V0 no-timestamp; - -for i in {11..20} ; do echo "foo" > $M0/dir1/foo$i ; done -for i in {11..20} ; do echo "foo" > $M0/dir2/foo$i ; done - -TEST $CLI snapshot create snap4 $V0 no-timestamp; - -TEST $CLI snapshot delete all; - -cleanup; -#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=000000 -#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=000000 diff --git a/tests/basic/tier/tier.t b/tests/basic/tier/tier.t deleted file mode 100755 index 7bac2dd03bb..00000000000 --- a/tests/basic/tier/tier.t +++ /dev/null @@ -1,209 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc - -LAST_BRICK=3 -CACHE_BRICK_FIRST=4 -CACHE_BRICK_LAST=5 -DEMOTE_TIMEOUT=12 -PROMOTE_TIMEOUT=5 -MIGRATION_TIMEOUT=10 -DEMOTE_FREQ=4 -PROMOTE_FREQ=12 - -function file_on_slow_tier { - found=0 - - for i in `seq 0 $LAST_BRICK`; do - test -e "$B0/${V0}${i}/$1" && found=1 && break; - done - - if [ "$found" == "1" ] - then - slow_hash1=$2 - slow_hash2=$(fingerprint "$B0/${V0}${i}/$1") - - if [ "$slow_hash1" == "$slow_hash2" ] - then - echo "0" - else - echo "2" - fi - else - echo "1" - fi - - # temporarily disable non-Linux tests. - case $OSTYPE in - NetBSD | FreeBSD | Darwin) - echo "0" - ;; - esac -} - -function file_on_fast_tier { - found=0 - - for j in `seq $CACHE_BRICK_FIRST $CACHE_BRICK_LAST`; do - test -e "$B0/${V0}${j}/$1" && found=1 && break; - done - - - if [ "$found" == "1" ] - then - fast_hash1=$2 - fast_hash2=$(fingerprint "$B0/${V0}${j}/$1") - - if [ "$fast_hash1" == "$fast_hash2" ] - then - echo "0" - else - echo "2" - fi - else - echo "1" - fi -} - - -cleanup - -TEST glusterd -TEST pidof glusterd - -TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0..$LAST_BRICK} -# testing bug 1215122, ie should fail if replica count and bricks are not compatible. - -TEST ! $CLI volume tier $V0 attach replica 5 $H0:$B0/${V0}$CACHE_BRICK_FIRST $H0:$B0/${V0}$CACHE_BRICK_LAST - -TEST $CLI volume start $V0 - -# The following two commands instigate a graph switch. Do them -# before attaching the tier. If done on a tiered volume the rebalance -# daemon will terminate and must be restarted manually. -TEST $CLI volume set $V0 performance.quick-read off -TEST $CLI volume set $V0 performance.io-cache off - -#Not a tier volume -TEST ! $CLI volume set $V0 cluster.tier-demote-frequency 4 - -#testing bug #1228112, glusterd crashed when trying to detach-tier commit force on a non-tiered volume. -TEST ! $CLI volume tier $V0 detach commit force - -TEST $CLI volume tier $V0 attach replica 2 $H0:$B0/${V0}$CACHE_BRICK_FIRST $H0:$B0/${V0}$CACHE_BRICK_LAST - -TEST $CLI volume set $V0 cluster.tier-mode test - -# create a file, make sure it can be deleted after attach tier. -TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; -cd $M0 -TEST touch delete_me.txt -TEST rm -f delete_me.txt - -# confirm watermark CLI works -TEST $CLI volume set $V0 cluster.watermark-hi 85 -TEST $CLI volume set $V0 cluster.watermark-low 75 -TEST $CLI volume set $V0 cluster.tier-max-mb 1000 -TEST $CLI volume set $V0 cluster.tier-max-files 1000 -TEST $CLI volume set $V0 cluster.tier-max-promote-file-size 1000 -TEST ! $CLI volume set $V0 cluster.tier-max-files -3 -TEST ! $CLI volume set $V0 cluster.watermark-low 90 -TEST ! $CLI volume set $V0 cluster.read-freq-threshold -12 -TEST ! $CLI volume set $V0 cluster.write-freq-threshold -12 - - -# stop the volume and restart it. The rebalance daemon should restart. -cd /tmp -umount $M0 -TEST $CLI volume stop $V0 -TEST $CLI volume start $V0 -TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; -cd $M0 - -sleep_first_cycle $DEMOTE_FREQ -$CLI volume tier $V0 status - -#Tier options expect non-negative value -TEST ! $CLI volume set $V0 cluster.tier-promote-frequency -1 - -#Tier options expect non-negative value -TEST ! $CLI volume set $V0 cluster.read-freq-threshold qwerty - - -TEST $CLI volume set $V0 cluster.tier-demote-frequency $DEMOTE_FREQ -TEST $CLI volume set $V0 cluster.tier-promote-frequency $PROMOTE_FREQ -TEST $CLI volume set $V0 cluster.read-freq-threshold 0 -TEST $CLI volume set $V0 cluster.write-freq-threshold 0 - -# Basic operations. -TEST stat . -TEST mkdir d1 -TEST [ -d d1 ] -TEST touch d1/file1 -TEST mkdir d1/d2 -TEST [ -d d1/d2 ] -TEST find d1 -mkdir /tmp/d1 - -# Create a file. It should be on the fast tier. -uuidgen > /tmp/d1/data.txt -md5data=$(fingerprint /tmp/d1/data.txt) -mv /tmp/d1/data.txt ./d1/data.txt - -TEST file_on_fast_tier d1/data.txt $md5data - -uuidgen > /tmp/d1/data2.txt -md5data2=$(fingerprint /tmp/d1/data2.txt) -cp /tmp/d1/data2.txt ./d1/data2.txt - -#File with spaces and special characters. -SPACE_FILE="file with spaces & $peci@l ch@r@cter$ @!@$%^$#@^^*&%$#$%.txt" - -uuidgen > "/tmp/d1/$SPACE_FILE" -md5space=$(fingerprint "/tmp/d1/$SPACE_FILE") -mv "/tmp/d1/$SPACE_FILE" "./d1/$SPACE_FILE" - -# Check auto-demotion on write new. -sleep $DEMOTE_TIMEOUT - -# Check auto-promotion on write append. -UUID=$(uuidgen) -echo $UUID >> /tmp/d1/data2.txt -md5data2=$(fingerprint /tmp/d1/data2.txt) - -sleep_until_mid_cycle $DEMOTE_FREQ -drop_cache $M0 - -echo $UUID >> ./d1/data2.txt -cat "./d1/$SPACE_FILE" - -sleep $PROMOTE_TIMEOUT -sleep $DEMOTE_FREQ -EXPECT_WITHIN $DEMOTE_TIMEOUT "0" check_counters 2 6 - -# stop gluster, when it comes back info file should have tiered volume -killall glusterd -TEST glusterd - -EXPECT "0" file_on_slow_tier d1/data.txt $md5data -EXPECT "0" file_on_slow_tier d1/data2.txt $md5data2 -EXPECT "0" file_on_slow_tier "./d1/$SPACE_FILE" $md5space - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "0" detach_start $V0 -EXPECT_WITHIN $REBALANCE_TIMEOUT "completed" remove_brick_status_completed_field "$V0 $H0:$B0/${V0}${CACHE_BRICK_FIRST}" - -TEST $CLI volume tier $V0 detach commit - -EXPECT "0" confirm_tier_removed ${V0}${CACHE_BRICK_FIRST} - -confirm_vol_stopped $V0 - -cd; - -cleanup -rm -rf /tmp/d1 - - -#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 diff --git a/tests/basic/tier/tier_lookup_heal.t b/tests/basic/tier/tier_lookup_heal.t deleted file mode 100755 index 825f81db392..00000000000 --- a/tests/basic/tier/tier_lookup_heal.t +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc - -LAST_BRICK=1 -CACHE_BRICK_FIRST=2 -CACHE_BRICK_LAST=3 -PROMOTE_TIMEOUT=5 - -function file_on_fast_tier { - local ret="1" - - s1=$(md5sum $1) - s2=$(md5sum $B0/${V0}${CACHE_BRICK_FIRST}/$1) - - if [ -e $B0/${V0}${CACHE_BRICK_FIRST}/$1 ] && ! [ "$s1" == "$s2" ]; then - echo "0" - else - echo "1" - fi -} - -cleanup - - -TEST glusterd -TEST pidof glusterd - -TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0..$LAST_BRICK} -TEST $CLI volume start $V0 -TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; - -# Create files before CTR xlator is on. -cd $M0 -TEST stat . -TEST touch file1 -TEST stat file1 - -# gf_file_tb and gf_flink_tb should be empty -ENTRY_COUNT=$(echo "select * from gf_file_tb; select * from gf_flink_tb;" | \ - sqlite3 $B0/${V0}$LAST_BRICK/.glusterfs/${V0}$LAST_BRICK.db | wc -l ) -TEST [ $ENTRY_COUNT -eq 0 ] - - -#Attach tier and switch ON CTR Xlator. -TEST $CLI volume attach-tier $V0 replica 2 $H0:$B0/${V0}$CACHE_BRICK_FIRST $H0:$B0/${V0}$CACHE_BRICK_LAST -TEST $CLI volume set $V0 features.ctr-enabled on -TEST $CLI volume set $V0 cluster.tier-demote-frequency 4 -TEST $CLI volume set $V0 cluster.tier-promote-frequency 4 -TEST $CLI volume set $V0 cluster.read-freq-threshold 0 -TEST $CLI volume set $V0 cluster.write-freq-threshold 0 -TEST $CLI volume set $V0 performance.quick-read off -TEST $CLI volume set $V0 performance.io-cache off -TEST $CLI volume set $V0 cluster.tier-mode test - -#The lookup should heal the database. -TEST ls file1 - -# gf_file_tb and gf_flink_tb should NOT be empty -ENTRY_COUNT=$(echo "select * from gf_file_tb; select * from gf_flink_tb;" | \ - sqlite3 $B0/${V0}$LAST_BRICK/.glusterfs/${V0}$LAST_BRICK.db | wc -l ) -TEST [ $ENTRY_COUNT -eq 2 ] - -# Heat-up the file -uuidgen > file1 -sleep 5 - -#Check if the file is promoted -EXPECT_WITHIN $PROMOTE_TIMEOUT "0" file_on_fast_tier file1 - -cd; - -cleanup -#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=000000 -#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=000000 diff --git a/tests/basic/tier/tierd_check.t b/tests/basic/tier/tierd_check.t deleted file mode 100644 index 1f88ea0b72e..00000000000 --- a/tests/basic/tier/tierd_check.t +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc -. $(dirname $0)/../../cluster.rc - - -# Creates a tiered volume with pure distribute hot and cold tiers -# Both hot and cold tiers will have an equal number of bricks. - -function check_peers { - $CLI_1 peer status | grep 'Peer in Cluster (Connected)' | wc -l -} - -function create_dist_tier_vol () { - TEST $CLI_1 volume create $V0 $H1:$B1/${V0} $H2:$B2/${V0} - TEST $CLI_1 volume start $V0 - TEST $CLI_1 volume attach-tier $V0 $H1:$B1/${V0}_h1 $H2:$B2/${V0}_h2 -} - -function tier_status () { - $CLI_1 volume tier $V0 status | grep progress | wc -l -} - -function tier_deamon_kill () { -pkill -f "rebalance/$V0" -echo "$?" -} - -cleanup; - -#setup cluster and test volume -TEST launch_cluster 3; # start 3-node virtual cluster -TEST $CLI_1 peer probe $H2; # peer probe server 2 from server 1 cli -TEST $CLI_1 peer probe $H3; # peer probe server 3 from server 1 cli - -EXPECT_WITHIN $PROBE_TIMEOUT 2 check_peers; - -#Create and start a tiered volume -create_dist_tier_vol - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT 0 tier_daemon_check - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" tier_status - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT 0 tier_deamon_kill - -TEST $CLI_1 volume tier $V0 start - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "0" tier_daemon_check - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" tier_status - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "0" tier_deamon_kill - -TEST $CLI_3 volume tier $V0 start force - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "0" tier_daemon_check - -#The pattern progress should occur twice only. -#it shouldn't come up on the third node without tierd even -#after the tier start force is issued on the node without -#tierd - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" tier_status - -#kill the node on which tier is not supposed to run -TEST kill_node 3 - -#bring the node back, it should not have tierd running on it -TEST $glusterd_3; - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" tier_status - -#after volume restart, check for tierd - -TEST $CLI_3 volume stop $V0 - -TEST $CLI_3 volume start $V0 - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" tier_status - -#check for detach start and stop - -TEST $CLI_3 volume tier $V0 detach start - -TEST $CLI_3 volume tier $V0 detach stop - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" tier_status - -TEST $CLI_1 volume tier $V0 start force - -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "0" tier_daemon_check - -# To test for detach start fail while the brick is down - -TEST pkill -f "$B1/$V0" - -TEST ! $CLI_1 volume tier $V0 detach start - -cleanup -#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 diff --git a/tests/basic/tier/unlink-during-migration.t b/tests/basic/tier/unlink-during-migration.t deleted file mode 100755 index 0c2255cfda6..00000000000 --- a/tests/basic/tier/unlink-during-migration.t +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc -. $(dirname $0)/../../tier.rc - - -DEMOTE_FREQ=5 -PROMOTE_FREQ=5 - -function create_dist_rep_vol () { - mkdir $B0/cold - mkdir $B0/hot - TEST $CLI volume create $V0 replica 2 $H0:$B0/cold/${V0}{0..3} - TEST $CLI volume set $V0 performance.quick-read off - TEST $CLI volume set $V0 performance.io-cache off - TEST $CLI volume set $V0 features.ctr-enabled on - TEST $CLI volume start $V0 -} - -function attach_dist_rep_tier () { - TEST $CLI volume attach-tier $V0 replica 2 $H0:$B0/hot/${V0}{0..3} - TEST $CLI volume set $V0 cluster.tier-demote-frequency $DEMOTE_FREQ - TEST $CLI volume set $V0 cluster.tier-promote-frequency $PROMOTE_FREQ - TEST $CLI volume set $V0 cluster.read-freq-threshold 0 - TEST $CLI volume set $V0 cluster.write-freq-threshold 0 - TEST $CLI volume set $V0 cluster.tier-mode test -} - -cleanup; - -#Basic checks -TEST glusterd -TEST pidof glusterd -TEST $CLI volume info - - -#Create and start a volume -create_dist_rep_vol - -# Mount FUSE -TEST glusterfs -s $H0 --volfile-id $V0 $M0 - -# Create a large file (320MB), so that rebalance takes time -TEST dd if=/dev/zero of=$M0/foo bs=64k count=5120 - -# Get the path of the file on the cold tier -CPATH=`find $B0/cold/ -name foo` -echo "File path on cold tier: "$CPATH - -#Now attach the tier -attach_dist_rep_tier - -#Write into the file to promote it -echo "good morning">>$M0/foo - -# Wait for the tier process to promote the file -EXPECT_WITHIN $REBALANCE_TIMEOUT "yes" is_sticky_set $CPATH - -# Get the path of the file on the hot tier -HPATH=`find $B0/hot/ -name foo` - -echo "File path on hot tier: "$HPATH -TEST rm -rf $M0/foo -TEST ! stat $HPATH -TEST ! stat $CPATH - -#unlink during demotion -HPATH=""; -CPATH=""; - -# Create a large file (320MB), so that rebalance takes time -TEST dd if=/dev/zero of=$M0/foo1 bs=64k count=5120 - -# Get the path of the file on the hot tier -HPATH=`find $B0/hot/ -name foo1` -echo "File path on hot tier : "$HPATH - -EXPECT_WITHIN $REBALANCE_TIMEOUT "yes" is_sticky_set $HPATH - -# Get the path of the file on the cold tier -CPATH=`find $B0/cold/ -name foo1` -echo "File path on cold tier : "$CPATH - -TEST rm -rf $M0/foo1 - -TEST ! stat $HPATH -TEST ! stat $CPATH - -cleanup; - -#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=000000 diff --git a/tests/basic/trace.t b/tests/basic/trace.t new file mode 100755 index 00000000000..01e7c9e0a25 --- /dev/null +++ b/tests/basic/trace.t @@ -0,0 +1,55 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +TEST mkdir -p $B0/single-brick +cat > $B0/template.vol <<EOF +volume posix + type storage/posix + option directory $B0/single-brick +end-volume + +volume trace + type debug/trace + option log-file yes + option log-history yes + subvolumes posix +end-volume +EOF + +TEST glusterfs -f $B0/template.vol $M0 + +TEST $(dirname $0)/rpc-coverage.sh --no-locks $M0 + +# Take statedump to get maximum code coverage +pid=$(ps auxww | grep glusterfs | grep -E "template.vol" | awk '{print $2}' | head -1) + +TEST generate_statedump $pid + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +# Now, use the glusterd way of enabling trace +TEST glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{1,2,3,4,5,6}; + +TEST $CLI volume set $V0 debug.trace marker +TEST $CLI volume set $V0 debug.log-file yes +#TEST $CLI volume set $V0 debug.log-history yes + +TEST $CLI volume start $V0; + +TEST $GFS -s $H0 --volfile-id $V0 $M1; + +TEST $(dirname $0)/rpc-coverage.sh --no-locks $M1 +cp $(dirname ${0})/gfapi/glfsxmp-coverage.c ./glfsxmp.c +build_tester ./glfsxmp.c -lgfapi +./glfsxmp $V0 $H0 > /dev/null +cleanup_tester ./glfsxmp +rm ./glfsxmp.c + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M1 + +cleanup; diff --git a/tests/basic/uss.t b/tests/basic/uss.t index 6cfc0303895..09dd00ef995 100644 --- a/tests/basic/uss.t +++ b/tests/basic/uss.t @@ -6,6 +6,8 @@ . $(dirname $0)/../fileio.rc . $(dirname $0)/../nfs.rc +#G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST + function check_readonly() { $@ 2>&1 | grep -q 'Read-only file system' @@ -34,6 +36,7 @@ TEST glusterd; TEST pidof glusterd; TEST $CLI volume create $V0 $H0:$L1 $H0:$L2 $H0:$L3; + TEST $CLI volume set $V0 nfs.disable false @@ -52,6 +55,7 @@ TEST ln $M0/f1 $M0/dir/f3 TEST $CLI snapshot config activate-on-create enable TEST $CLI volume set $V0 features.uss enable; +TEST ! $CLI snapshot create snap1 $V0 no-timestamp description ""; TEST $CLI snapshot create snap1 $V0 no-timestamp; for i in {11..20} ; do echo "file" > $M0/file$i ; done @@ -371,6 +375,15 @@ TEST rm -f $M0/aaa; TEST $CLI snapshot delete snap6; +# drop the caches so that, the dentry for "snap6" is +# is forgotten from the client cache. +drop_cache $M0 + +EXPECT_WITHIN 30 "5" count_snaps $M0; + +# This should fail, as snap6 just got deleted. +TEST ! stat $M0/.history/snap6 + TEST $CLI snapshot create snap6 $V0 no-timestamp TEST ls $M0/.history; @@ -381,4 +394,28 @@ TEST ls $M0/.history/snap6/; TEST ! stat $M0/.history/snap6/aaa; +TEST stat $M0 + +# done with the tests start cleaning up of things +TEST $CLI volume set $V0 features.uss disable + +TEST $CLI snapshot delete snap6; + +TEST $CLI snapshot delete snap5; + +TEST $CLI snapshot delete snap4; + +TEST $CLI snapshot delete snap3; + +TEST $CLI snapshot delete snap2; + +TEST $CLI snapshot delete snap1; + +# nfs client has been already unmounted at line 333 +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +TEST $CLI volume stop $V0 + +TEST $CLI volume delete $V0 + cleanup; diff --git a/tests/basic/volfile-sanity.t b/tests/basic/volfile-sanity.t new file mode 100644 index 00000000000..ef2f9344468 --- /dev/null +++ b/tests/basic/volfile-sanity.t @@ -0,0 +1,29 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc + +cleanup; + +## Start and create a volume +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/${V0}1 + +killall glusterd + +# Client by default tries to connect to port 24007 +# So, start server on that port, and you can see +# client successfully working. +TEST $GFS --xlator-option "${V0}-server.transport.socket.listen-port=24007" \ + -f /var/lib/glusterd/vols/${V0}/${V0}.${H0}.*.vol +TEST $GFS -f /var/lib/glusterd/vols/${V0}/${V0}.tcp-fuse.vol $M0 + +TEST $(df -h $M0 | grep -q ${V0}) +TEST $(cat /proc/mounts | grep -q $M0) + +TEST ! stat $M0/newfile; +TEST touch $M0/newfile; +TEST rm $M0/newfile; + +cleanup; diff --git a/tests/basic/volume-scale-shd-mux.t b/tests/basic/volume-scale-shd-mux.t new file mode 100644 index 00000000000..102de22468e --- /dev/null +++ b/tests/basic/volume-scale-shd-mux.t @@ -0,0 +1,116 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +TESTS_EXPECTED_IN_LOOP=6 + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2,3,4,5} +TEST $CLI volume set $V0 cluster.background-self-heal-count 0 +TEST $CLI volume set $V0 cluster.eager-lock off +TEST $CLI volume set $V0 performance.flush-behind off +TEST $CLI volume start $V0 + +for i in $(seq 1 2); do + TEST $CLI volume create ${V0}_afr$i replica 3 $H0:$B0/${V0}_afr${i}{0,1,2,3,4,5} + TEST $CLI volume start ${V0}_afr$i + TEST $CLI volume create ${V0}_ec$i disperse 6 redundancy 2 $H0:$B0/${V0}_ec${i}{0,1,2,3,4,5} + TEST $CLI volume start ${V0}_ec$i +done + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" shd_count +#Check the thread count become to number of volumes*number of ec subvolume (2*6=12) +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^12$" number_healer_threads_shd $V0 "ec_shd_index_healer" +#Check the thread count become to number of volumes*number of afr subvolume (3*6=18) +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^18$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +TEST $CLI volume add-brick $V0 replica 3 $H0:$B0/${V0}{6,7,8}; +#Check the thread count become to number of volumes*number of afr subvolume plus 3 additional threads from newly added bricks (3*6+3=21) + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" shd_count +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^21$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +#Remove the brick and check the detach is successful +$CLI volume remove-brick $V0 $H0:$B0/${V0}{6,7,8} force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^18$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^0$" number_healer_threads_shd $V0 "glusterfs_graph_cleanup" +TEST $CLI volume add-brick ${V0}_ec1 $H0:$B0/${V0}_ec1_add{0,1,2,3,4,5}; +#Check the thread count become to number of volumes*number of ec subvolume plus 2 additional threads from newly added bricks (2*6+6=18) + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" shd_count +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^18$" number_healer_threads_shd $V0 "ec_shd_index_healer" + +#Remove the brick and check the detach is successful +$CLI volume remove-brick ${V0}_ec1 $H0:$B0/${V0}_ec1_add{0,1,2,3,4,5} force + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^12$" number_healer_threads_shd $V0 "ec_shd_index_healer" + + +for i in $(seq 1 2); do + TEST $CLI volume stop ${V0}_afr$i + TEST $CLI volume stop ${V0}_ec$i +done + +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^6$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0 + +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST kill_brick $V0 $H0 $B0/${V0}4 + +TEST touch $M0/foo{1..100} + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^204$" get_pending_heal_count $V0 + +TEST $CLI volume start ${V0} force + +EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0 + +TEST rm -rf $M0/* +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +shd_pid=$(get_shd_mux_pid $V0) +TEST $CLI volume create ${V0}_distribute1 $H0:$B0/${V0}_distribute10 +TEST $CLI volume start ${V0}_distribute1 + +#Creating a non-replicate/non-ec volume should not have any effect in shd +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^6$" number_healer_threads_shd $V0 "afr_shd_index_healer" +EXPECT "^${shd_pid}$" get_shd_mux_pid $V0 + +TEST mkdir $B0/add/ +#Now convert the distributed volume to replicate +TEST $CLI volume add-brick ${V0}_distribute1 replica 3 $H0:$B0/add/{2..3} +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^9$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +#scale down the volume +TEST $CLI volume remove-brick ${V0}_distribute1 replica 1 $H0:$B0/add/{2..3} force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^6$" number_healer_threads_shd $V0 "afr_shd_index_healer" + +#Before stopping the process, make sure there is no pending clenup threads hanging +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^0$" number_healer_threads_shd $V0 "glusterfs_graph_cleanup" + +TEST $CLI volume stop ${V0} +TEST $CLI volume delete ${V0} +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^0$" shd_count + +TEST rm -rf $B0/add/2 $B0/add/3 + +#Now convert the distributed volume back to replicate and make sure that a new shd is spawned +TEST $CLI volume add-brick ${V0}_distribute1 replica 3 $H0:$B0/add/{2..3}; +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" shd_count +EXPECT_WITHIN $HEAL_TIMEOUT "^3$" number_healer_threads_shd ${V0}_distribute1 "afr_shd_index_healer" + +#Now convert the replica volume to distribute again and make sure the shd is now stopped +TEST $CLI volume remove-brick ${V0}_distribute1 replica 1 $H0:$B0/add/{2..3} force +TEST rm -rf $B0/add/ + +EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "^0$" shd_count + +cleanup + +#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=1708929 +#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=1708929 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-snapshot-clone.t b/tests/basic/volume-snapshot-clone.t index 7c0ec7e0f5a..e6da9d7ddca 100755 --- a/tests/basic/volume-snapshot-clone.t +++ b/tests/basic/volume-snapshot-clone.t @@ -90,12 +90,27 @@ EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M1 TEST kill_glusterd 2; +sleep 15 TEST $glusterd_2; +sleep 15 EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count; EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'Started' volinfo_field ${V0}_clone 'Status'; EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'Started' volinfo_field ${V1}_clone 'Status'; + +TEST $CLI_1 volume stop ${V0}_clone +TEST $CLI_1 volume stop ${V1}_clone + +TEST $CLI_1 volume delete ${V0}_clone +TEST $CLI_1 volume delete ${V1}_clone + +TEST $CLI_1 snapshot clone ${V0}_clone ${V0}_snap +TEST $CLI_1 snapshot clone ${V1}_clone ${V1}_snap + +EXPECT 'Created' volinfo_field ${V0}_clone 'Status'; +EXPECT 'Created' volinfo_field ${V1}_clone 'Status'; + #Clean up stop_force_volumes 2 EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT 'Stopped' volinfo_field $V0 'Status'; diff --git a/tests/basic/volume-snapshot-xml.t b/tests/basic/volume-snapshot-xml.t index d58e898083a..ff63b54538d 100755 --- a/tests/basic/volume-snapshot-xml.t +++ b/tests/basic/volume-snapshot-xml.t @@ -1,13 +1,9 @@ #!/bin/bash . $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc . $(dirname $0)/../snapshot.rc -function get-xml() -{ - $CLI $1 --xml | xmllint --format - | grep $2 | sed 's/\(<"$2">\|<\/"$2">\)//g' -} - cleanup; TEST verify_lvm_version; TEST glusterd; @@ -46,7 +42,7 @@ EXPECT "snap2" get-xml "snapshot list $V0" "snapshot" # Snapshot status xmls EXPECT "snap2" get-xml "snapshot status" "name" EXPECT "snap2" get-xml "snapshot deactivate snap2" "name" -EXPECT "N/A" get-xml "snapshot status" "pid" +#XPECT "N/A" get-xml "snapshot status" "pid" EXPECT "snap1" get-xml "snapshot status snap1" "name" EXPECT "Yes" get-xml "snapshot status snap1" "brick_running" @@ -57,18 +53,18 @@ EXPECT "30807" get-xml "snapshot restore snap2" "opErrno" EXPECT "0" get-xml "snapshot restore snap1" "opErrno" # Snapshot delete xmls -TEST $CLI volume start $V0 +TEST $CLI volume start $V0 force EXPECT "snap1" get-xml "snapshot create snap1 $V0 no-timestamp" "name" EXPECT "snap2" get-xml "snapshot create snap2 $V0 no-timestamp" "name" EXPECT "snap3" get-xml "snapshot create snap3 $V0 no-timestamp" "name" EXPECT "Success" get-xml "snapshot delete snap3" "status" EXPECT "Success" get-xml "snapshot delete all" "status" EXPECT "0" get-xml "snapshot list" "count" -EXPECT "snap1" get-xml "snapshot create snap1 $V0 no-timestamp" "name" -EXPECT "snap2" get-xml "snapshot create snap2 $V0 no-timestamp" "name" -EXPECT "snap3" get-xml "snapshot create snap3 $V0 no-timestamp" "name" -EXPECT "Success" get-xml "snapshot delete volume $V0" "status" -EXPECT "0" get-xml "snapshot list" "count" +#XPECT "snap1" get-xml "snapshot create snap1 $V0 no-timestamp" "name" +#XPECT "snap2" get-xml "snapshot create snap2 $V0 no-timestamp" "name" +#XPECT "snap3" get-xml "snapshot create snap3 $V0 no-timestamp" "name" +#XPECT "Success" get-xml "snapshot delete volume $V0" "status" +#XPECT "0" get-xml "snapshot list" "count" # Snapshot clone xmls # Snapshot clone xml is broken. Once it is fixed it will be added here. diff --git a/tests/basic/volume-status.t b/tests/basic/volume-status.t index f87b0a93edf..01d7ebf6c07 100644 --- a/tests/basic/volume-status.t +++ b/tests/basic/volume-status.t @@ -4,13 +4,27 @@ . $(dirname $0)/../volume.rc . $(dirname $0)/../nfs.rc +#G_TESTDEF_TEST_STATUS_CENTOS6=NFS_TEST + cleanup; +function gluster_client_list_status () { + gluster volume status $V0 client-list | sed -n '/Name/','/total/'p | wc -l +} + +function gluster_fd_status () { + gluster volume status $V0 fd | sed -n '/Brick :/ p' | wc -l +} + +function gluster_inode_status () { + gluster volume status $V0 inode | sed -n '/Connection / p' | wc -l +} + TEST glusterd TEST pidof glusterd TEST $CLI volume info; -TEST $CLI volume create $V0 replica 2 stripe 2 $H0:$B0/${V0}{1,2,3,4,5,6,7,8}; +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{1,2,3,4,5,6}; TEST $CLI volume set $V0 nfs.disable false TEST $CLI volume start $V0; @@ -20,6 +34,14 @@ EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" nfs_up_status ## Mount FUSE TEST $GFS -s $H0 --volfile-id $V0 $M0; +TEST touch $M0/file{1..20} + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "6" gluster_fd_status + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "768" gluster_inode_status + +##Disabling this test until the client-list command works for brick-multiplexing +#EXPECT_WITHIN $PROCESS_UP_TIMEOUT "7" gluster_client_list_status ##Wait for connection establishment between nfs server and brick process EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "1" is_nfs_export_available; @@ -36,6 +58,8 @@ function test_nfs_cmds () { for cmd in ${nfs_cmds[@]}; do $CLI volume status $V0 nfs $cmd (( ret += $? )) + $CLI volume status $V0 nfs $cmd --xml + (( ret += $? )) done return $ret } @@ -46,6 +70,8 @@ function test_shd_cmds () { for cmd in ${shd_cmds[@]}; do $CLI volume status $V0 shd $cmd (( ret += $? )) + $CLI volume status $V0 shd $cmd --xml + (( ret += $? )) done return $ret } @@ -57,14 +83,29 @@ function test_brick_cmds () { for i in {1..2}; do $CLI volume status $V0 $H0:$B0/${V0}$i $cmd (( ret += $? )) + $CLI volume status $V0 $H0:$B0/${V0}$i $cmd --xml + (( ret += $? )) done done return $ret } +function test_status_cmds () { + local ret=0 + declare -a cmds=("detail" "clients" "mem" "inode" "fd" "callpool" "tasks" "client-list") + for cmd in ${cmds[@]}; do + $CLI volume status $V0 $cmd + (( ret += $? )) + $CLI volume status $V0 $cmd --xml + (( ret += $? )) + done + return $ret +} + TEST test_shd_cmds; TEST test_nfs_cmds; TEST test_brick_cmds; +TEST test_status_cmds; ## Before killing daemon to avoid deadlocks diff --git a/tests/basic/volume.t b/tests/basic/volume.t index 23b740af1ed..27fe093d07d 100755..100644 --- a/tests/basic/volume.t +++ b/tests/basic/volume.t @@ -9,26 +9,52 @@ TEST glusterd TEST pidof glusterd TEST $CLI volume info; -TEST $CLI volume create $V0 replica 2 stripe 2 $H0:$B0/${V0}{1,2,3,4,5,6,7,8}; - +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 '8' brick_count $V0 +EXPECT '6' brick_count $V0 TEST $CLI volume start $V0; EXPECT 'Started' volinfo_field $V0 'Status'; -TEST $CLI volume add-brick $V0 $H0:$B0/${V0}{9,10,11,12}; -EXPECT '12' brick_count $V0 +TEST $CLI volume add-brick $V0 $H0:$B0/${V0}{9,10,11}; +EXPECT '9' brick_count $V0 + +TEST $CLI volume remove-brick $V0 $H0:$B0/${V0}{1,2,3} force; +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 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 $CLI volume remove-brick $V0 $H0:$B0/${V0}{1,2,3,4} force; -EXPECT '8' brick_count $V0 +TEST rm -rf $D0/level -TEST $CLI volume stop $V0; -EXPECT 'Stopped' volinfo_field $V0 'Status'; +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/basic/xlator-pass-through-sanity.t b/tests/basic/xlator-pass-through-sanity.t new file mode 100644 index 00000000000..e996be89260 --- /dev/null +++ b/tests/basic/xlator-pass-through-sanity.t @@ -0,0 +1,22 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/${V0} +TEST $CLI volume set $V0 performance.io-cache-pass-through enable; +TEST $CLI volume start $V0; + +## Mount FUSE +TEST $GFS -s $H0 --volfile-id $V0 $M1; + +# This test covers lookup, mkdir, mknod, symlink, link, rename, +# create operations +TEST $(dirname $0)/rpc-coverage.sh $M1 + +cleanup; |
