Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 24 Aug 2016 22:48:56 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r304776 - projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_destroy
Message-ID:  <201608242248.u7OMmuYq053455@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Wed Aug 24 22:48:55 2016
New Revision: 304776
URL: https://svnweb.freebsd.org/changeset/base/304776

Log:
  Fix intermittent failures in zpool_destroy_004_pos
  
  The test case has multiple zfs send/recv scenarios.
  The scenario that was commonly failing was as follows;
  1.) zfs send poolA | zfs recv poolB
  2.) wait
  3.) destroy -f poolA
  4.) declare an error if the exit status of the send/recv pipeline
  was success.
  
  Step 4 was attempting to assert that the destruction of poolA interrupted
  the zfs send. The problem is that the zfs send could complete before the zfs
  destroy -f poolA was issued. If this occured then the receive half of the
  pipeline would succeed and the exit code of the pipeline would be zero.
  
  It is not possible to manage this race from a shell script.
  
  Changed test to allow the scenario described above to not declare an error
  if the zfs receive succeeds.
  
  Submitted by:	Dave Baukus
  Reviewed by:	asomers
  Sponsored by:	Spectra Logic Corp

Modified:
  projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_destroy/zpool_destroy_004_pos.ksh

Modified: projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_destroy/zpool_destroy_004_pos.ksh
==============================================================================
--- projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_destroy/zpool_destroy_004_pos.ksh	Wed Aug 24 22:38:06 2016	(r304775)
+++ projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_destroy/zpool_destroy_004_pos.ksh	Wed Aug 24 22:48:55 2016	(r304776)
@@ -56,28 +56,77 @@ function create_sender_and_receiver
 	create_pool "$TESTPOOL1" "$DISK1"
 }
 
+function check_recv_status
+{
+	rcv_pid="$1"
+	rcv_status="$2"
+	destroyed="$3"
+
+	if ((rcv_status != 0))
+	then
+		log_note \
+	"zfs receive interrupted by destruction of $destroyed as expected"
+		return 0
+	fi
+
+	log_note "zfs receive NOT interrupted by destruction of $destroyed"
+	case $destroyed
+	in
+		SAME_POOL|RECEIVER)
+		log_fail "expected zfs receive failure did not occur"
+		;;
+		
+		SENDER)
+		log_note "zfs send completed before destruction of $destroyed"
+		;;
+
+		*)
+		log_fail "unknown parameter $destroyed"
+		;;
+	esac
+	return 0
+}
+
 function send_recv_destroy
 {
 	sleeptime=$1
 	recv=$2
 	to_destroy=$3
+	who_to_destroy="$4"
 
+	# The pid of this send/receive pipeline is that of zfs receive.
+	# We can not get the exit status of the zfs send. We can, however,
+	# infer the status of the send; see note below.
+	#
 	( $ZFS send -RP $TESTPOOL/$TESTFS@snap1 | $ZFS receive -Fu $recv/d1 ) &
-	sendrecvpid=$!
+	recvpid=$!
+	sndrcv_start=$(date '+%s')
 
 	log_must sleep $sleeptime
 	destroy_start=$(date '+%s')
 	log_must $ZPOOL destroy -f $to_destroy
 	destroy_end=$(date '+%s')
-	dtime=$(expr ${destroy_end} - ${destroy_start})
-	log_note "Destroy took ${dtime} seconds."
+	dtime=$((destroy_end - destroy_start))
+	log_note "Destroy of $who_to_destroy took ${dtime} seconds."
 
-	log_note "If this wait returns 0, it means send or receive succeeded."
-	log_mustnot wait $sendrecvpid
+	# NOTE:
+	# If the we have destroyed the send pool then the send/receive may
+	# succeed.
+	# 	1.) If the destruction of the send pool interrupts the zfs 
+	#	    send then this error will be detected by the receiver;
+	#	    the entire operation will fail.
+	#
+	#	2.) If the send completes before the destruction of the send 
+	# 	    pool then the receive will succeed.
+	#
+	wait $recvpid
+	rc=$?
 	wait_end=$(date '+%s')
-	wtime=$(expr ${wait_end} - ${destroy_end})
-	log_note "send|receive took ${wtime} seconds to finish."
+	log_note "$recvpid rc = $rc for destruction of $who_to_destroy"
+	check_recv_status $recvpid $rc $who_to_destroy
 
+	wtime=$((wait_end - sndrcv_start))
+	log_note "send|receive took ${wtime} seconds to finish."
 	log_mustnot $ZPOOL list $to_destroy
 }
 
@@ -85,15 +134,15 @@ function run_tests
 {
 	log_note "TEST: send|receive to the same pool"
 	create_sender
-	send_recv_destroy $sleeptime $TESTPOOL $TESTPOOL
+	send_recv_destroy $sleeptime $TESTPOOL $TESTPOOL SAME_POOL 
 
 	log_note "TEST: send|receive to different pools, destroy sender"
 	create_sender_and_receiver
-	send_recv_destroy $sleeptime $TESTPOOL1 $TESTPOOL
+	send_recv_destroy $sleeptime $TESTPOOL1 $TESTPOOL SENDER
 
 	log_note "TEST: send|receive to different pools, destroy receiver"
 	create_sender_and_receiver
-	send_recv_destroy $sleeptime $TESTPOOL1 $TESTPOOL1
+	send_recv_destroy $sleeptime $TESTPOOL1 $TESTPOOL1 RECEIVER
 }
 
 log_assert "'zpool destroy -f <pool>' can force destroy active pool"
@@ -112,7 +161,7 @@ done
 # time after the start of the run.
 arcmem=$(sysctl -n vfs.zfs.arc_max)
 # ARC will use 2xdatasz memory since it caches both the src and dst copies
-datasz=$(expr ${arcmem} / 1048576 \* 2 / 3)
+datasz=$((arcmem / 1048576 * 2 / 3))
 log_note "Running longer test with ${datasz}MB of data"
 sleeptime=15
 run_tests



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201608242248.u7OMmuYq053455>