xref: /freebsd/sys/contrib/openzfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
1# SPDX-License-Identifier: CDDL-1.0
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or https://opensource.org/licenses/CDDL-1.0.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22
23#
24# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
25#
26
27. $STF_SUITE/include/libtest.shlib
28. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
29. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
30
31#
32# Wait for udev to settle, completely.
33# This is quite discomforting, but there's a race condition here
34# (Amazon 2015.09 x86_64 Release (TEST) is good at triggering this)  where the
35# kernel tries to remove zvol device nodes while they're open by [blkid],
36# [zvol_id] or other udev related processes.
37# Calling 'udevadm settle' is not enough: wait for those processes "manually".
38#
39function udev_wait
40{
41	udevadm trigger --action=change
42	udevadm settle
43	for i in {1..3}; do
44		blkid="$(pgrep blkid | wc -l)"
45		zvol_id="$(pgrep zvol_id | wc -l)"
46		[[ "0" == "$zvol_id" && "0" == "$blkid" ]] && return
47		udevadm settle
48	done
49	log_fail "Wait timeout reached for udev_wait"
50}
51
52#
53# Clean up udev status
54# This is also a problem on "Amazon 2015.09 x86_64 Release (TEST)" where udev,
55# sometimes, does not clean up /dev/zvol symlinks correctly for removed ZVOLs.
56# Prune those links manually, then tell udev to forget them.
57#
58function udev_cleanup
59{
60	log_note "Pruning broken ZVOL symlinks ..."
61
62	udevadm settle
63	# find all dangling links and delete them
64	find -L "${ZVOL_DEVDIR}" -type l -print -delete
65	# purge those links from udev database
66	udevadm info --cleanup-db
67}
68
69#
70# Verify $device exists and is a block device
71#
72function blockdev_exists # device
73{
74	typeset device="$1"
75
76	# we wait here instead of doing it in a wrapper around 'zfs set snapdev'
77	# because there are other commands (zfs snap, zfs inherit, zfs destroy)
78	# that can affect device nodes
79	for i in {1..3}; do
80		is_linux && udev_wait
81		block_device_wait "$device"
82		is_disk_device "$device" && return 0
83	done
84	log_fail "$device does not exist as a block device"
85}
86
87#
88# Verify $device does not exist
89#
90function blockdev_missing # device
91{
92	typeset device="$1"
93
94	# we wait here instead of doing it in a wrapper around 'zfs set snapdev'
95	# because there are other commands (zfs snap, zfs inherit, zfs destroy)
96	# that can affect device nodes
97	for i in {1..3}; do
98		is_linux && udev_wait
99		block_device_wait
100		is_disk_device "$device" || return 0
101	done
102	log_fail "$device exists when not expected"
103}
104
105#
106# Verify $property on $dataset is inherited by $parent and is set to $value
107#
108function verify_inherited # property value dataset parent
109{
110	typeset property="$1"
111	typeset value="$2"
112	typeset dataset="$3"
113	typeset parent="$4"
114
115	typeset val=$(get_prop "$property" "$dataset")
116	typeset src=$(get_source "$property" "$dataset")
117	if [[ "$val" != "$value" || "$src" != "inherited from $parent" ]]; then
118		log_fail "Dataset $dataset did not inherit $property properly:"\
119		    "expected=$value, value=$val, source=$src."
120	fi
121}
122
123#
124# Create a small partition on $device, then verify if we can access it
125#
126function verify_partition # device
127{
128	typeset device="$1"
129
130	if ! is_disk_device "$device"; then
131		log_fail "$device is not a block device"
132	fi
133	# create a small dummy partition
134	set_partition 0 "" 1m $device
135	# verify we can access the partition on the device
136	devname="$(readlink -f "$device")"
137	if is_linux || is_freebsd; then
138		is_disk_device "${devname}p1"
139	else
140		is_disk_device "${devname}s0"
141	fi
142}
143