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