xref: /freebsd/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
1#!/bin/ksh
2# SPDX-License-Identifier: CDDL-1.0
3#
4# This file and its contents are supplied under the terms of the
5# Common Development and Distribution License ("CDDL"), version 1.0.
6# You may only use this file in accordance with the terms of version
7# 1.0 of the CDDL.
8#
9# A full copy of the text of the CDDL should have accompanied this
10# source.  A copy of the CDDL is also available via the Internet at
11# http://www.illumos.org/license/CDDL.
12#
13
14#
15# Copyright (c) 2018 by Delphix. All rights reserved.
16#
17
18typeset -a disk_array=($(find_disks $DISKS))
19
20typeset -r DISK1=${disk_array[0]}
21typeset -r DISK2=${disk_array[1]}
22typeset -r DISK3=${disk_array[2]}
23
24#
25# When the condition it is waiting for becomes true, 'zpool wait' should return
26# promptly. We want to enforce this, but any check will be racey because it will
27# take some small but indeterminate amount of time for the waiting thread to be
28# woken up and for the process to exit.
29#
30# To deal with this, we provide a grace period after the condition becomes true
31# during which 'zpool wait' can exit. If it hasn't exited by the time the grace
32# period expires we assume something is wrong and fail the test. While there is
33# no value that can really be correct, the idea is we choose something large
34# enough that it shouldn't cause issues in practice.
35#
36typeset -r WAIT_EXIT_GRACE=2.0
37
38function add_io_delay # pool
39{
40	for disk in $(get_disklist $1); do
41		log_must zinject -d $disk -D20:1 $1
42	done
43}
44
45function remove_io_delay
46{
47	log_must zinject -c all
48}
49
50function proc_exists # pid
51{
52	ps -p $1 >/dev/null
53}
54
55function proc_must_exist # pid
56{
57	proc_exists $1 || log_fail "zpool process exited too soon"
58}
59
60function proc_must_not_exist # pid
61{
62	proc_exists $1 && log_fail "zpool process took too long to exit"
63}
64
65function get_time
66{
67	date +'%H:%M:%S'
68}
69
70function kill_if_running
71{
72	typeset pid=$1
73	[[ $pid ]] && proc_exists $pid && log_must kill -s TERM $pid
74}
75
76# Log a command and then start it running in the background
77function log_bkgrnd
78{
79	log_note "$(get_time) Starting cmd in background '$@'"
80	"$@" &
81}
82
83# Check that a background process has completed and exited with a status of 0
84function bkgrnd_proc_succeeded
85{
86	typeset pid=$1
87
88	log_must sleep $WAIT_EXIT_GRACE
89
90	proc_must_not_exist $pid
91	wait $pid || log_fail "zpool process exited with status $?"
92	log_note "$(get_time) wait completed successfully"
93}
94
95#
96# Check that 'zpool wait' returns reasonably promptly after the condition
97# waited for becomes true, and not before.
98#
99function check_while_waiting
100{
101	# The pid of the waiting process
102	typeset wait_proc_pid=$1
103	# A check that should be true while the activity is in progress
104	typeset activity_check=$2
105
106	log_note "$(get_time) waiting for process $wait_proc_pid using" \
107	    "activity check '$activity_check'"
108	while proc_exists $wait_proc_pid && eval "$activity_check"; do
109		log_must sleep .5
110	done
111
112	#
113	# If the activity being waited on is still in progress, then zpool wait
114	# exited too soon.
115	#
116	log_mustnot eval "$activity_check"
117
118	bkgrnd_proc_succeeded $wait_proc_pid
119}
120
121# Whether any vdev in the given pool is initializing
122function is_vdev_initializing # pool
123{
124	zpool status -i "$1" | grep -q 'initialized, started'
125}
126