From 31260068ba0ea15ca911d96e160fb440a5eec3a6 Mon Sep 17 00:00:00 2001 From: Tony Hutter Date: Thu, 11 Aug 2016 15:48:27 -0700 Subject: [PATCH] Add 'filetest_001_pos' checksum tests, random data for file_write - Add filetest_001_pos.ksh checksum sanity test - Add option to write psudorandom data in file_write utility --- tests/zfs-tests/cmd/file_write/file_write.c | 46 +++++-- tests/zfs-tests/include/libtest.shlib | 14 ++ tests/zfs-tests/include/properties.shlib | 3 +- .../tests/functional/checksum/Makefile.am | 3 +- .../functional/checksum/filetest_001_pos.ksh | 125 ++++++++++++++++++ .../tests/functional/checksum/setup.ksh | 2 +- 6 files changed, 182 insertions(+), 11 deletions(-) create mode 100755 tests/zfs-tests/tests/functional/checksum/filetest_001_pos.ksh diff --git a/tests/zfs-tests/cmd/file_write/file_write.c b/tests/zfs-tests/cmd/file_write/file_write.c index 43fd96ac465a..94d2225e563e 100644 --- a/tests/zfs-tests/cmd/file_write/file_write.c +++ b/tests/zfs-tests/cmd/file_write/file_write.c @@ -30,6 +30,9 @@ #include #include #include +#include +#include +#include typedef unsigned char uchar_t; typedef long long longlong_t; @@ -44,6 +47,16 @@ static unsigned char bigbuffer[BIGBUFFERSIZE]; static void usage(char *); +/* + * psudo-randomize the buffer + */ +void randomize_buffer(int block_size) { + int i; + char rnd = rand() & 0xff; + for (i = 0; i < block_size; i++) + bigbuffer[i] ^= rnd; +} + int main(int argc, char **argv) { @@ -81,7 +94,10 @@ main(int argc, char **argv) write_count = atoi(optarg); break; case 'd': - fillchar = atoi(optarg); + if (optarg[0] == 'R') + fillchar = 'R'; /* R = random data */ + else + fillchar = atoi(optarg); break; case 's': offset = atoll(optarg); @@ -135,6 +151,9 @@ main(int argc, char **argv) nxtfillchar = fillchar; k = 0; + if (fillchar == 'R') + srand(time(NULL)); + for (i = 0; i < block_size; i++) { bigbuffer[i] = nxtfillchar; @@ -143,6 +162,8 @@ main(int argc, char **argv) k = 0; } nxtfillchar = k++; + } else if (fillchar == 'R') { + nxtfillchar = rand() & 0xff; } } @@ -188,14 +209,21 @@ main(int argc, char **argv) if (verbose) { (void) printf("%s: block_size = %d, write_count = %d, " - "offset = %lld, data = %s%d\n", filename, block_size, - write_count, offset, - (fillchar == 0) ? "0->" : "", - (fillchar == 0) ? DATA_RANGE : fillchar); + "offset = %lld, ", filename, block_size, + write_count, offset); + if (fillchar == 'R') { + (void) printf("data = [random]\n"); + } else { + (void) printf("data = %s%d\n", + (fillchar == 0) ? "0->" : "", + (fillchar == 0) ? DATA_RANGE : fillchar); + } } for (i = 0; i < write_count; i++) { ssize_t n; + if (fillchar == 'R') + randomize_buffer(block_size); if ((n = write(bigfd, &bigbuffer, block_size)) == -1) { (void) printf("write failed (%ld), good_writes = %" @@ -221,9 +249,11 @@ usage(char *prog) { (void) printf("Usage: %s [-v] -o {create,overwrite,append} -f file_name" " [-b block_size]\n" - "\t[-s offset] [-c write_count] [-d data]\n" - "\twhere [data] equal to zero causes chars " - "0->%d to be repeated throughout\n", prog, DATA_RANGE); + "\t[-s offset] [-c write_count] [-d data]\n\n" + "Where [data] equal to zero causes chars " + "0->%d to be repeated throughout, or [data]\n" + "equal to 'R' for psudorandom data.\n", + prog, DATA_RANGE); exit(1); } diff --git a/tests/zfs-tests/include/libtest.shlib b/tests/zfs-tests/include/libtest.shlib index a9236a3bc773..875a792a0d28 100644 --- a/tests/zfs-tests/include/libtest.shlib +++ b/tests/zfs-tests/include/libtest.shlib @@ -147,12 +147,14 @@ function default_setup_noexit typeset disklist=$1 typeset container=$2 typeset volume=$3 + log_note begin default_setup_noexit if is_global_zone; then if poolexists $TESTPOOL ; then destroy_pool $TESTPOOL fi [[ -d /$TESTPOOL ]] && $RM -rf /$TESTPOOL + log_note creating poool $TESTPOOL $disklist log_must $ZPOOL create -f $TESTPOOL $disklist else reexport_pool @@ -1471,6 +1473,18 @@ function get_disklist # pool $ECHO $disklist } +# +# Given a pool, and this function list all disks in the pool with their full +# path (like "/dev/sda" instead of "sda"). +# +function get_disklist_fullpath # pool +{ + args="-P $1" + get_disklist $args +} + + + # /** # This function kills a given list of processes after a time period. We use # this in the stress tests instead of STF_TIMEOUT so that we can have processes diff --git a/tests/zfs-tests/include/properties.shlib b/tests/zfs-tests/include/properties.shlib index bb0b4ff58618..c495eecb477b 100644 --- a/tests/zfs-tests/include/properties.shlib +++ b/tests/zfs-tests/include/properties.shlib @@ -16,7 +16,8 @@ typeset -a compress_props=('on' 'off' 'lzjb' 'gzip' 'gzip-1' 'gzip-2' 'gzip-3' 'gzip-4' 'gzip-5' 'gzip-6' 'gzip-7' 'gzip-8' 'gzip-9' 'zle') -typeset -a checksum_props=('on' 'off' 'fletcher2' 'fletcher4' 'sha256') +typeset -a checksum_props=('on' 'off' 'fletcher2' 'fletcher4' 'sha256' 'sha512' + 'edonr' 'skein' 'noparity') # # Given the property array passed in, return 'num_props' elements to the diff --git a/tests/zfs-tests/tests/functional/checksum/Makefile.am b/tests/zfs-tests/tests/functional/checksum/Makefile.am index 309b0a62cebd..2d7d271a095d 100644 --- a/tests/zfs-tests/tests/functional/checksum/Makefile.am +++ b/tests/zfs-tests/tests/functional/checksum/Makefile.am @@ -11,7 +11,8 @@ dist_pkgdata_SCRIPTS = \ cleanup.ksh \ run_edonr_test.ksh \ run_sha2_test.ksh \ - run_skein_test.ksh + run_skein_test.ksh \ + filetest_001_pos.ksh pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/checksum diff --git a/tests/zfs-tests/tests/functional/checksum/filetest_001_pos.ksh b/tests/zfs-tests/tests/functional/checksum/filetest_001_pos.ksh new file mode 100755 index 000000000000..230dbe3db6c1 --- /dev/null +++ b/tests/zfs-tests/tests/functional/checksum/filetest_001_pos.ksh @@ -0,0 +1,125 @@ +#! /bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/include/properties.shlib + +# DESCRIPTION: +# Sanity test to make sure checksum algorithms work. +# For each checksum, create a file in the pool using that checksum. Verify +# that there are no checksum errors. Next, for each checksum, create a single +# file in the pool using that checksum, scramble the underlying vdev, and +# verify that we correctly catch the checksum errors. +# +# STRATEGY: +# Test 1 +# 1. Create a mirrored pool +# 2. Create a file using each checksum +# 3. Export/import/scrub the pool +# 4. Verify there's no checksum errors. +# 5. Clear the pool +# +# Test 2 +# 6. For each checksum: +# 7. Create a file using the checksum +# 8. Export the pool +# 9. Scramble the data on one of the underlying VDEVs +# 10. Import the pool +# 11. Scrub the pool +# 12. Verify that there are checksum errors + +verify_runnable "both" + +function cleanup +{ + $ECHO cleanup + [[ -e $TESTDIR ]] && \ + log_must $RM -rf $TESTDIR/* > /dev/null 2>&1 +} + +log_assert "Create and read back files with using different checksum algorithms" + +log_onexit cleanup + +FSSIZE=$($ZPOOL list -Hp -o size $TESTPOOL) +WRITESZ=1048576 +WRITECNT=$((($FSSIZE) / $WRITESZ )) +# Skip the first and last 4MB +SKIP=4127518 +SKIPCNT=$((($SKIP / $WRITESZ ))) +SKIPCNT=$((($SKIPCNT * 2))) +WRITECNT=$((($WRITECNT - $SKIPCNT))) + +# Get a list of vdevs in our pool +set -A array $(get_disklist_fullpath) + +# Get the first vdev, since we will corrupt it later +firstvdev=${array[0]} + +# First test each checksum by writing a file using it, and confirm there's no +# errors. +for ((count = 0; count < ${#checksum_props[*]} ; count++)); do + i=${checksum_props[$count]} + $ZFS set checksum=$i $TESTPOOL + $FILE_WRITE -o overwrite -f $TESTDIR/test_$i -b $WRITESZ -c 5 -d R +done +$ZPOOL export $TESTPOOL +$ZPOOL import $TESTPOOL +$ZPOOL scrub $TESTPOOL +while is_pool_scrubbing $TESTPOOL; do + $SLEEP 1 +done +$ZPOOL status -P -v $TESTPOOL | grep $firstvdev | read -r name state rd wr cksum +log_assert "Normal file write test saw: $cksum errors" +log_must [ $cksum -eq 0 ] + +rm -fr $TESTDIR/* + +log_assert "Test scrambling the disk and seeing checksum errors" +for ((count = 0; count < ${#checksum_props[*]} ; count++)); do + i=${checksum_props[$count]} + $ZFS set checksum=$i $TESTPOOL + $FILE_WRITE -o overwrite -f $TESTDIR/test_$i -b $WRITESZ -c 5 -d R + + $ZPOOL export $TESTPOOL + + # Scramble the data on the first vdev in our pool. + # Skip the first and last 16MB of data, then scramble the rest after that + # + $FILE_WRITE -o overwrite -f $firstvdev -s $SKIP -c $WRITECNT -b $WRITESZ -d R + + $ZPOOL import $TESTPOOL + + i=${checksum_props[$count]} + $ZPOOL scrub $TESTPOOL + while is_pool_scrubbing $TESTPOOL; do + $SLEEP 1 + done + + $ZPOOL status -P -v $TESTPOOL | grep $firstvdev | read -r name state rd wr cksum + + log_assert "Checksum '$i' caught $cksum checksum errors" + log_must [ $cksum -ne 0 ] + + rm -f $TESTDIR/test_$i + $ZPOOL clear $TESTPOOL +done diff --git a/tests/zfs-tests/tests/functional/checksum/setup.ksh b/tests/zfs-tests/tests/functional/checksum/setup.ksh index 0c5d38f191c3..27e125df4a3d 100755 --- a/tests/zfs-tests/tests/functional/checksum/setup.ksh +++ b/tests/zfs-tests/tests/functional/checksum/setup.ksh @@ -28,4 +28,4 @@ . $STF_SUITE/include/libtest.shlib DISK=${DISKS%% *} -default_setup $DISK +default_mirror_setup $DISKS