1#!/usr/local/bin/ksh93 -p
2#
3# Copyright 2015 Spectra Logic Corporation.
4#
5
6# $FreeBSD$
7
8. $STF_SUITE/include/libtest.kshlib
9
10################################################################################
11#
12# __stc_assertion_start
13#
14# ID: zpool_destroy_004_pos
15#
16# DESCRIPTION:
17#	'zpool destroy -f <pool>' can forcibly destroy the specified pool,
18#       even if that pool has running zfs send or receive activity.
19#
20# STRATEGY:
21#	1. Create a storage pool
22#       2. For each sleep time in a set:
23#       2a. For each destroy type (same pool, sender only, receiver only):
24#	    - Create a dataset with some amount of data
25#           - Run zfs send | zfs receive in the background.
26#           - Sleep the amount of time specified for this run.
27#	    - 'zpool destroy -f' the pool.
28#	    - Wait for the send|receive to exit.  It must not be killed in
29#	      order to ensure that the destroy takes care of doing so.
30#	    - Verify the pool destroyed successfully
31#
32# __stc_assertion_end
33#
34###############################################################################
35
36verify_runnable "global"
37
38function cleanup
39{
40	poolexists $TESTPOOL && destroy_pool $TESTPOOL
41	poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
42}
43
44function create_sender
45{
46	cleanup
47	create_pool "$TESTPOOL" "$DISK0"
48	log_must $ZFS create $TESTPOOL/$TESTFS
49	log_must $MKDIR -p $TESTDIR
50	log_must $ZFS set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
51	log_must dd if=/dev/zero of=$TESTDIR/f0 bs=1024k count=$datasz
52	log_must $ZFS snapshot $TESTPOOL/$TESTFS@snap1
53}
54
55function create_sender_and_receiver
56{
57	create_sender
58	create_pool "$TESTPOOL1" "$DISK1"
59}
60
61function send_recv_destroy
62{
63	sleeptime=$1
64	recv=$2
65	to_destroy=$3
66	who_to_destroy="$4"
67
68	# The pid of this pipe line is that of zfs receive
69	#
70	( $ZFS send -RP $TESTPOOL/$TESTFS@snap1 | $ZFS receive -Fu $recv/d1 ) &
71	sndrcv_start=$(date '+%s')
72	rcvpid=$!
73	sndpid=$(pgrep -P $rcvpid)
74
75	log_must sleep $sleeptime
76	log_note "post sleep: $(ps -p ${sndpid},${rcvpid} -o command)"
77
78	destroy_start=$(date '+%s')
79	log_must $ZPOOL destroy -f $to_destroy
80	destroy_end=$(date '+%s')
81	dtime=$((destroy_end - destroy_start))
82	log_note "Destroy of $who_to_destroy took ${dtime} seconds."
83
84	log_note "post destroy: $(ps -p ${sndpid},${rcvpid} -o command)"
85
86	# Wait for send and recv to exit.
87	#
88	wait $sndpid
89	snderr=$?
90	wait $rcvpid
91	rcverr=$?
92	wait_end=$(date '+%s')
93	wtime=$((wait_end - sndrcv_start))
94	log_note "send|receive took ${wtime} seconds to finish."
95
96	# KSH: "wait pid" exit status of 127 means that process never existed
97	# or already completed; ksh's wait only returns the status of the
98	# child process if the child was running when the wait was issued.
99	# Therefore, we can not imply much about the interruption of the
100	# send | recv by zpool destroy -f
101	#
102	# The real test of success is simply that the pool was destroyed.
103	#
104	log_note \
105	"Destruction of ${who_to_destroy}: send ${snderr}, recv ${rcverr}"
106
107	log_mustnot $ZPOOL list $to_destroy
108}
109
110function run_tests
111{
112	log_note "TEST: send|receive to the same pool"
113	create_sender
114	send_recv_destroy $sleeptime $TESTPOOL $TESTPOOL SAME_POOL
115
116	log_note "TEST: send|receive to different pools, destroy sender"
117	create_sender_and_receiver
118	send_recv_destroy $sleeptime $TESTPOOL1 $TESTPOOL SENDER
119
120	log_note "TEST: send|receive to different pools, destroy receiver"
121	create_sender_and_receiver
122	send_recv_destroy $sleeptime $TESTPOOL1 $TESTPOOL1 RECEIVER
123}
124
125log_assert "'zpool destroy -f <pool>' can force destroy active pool"
126log_onexit cleanup
127set_disks
128
129# Faster tests using 1GB data size
130datasz=1000
131log_note "Running fast tests with 1000MB of data"
132for sleeptime in 0.1 0.3 0.5 0.75 1 2 3; do
133	run_tests
134done
135
136# A longer test that simulates a more realistic send|receive that exceeds
137# the size of arc memory by 1/3 and gets interrupted a decent amount of
138# time after the start of the run.
139arcmem=$(sysctl -n vfs.zfs.arc_max)
140# ARC will use 2xdatasz memory since it caches both the src and dst copies
141datasz=$((arcmem / 1048576 * 2 / 3))
142log_note "Running longer test with ${datasz}MB of data"
143sleeptime=15
144run_tests
145
146log_pass "'zpool destroy -f <pool>' successful with active pools."
147