1#!/bin/ksh -p
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 http://www.opensolaris.org/os/licensing.
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 <[email protected]>. 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. $STF_SUITE/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib
31
32#
33# DESCRIPTION:
34# Verify that ZFS volume property "volmode" works as intended.
35#
36# STRATEGY:
37# 1. Verify "volmode" property does not accept invalid values
38# 2. Verify "volmode=none" hides ZVOL device nodes
39# 3. Verify "volmode=full" exposes a fully functional device
40# 4. Verify "volmode=dev" hides partition info on the device
41# 5. Verify "volmode=default" behaves accordingly to "volmode" module parameter
42# 6. Verify "volmode" property is inherited correctly
43# 7. Verify "volmode" behaves correctly at import time
44# 8. Verify "volmode" behaves accordingly to zvol_inhibit_dev (Linux only)
45#
46# NOTE: changing volmode may need to remove minors, which could be open, so call
47#       udev_wait() before we "zfs set volmode=<value>".
48
49verify_runnable "global"
50
51function cleanup
52{
53	datasetexists $VOLFS && log_must_busy zfs destroy -r $VOLFS
54	datasetexists $ZVOL && log_must_busy zfs destroy -r $ZVOL
55	log_must zfs inherit volmode $TESTPOOL
56	udev_wait
57	sysctl_inhibit_dev 0
58	sysctl_volmode 1
59	udev_cleanup
60}
61
62#
63# Set zvol_inhibit_dev tunable to $value
64#
65function sysctl_inhibit_dev # value
66{
67	typeset value="$1"
68
69	if is_linux; then
70		log_note "Setting zvol_inhibit_dev tunable to $value"
71		log_must set_tunable32 VOL_INHIBIT_DEV $value
72	fi
73}
74
75#
76# Set volmode tunable to $value
77#
78function sysctl_volmode # value
79{
80	typeset value="$1"
81
82	log_note "Setting volmode tunable to $value"
83	log_must set_tunable32 VOL_MODE $value
84}
85
86#
87# Exercise open and close, read and write operations
88#
89function test_io # dev
90{
91	typeset dev=$1
92
93	log_must dd if=/dev/zero of=$dev count=1
94	log_must dd if=$dev of=/dev/null count=1
95}
96
97log_assert "Verify that ZFS volume property 'volmode' works as intended"
98log_onexit cleanup
99
100VOLFS="$TESTPOOL/volfs"
101ZVOL="$TESTPOOL/vol"
102ZDEV="${ZVOL_DEVDIR}/$ZVOL"
103SUBZVOL="$VOLFS/subvol"
104SUBZDEV="${ZVOL_DEVDIR}/$SUBZVOL"
105
106log_must zfs create -o mountpoint=none $VOLFS
107log_must zfs create -V $VOLSIZE -s $SUBZVOL
108log_must zfs create -V $VOLSIZE -s $ZVOL
109udev_wait
110test_io $ZDEV
111test_io $SUBZDEV
112
113# 1. Verify "volmode" property does not accept invalid values
114typeset badvals=("off" "on" "1" "nope" "-")
115for badval in ${badvals[@]}
116do
117	log_mustnot zfs set volmode="$badval" $ZVOL
118done
119
120# 2. Verify "volmode=none" hides ZVOL device nodes
121log_must zfs set volmode=none $ZVOL
122blockdev_missing $ZDEV
123log_must_busy zfs destroy $ZVOL
124
125# 3. Verify "volmode=full" exposes a fully functional device
126log_must zfs create -V $VOLSIZE -s $ZVOL
127udev_wait
128log_must zfs set volmode=full $ZVOL
129blockdev_exists $ZDEV
130test_io $ZDEV
131log_must verify_partition $ZDEV
132udev_wait
133# 3.1 Verify "volmode=geom" is an alias for "volmode=full"
134log_must zfs set volmode=geom $ZVOL
135blockdev_exists $ZDEV
136if [[ "$(get_prop 'volmode' $ZVOL)" != "full" ]]; then
137	log_fail " Volmode value 'geom' is not an alias for 'full'"
138fi
139udev_wait
140log_must_busy zfs destroy $ZVOL
141
142# 4. Verify "volmode=dev" hides partition info on the device
143log_must zfs create -V $VOLSIZE -s $ZVOL
144udev_wait
145log_must zfs set volmode=dev $ZVOL
146blockdev_exists $ZDEV
147test_io $ZDEV
148log_mustnot verify_partition $ZDEV
149udev_wait
150log_must_busy zfs destroy $ZVOL
151
152# 5. Verify "volmode=default" behaves accordingly to "volmode" module parameter
153# 5.1 Verify sysctl "volmode=full"
154sysctl_volmode 1
155log_must zfs create -V $VOLSIZE -s $ZVOL
156udev_wait
157log_must zfs set volmode=default $ZVOL
158blockdev_exists $ZDEV
159log_must verify_partition $ZDEV
160udev_wait
161log_must_busy zfs destroy $ZVOL
162# 5.2 Verify sysctl "volmode=dev"
163sysctl_volmode 2
164log_must zfs create -V $VOLSIZE -s $ZVOL
165udev_wait
166log_must zfs set volmode=default $ZVOL
167blockdev_exists $ZDEV
168log_mustnot verify_partition $ZDEV
169udev_wait
170log_must_busy zfs destroy $ZVOL
171# 5.2 Verify sysctl "volmode=none"
172sysctl_volmode 3
173log_must zfs create -V $VOLSIZE -s $ZVOL
174udev_wait
175log_must zfs set volmode=default $ZVOL
176blockdev_missing $ZDEV
177
178# 6. Verify "volmode" property is inherited correctly
179log_must zfs inherit volmode $ZVOL
180# 6.1 Check volmode=full case
181log_must zfs set volmode=full $TESTPOOL
182verify_inherited 'volmode' 'full' $ZVOL $TESTPOOL
183blockdev_exists $ZDEV
184# 6.2 Check volmode=none case
185log_must zfs set volmode=none $TESTPOOL
186verify_inherited 'volmode' 'none' $ZVOL $TESTPOOL
187blockdev_missing $ZDEV
188# 6.3 Check volmode=dev case
189log_must zfs set volmode=dev $TESTPOOL
190verify_inherited 'volmode' 'dev' $ZVOL $TESTPOOL
191blockdev_exists $ZDEV
192# 6.4 Check volmode=default case
193sysctl_volmode 1
194log_must zfs set volmode=default $TESTPOOL
195verify_inherited 'volmode' 'default' $ZVOL $TESTPOOL
196blockdev_exists $ZDEV
197# 6.5 Check inheritance on multiple levels
198log_must zfs inherit volmode $SUBZVOL
199udev_wait
200log_must zfs set volmode=none $VOLFS
201udev_wait
202log_must zfs set volmode=full $TESTPOOL
203verify_inherited 'volmode' 'none' $SUBZVOL $VOLFS
204blockdev_missing $SUBZDEV
205blockdev_exists $ZDEV
206
207# 7. Verify "volmode" behaves correctly at import time
208log_must zpool export $TESTPOOL
209blockdev_missing $ZDEV
210blockdev_missing $SUBZDEV
211log_must zpool import $TESTPOOL
212blockdev_exists $ZDEV
213blockdev_missing $SUBZDEV
214log_must_busy zfs destroy $ZVOL
215log_must_busy zfs destroy $SUBZVOL
216
217# 8. Verify "volmode" behaves accordingly to zvol_inhibit_dev (Linux only)
218if is_linux; then
219	sysctl_inhibit_dev 1
220	# 7.1 Verify device nodes not are not created with "volmode=full"
221	sysctl_volmode 1
222	log_must zfs create -V $VOLSIZE -s $ZVOL
223	blockdev_missing $ZDEV
224	log_must zfs set volmode=full $ZVOL
225	blockdev_missing $ZDEV
226	log_must_busy zfs destroy $ZVOL
227	# 7.1 Verify device nodes not are not created with "volmode=dev"
228	sysctl_volmode 2
229	log_must zfs create -V $VOLSIZE -s $ZVOL
230	blockdev_missing $ZDEV
231	log_must zfs set volmode=dev $ZVOL
232	blockdev_missing $ZDEV
233	log_must_busy zfs destroy $ZVOL
234	# 7.1 Verify device nodes not are not created with "volmode=none"
235	sysctl_volmode 3
236	log_must zfs create -V $VOLSIZE -s $ZVOL
237	blockdev_missing $ZDEV
238	log_must zfs set volmode=none $ZVOL
239	blockdev_missing $ZDEV
240fi
241
242log_pass "Verify that ZFS volume property 'volmode' works as intended"
243