1# SPDX-License-Identifier: BSD-2-Clause 2# 3# Copyright (c) 2026 voidanix <voidanix@FreeBSD.org> 4# 5 6MD_DEV_FILE="md.dev" 7 8alloc_zoned_md() 9{ 10 atf_check truncate -s 1025m backing_file 11 md=$(mdconfig -a -t vnode -f backing_file) || \ 12 atf_fail "mdconfig -a failed" 13 echo ${md} > $MD_DEV_FILE 14} 15 16# Print the number of zones matching a report option. 17zone_count() 18{ 19 zonectl -d /dev/${md}.zoned -c rz -o $1 -P summary | \ 20 awk '/zones,/ {print $1}' 21} 22 23zoned_md_cleanup() 24{ 25 if [ -f "$MD_DEV_FILE" ]; then 26 read md < $MD_DEV_FILE 27 [ -c /dev/${md}.zoned ] && \ 28 gzoned destroy ${md}.zoned 2>/dev/null 29 mdconfig -d -u ${md} 2>/dev/null 30 fi 31 true 32} 33 34atf_test_case report_filter cleanup 35report_filter_head() 36{ 37 atf_set "descr" "zonectl -o only reports zones matching the filter" 38 atf_set "require.user" "root" 39 atf_set "require.kmods" "g_md g_zoned" 40} 41report_filter_body() 42{ 43 alloc_zoned_md 44 atf_check gzoned create -s 256m -c 0-1 ${md} 45 46 atf_check_equal "2" \ 47 "$(zonectl -d /dev/${md}.zoned -c rz -o nonwp -P summary | \ 48 awk '/zones,/ {print $1}')" 49 atf_check_equal "2" \ 50 "$(zonectl -d /dev/${md}.zoned -c rz -o empty -P summary | \ 51 awk '/zones,/ {print $1}')" 52 atf_check_equal "0" \ 53 "$(zonectl -d /dev/${md}.zoned -c rz -o full -P summary | \ 54 awk '/zones,/ {print $1}')" 55} 56report_filter_cleanup() 57{ 58 zoned_md_cleanup 59} 60 61atf_test_case report_zones cleanup 62report_zones_head() 63{ 64 atf_set "descr" "zonectl -c rz reports every zone" 65 atf_set "require.user" "root" 66 atf_set "require.kmods" "g_md g_zoned" 67} 68report_zones_body() 69{ 70 alloc_zoned_md 71 atf_check gzoned create -s 256m ${md} 72 atf_check -o match:"^4 zones," \ 73 zonectl -d /dev/${md}.zoned -c rz -P summary 74 atf_check_equal "4" \ 75 "$(zonectl -d /dev/${md}.zoned -c rz -P script | \ 76 awk 'END {print NR}')" 77} 78report_zones_cleanup() 79{ 80 zoned_md_cleanup 81} 82 83atf_test_case report_starting_lba cleanup 84report_starting_lba_head() 85{ 86 atf_set "descr" "zonectl -c rz -l reports zones from a starting LBA" 87 atf_set "require.user" "root" 88 atf_set "require.kmods" "g_md g_zoned" 89} 90report_starting_lba_body() 91{ 92 alloc_zoned_md 93 atf_check gzoned create -s 256m ${md} 94 # Only zones 2 and 3 lie at or past LBA 0x100000 (512m). 95 atf_check_equal "2" \ 96 "$(zonectl -d /dev/${md}.zoned -c rz -l 0x100000 -P summary | \ 97 awk '/zones,/ {print $1}')" 98 atf_check_equal "0x100000" \ 99 "$(zonectl -d /dev/${md}.zoned -c rz -l 0x100000 -P script | \ 100 awk -F',' 'NR == 1 {gsub(/ /, "", $1); print $1}')" 101} 102report_starting_lba_cleanup() 103{ 104 zoned_md_cleanup 105} 106 107atf_test_case report_params cleanup 108report_params_head() 109{ 110 atf_set "descr" "zonectl -c params reports the device parameters" 111 atf_set "require.user" "root" 112 atf_set "require.kmods" "g_md g_zoned" 113} 114report_params_body() 115{ 116 alloc_zoned_md 117 atf_check gzoned create -s 256m -m 3 ${md} 118 atf_check -o match:"Zone Mode: Host Managed" \ 119 -o match:"URSWRZ.*: Yes" \ 120 -o match:"Open Sequential Write Required Zones: 3" \ 121 zonectl -d /dev/${md}.zoned -c params 122} 123report_params_cleanup() 124{ 125 zoned_md_cleanup 126} 127 128atf_test_case open_zone cleanup 129open_zone_head() 130{ 131 atf_set "descr" "zonectl -c open explicitly opens a zone" 132 atf_set "require.user" "root" 133 atf_set "require.kmods" "g_md g_zoned" 134} 135open_zone_body() 136{ 137 alloc_zoned_md 138 atf_check gzoned create -s 256m ${md} 139 atf_check zonectl -d /dev/${md}.zoned -c open -l 0 140 atf_check_equal "1" "$(zone_count exp_open)" 141} 142open_zone_cleanup() 143{ 144 zoned_md_cleanup 145} 146 147atf_test_case close_zone cleanup 148close_zone_head() 149{ 150 atf_set "descr" "zonectl -c close closes an open zone" 151 atf_set "require.user" "root" 152 atf_set "require.kmods" "g_md g_zoned" 153} 154close_zone_body() 155{ 156 alloc_zoned_md 157 atf_check gzoned create -s 256m ${md} 158 atf_check -e ignore dd if=/dev/zero of=/dev/${md}.zoned bs=1m count=1 159 atf_check_equal "1" "$(zone_count imp_open)" 160 atf_check zonectl -d /dev/${md}.zoned -c close -l 0 161 atf_check_equal "1" "$(zone_count closed)" 162 atf_check_equal "0" "$(zone_count imp_open)" 163} 164close_zone_cleanup() 165{ 166 zoned_md_cleanup 167} 168 169atf_test_case finish_zone cleanup 170finish_zone_head() 171{ 172 atf_set "descr" "zonectl -c finish transitions a zone to full" 173 atf_set "require.user" "root" 174 atf_set "require.kmods" "g_md g_zoned" 175} 176finish_zone_body() 177{ 178 alloc_zoned_md 179 atf_check gzoned create -s 256m ${md} 180 atf_check -e ignore dd if=/dev/zero of=/dev/${md}.zoned bs=1m count=1 181 atf_check zonectl -d /dev/${md}.zoned -c finish -l 0 182 atf_check_equal "1" "$(zone_count full)" 183} 184finish_zone_cleanup() 185{ 186 zoned_md_cleanup 187} 188 189atf_test_case zone_state_handling cleanup 190zone_state_handling_head() 191{ 192 atf_set "descr" \ 193 "zone commands follow ZBC spec outside their transition states" 194 atf_set "require.user" "root" 195 atf_set "require.kmods" "g_md g_zoned" 196} 197zone_state_handling_body() 198{ 199 alloc_zoned_md 200 atf_check gzoned create -s 256m -c 0 ${md} 201 202 # Explicitly targeting a conventional zone is the caller's error. 203 atf_check -s not-exit:0 -e ignore \ 204 zonectl -d /dev/${md}.zoned -c finish -l 0 205 # Closing an empty zone is a no-op. 206 atf_check zonectl -d /dev/${md}.zoned -c close -l 0x80000 207 atf_check_equal "3" "$(zone_count empty)" 208 # So is opening a full zone: it must stay full. 209 atf_check zonectl -d /dev/${md}.zoned -c finish -l 0x100000 210 atf_check zonectl -d /dev/${md}.zoned -c open -l 0x100000 211 atf_check_equal "1" "$(zone_count full)" 212 atf_check_equal "0" "$(zone_count exp_open)" 213} 214zone_state_handling_cleanup() 215{ 216 zoned_md_cleanup 217} 218 219atf_init_test_cases() 220{ 221 atf_add_test_case report_filter 222 atf_add_test_case report_zones 223 atf_add_test_case report_starting_lba 224 atf_add_test_case report_params 225 atf_add_test_case open_zone 226 atf_add_test_case close_zone 227 atf_add_test_case finish_zone 228 atf_add_test_case zone_state_handling 229} 230