1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2026 Western Digital. All rights reserved. 4 */ 5 6 #include <linux/cleanup.h> 7 #include <linux/sizes.h> 8 9 #include "btrfs-tests.h" 10 #include "../space-info.h" 11 #include "../volumes.h" 12 #include "../zoned.h" 13 14 #define WP_MISSING_DEV ((u64)-1) 15 #define WP_CONVENTIONAL ((u64)-2) 16 #define ZONE_SIZE SZ_256M 17 18 #define HALF_STRIPE_LEN (BTRFS_STRIPE_LEN >> 1) 19 20 struct load_zone_info_test_vector { 21 u64 raid_type; 22 u64 num_stripes; 23 u64 alloc_offsets[8]; 24 u64 last_alloc; 25 u64 bg_length; 26 bool degraded; 27 28 int expected_result; 29 u64 expected_alloc_offset; 30 31 const char *description; 32 }; 33 34 struct zone_info { 35 u64 physical; 36 u64 capacity; 37 u64 alloc_offset; 38 }; 39 40 static int test_load_zone_info(struct btrfs_fs_info *fs_info, 41 const struct load_zone_info_test_vector *test) 42 { 43 struct btrfs_block_group *bg __free(btrfs_free_dummy_block_group) = NULL; 44 struct btrfs_chunk_map *map __free(btrfs_free_chunk_map) = NULL; 45 struct zone_info AUTO_KFREE(zone_info); 46 unsigned long AUTO_KFREE(active); 47 int ret; 48 49 bg = btrfs_alloc_dummy_block_group(fs_info, test->bg_length); 50 if (!bg) { 51 test_std_err(TEST_ALLOC_BLOCK_GROUP); 52 return -ENOMEM; 53 } 54 55 map = btrfs_alloc_chunk_map(test->num_stripes, GFP_KERNEL); 56 if (!map) { 57 test_std_err(TEST_ALLOC_EXTENT_MAP); 58 return -ENOMEM; 59 } 60 61 zone_info = kzalloc_objs(*zone_info, test->num_stripes, GFP_KERNEL); 62 if (!zone_info) { 63 test_err("cannot allocate zone info"); 64 return -ENOMEM; 65 } 66 67 active = bitmap_zalloc(test->num_stripes, GFP_KERNEL); 68 if (!zone_info) { 69 test_err("cannot allocate active bitmap"); 70 return -ENOMEM; 71 } 72 73 map->type = test->raid_type; 74 map->num_stripes = test->num_stripes; 75 if (test->raid_type == BTRFS_BLOCK_GROUP_RAID10) 76 map->sub_stripes = 2; 77 for (int i = 0; i < test->num_stripes; i++) { 78 zone_info[i].physical = 0; 79 zone_info[i].alloc_offset = test->alloc_offsets[i]; 80 zone_info[i].capacity = ZONE_SIZE; 81 if (zone_info[i].alloc_offset && zone_info[i].alloc_offset < ZONE_SIZE) 82 __set_bit(i, active); 83 } 84 if (test->degraded) 85 btrfs_set_opt(fs_info->mount_opt, DEGRADED); 86 else 87 btrfs_clear_opt(fs_info->mount_opt, DEGRADED); 88 89 ret = btrfs_load_block_group_by_raid_type(bg, map, zone_info, active, 90 test->last_alloc); 91 92 if (ret != test->expected_result) { 93 test_err("unexpected return value: ret %d expected %d", ret, 94 test->expected_result); 95 return -EINVAL; 96 } 97 98 if (!ret && bg->alloc_offset != test->expected_alloc_offset) { 99 test_err("unexpected alloc_offset: alloc_offset %llu expected %llu", 100 bg->alloc_offset, test->expected_alloc_offset); 101 return -EINVAL; 102 } 103 104 return 0; 105 } 106 107 static const struct load_zone_info_test_vector load_zone_info_tests[] = { 108 /* SINGLE */ 109 { 110 .description = "SINGLE: load write pointer from sequential zone", 111 .raid_type = 0, 112 .num_stripes = 1, 113 .alloc_offsets = { 114 SZ_1M, 115 }, 116 .expected_alloc_offset = SZ_1M, 117 }, 118 /* 119 * SINGLE block group on a conventional zone sets last_alloc outside of 120 * btrfs_load_block_group_*(). Do not test that case. 121 */ 122 123 /* DUP */ 124 /* Normal case */ 125 { 126 .description = "DUP: having matching write pointers", 127 .raid_type = BTRFS_BLOCK_GROUP_DUP, 128 .num_stripes = 2, 129 .alloc_offsets = { 130 SZ_1M, SZ_1M, 131 }, 132 .expected_alloc_offset = SZ_1M, 133 }, 134 /* 135 * One sequential zone and one conventional zone, having matching 136 * last_alloc. 137 */ 138 { 139 .description = "DUP: seq zone and conv zone, matching last_alloc", 140 .raid_type = BTRFS_BLOCK_GROUP_DUP, 141 .num_stripes = 2, 142 .alloc_offsets = { 143 SZ_1M, WP_CONVENTIONAL, 144 }, 145 .last_alloc = SZ_1M, 146 .expected_alloc_offset = SZ_1M, 147 }, 148 /* 149 * One sequential and one conventional zone, but having smaller 150 * last_alloc than write pointer. 151 */ 152 { 153 .description = "DUP: seq zone and conv zone, smaller last_alloc", 154 .raid_type = BTRFS_BLOCK_GROUP_DUP, 155 .num_stripes = 2, 156 .alloc_offsets = { 157 SZ_1M, WP_CONVENTIONAL, 158 }, 159 .last_alloc = 0, 160 .expected_alloc_offset = SZ_1M, 161 }, 162 /* Error case: having different write pointers. */ 163 { 164 .description = "DUP: fail: different write pointers", 165 .raid_type = BTRFS_BLOCK_GROUP_DUP, 166 .num_stripes = 2, 167 .alloc_offsets = { 168 SZ_1M, SZ_2M, 169 }, 170 .expected_result = -EIO, 171 }, 172 /* Error case: partial missing device should not happen on DUP. */ 173 { 174 .description = "DUP: fail: missing device", 175 .raid_type = BTRFS_BLOCK_GROUP_DUP, 176 .num_stripes = 2, 177 .alloc_offsets = { 178 SZ_1M, WP_MISSING_DEV, 179 }, 180 .expected_result = -EIO, 181 }, 182 /* 183 * Error case: one sequential and one conventional zone, but having larger 184 * last_alloc than write pointer. 185 */ 186 { 187 .description = "DUP: fail: seq zone and conv zone, larger last_alloc", 188 .raid_type = BTRFS_BLOCK_GROUP_DUP, 189 .num_stripes = 2, 190 .alloc_offsets = { 191 SZ_1M, WP_CONVENTIONAL, 192 }, 193 .last_alloc = SZ_2M, 194 .expected_result = -EIO, 195 }, 196 197 /* RAID1 */ 198 /* Normal case */ 199 { 200 .description = "RAID1: having matching write pointers", 201 .raid_type = BTRFS_BLOCK_GROUP_RAID1, 202 .num_stripes = 2, 203 .alloc_offsets = { 204 SZ_1M, SZ_1M, 205 }, 206 .expected_alloc_offset = SZ_1M, 207 }, 208 /* 209 * One sequential zone and one conventional zone, having matching 210 * last_alloc. 211 */ 212 { 213 .description = "RAID1: seq zone and conv zone, matching last_alloc", 214 .raid_type = BTRFS_BLOCK_GROUP_RAID1, 215 .num_stripes = 2, 216 .alloc_offsets = { 217 SZ_1M, WP_CONVENTIONAL, 218 }, 219 .last_alloc = SZ_1M, 220 .expected_alloc_offset = SZ_1M, 221 }, 222 /* 223 * One sequential and one conventional zone, but having smaller 224 * last_alloc than write pointer. 225 */ 226 { 227 .description = "RAID1: seq zone and conv zone, smaller last_alloc", 228 .raid_type = BTRFS_BLOCK_GROUP_RAID1, 229 .num_stripes = 2, 230 .alloc_offsets = { 231 SZ_1M, WP_CONVENTIONAL, 232 }, 233 .last_alloc = 0, 234 .expected_alloc_offset = SZ_1M, 235 }, 236 /* Partial missing device should be recovered on DEGRADED mount */ 237 { 238 .description = "RAID1: fail: missing device on DEGRADED", 239 .raid_type = BTRFS_BLOCK_GROUP_RAID1, 240 .num_stripes = 2, 241 .alloc_offsets = { 242 SZ_1M, WP_MISSING_DEV, 243 }, 244 .degraded = true, 245 .expected_alloc_offset = SZ_1M, 246 }, 247 /* Error case: having different write pointers. */ 248 { 249 .description = "RAID1: fail: different write pointers", 250 .raid_type = BTRFS_BLOCK_GROUP_RAID1, 251 .num_stripes = 2, 252 .alloc_offsets = { 253 SZ_1M, SZ_2M, 254 }, 255 .expected_result = -EIO, 256 }, 257 /* 258 * Partial missing device is not allowed on non-DEGRADED mount never happen 259 * as it is rejected beforehand. 260 */ 261 /* 262 * Error case: one sequential and one conventional zone, but having larger 263 * last_alloc than write pointer. 264 */ 265 { 266 .description = "RAID1: fail: seq zone and conv zone, larger last_alloc", 267 .raid_type = BTRFS_BLOCK_GROUP_RAID1, 268 .num_stripes = 2, 269 .alloc_offsets = { 270 SZ_1M, WP_CONVENTIONAL, 271 }, 272 .last_alloc = SZ_2M, 273 .expected_result = -EIO, 274 }, 275 276 /* RAID0 */ 277 /* Normal case */ 278 { 279 .description = "RAID0: initial partial write", 280 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 281 .num_stripes = 4, 282 .alloc_offsets = { 283 HALF_STRIPE_LEN, 0, 0, 0, 284 }, 285 .expected_alloc_offset = HALF_STRIPE_LEN, 286 }, 287 { 288 .description = "RAID0: while in second stripe", 289 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 290 .num_stripes = 4, 291 .alloc_offsets = { 292 BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN + HALF_STRIPE_LEN, 293 BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 294 }, 295 .expected_alloc_offset = BTRFS_STRIPE_LEN * 5 + HALF_STRIPE_LEN, 296 }, 297 { 298 .description = "RAID0: one stripe advanced", 299 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 300 .num_stripes = 2, 301 .alloc_offsets = { 302 SZ_1M + BTRFS_STRIPE_LEN, SZ_1M, 303 }, 304 .expected_alloc_offset = SZ_2M + BTRFS_STRIPE_LEN, 305 }, 306 /* Error case: having different write pointers. */ 307 { 308 .description = "RAID0: fail: disordered stripes", 309 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 310 .num_stripes = 4, 311 .alloc_offsets = { 312 BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN * 2, 313 BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 314 }, 315 .expected_result = -EIO, 316 }, 317 { 318 .description = "RAID0: fail: far distance", 319 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 320 .num_stripes = 4, 321 .alloc_offsets = { 322 BTRFS_STRIPE_LEN * 3, BTRFS_STRIPE_LEN, 323 BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 324 }, 325 .expected_result = -EIO, 326 }, 327 { 328 .description = "RAID0: fail: too many partial write", 329 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 330 .num_stripes = 4, 331 .alloc_offsets = { 332 HALF_STRIPE_LEN, HALF_STRIPE_LEN, 0, 0, 333 }, 334 .expected_result = -EIO, 335 }, 336 /* 337 * Error case: Partial missing device is not allowed even on non-DEGRADED 338 * mount. 339 */ 340 { 341 .description = "RAID0: fail: missing device on DEGRADED", 342 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 343 .num_stripes = 2, 344 .alloc_offsets = { 345 SZ_1M, WP_MISSING_DEV, 346 }, 347 .degraded = true, 348 .expected_result = -EIO, 349 }, 350 351 /* 352 * One sequential zone and one conventional zone, having matching 353 * last_alloc. 354 */ 355 { 356 .description = "RAID0: seq zone and conv zone, partially written stripe", 357 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 358 .num_stripes = 2, 359 .alloc_offsets = { 360 SZ_1M, WP_CONVENTIONAL, 361 }, 362 .last_alloc = SZ_2M - SZ_4K, 363 .expected_alloc_offset = SZ_2M - SZ_4K, 364 }, 365 { 366 .description = "RAID0: conv zone and seq zone, partially written stripe", 367 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 368 .num_stripes = 2, 369 .alloc_offsets = { 370 WP_CONVENTIONAL, SZ_1M, 371 }, 372 .last_alloc = SZ_2M + SZ_4K, 373 .expected_alloc_offset = SZ_2M + SZ_4K, 374 }, 375 /* 376 * Error case: one sequential and one conventional zone, but having larger 377 * last_alloc than write pointer. 378 */ 379 { 380 .description = "RAID0: fail: seq zone and conv zone, larger last_alloc", 381 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 382 .num_stripes = 2, 383 .alloc_offsets = { 384 SZ_1M, WP_CONVENTIONAL, 385 }, 386 .last_alloc = SZ_2M + BTRFS_STRIPE_LEN * 2, 387 .expected_result = -EIO, 388 }, 389 390 /* RAID0, 4 stripes with seq zones and conv zones. */ 391 { 392 .description = "RAID0: stripes [2, 2, ?, ?] last_alloc = 6", 393 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 394 .num_stripes = 4, 395 .alloc_offsets = { 396 BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 397 WP_CONVENTIONAL, WP_CONVENTIONAL, 398 }, 399 .last_alloc = BTRFS_STRIPE_LEN * 6, 400 .expected_alloc_offset = BTRFS_STRIPE_LEN * 6, 401 }, 402 { 403 .description = "RAID0: stripes [2, 2, ?, ?] last_alloc = 7.5", 404 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 405 .num_stripes = 4, 406 .alloc_offsets = { 407 BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 408 WP_CONVENTIONAL, WP_CONVENTIONAL, 409 }, 410 .last_alloc = BTRFS_STRIPE_LEN * 7 + HALF_STRIPE_LEN, 411 .expected_alloc_offset = BTRFS_STRIPE_LEN * 7 + HALF_STRIPE_LEN, 412 }, 413 { 414 .description = "RAID0: stripes [3, ?, ?, ?] last_alloc = 1", 415 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 416 .num_stripes = 4, 417 .alloc_offsets = { 418 BTRFS_STRIPE_LEN * 3, WP_CONVENTIONAL, 419 WP_CONVENTIONAL, WP_CONVENTIONAL, 420 }, 421 .last_alloc = BTRFS_STRIPE_LEN, 422 .expected_alloc_offset = BTRFS_STRIPE_LEN * 9, 423 }, 424 { 425 .description = "RAID0: stripes [2, ?, 1, ?] last_alloc = 5", 426 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 427 .num_stripes = 4, 428 .alloc_offsets = { 429 BTRFS_STRIPE_LEN * 2, WP_CONVENTIONAL, 430 BTRFS_STRIPE_LEN, WP_CONVENTIONAL, 431 }, 432 .last_alloc = BTRFS_STRIPE_LEN * 5, 433 .expected_alloc_offset = BTRFS_STRIPE_LEN * 5, 434 }, 435 { 436 .description = "RAID0: fail: stripes [2, ?, 1, ?] last_alloc = 7", 437 .raid_type = BTRFS_BLOCK_GROUP_RAID0, 438 .num_stripes = 4, 439 .alloc_offsets = { 440 BTRFS_STRIPE_LEN * 2, WP_CONVENTIONAL, 441 BTRFS_STRIPE_LEN, WP_CONVENTIONAL, 442 }, 443 .last_alloc = BTRFS_STRIPE_LEN * 7, 444 .expected_result = -EIO, 445 }, 446 447 /* RAID10 */ 448 /* Normal case */ 449 { 450 .description = "RAID10: initial partial write", 451 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 452 .num_stripes = 4, 453 .alloc_offsets = { 454 HALF_STRIPE_LEN, HALF_STRIPE_LEN, 0, 0, 455 }, 456 .expected_alloc_offset = HALF_STRIPE_LEN, 457 }, 458 { 459 .description = "RAID10: while in second stripe", 460 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 461 .num_stripes = 8, 462 .alloc_offsets = { 463 BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 464 BTRFS_STRIPE_LEN + HALF_STRIPE_LEN, 465 BTRFS_STRIPE_LEN + HALF_STRIPE_LEN, 466 BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 467 BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 468 }, 469 .expected_alloc_offset = BTRFS_STRIPE_LEN * 5 + HALF_STRIPE_LEN, 470 }, 471 { 472 .description = "RAID10: one stripe advanced", 473 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 474 .num_stripes = 4, 475 .alloc_offsets = { 476 SZ_1M + BTRFS_STRIPE_LEN, SZ_1M + BTRFS_STRIPE_LEN, 477 SZ_1M, SZ_1M, 478 }, 479 .expected_alloc_offset = SZ_2M + BTRFS_STRIPE_LEN, 480 }, 481 { 482 .description = "RAID10: one stripe advanced, with conventional zone", 483 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 484 .num_stripes = 4, 485 .alloc_offsets = { 486 SZ_1M + BTRFS_STRIPE_LEN, WP_CONVENTIONAL, 487 WP_CONVENTIONAL, SZ_1M, 488 }, 489 .expected_alloc_offset = SZ_2M + BTRFS_STRIPE_LEN, 490 }, 491 /* Error case: having different write pointers. */ 492 { 493 .description = "RAID10: fail: disordered stripes", 494 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 495 .num_stripes = 8, 496 .alloc_offsets = { 497 BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 498 BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 499 BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 500 BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 501 }, 502 .expected_result = -EIO, 503 }, 504 { 505 .description = "RAID10: fail: far distance", 506 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 507 .num_stripes = 8, 508 .alloc_offsets = { 509 BTRFS_STRIPE_LEN * 3, BTRFS_STRIPE_LEN * 3, 510 BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 511 BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 512 BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 513 }, 514 .expected_result = -EIO, 515 }, 516 { 517 .description = "RAID10: fail: too many partial write", 518 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 519 .num_stripes = 8, 520 .alloc_offsets = { 521 HALF_STRIPE_LEN, HALF_STRIPE_LEN, 522 HALF_STRIPE_LEN, HALF_STRIPE_LEN, 523 0, 0, 0, 0, 524 }, 525 .expected_result = -EIO, 526 }, 527 /* 528 * Error case: Partial missing device in RAID0 level is not allowed even on 529 * non-DEGRADED mount. 530 */ 531 { 532 .description = "RAID10: fail: missing device on DEGRADED", 533 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 534 .num_stripes = 4, 535 .alloc_offsets = { 536 SZ_1M, SZ_1M, 537 WP_MISSING_DEV, WP_MISSING_DEV, 538 }, 539 .degraded = true, 540 .expected_result = -EIO, 541 }, 542 543 /* 544 * One sequential zone and one conventional zone, having matching 545 * last_alloc. 546 */ 547 { 548 .description = "RAID10: seq zone and conv zone, partially written stripe", 549 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 550 .num_stripes = 4, 551 .alloc_offsets = { 552 SZ_1M, SZ_1M, 553 WP_CONVENTIONAL, WP_CONVENTIONAL, 554 }, 555 .last_alloc = SZ_2M - SZ_4K, 556 .expected_alloc_offset = SZ_2M - SZ_4K, 557 }, 558 { 559 .description = "RAID10: conv zone and seq zone, partially written stripe", 560 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 561 .num_stripes = 4, 562 .alloc_offsets = { 563 WP_CONVENTIONAL, WP_CONVENTIONAL, 564 SZ_1M, SZ_1M, 565 }, 566 .last_alloc = SZ_2M + SZ_4K, 567 .expected_alloc_offset = SZ_2M + SZ_4K, 568 }, 569 /* 570 * Error case: one sequential and one conventional zone, but having larger 571 * last_alloc than write pointer. 572 */ 573 { 574 .description = "RAID10: fail: seq zone and conv zone, larger last_alloc", 575 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 576 .num_stripes = 4, 577 .alloc_offsets = { 578 SZ_1M, SZ_1M, 579 WP_CONVENTIONAL, WP_CONVENTIONAL, 580 }, 581 .last_alloc = SZ_2M + BTRFS_STRIPE_LEN * 2, 582 .expected_result = -EIO, 583 }, 584 585 /* RAID10, 4 stripes with seq zones and conv zones. */ 586 { 587 .description = "RAID10: stripes [2, 2, ?, ?] last_alloc = 6", 588 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 589 .num_stripes = 8, 590 .alloc_offsets = { 591 BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 592 BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 593 WP_CONVENTIONAL, WP_CONVENTIONAL, 594 WP_CONVENTIONAL, WP_CONVENTIONAL, 595 }, 596 .last_alloc = BTRFS_STRIPE_LEN * 6, 597 .expected_alloc_offset = BTRFS_STRIPE_LEN * 6, 598 }, 599 { 600 .description = "RAID10: stripes [2, 2, ?, ?] last_alloc = 7.5", 601 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 602 .num_stripes = 8, 603 .alloc_offsets = { 604 BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 605 BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 606 WP_CONVENTIONAL, WP_CONVENTIONAL, 607 WP_CONVENTIONAL, WP_CONVENTIONAL, 608 }, 609 .last_alloc = BTRFS_STRIPE_LEN * 7 + HALF_STRIPE_LEN, 610 .expected_alloc_offset = BTRFS_STRIPE_LEN * 7 + HALF_STRIPE_LEN, 611 }, 612 { 613 .description = "RAID10: stripes [3, ?, ?, ?] last_alloc = 1", 614 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 615 .num_stripes = 8, 616 .alloc_offsets = { 617 BTRFS_STRIPE_LEN * 3, BTRFS_STRIPE_LEN * 3, 618 WP_CONVENTIONAL, WP_CONVENTIONAL, 619 WP_CONVENTIONAL, WP_CONVENTIONAL, 620 WP_CONVENTIONAL, WP_CONVENTIONAL, 621 }, 622 .last_alloc = BTRFS_STRIPE_LEN, 623 .expected_alloc_offset = BTRFS_STRIPE_LEN * 9, 624 }, 625 { 626 .description = "RAID10: stripes [2, ?, 1, ?] last_alloc = 5", 627 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 628 .num_stripes = 8, 629 .alloc_offsets = { 630 BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 631 WP_CONVENTIONAL, WP_CONVENTIONAL, 632 BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 633 WP_CONVENTIONAL, WP_CONVENTIONAL, 634 }, 635 .last_alloc = BTRFS_STRIPE_LEN * 5, 636 .expected_alloc_offset = BTRFS_STRIPE_LEN * 5, 637 }, 638 { 639 .description = "RAID10: fail: stripes [2, ?, 1, ?] last_alloc = 7", 640 .raid_type = BTRFS_BLOCK_GROUP_RAID10, 641 .num_stripes = 8, 642 .alloc_offsets = { 643 BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 644 WP_CONVENTIONAL, WP_CONVENTIONAL, 645 BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 646 WP_CONVENTIONAL, WP_CONVENTIONAL, 647 }, 648 .last_alloc = BTRFS_STRIPE_LEN * 7, 649 .expected_result = -EIO, 650 }, 651 }; 652 653 int btrfs_test_zoned(void) 654 { 655 struct btrfs_fs_info *fs_info __free(btrfs_free_dummy_fs_info) = NULL; 656 int ret; 657 658 test_msg("running zoned tests (error messages are expected)"); 659 660 fs_info = btrfs_alloc_dummy_fs_info(PAGE_SIZE, PAGE_SIZE); 661 if (!fs_info) { 662 test_std_err(TEST_ALLOC_FS_INFO); 663 return -ENOMEM; 664 } 665 666 for (int i = 0; i < ARRAY_SIZE(load_zone_info_tests); i++) { 667 ret = test_load_zone_info(fs_info, &load_zone_info_tests[i]); 668 if (ret) { 669 test_err("test case \"%s\" failed", load_zone_info_tests[i].description); 670 return ret; 671 } 672 } 673 674 return 0; 675 } 676