1*a60ca23dSTom Caputi#
2*a60ca23dSTom Caputi# This file and its contents are supplied under the terms of the
3*a60ca23dSTom Caputi# Common Development and Distribution License ("CDDL"), version 1.0.
4*a60ca23dSTom Caputi# You may only use this file in accordance with the terms of version
5*a60ca23dSTom Caputi# 1.0 of the CDDL.
6*a60ca23dSTom Caputi#
7*a60ca23dSTom Caputi# A full copy of the text of the CDDL should have accompanied this
8*a60ca23dSTom Caputi# source.  A copy of the CDDL is also available via the Internet at
9*a60ca23dSTom Caputi# http://www.illumos.org/license/CDDL.
10*a60ca23dSTom Caputi#
11*a60ca23dSTom Caputi
12*a60ca23dSTom Caputi#
13*a60ca23dSTom Caputi# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
14*a60ca23dSTom Caputi# Use is subject to license terms.
15*a60ca23dSTom Caputi# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
16*a60ca23dSTom Caputi# Copyright 2016 Nexenta Systems, Inc.
17*a60ca23dSTom Caputi# Copyright (c) 2016, 2017 by Intel Corporation. All rights reserved.
18*a60ca23dSTom Caputi# Copyright (c) 2017 Lawrence Livermore National Security, LLC.
19*a60ca23dSTom Caputi# Copyright (c) 2017 Datto Inc.
20*a60ca23dSTom Caputi# Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
21*a60ca23dSTom Caputi#
22*a60ca23dSTom Caputi
23*a60ca23dSTom Caputi#
24*a60ca23dSTom Caputi# Returns SCSI host number for the given disk
25*a60ca23dSTom Caputi#
26*a60ca23dSTom Caputifunction get_scsi_host #disk
27*a60ca23dSTom Caputi{
28*a60ca23dSTom Caputi	typeset disk=$1
29*a60ca23dSTom Caputi	ls /sys/block/${disk}/device/scsi_device | cut -d : -f 1
30*a60ca23dSTom Caputi}
31*a60ca23dSTom Caputi
32*a60ca23dSTom Caputi#
33*a60ca23dSTom Caputi# Cause a scan of all scsi host adapters by default
34*a60ca23dSTom Caputi#
35*a60ca23dSTom Caputi# $1 optional host number
36*a60ca23dSTom Caputi#
37*a60ca23dSTom Caputifunction scan_scsi_hosts
38*a60ca23dSTom Caputi{
39*a60ca23dSTom Caputi	typeset hostnum=${1}
40*a60ca23dSTom Caputi
41*a60ca23dSTom Caputi	if is_linux; then
42*a60ca23dSTom Caputi		if [[ -z $hostnum ]]; then
43*a60ca23dSTom Caputi			for host in /sys/class/scsi_host/host*; do
44*a60ca23dSTom Caputi				log_must eval "echo '- - -' > $host/scan"
45*a60ca23dSTom Caputi			done
46*a60ca23dSTom Caputi		else
47*a60ca23dSTom Caputi			log_must eval \
48*a60ca23dSTom Caputi			    "echo /sys/class/scsi_host/host$hostnum/scan" \
49*a60ca23dSTom Caputi			    > /dev/null
50*a60ca23dSTom Caputi			log_must eval \
51*a60ca23dSTom Caputi			    "echo '- - -' > /sys/class/scsi_host/host$hostnum/scan"
52*a60ca23dSTom Caputi		fi
53*a60ca23dSTom Caputi	fi
54*a60ca23dSTom Caputi}
55*a60ca23dSTom Caputi
56*a60ca23dSTom Caputi#
57*a60ca23dSTom Caputi# Wait for newly created block devices to have their minors created.
58*a60ca23dSTom Caputi#
59*a60ca23dSTom Caputifunction block_device_wait
60*a60ca23dSTom Caputi{
61*a60ca23dSTom Caputi	if is_linux; then
62*a60ca23dSTom Caputi		udevadm trigger
63*a60ca23dSTom Caputi		udevadm settle
64*a60ca23dSTom Caputi	fi
65*a60ca23dSTom Caputi}
66*a60ca23dSTom Caputi
67*a60ca23dSTom Caputi#
68*a60ca23dSTom Caputi# Check if the given device is physical device
69*a60ca23dSTom Caputi#
70*a60ca23dSTom Caputifunction is_physical_device #device
71*a60ca23dSTom Caputi{
72*a60ca23dSTom Caputi	typeset device=${1#$DEV_DSKDIR}
73*a60ca23dSTom Caputi	device=${device#$DEV_RDSKDIR}
74*a60ca23dSTom Caputi
75*a60ca23dSTom Caputi	if is_linux; then
76*a60ca23dSTom Caputi		[[ -b "$DEV_DSKDIR/$device" ]] && \
77*a60ca23dSTom Caputi		[[ -f /sys/module/loop/parameters/max_part ]]
78*a60ca23dSTom Caputi		return $?
79*a60ca23dSTom Caputi	else
80*a60ca23dSTom Caputi		echo $device | egrep "^c[0-F]+([td][0-F]+)+$" > /dev/null 2>&1
81*a60ca23dSTom Caputi		return $?
82*a60ca23dSTom Caputi	fi
83*a60ca23dSTom Caputi}
84*a60ca23dSTom Caputi
85*a60ca23dSTom Caputi#
86*a60ca23dSTom Caputi# Check if the given device is a real device (ie SCSI device)
87*a60ca23dSTom Caputi#
88*a60ca23dSTom Caputifunction is_real_device #disk
89*a60ca23dSTom Caputi{
90*a60ca23dSTom Caputi	typeset disk=$1
91*a60ca23dSTom Caputi	[[ -z $disk ]] && log_fail "No argument for disk given."
92*a60ca23dSTom Caputi
93*a60ca23dSTom Caputi	if is_linux; then
94*a60ca23dSTom Caputi		lsblk $DEV_RDSKDIR/$disk -o TYPE 2>/dev/null | \
95*a60ca23dSTom Caputi		    egrep disk >/dev/null
96*a60ca23dSTom Caputi		return $?
97*a60ca23dSTom Caputi	fi
98*a60ca23dSTom Caputi}
99*a60ca23dSTom Caputi
100*a60ca23dSTom Caputi#
101*a60ca23dSTom Caputi# Check if the given device is a loop device
102*a60ca23dSTom Caputi#
103*a60ca23dSTom Caputifunction is_loop_device #disk
104*a60ca23dSTom Caputi{
105*a60ca23dSTom Caputi	typeset disk=$1
106*a60ca23dSTom Caputi	[[ -z $disk ]] && log_fail "No argument for disk given."
107*a60ca23dSTom Caputi
108*a60ca23dSTom Caputi	if is_linux; then
109*a60ca23dSTom Caputi		lsblk $DEV_RDSKDIR/$disk -o TYPE 2>/dev/null | \
110*a60ca23dSTom Caputi		    egrep loop >/dev/null
111*a60ca23dSTom Caputi		return $?
112*a60ca23dSTom Caputi	fi
113*a60ca23dSTom Caputi}
114*a60ca23dSTom Caputi
115*a60ca23dSTom Caputi#
116*a60ca23dSTom Caputi# Check if the given device is a multipath device and if there is a symbolic
117*a60ca23dSTom Caputi# link to a device mapper and to a disk
118*a60ca23dSTom Caputi# Currently no support for dm devices alone without multipath
119*a60ca23dSTom Caputi#
120*a60ca23dSTom Caputifunction is_mpath_device #disk
121*a60ca23dSTom Caputi{
122*a60ca23dSTom Caputi	typeset disk=$1
123*a60ca23dSTom Caputi	[[ -z $disk ]] && log_fail "No argument for disk given."
124*a60ca23dSTom Caputi
125*a60ca23dSTom Caputi	if is_linux; then
126*a60ca23dSTom Caputi		lsblk $DEV_MPATHDIR/$disk -o TYPE 2>/dev/null | \
127*a60ca23dSTom Caputi		   egrep mpath >/dev/null
128*a60ca23dSTom Caputi		if (($? == 0)); then
129*a60ca23dSTom Caputi			readlink $DEV_MPATHDIR/$disk > /dev/null 2>&1
130*a60ca23dSTom Caputi			return $?
131*a60ca23dSTom Caputi		else
132*a60ca23dSTom Caputi			return $?
133*a60ca23dSTom Caputi		fi
134*a60ca23dSTom Caputi	fi
135*a60ca23dSTom Caputi}
136*a60ca23dSTom Caputi
137*a60ca23dSTom Caputi# Set the slice prefix for disk partitioning depending
138*a60ca23dSTom Caputi# on whether the device is a real, multipath, or loop device.
139*a60ca23dSTom Caputi# Currently all disks have to be of the same type, so only
140*a60ca23dSTom Caputi# checks first disk to determine slice prefix.
141*a60ca23dSTom Caputi#
142*a60ca23dSTom Caputifunction set_slice_prefix
143*a60ca23dSTom Caputi{
144*a60ca23dSTom Caputi	typeset disk
145*a60ca23dSTom Caputi	typeset -i i=0
146*a60ca23dSTom Caputi
147*a60ca23dSTom Caputi	if is_linux; then
148*a60ca23dSTom Caputi		while (( i < $DISK_ARRAY_NUM )); do
149*a60ca23dSTom Caputi			disk="$(echo $DISKS | nawk '{print $(i + 1)}')"
150*a60ca23dSTom Caputi			if ( is_mpath_device $disk ) && [[ -z $(echo $disk | awk 'substr($1,18,1)\
151*a60ca23dSTom Caputi			     ~ /^[[:digit:]]+$/') ]] || ( is_real_device $disk ); then
152*a60ca23dSTom Caputi				export SLICE_PREFIX=""
153*a60ca23dSTom Caputi				return 0
154*a60ca23dSTom Caputi			elif ( is_mpath_device $disk || is_loop_device \
155*a60ca23dSTom Caputi			    $disk ); then
156*a60ca23dSTom Caputi				export SLICE_PREFIX="p"
157*a60ca23dSTom Caputi				return 0
158*a60ca23dSTom Caputi			else
159*a60ca23dSTom Caputi				log_fail "$disk not supported for partitioning."
160*a60ca23dSTom Caputi			fi
161*a60ca23dSTom Caputi			(( i = i + 1))
162*a60ca23dSTom Caputi		done
163*a60ca23dSTom Caputi	fi
164*a60ca23dSTom Caputi}
165*a60ca23dSTom Caputi
166*a60ca23dSTom Caputi#
167*a60ca23dSTom Caputi# Set the directory path of the listed devices in $DISK_ARRAY_NUM
168*a60ca23dSTom Caputi# Currently all disks have to be of the same type, so only
169*a60ca23dSTom Caputi# checks first disk to determine device directory
170*a60ca23dSTom Caputi# default = /dev (linux)
171*a60ca23dSTom Caputi# real disk = /dev (linux)
172*a60ca23dSTom Caputi# multipath device = /dev/mapper (linux)
173*a60ca23dSTom Caputi#
174*a60ca23dSTom Caputifunction set_device_dir
175*a60ca23dSTom Caputi{
176*a60ca23dSTom Caputi	typeset disk
177*a60ca23dSTom Caputi	typeset -i i=0
178*a60ca23dSTom Caputi
179*a60ca23dSTom Caputi	if is_linux; then
180*a60ca23dSTom Caputi		while (( i < $DISK_ARRAY_NUM )); do
181*a60ca23dSTom Caputi			disk="$(echo $DISKS | nawk '{print $(i + 1)}')"
182*a60ca23dSTom Caputi			if is_mpath_device $disk; then
183*a60ca23dSTom Caputi				export DEV_DSKDIR=$DEV_MPATHDIR
184*a60ca23dSTom Caputi				return 0
185*a60ca23dSTom Caputi			else
186*a60ca23dSTom Caputi				export DEV_DSKDIR=$DEV_RDSKDIR
187*a60ca23dSTom Caputi				return 0
188*a60ca23dSTom Caputi			fi
189*a60ca23dSTom Caputi			(( i = i + 1))
190*a60ca23dSTom Caputi		done
191*a60ca23dSTom Caputi	else
192*a60ca23dSTom Caputi		export DEV_DSKDIR=$DEV_RDSKDIR
193*a60ca23dSTom Caputi	fi
194*a60ca23dSTom Caputi}
195*a60ca23dSTom Caputi
196*a60ca23dSTom Caputi#
197*a60ca23dSTom Caputi# Get the directory path of given device
198*a60ca23dSTom Caputi#
199*a60ca23dSTom Caputifunction get_device_dir #device
200*a60ca23dSTom Caputi{
201*a60ca23dSTom Caputi	typeset device=$1
202*a60ca23dSTom Caputi
203*a60ca23dSTom Caputi	if ! $(is_physical_device $device) ; then
204*a60ca23dSTom Caputi		if [[ $device != "/" ]]; then
205*a60ca23dSTom Caputi			device=${device%/*}
206*a60ca23dSTom Caputi		fi
207*a60ca23dSTom Caputi		if [[ -b "$DEV_DSKDIR/$device" ]]; then
208*a60ca23dSTom Caputi			device="$DEV_DSKDIR"
209*a60ca23dSTom Caputi		fi
210*a60ca23dSTom Caputi		echo $device
211*a60ca23dSTom Caputi	else
212*a60ca23dSTom Caputi		echo "$DEV_DSKDIR"
213*a60ca23dSTom Caputi	fi
214*a60ca23dSTom Caputi}
215*a60ca23dSTom Caputi
216*a60ca23dSTom Caputi#
217*a60ca23dSTom Caputi# Get persistent name for given disk
218*a60ca23dSTom Caputi#
219*a60ca23dSTom Caputifunction get_persistent_disk_name #device
220*a60ca23dSTom Caputi{
221*a60ca23dSTom Caputi	typeset device=$1
222*a60ca23dSTom Caputi	typeset dev_id
223*a60ca23dSTom Caputi
224*a60ca23dSTom Caputi	if is_linux; then
225*a60ca23dSTom Caputi		if is_real_device $device; then
226*a60ca23dSTom Caputi			dev_id="$(udevadm info -q all -n $DEV_DSKDIR/$device \
227*a60ca23dSTom Caputi			    | egrep disk/by-id | nawk '{print $2; exit}' \
228*a60ca23dSTom Caputi			    | nawk -F / '{print $3}')"
229*a60ca23dSTom Caputi			echo $dev_id
230*a60ca23dSTom Caputi		elif is_mpath_device $device; then
231*a60ca23dSTom Caputi			dev_id="$(udevadm info -q all -n $DEV_DSKDIR/$device \
232*a60ca23dSTom Caputi			    | egrep disk/by-id/dm-uuid \
233*a60ca23dSTom Caputi			    | nawk '{print $2; exit}' \
234*a60ca23dSTom Caputi			    | nawk -F / '{print $3}')"
235*a60ca23dSTom Caputi			echo $dev_id
236*a60ca23dSTom Caputi		else
237*a60ca23dSTom Caputi			echo $device
238*a60ca23dSTom Caputi		fi
239*a60ca23dSTom Caputi	else
240*a60ca23dSTom Caputi		echo $device
241*a60ca23dSTom Caputi	fi
242*a60ca23dSTom Caputi}
243*a60ca23dSTom Caputi
244*a60ca23dSTom Caputi#
245*a60ca23dSTom Caputi# Online or offline a disk on the system
246*a60ca23dSTom Caputi#
247*a60ca23dSTom Caputi# First checks state of disk. Test will fail if disk is not properly onlined
248*a60ca23dSTom Caputi# or offlined. Online is a full rescan of SCSI disks by echoing to every
249*a60ca23dSTom Caputi# host entry.
250*a60ca23dSTom Caputi#
251*a60ca23dSTom Caputifunction on_off_disk # disk state{online,offline} host
252*a60ca23dSTom Caputi{
253*a60ca23dSTom Caputi	typeset disk=$1
254*a60ca23dSTom Caputi	typeset state=$2
255*a60ca23dSTom Caputi	typeset host=$3
256*a60ca23dSTom Caputi
257*a60ca23dSTom Caputi	[[ -z $disk ]] || [[ -z $state ]] &&  \
258*a60ca23dSTom Caputi	    log_fail "Arguments invalid or missing"
259*a60ca23dSTom Caputi
260*a60ca23dSTom Caputi	if is_linux; then
261*a60ca23dSTom Caputi		if [[ $state == "offline" ]] && ( is_mpath_device $disk ); then
262*a60ca23dSTom Caputi			dm_name="$(readlink $DEV_DSKDIR/$disk \
263*a60ca23dSTom Caputi			    | nawk -F / '{print $2}')"
264*a60ca23dSTom Caputi			slave="$(ls /sys/block/${dm_name}/slaves \
265*a60ca23dSTom Caputi			    | nawk '{print $1}')"
266*a60ca23dSTom Caputi			while [[ -n $slave ]]; do
267*a60ca23dSTom Caputi				#check if disk is online
268*a60ca23dSTom Caputi				lsscsi | egrep $slave > /dev/null
269*a60ca23dSTom Caputi				if (($? == 0)); then
270*a60ca23dSTom Caputi					slave_dir="/sys/block/${dm_name}"
271*a60ca23dSTom Caputi					slave_dir+="/slaves/${slave}/device"
272*a60ca23dSTom Caputi					ss="${slave_dir}/state"
273*a60ca23dSTom Caputi					sd="${slave_dir}/delete"
274*a60ca23dSTom Caputi					log_must eval "echo 'offline' > ${ss}"
275*a60ca23dSTom Caputi					log_must eval "echo '1' > ${sd}"
276*a60ca23dSTom Caputi					lsscsi | egrep $slave > /dev/null
277*a60ca23dSTom Caputi						if (($? == 0)); then
278*a60ca23dSTom Caputi							log_fail "Offlining" \
279*a60ca23dSTom Caputi							    "$disk failed"
280*a60ca23dSTom Caputi						fi
281*a60ca23dSTom Caputi				fi
282*a60ca23dSTom Caputi				slave="$(ls /sys/block/$dm_name/slaves \
283*a60ca23dSTom Caputi				    2>/dev/null | nawk '{print $1}')"
284*a60ca23dSTom Caputi			done
285*a60ca23dSTom Caputi		elif [[ $state == "offline" ]] && ( is_real_device $disk ); then
286*a60ca23dSTom Caputi			#check if disk is online
287*a60ca23dSTom Caputi			lsscsi | egrep $disk > /dev/null
288*a60ca23dSTom Caputi			if (($? == 0)); then
289*a60ca23dSTom Caputi				dev_state="/sys/block/$disk/device/state"
290*a60ca23dSTom Caputi				dev_delete="/sys/block/$disk/device/delete"
291*a60ca23dSTom Caputi				log_must eval "echo 'offline' > ${dev_state}"
292*a60ca23dSTom Caputi				log_must eval "echo '1' > ${dev_delete}"
293*a60ca23dSTom Caputi				lsscsi | egrep $disk > /dev/null
294*a60ca23dSTom Caputi					if (($? == 0)); then
295*a60ca23dSTom Caputi						log_fail "Offlining $disk" \
296*a60ca23dSTom Caputi						    "failed"
297*a60ca23dSTom Caputi					fi
298*a60ca23dSTom Caputi			else
299*a60ca23dSTom Caputi				log_note "$disk is already offline"
300*a60ca23dSTom Caputi			fi
301*a60ca23dSTom Caputi		elif [[ $state == "online" ]]; then
302*a60ca23dSTom Caputi			#force a full rescan
303*a60ca23dSTom Caputi			scan_scsi_hosts $host
304*a60ca23dSTom Caputi			block_device_wait
305*a60ca23dSTom Caputi			if is_mpath_device $disk; then
306*a60ca23dSTom Caputi				dm_name="$(readlink $DEV_DSKDIR/$disk \
307*a60ca23dSTom Caputi				    | nawk -F / '{print $2}')"
308*a60ca23dSTom Caputi				slave="$(ls /sys/block/$dm_name/slaves \
309*a60ca23dSTom Caputi				    | nawk '{print $1}')"
310*a60ca23dSTom Caputi				lsscsi | egrep $slave > /dev/null
311*a60ca23dSTom Caputi				if (($? != 0)); then
312*a60ca23dSTom Caputi					log_fail "Onlining $disk failed"
313*a60ca23dSTom Caputi				fi
314*a60ca23dSTom Caputi			elif is_real_device $disk; then
315*a60ca23dSTom Caputi				block_device_wait
316*a60ca23dSTom Caputi				typeset -i retries=0
317*a60ca23dSTom Caputi				while ! lsscsi | egrep -q $disk; do
318*a60ca23dSTom Caputi					if (( $retries > 2 )); then
319*a60ca23dSTom Caputi						log_fail "Onlining $disk failed"
320*a60ca23dSTom Caputi						break
321*a60ca23dSTom Caputi					fi
322*a60ca23dSTom Caputi					(( ++retries ))
323*a60ca23dSTom Caputi					sleep 1
324*a60ca23dSTom Caputi				done
325*a60ca23dSTom Caputi			else
326*a60ca23dSTom Caputi				log_fail "$disk is not a real dev"
327*a60ca23dSTom Caputi			fi
328*a60ca23dSTom Caputi		else
329*a60ca23dSTom Caputi			log_fail "$disk failed to $state"
330*a60ca23dSTom Caputi		fi
331*a60ca23dSTom Caputi	fi
332*a60ca23dSTom Caputi}
333*a60ca23dSTom Caputi
334*a60ca23dSTom Caputi#
335*a60ca23dSTom Caputi# Simulate disk removal
336*a60ca23dSTom Caputi#
337*a60ca23dSTom Caputifunction remove_disk #disk
338*a60ca23dSTom Caputi{
339*a60ca23dSTom Caputi	typeset disk=$1
340*a60ca23dSTom Caputi	on_off_disk $disk "offline"
341*a60ca23dSTom Caputi	block_device_wait
342*a60ca23dSTom Caputi}
343*a60ca23dSTom Caputi
344*a60ca23dSTom Caputi#
345*a60ca23dSTom Caputi# Simulate disk insertion for the given SCSI host
346*a60ca23dSTom Caputi#
347*a60ca23dSTom Caputifunction insert_disk #disk scsi_host
348*a60ca23dSTom Caputi{
349*a60ca23dSTom Caputi	typeset disk=$1
350*a60ca23dSTom Caputi	typeset scsi_host=$2
351*a60ca23dSTom Caputi	on_off_disk $disk "online" $scsi_host
352*a60ca23dSTom Caputi	block_device_wait
353*a60ca23dSTom Caputi}
354*a60ca23dSTom Caputi
355*a60ca23dSTom Caputi#
356*a60ca23dSTom Caputi# Load scsi_debug module with specified parameters
357*a60ca23dSTom Caputi# $blksz can be either one of: < 512b | 512e | 4Kn >
358*a60ca23dSTom Caputi#
359*a60ca23dSTom Caputifunction load_scsi_debug # dev_size_mb add_host num_tgts max_luns blksz
360*a60ca23dSTom Caputi{
361*a60ca23dSTom Caputi	typeset devsize=$1
362*a60ca23dSTom Caputi	typeset hosts=$2
363*a60ca23dSTom Caputi	typeset tgts=$3
364*a60ca23dSTom Caputi	typeset luns=$4
365*a60ca23dSTom Caputi	typeset blksz=$5
366*a60ca23dSTom Caputi
367*a60ca23dSTom Caputi	[[ -z $devsize ]] || [[ -z $hosts ]] || [[ -z $tgts ]] || \
368*a60ca23dSTom Caputi	    [[ -z $luns ]] || [[ -z $blksz ]] && \
369*a60ca23dSTom Caputi	    log_fail "Arguments invalid or missing"
370*a60ca23dSTom Caputi
371*a60ca23dSTom Caputi	case "$5" in
372*a60ca23dSTom Caputi		'512b')
373*a60ca23dSTom Caputi			typeset sector=512
374*a60ca23dSTom Caputi			typeset blkexp=0
375*a60ca23dSTom Caputi		;;
376*a60ca23dSTom Caputi		'512e')
377*a60ca23dSTom Caputi			typeset sector=512
378*a60ca23dSTom Caputi			typeset blkexp=3
379*a60ca23dSTom Caputi		;;
380*a60ca23dSTom Caputi		'4Kn')
381*a60ca23dSTom Caputi			typeset sector=4096
382*a60ca23dSTom Caputi			typeset blkexp=0
383*a60ca23dSTom Caputi		;;
384*a60ca23dSTom Caputi		*) log_fail "Unsupported blksz value: $5" ;;
385*a60ca23dSTom Caputi	esac
386*a60ca23dSTom Caputi
387*a60ca23dSTom Caputi	if is_linux; then
388*a60ca23dSTom Caputi		modprobe -n scsi_debug
389*a60ca23dSTom Caputi		if (($? != 0)); then
390*a60ca23dSTom Caputi			log_unsupported "Platform does not have scsi_debug"
391*a60ca23dSTom Caputi			    "module"
392*a60ca23dSTom Caputi		fi
393*a60ca23dSTom Caputi		lsmod | egrep scsi_debug > /dev/null
394*a60ca23dSTom Caputi		if (($? == 0)); then
395*a60ca23dSTom Caputi			log_fail "scsi_debug module already installed"
396*a60ca23dSTom Caputi		else
397*a60ca23dSTom Caputi			log_must modprobe scsi_debug dev_size_mb=$devsize \
398*a60ca23dSTom Caputi			    add_host=$hosts num_tgts=$tgts max_luns=$luns \
399*a60ca23dSTom Caputi			    sector_size=$sector physblk_exp=$blkexp
400*a60ca23dSTom Caputi			block_device_wait
401*a60ca23dSTom Caputi			lsscsi | egrep scsi_debug > /dev/null
402*a60ca23dSTom Caputi			if (($? == 1)); then
403*a60ca23dSTom Caputi				log_fail "scsi_debug module install failed"
404*a60ca23dSTom Caputi			fi
405*a60ca23dSTom Caputi		fi
406*a60ca23dSTom Caputi	fi
407*a60ca23dSTom Caputi}
408*a60ca23dSTom Caputi
409*a60ca23dSTom Caputi#
410*a60ca23dSTom Caputi# Unload scsi_debug module, if needed.
411*a60ca23dSTom Caputi#
412*a60ca23dSTom Caputifunction unload_scsi_debug
413*a60ca23dSTom Caputi{
414*a60ca23dSTom Caputi	log_must_retry "in use" 5 modprobe -r scsi_debug
415*a60ca23dSTom Caputi}
416*a60ca23dSTom Caputi
417*a60ca23dSTom Caputi#
418*a60ca23dSTom Caputi# Get scsi_debug device name.
419*a60ca23dSTom Caputi# Returns basename of scsi_debug device (for example "sdb").
420*a60ca23dSTom Caputi#
421*a60ca23dSTom Caputifunction get_debug_device
422*a60ca23dSTom Caputi{
423*a60ca23dSTom Caputi	for i in {1..10} ; do
424*a60ca23dSTom Caputi		val=$(lsscsi | nawk '/scsi_debug/ {print $6; exit}' | cut -d / -f3)
425*a60ca23dSTom Caputi
426*a60ca23dSTom Caputi		# lsscsi can take time to settle
427*a60ca23dSTom Caputi		if [ "$val" != "-" ] ; then
428*a60ca23dSTom Caputi			break
429*a60ca23dSTom Caputi		fi
430*a60ca23dSTom Caputi		sleep 1
431*a60ca23dSTom Caputi	done
432*a60ca23dSTom Caputi	echo "$val"
433*a60ca23dSTom Caputi}
434*a60ca23dSTom Caputi
435*a60ca23dSTom Caputi#
436*a60ca23dSTom Caputi# Get actual devices used by the pool (i.e. linux sdb1 not sdb).
437*a60ca23dSTom Caputi#
438*a60ca23dSTom Caputifunction get_pool_devices #testpool #devdir
439*a60ca23dSTom Caputi{
440*a60ca23dSTom Caputi	typeset testpool=$1
441*a60ca23dSTom Caputi	typeset devdir=$2
442*a60ca23dSTom Caputi	typeset out=""
443*a60ca23dSTom Caputi
444*a60ca23dSTom Caputi	if is_linux; then
445*a60ca23dSTom Caputi		out=$(zpool status -P $testpool |grep ${devdir} | awk '{print $1}')
446*a60ca23dSTom Caputi		out=$(echo $out | sed -e "s|${devdir}/||g" | tr '\n' ' ')
447*a60ca23dSTom Caputi	fi
448*a60ca23dSTom Caputi	echo $out
449*a60ca23dSTom Caputi}