xref: /freebsd/tests/sys/cam/ctl/persist.sh (revision ece617cda6b5999e6e57c2227f98c18c1ca1d79d)
1# SPDX-License-Identifier: BSD-2-Clause
2#
3# Copyright (c) 2024 ConnectWise
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS DOCUMENTATION IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26. $(atf_get_srcdir)/ctl.subr
27
28# TODO
29# * PRIN READ RESERVATION, with one reservation
30# * PROUT with illegal type
31# * PROUT REGISTER AND IGNORE EXISTING KEY
32# * PROUT REGISTER AND IGNORE EXISTING KEY with a RESERVATION KEY that isn't registered
33# * PROUT REGISTER AND IGNORE EXISTING KEY to unregister
34# * PROUT CLEAR allows previously prevented medium removal
35# * PROUT PREEMPT
36# * PROUT PREEMPT with a RESERVATION KEY that isn't registered
37# * PROUT PREEMPT_AND_ABORT
38# * PROUT PREEMPT_AND_ABORT with a RESERVATION KEY that isn't registered
39# * PROUT REGISTER AND MOVE
40# * PROUT REGISTER AND MOVE with a RESERVATION KEY that isn't registered
41# * multiple initiators
42
43# Not Tested
44# * PROUT REPLACE LOST RESERVATION (not supported by ctl)
45# * Specify Initiator Ports bit (not supported by ctl)
46# * Activate Persist Through Power Loss bit (not supported by ctl)
47# * All Target Ports bit (not supported by ctl)
48
49RESERVATION_KEY=0xdeadbeef1a7ebabe
50
51atf_test_case prin_read_full_status_empty cleanup
52prin_read_full_status_empty_head()
53{
54	atf_set "descr" "PERSISTENT RESERVATION IN with the READ FULL STATUS service action, with no status descriptors"
55	atf_set "require.user" "root"
56	atf_set "require.progs" sg_persist ctladm
57}
58prin_read_full_status_empty_body()
59{
60	create_ramdisk
61
62	atf_check -o match:"No full status descriptors" sg_persist -ns /dev/$dev
63}
64prin_read_full_status_empty_cleanup()
65{
66	cleanup
67}
68
69atf_test_case prin_read_keys_empty cleanup
70prin_read_keys_empty_head()
71{
72	atf_set "descr" "PERSISTENT RESERVATION IN with the READ KEYS service action, with no registered keys"
73	atf_set "require.user" "root"
74	atf_set "require.progs" sg_persist ctladm
75}
76prin_read_keys_empty_body()
77{
78	create_ramdisk
79
80	atf_check -o match:"there are NO registered reservation keys" sg_persist -nk /dev/$dev
81}
82prin_read_keys_empty_cleanup()
83{
84	cleanup
85}
86
87atf_test_case prin_read_reservation_empty cleanup
88prin_read_reservation_empty_head()
89{
90	atf_set "descr" "PERSISTENT RESERVATION IN with the READ RESERVATION service action, with no reservations"
91	atf_set "require.user" "root"
92	atf_set "require.progs" sg_persist ctladm
93}
94prin_read_reservation_empty_body()
95{
96	create_ramdisk
97
98	atf_check -o match:"there is NO reservation held" sg_persist -nr /dev/$dev
99}
100prin_read_reservation_empty_cleanup()
101{
102	cleanup
103}
104
105atf_test_case prin_report_capabilities cleanup
106prin_report_capabilities_head()
107{
108	atf_set "descr" "PERSISTENT RESERVATION IN with the REPORT CAPABILITIES service action"
109	atf_set "require.user" "root"
110	atf_set "require.progs" sg_persist ctladm
111}
112prin_report_capabilities_body()
113{
114	create_ramdisk
115
116	cat > expected <<HERE
117Report capabilities response:
118  Replace Lost Reservation Capable(RLR_C): 0
119  Compatible Reservation Handling(CRH): 1
120  Specify Initiator Ports Capable(SIP_C): 0
121  All Target Ports Capable(ATP_C): 0
122  Persist Through Power Loss Capable(PTPL_C): 0
123  Type Mask Valid(TMV): 1
124  Allow Commands: 5
125  Persist Through Power Loss Active(PTPL_A): 0
126    Support indicated in Type mask:
127      Write Exclusive, all registrants: 1
128      Exclusive Access, registrants only: 1
129      Write Exclusive, registrants only: 1
130      Exclusive Access: 1
131      Write Exclusive: 1
132      Exclusive Access, all registrants: 1
133HERE
134	atf_check -o file:expected sg_persist -nc /dev/$dev
135}
136prin_report_capabilities_cleanup()
137{
138	cleanup
139}
140
141atf_test_case prout_clear cleanup
142prout_clear_head()
143{
144	atf_set "descr" "PERSISTENT RESERVATION OUT with the CLEAR service action"
145	atf_set "require.user" "root"
146	atf_set "require.progs" sg_persist ctladm
147}
148prout_clear_body()
149{
150	create_ramdisk
151
152	# First register a key
153	atf_check sg_persist -n --out --param-rk=0 --param-sark=$RESERVATION_KEY -G /dev/$dev
154
155	# Then make a reservation using that key
156	atf_check sg_persist -n --out --param-rk=$RESERVATION_KEY --reserve --prout-type=8 /dev/$dev
157
158	# Now, clear all reservations and registrations
159	atf_check sg_persist -n --out --param-rk=$RESERVATION_KEY --clear /dev/$dev
160
161	# Finally, check that all reservations and keys are gone
162	atf_check -o match:"there is NO reservation held" sg_persist -nr /dev/$dev
163	atf_check -o match:"there are NO registered reservation keys" sg_persist -nk /dev/$dev
164}
165prout_clear_cleanup()
166{
167	cleanup
168}
169
170
171atf_test_case prout_register cleanup
172prout_register_head()
173{
174	atf_set "descr" "PERSISTENT RESERVATION OUT with the REGISTER service action"
175	atf_set "require.user" "root"
176	atf_set "require.progs" sg_persist ctladm
177}
178prout_register_body()
179{
180	create_ramdisk
181	atf_check sg_persist -n --out --param-rk=0 --param-sark=$RESERVATION_KEY -G /dev/$dev
182	atf_check -o match:$RESERVATION_KEY sg_persist -nk /dev/$dev
183}
184prout_register_cleanup()
185{
186	cleanup
187}
188
189atf_test_case prout_register_duplicate cleanup
190prout_register_duplicate_head()
191{
192	atf_set "descr" "attempting to register a key twice should fail"
193	atf_set "require.user" "root"
194	atf_set "require.progs" sg_persist ctladm
195}
196prout_register_duplicate_body()
197{
198	create_ramdisk
199	atf_check sg_persist -n --out --param-rk=0 --param-sark=$RESERVATION_KEY -G /dev/$dev
200	atf_check -s exit:24 -e match:"Reservation conflict" sg_persist -n --out --param-rk=0 --param-sark=$RESERVATION_KEY -G /dev/$dev
201	atf_check -o match:$RESERVATION_KEY sg_persist -nk /dev/$dev
202}
203prout_register_duplicate_cleanup()
204{
205	cleanup
206}
207
208atf_test_case prout_register_huge_cdb cleanup
209prout_register_huge_cdb_head()
210{
211	atf_set "descr" "PERSISTENT RESERVATION OUT with an enormous CDB size should not cause trouble"
212	atf_set "require.user" "root"
213	atf_set "require.progs" sg_persist ctladm
214}
215prout_register_huge_cdb_body()
216{
217	create_ramdisk
218
219	atf_check -s exit:1 $(atf_get_srcdir)/prout_register_huge_cdb $LUN
220}
221prout_register_huge_cdb_cleanup()
222{
223	cleanup
224}
225
226atf_test_case prout_register_unregister cleanup
227prout_register_unregister_head()
228{
229	atf_set "descr" "use PERSISTENT RESERVATION OUT with the REGISTER service action to remove a prior registration"
230	atf_set "require.user" "root"
231	atf_set "require.progs" sg_persist ctladm
232}
233prout_register_unregister_body()
234{
235	create_ramdisk
236	# First register a key
237	atf_check sg_persist -n --out --param-rk=0 --param-sark=$RESERVATION_KEY -G /dev/$dev
238	# Then unregister it
239	atf_check sg_persist -n --out --param-sark=0 --param-rk=$RESERVATION_KEY -G /dev/$dev
240	# Finally, check that no keys are registered
241	atf_check -o match:"there are NO registered reservation keys" sg_persist -nk /dev/$dev
242}
243prout_register_unregister_cleanup()
244{
245	cleanup
246}
247
248atf_test_case prout_release cleanup
249prout_release_head()
250{
251	atf_set "descr" "PERSISTENT RESERVATION OUT with the RESERVE service action"
252	atf_set "require.user" "root"
253	atf_set "require.progs" sg_persist ctladm
254}
255prout_release_body()
256{
257	create_ramdisk
258
259	# First register a key
260	atf_check sg_persist -n --out --param-rk=0 --param-sark=$RESERVATION_KEY -G /dev/$dev
261
262	# Then make a reservation using that key
263	atf_check sg_persist -n --out --param-rk=$RESERVATION_KEY --reserve --prout-type=8 /dev/$dev
264	atf_check sg_persist -n --out --param-rk=$RESERVATION_KEY --prout-type=8 --release /dev/$dev
265
266	# Now check that the reservation is released
267	atf_check -o match:"there is NO reservation held" sg_persist -nr /dev/$dev
268	# But the registration shouldn't be.
269	atf_check -o match:$RESERVATION_KEY sg_persist -nk /dev/$dev
270}
271prout_release_cleanup()
272{
273	cleanup
274}
275
276
277atf_test_case prout_reserve cleanup
278prout_reserve_head()
279{
280	atf_set "descr" "PERSISTENT RESERVATION OUT with the RESERVE service action"
281	atf_set "require.user" "root"
282	atf_set "require.progs" sg_persist ctladm
283}
284prout_reserve_body()
285{
286	create_ramdisk
287	# First register a key
288	atf_check sg_persist -n --out --param-rk=0 --param-sark=$RESERVATION_KEY -G /dev/$dev
289	# Then make a reservation using that key
290	atf_check sg_persist -n --out --param-rk=$RESERVATION_KEY --reserve --prout-type=8 /dev/$dev
291	# Finally, check that the reservation is correct
292	cat > expected <<HERE
293  PR generation=0x1
294    Key=0xdeadbeef1a7ebabe
295      All target ports bit clear
296      Relative port address: 0x0
297      << Reservation holder >>
298      scope: LU_SCOPE,  type: Exclusive Access, all registrants
299      Transport Id of initiator:
300        Parallel SCSI initiator SCSI address: 0x1
301        relative port number (of corresponding target): 0x0
302HERE
303	atf_check -o file:expected sg_persist -ns /dev/$dev
304}
305prout_reserve_cleanup()
306{
307	cleanup
308}
309
310atf_test_case prout_reserve_bad_scope cleanup
311prout_reserve_bad_scope_head()
312{
313	atf_set "descr" "PERSISTENT RESERVATION OUT will be rejected with an unknown scope field"
314	atf_set "require.user" "root"
315	atf_set "require.progs" sg_persist camcontrol ctladm
316}
317prout_reserve_bad_scope_body()
318{
319	create_ramdisk
320	# First register a key
321	atf_check sg_persist -n --out --param-rk=0 --param-sark=$RESERVATION_KEY -G /dev/$dev
322
323	# Then make a reservation using that key
324	atf_check -s exit:1 -e match:"ILLEGAL REQUEST asc:24,0 .Invalid field in CDB." camcontrol persist $dev -o reserve -k $RESERVATION_KEY -T read_shared -s 15 -v
325
326	# Finally, check that nothing has been reserved
327	atf_check -o match:"there is NO reservation held" sg_persist -nr /dev/$dev
328}
329prout_reserve_bad_scope_cleanup()
330{
331	cleanup
332}
333
334
335atf_init_test_cases()
336{
337	atf_add_test_case prin_read_full_status_empty
338	atf_add_test_case prin_read_keys_empty
339	atf_add_test_case prin_read_reservation_empty
340	atf_add_test_case prin_report_capabilities
341	atf_add_test_case prout_clear
342	atf_add_test_case prout_register
343	atf_add_test_case prout_register_duplicate
344	atf_add_test_case prout_register_huge_cdb
345	atf_add_test_case prout_register_unregister
346	atf_add_test_case prout_release
347	atf_add_test_case prout_reserve
348	atf_add_test_case prout_reserve_bad_scope
349}
350