11ba19a6eSNaohiro Aota // SPDX-License-Identifier: GPL-2.0 21ba19a6eSNaohiro Aota /* 31ba19a6eSNaohiro Aota * Copyright (C) 2026 Western Digital. All rights reserved. 41ba19a6eSNaohiro Aota */ 51ba19a6eSNaohiro Aota 61ba19a6eSNaohiro Aota #include <linux/cleanup.h> 71ba19a6eSNaohiro Aota #include <linux/sizes.h> 81ba19a6eSNaohiro Aota 91ba19a6eSNaohiro Aota #include "btrfs-tests.h" 101ba19a6eSNaohiro Aota #include "../space-info.h" 111ba19a6eSNaohiro Aota #include "../volumes.h" 121ba19a6eSNaohiro Aota #include "../zoned.h" 131ba19a6eSNaohiro Aota 141ba19a6eSNaohiro Aota #define WP_MISSING_DEV ((u64)-1) 151ba19a6eSNaohiro Aota #define WP_CONVENTIONAL ((u64)-2) 161ba19a6eSNaohiro Aota #define ZONE_SIZE SZ_256M 171ba19a6eSNaohiro Aota 181ba19a6eSNaohiro Aota #define HALF_STRIPE_LEN (BTRFS_STRIPE_LEN >> 1) 191ba19a6eSNaohiro Aota 201ba19a6eSNaohiro Aota struct load_zone_info_test_vector { 211ba19a6eSNaohiro Aota u64 raid_type; 221ba19a6eSNaohiro Aota u64 num_stripes; 231ba19a6eSNaohiro Aota u64 alloc_offsets[8]; 241ba19a6eSNaohiro Aota u64 last_alloc; 251ba19a6eSNaohiro Aota u64 bg_length; 261ba19a6eSNaohiro Aota bool degraded; 271ba19a6eSNaohiro Aota 281ba19a6eSNaohiro Aota int expected_result; 291ba19a6eSNaohiro Aota u64 expected_alloc_offset; 301ba19a6eSNaohiro Aota 311ba19a6eSNaohiro Aota const char *description; 321ba19a6eSNaohiro Aota }; 331ba19a6eSNaohiro Aota 341ba19a6eSNaohiro Aota struct zone_info { 351ba19a6eSNaohiro Aota u64 physical; 361ba19a6eSNaohiro Aota u64 capacity; 371ba19a6eSNaohiro Aota u64 alloc_offset; 381ba19a6eSNaohiro Aota }; 391ba19a6eSNaohiro Aota 401ba19a6eSNaohiro Aota static int test_load_zone_info(struct btrfs_fs_info *fs_info, 411ba19a6eSNaohiro Aota const struct load_zone_info_test_vector *test) 421ba19a6eSNaohiro Aota { 431ba19a6eSNaohiro Aota struct btrfs_block_group *bg __free(btrfs_free_dummy_block_group) = NULL; 441ba19a6eSNaohiro Aota struct btrfs_chunk_map *map __free(btrfs_free_chunk_map) = NULL; 451ba19a6eSNaohiro Aota struct zone_info AUTO_KFREE(zone_info); 461ba19a6eSNaohiro Aota unsigned long AUTO_KFREE(active); 471ba19a6eSNaohiro Aota int ret; 481ba19a6eSNaohiro Aota 491ba19a6eSNaohiro Aota bg = btrfs_alloc_dummy_block_group(fs_info, test->bg_length); 501ba19a6eSNaohiro Aota if (!bg) { 511ba19a6eSNaohiro Aota test_std_err(TEST_ALLOC_BLOCK_GROUP); 521ba19a6eSNaohiro Aota return -ENOMEM; 531ba19a6eSNaohiro Aota } 541ba19a6eSNaohiro Aota 551ba19a6eSNaohiro Aota map = btrfs_alloc_chunk_map(test->num_stripes, GFP_KERNEL); 561ba19a6eSNaohiro Aota if (!map) { 571ba19a6eSNaohiro Aota test_std_err(TEST_ALLOC_EXTENT_MAP); 581ba19a6eSNaohiro Aota return -ENOMEM; 591ba19a6eSNaohiro Aota } 601ba19a6eSNaohiro Aota 61*2d2b5507SMiquel Sabaté Solà zone_info = kzalloc_objs(*zone_info, test->num_stripes, GFP_KERNEL); 621ba19a6eSNaohiro Aota if (!zone_info) { 631ba19a6eSNaohiro Aota test_err("cannot allocate zone info"); 641ba19a6eSNaohiro Aota return -ENOMEM; 651ba19a6eSNaohiro Aota } 661ba19a6eSNaohiro Aota 671ba19a6eSNaohiro Aota active = bitmap_zalloc(test->num_stripes, GFP_KERNEL); 681ba19a6eSNaohiro Aota if (!zone_info) { 691ba19a6eSNaohiro Aota test_err("cannot allocate active bitmap"); 701ba19a6eSNaohiro Aota return -ENOMEM; 711ba19a6eSNaohiro Aota } 721ba19a6eSNaohiro Aota 731ba19a6eSNaohiro Aota map->type = test->raid_type; 741ba19a6eSNaohiro Aota map->num_stripes = test->num_stripes; 751ba19a6eSNaohiro Aota if (test->raid_type == BTRFS_BLOCK_GROUP_RAID10) 761ba19a6eSNaohiro Aota map->sub_stripes = 2; 771ba19a6eSNaohiro Aota for (int i = 0; i < test->num_stripes; i++) { 781ba19a6eSNaohiro Aota zone_info[i].physical = 0; 791ba19a6eSNaohiro Aota zone_info[i].alloc_offset = test->alloc_offsets[i]; 801ba19a6eSNaohiro Aota zone_info[i].capacity = ZONE_SIZE; 811ba19a6eSNaohiro Aota if (zone_info[i].alloc_offset && zone_info[i].alloc_offset < ZONE_SIZE) 821ba19a6eSNaohiro Aota __set_bit(i, active); 831ba19a6eSNaohiro Aota } 841ba19a6eSNaohiro Aota if (test->degraded) 851ba19a6eSNaohiro Aota btrfs_set_opt(fs_info->mount_opt, DEGRADED); 861ba19a6eSNaohiro Aota else 871ba19a6eSNaohiro Aota btrfs_clear_opt(fs_info->mount_opt, DEGRADED); 881ba19a6eSNaohiro Aota 891ba19a6eSNaohiro Aota ret = btrfs_load_block_group_by_raid_type(bg, map, zone_info, active, 901ba19a6eSNaohiro Aota test->last_alloc); 911ba19a6eSNaohiro Aota 921ba19a6eSNaohiro Aota if (ret != test->expected_result) { 931ba19a6eSNaohiro Aota test_err("unexpected return value: ret %d expected %d", ret, 941ba19a6eSNaohiro Aota test->expected_result); 951ba19a6eSNaohiro Aota return -EINVAL; 961ba19a6eSNaohiro Aota } 971ba19a6eSNaohiro Aota 981ba19a6eSNaohiro Aota if (!ret && bg->alloc_offset != test->expected_alloc_offset) { 991ba19a6eSNaohiro Aota test_err("unexpected alloc_offset: alloc_offset %llu expected %llu", 1001ba19a6eSNaohiro Aota bg->alloc_offset, test->expected_alloc_offset); 1011ba19a6eSNaohiro Aota return -EINVAL; 1021ba19a6eSNaohiro Aota } 1031ba19a6eSNaohiro Aota 1041ba19a6eSNaohiro Aota return 0; 1051ba19a6eSNaohiro Aota } 1061ba19a6eSNaohiro Aota 1071ba19a6eSNaohiro Aota static const struct load_zone_info_test_vector load_zone_info_tests[] = { 1081ba19a6eSNaohiro Aota /* SINGLE */ 1091ba19a6eSNaohiro Aota { 1101ba19a6eSNaohiro Aota .description = "SINGLE: load write pointer from sequential zone", 1111ba19a6eSNaohiro Aota .raid_type = 0, 1121ba19a6eSNaohiro Aota .num_stripes = 1, 1131ba19a6eSNaohiro Aota .alloc_offsets = { 1141ba19a6eSNaohiro Aota SZ_1M, 1151ba19a6eSNaohiro Aota }, 1161ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_1M, 1171ba19a6eSNaohiro Aota }, 1181ba19a6eSNaohiro Aota /* 1191ba19a6eSNaohiro Aota * SINGLE block group on a conventional zone sets last_alloc outside of 1201ba19a6eSNaohiro Aota * btrfs_load_block_group_*(). Do not test that case. 1211ba19a6eSNaohiro Aota */ 1221ba19a6eSNaohiro Aota 1231ba19a6eSNaohiro Aota /* DUP */ 1241ba19a6eSNaohiro Aota /* Normal case */ 1251ba19a6eSNaohiro Aota { 1261ba19a6eSNaohiro Aota .description = "DUP: having matching write pointers", 1271ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_DUP, 1281ba19a6eSNaohiro Aota .num_stripes = 2, 1291ba19a6eSNaohiro Aota .alloc_offsets = { 1301ba19a6eSNaohiro Aota SZ_1M, SZ_1M, 1311ba19a6eSNaohiro Aota }, 1321ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_1M, 1331ba19a6eSNaohiro Aota }, 1341ba19a6eSNaohiro Aota /* 1351ba19a6eSNaohiro Aota * One sequential zone and one conventional zone, having matching 1361ba19a6eSNaohiro Aota * last_alloc. 1371ba19a6eSNaohiro Aota */ 1381ba19a6eSNaohiro Aota { 1391ba19a6eSNaohiro Aota .description = "DUP: seq zone and conv zone, matching last_alloc", 1401ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_DUP, 1411ba19a6eSNaohiro Aota .num_stripes = 2, 1421ba19a6eSNaohiro Aota .alloc_offsets = { 1431ba19a6eSNaohiro Aota SZ_1M, WP_CONVENTIONAL, 1441ba19a6eSNaohiro Aota }, 1451ba19a6eSNaohiro Aota .last_alloc = SZ_1M, 1461ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_1M, 1471ba19a6eSNaohiro Aota }, 1481ba19a6eSNaohiro Aota /* 1491ba19a6eSNaohiro Aota * One sequential and one conventional zone, but having smaller 1501ba19a6eSNaohiro Aota * last_alloc than write pointer. 1511ba19a6eSNaohiro Aota */ 1521ba19a6eSNaohiro Aota { 1531ba19a6eSNaohiro Aota .description = "DUP: seq zone and conv zone, smaller last_alloc", 1541ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_DUP, 1551ba19a6eSNaohiro Aota .num_stripes = 2, 1561ba19a6eSNaohiro Aota .alloc_offsets = { 1571ba19a6eSNaohiro Aota SZ_1M, WP_CONVENTIONAL, 1581ba19a6eSNaohiro Aota }, 1591ba19a6eSNaohiro Aota .last_alloc = 0, 1601ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_1M, 1611ba19a6eSNaohiro Aota }, 1621ba19a6eSNaohiro Aota /* Error case: having different write pointers. */ 1631ba19a6eSNaohiro Aota { 1641ba19a6eSNaohiro Aota .description = "DUP: fail: different write pointers", 1651ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_DUP, 1661ba19a6eSNaohiro Aota .num_stripes = 2, 1671ba19a6eSNaohiro Aota .alloc_offsets = { 1681ba19a6eSNaohiro Aota SZ_1M, SZ_2M, 1691ba19a6eSNaohiro Aota }, 1701ba19a6eSNaohiro Aota .expected_result = -EIO, 1711ba19a6eSNaohiro Aota }, 1721ba19a6eSNaohiro Aota /* Error case: partial missing device should not happen on DUP. */ 1731ba19a6eSNaohiro Aota { 1741ba19a6eSNaohiro Aota .description = "DUP: fail: missing device", 1751ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_DUP, 1761ba19a6eSNaohiro Aota .num_stripes = 2, 1771ba19a6eSNaohiro Aota .alloc_offsets = { 1781ba19a6eSNaohiro Aota SZ_1M, WP_MISSING_DEV, 1791ba19a6eSNaohiro Aota }, 1801ba19a6eSNaohiro Aota .expected_result = -EIO, 1811ba19a6eSNaohiro Aota }, 1821ba19a6eSNaohiro Aota /* 1831ba19a6eSNaohiro Aota * Error case: one sequential and one conventional zone, but having larger 1841ba19a6eSNaohiro Aota * last_alloc than write pointer. 1851ba19a6eSNaohiro Aota */ 1861ba19a6eSNaohiro Aota { 1871ba19a6eSNaohiro Aota .description = "DUP: fail: seq zone and conv zone, larger last_alloc", 1881ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_DUP, 1891ba19a6eSNaohiro Aota .num_stripes = 2, 1901ba19a6eSNaohiro Aota .alloc_offsets = { 1911ba19a6eSNaohiro Aota SZ_1M, WP_CONVENTIONAL, 1921ba19a6eSNaohiro Aota }, 1931ba19a6eSNaohiro Aota .last_alloc = SZ_2M, 1941ba19a6eSNaohiro Aota .expected_result = -EIO, 1951ba19a6eSNaohiro Aota }, 1961ba19a6eSNaohiro Aota 1971ba19a6eSNaohiro Aota /* RAID1 */ 1981ba19a6eSNaohiro Aota /* Normal case */ 1991ba19a6eSNaohiro Aota { 2001ba19a6eSNaohiro Aota .description = "RAID1: having matching write pointers", 2011ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID1, 2021ba19a6eSNaohiro Aota .num_stripes = 2, 2031ba19a6eSNaohiro Aota .alloc_offsets = { 2041ba19a6eSNaohiro Aota SZ_1M, SZ_1M, 2051ba19a6eSNaohiro Aota }, 2061ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_1M, 2071ba19a6eSNaohiro Aota }, 2081ba19a6eSNaohiro Aota /* 2091ba19a6eSNaohiro Aota * One sequential zone and one conventional zone, having matching 2101ba19a6eSNaohiro Aota * last_alloc. 2111ba19a6eSNaohiro Aota */ 2121ba19a6eSNaohiro Aota { 2131ba19a6eSNaohiro Aota .description = "RAID1: seq zone and conv zone, matching last_alloc", 2141ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID1, 2151ba19a6eSNaohiro Aota .num_stripes = 2, 2161ba19a6eSNaohiro Aota .alloc_offsets = { 2171ba19a6eSNaohiro Aota SZ_1M, WP_CONVENTIONAL, 2181ba19a6eSNaohiro Aota }, 2191ba19a6eSNaohiro Aota .last_alloc = SZ_1M, 2201ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_1M, 2211ba19a6eSNaohiro Aota }, 2221ba19a6eSNaohiro Aota /* 2231ba19a6eSNaohiro Aota * One sequential and one conventional zone, but having smaller 2241ba19a6eSNaohiro Aota * last_alloc than write pointer. 2251ba19a6eSNaohiro Aota */ 2261ba19a6eSNaohiro Aota { 2271ba19a6eSNaohiro Aota .description = "RAID1: seq zone and conv zone, smaller last_alloc", 2281ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID1, 2291ba19a6eSNaohiro Aota .num_stripes = 2, 2301ba19a6eSNaohiro Aota .alloc_offsets = { 2311ba19a6eSNaohiro Aota SZ_1M, WP_CONVENTIONAL, 2321ba19a6eSNaohiro Aota }, 2331ba19a6eSNaohiro Aota .last_alloc = 0, 2341ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_1M, 2351ba19a6eSNaohiro Aota }, 2361ba19a6eSNaohiro Aota /* Partial missing device should be recovered on DEGRADED mount */ 2371ba19a6eSNaohiro Aota { 2381ba19a6eSNaohiro Aota .description = "RAID1: fail: missing device on DEGRADED", 2391ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID1, 2401ba19a6eSNaohiro Aota .num_stripes = 2, 2411ba19a6eSNaohiro Aota .alloc_offsets = { 2421ba19a6eSNaohiro Aota SZ_1M, WP_MISSING_DEV, 2431ba19a6eSNaohiro Aota }, 2441ba19a6eSNaohiro Aota .degraded = true, 2451ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_1M, 2461ba19a6eSNaohiro Aota }, 2471ba19a6eSNaohiro Aota /* Error case: having different write pointers. */ 2481ba19a6eSNaohiro Aota { 2491ba19a6eSNaohiro Aota .description = "RAID1: fail: different write pointers", 2501ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID1, 2511ba19a6eSNaohiro Aota .num_stripes = 2, 2521ba19a6eSNaohiro Aota .alloc_offsets = { 2531ba19a6eSNaohiro Aota SZ_1M, SZ_2M, 2541ba19a6eSNaohiro Aota }, 2551ba19a6eSNaohiro Aota .expected_result = -EIO, 2561ba19a6eSNaohiro Aota }, 2571ba19a6eSNaohiro Aota /* 2581ba19a6eSNaohiro Aota * Partial missing device is not allowed on non-DEGRADED mount never happen 2591ba19a6eSNaohiro Aota * as it is rejected beforehand. 2601ba19a6eSNaohiro Aota */ 2611ba19a6eSNaohiro Aota /* 2621ba19a6eSNaohiro Aota * Error case: one sequential and one conventional zone, but having larger 2631ba19a6eSNaohiro Aota * last_alloc than write pointer. 2641ba19a6eSNaohiro Aota */ 2651ba19a6eSNaohiro Aota { 2661ba19a6eSNaohiro Aota .description = "RAID1: fail: seq zone and conv zone, larger last_alloc", 2671ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID1, 2681ba19a6eSNaohiro Aota .num_stripes = 2, 2691ba19a6eSNaohiro Aota .alloc_offsets = { 2701ba19a6eSNaohiro Aota SZ_1M, WP_CONVENTIONAL, 2711ba19a6eSNaohiro Aota }, 2721ba19a6eSNaohiro Aota .last_alloc = SZ_2M, 2731ba19a6eSNaohiro Aota .expected_result = -EIO, 2741ba19a6eSNaohiro Aota }, 2751ba19a6eSNaohiro Aota 2761ba19a6eSNaohiro Aota /* RAID0 */ 2771ba19a6eSNaohiro Aota /* Normal case */ 2781ba19a6eSNaohiro Aota { 2791ba19a6eSNaohiro Aota .description = "RAID0: initial partial write", 2801ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 2811ba19a6eSNaohiro Aota .num_stripes = 4, 2821ba19a6eSNaohiro Aota .alloc_offsets = { 2831ba19a6eSNaohiro Aota HALF_STRIPE_LEN, 0, 0, 0, 2841ba19a6eSNaohiro Aota }, 2851ba19a6eSNaohiro Aota .expected_alloc_offset = HALF_STRIPE_LEN, 2861ba19a6eSNaohiro Aota }, 2871ba19a6eSNaohiro Aota { 2881ba19a6eSNaohiro Aota .description = "RAID0: while in second stripe", 2891ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 2901ba19a6eSNaohiro Aota .num_stripes = 4, 2911ba19a6eSNaohiro Aota .alloc_offsets = { 2921ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN + HALF_STRIPE_LEN, 2931ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 2941ba19a6eSNaohiro Aota }, 2951ba19a6eSNaohiro Aota .expected_alloc_offset = BTRFS_STRIPE_LEN * 5 + HALF_STRIPE_LEN, 2961ba19a6eSNaohiro Aota }, 2971ba19a6eSNaohiro Aota { 2981ba19a6eSNaohiro Aota .description = "RAID0: one stripe advanced", 2991ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 3001ba19a6eSNaohiro Aota .num_stripes = 2, 3011ba19a6eSNaohiro Aota .alloc_offsets = { 3021ba19a6eSNaohiro Aota SZ_1M + BTRFS_STRIPE_LEN, SZ_1M, 3031ba19a6eSNaohiro Aota }, 3041ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_2M + BTRFS_STRIPE_LEN, 3051ba19a6eSNaohiro Aota }, 3061ba19a6eSNaohiro Aota /* Error case: having different write pointers. */ 3071ba19a6eSNaohiro Aota { 3081ba19a6eSNaohiro Aota .description = "RAID0: fail: disordered stripes", 3091ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 3101ba19a6eSNaohiro Aota .num_stripes = 4, 3111ba19a6eSNaohiro Aota .alloc_offsets = { 3121ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN * 2, 3131ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 3141ba19a6eSNaohiro Aota }, 3151ba19a6eSNaohiro Aota .expected_result = -EIO, 3161ba19a6eSNaohiro Aota }, 3171ba19a6eSNaohiro Aota { 3181ba19a6eSNaohiro Aota .description = "RAID0: fail: far distance", 3191ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 3201ba19a6eSNaohiro Aota .num_stripes = 4, 3211ba19a6eSNaohiro Aota .alloc_offsets = { 3221ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 3, BTRFS_STRIPE_LEN, 3231ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 3241ba19a6eSNaohiro Aota }, 3251ba19a6eSNaohiro Aota .expected_result = -EIO, 3261ba19a6eSNaohiro Aota }, 3271ba19a6eSNaohiro Aota { 3281ba19a6eSNaohiro Aota .description = "RAID0: fail: too many partial write", 3291ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 3301ba19a6eSNaohiro Aota .num_stripes = 4, 3311ba19a6eSNaohiro Aota .alloc_offsets = { 3321ba19a6eSNaohiro Aota HALF_STRIPE_LEN, HALF_STRIPE_LEN, 0, 0, 3331ba19a6eSNaohiro Aota }, 3341ba19a6eSNaohiro Aota .expected_result = -EIO, 3351ba19a6eSNaohiro Aota }, 3361ba19a6eSNaohiro Aota /* 3371ba19a6eSNaohiro Aota * Error case: Partial missing device is not allowed even on non-DEGRADED 3381ba19a6eSNaohiro Aota * mount. 3391ba19a6eSNaohiro Aota */ 3401ba19a6eSNaohiro Aota { 3411ba19a6eSNaohiro Aota .description = "RAID0: fail: missing device on DEGRADED", 3421ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 3431ba19a6eSNaohiro Aota .num_stripes = 2, 3441ba19a6eSNaohiro Aota .alloc_offsets = { 3451ba19a6eSNaohiro Aota SZ_1M, WP_MISSING_DEV, 3461ba19a6eSNaohiro Aota }, 3471ba19a6eSNaohiro Aota .degraded = true, 3481ba19a6eSNaohiro Aota .expected_result = -EIO, 3491ba19a6eSNaohiro Aota }, 3501ba19a6eSNaohiro Aota 3511ba19a6eSNaohiro Aota /* 3521ba19a6eSNaohiro Aota * One sequential zone and one conventional zone, having matching 3531ba19a6eSNaohiro Aota * last_alloc. 3541ba19a6eSNaohiro Aota */ 3551ba19a6eSNaohiro Aota { 3561ba19a6eSNaohiro Aota .description = "RAID0: seq zone and conv zone, partially written stripe", 3571ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 3581ba19a6eSNaohiro Aota .num_stripes = 2, 3591ba19a6eSNaohiro Aota .alloc_offsets = { 3601ba19a6eSNaohiro Aota SZ_1M, WP_CONVENTIONAL, 3611ba19a6eSNaohiro Aota }, 3621ba19a6eSNaohiro Aota .last_alloc = SZ_2M - SZ_4K, 3631ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_2M - SZ_4K, 3641ba19a6eSNaohiro Aota }, 3651ba19a6eSNaohiro Aota { 3661ba19a6eSNaohiro Aota .description = "RAID0: conv zone and seq zone, partially written stripe", 3671ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 3681ba19a6eSNaohiro Aota .num_stripes = 2, 3691ba19a6eSNaohiro Aota .alloc_offsets = { 3701ba19a6eSNaohiro Aota WP_CONVENTIONAL, SZ_1M, 3711ba19a6eSNaohiro Aota }, 3721ba19a6eSNaohiro Aota .last_alloc = SZ_2M + SZ_4K, 3731ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_2M + SZ_4K, 3741ba19a6eSNaohiro Aota }, 3751ba19a6eSNaohiro Aota /* 3761ba19a6eSNaohiro Aota * Error case: one sequential and one conventional zone, but having larger 3771ba19a6eSNaohiro Aota * last_alloc than write pointer. 3781ba19a6eSNaohiro Aota */ 3791ba19a6eSNaohiro Aota { 3801ba19a6eSNaohiro Aota .description = "RAID0: fail: seq zone and conv zone, larger last_alloc", 3811ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 3821ba19a6eSNaohiro Aota .num_stripes = 2, 3831ba19a6eSNaohiro Aota .alloc_offsets = { 3841ba19a6eSNaohiro Aota SZ_1M, WP_CONVENTIONAL, 3851ba19a6eSNaohiro Aota }, 3861ba19a6eSNaohiro Aota .last_alloc = SZ_2M + BTRFS_STRIPE_LEN * 2, 3871ba19a6eSNaohiro Aota .expected_result = -EIO, 3881ba19a6eSNaohiro Aota }, 3891ba19a6eSNaohiro Aota 3901ba19a6eSNaohiro Aota /* RAID0, 4 stripes with seq zones and conv zones. */ 3911ba19a6eSNaohiro Aota { 3921ba19a6eSNaohiro Aota .description = "RAID0: stripes [2, 2, ?, ?] last_alloc = 6", 3931ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 3941ba19a6eSNaohiro Aota .num_stripes = 4, 3951ba19a6eSNaohiro Aota .alloc_offsets = { 3961ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 3971ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 3981ba19a6eSNaohiro Aota }, 3991ba19a6eSNaohiro Aota .last_alloc = BTRFS_STRIPE_LEN * 6, 4001ba19a6eSNaohiro Aota .expected_alloc_offset = BTRFS_STRIPE_LEN * 6, 4011ba19a6eSNaohiro Aota }, 4021ba19a6eSNaohiro Aota { 4031ba19a6eSNaohiro Aota .description = "RAID0: stripes [2, 2, ?, ?] last_alloc = 7.5", 4041ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 4051ba19a6eSNaohiro Aota .num_stripes = 4, 4061ba19a6eSNaohiro Aota .alloc_offsets = { 4071ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 4081ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 4091ba19a6eSNaohiro Aota }, 4101ba19a6eSNaohiro Aota .last_alloc = BTRFS_STRIPE_LEN * 7 + HALF_STRIPE_LEN, 4111ba19a6eSNaohiro Aota .expected_alloc_offset = BTRFS_STRIPE_LEN * 7 + HALF_STRIPE_LEN, 4121ba19a6eSNaohiro Aota }, 4131ba19a6eSNaohiro Aota { 4141ba19a6eSNaohiro Aota .description = "RAID0: stripes [3, ?, ?, ?] last_alloc = 1", 4151ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 4161ba19a6eSNaohiro Aota .num_stripes = 4, 4171ba19a6eSNaohiro Aota .alloc_offsets = { 4181ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 3, WP_CONVENTIONAL, 4191ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 4201ba19a6eSNaohiro Aota }, 4211ba19a6eSNaohiro Aota .last_alloc = BTRFS_STRIPE_LEN, 4221ba19a6eSNaohiro Aota .expected_alloc_offset = BTRFS_STRIPE_LEN * 9, 4231ba19a6eSNaohiro Aota }, 4241ba19a6eSNaohiro Aota { 4251ba19a6eSNaohiro Aota .description = "RAID0: stripes [2, ?, 1, ?] last_alloc = 5", 4261ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 4271ba19a6eSNaohiro Aota .num_stripes = 4, 4281ba19a6eSNaohiro Aota .alloc_offsets = { 4291ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 2, WP_CONVENTIONAL, 4301ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, WP_CONVENTIONAL, 4311ba19a6eSNaohiro Aota }, 4321ba19a6eSNaohiro Aota .last_alloc = BTRFS_STRIPE_LEN * 5, 4331ba19a6eSNaohiro Aota .expected_alloc_offset = BTRFS_STRIPE_LEN * 5, 4341ba19a6eSNaohiro Aota }, 4351ba19a6eSNaohiro Aota { 4361ba19a6eSNaohiro Aota .description = "RAID0: fail: stripes [2, ?, 1, ?] last_alloc = 7", 4371ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID0, 4381ba19a6eSNaohiro Aota .num_stripes = 4, 4391ba19a6eSNaohiro Aota .alloc_offsets = { 4401ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 2, WP_CONVENTIONAL, 4411ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, WP_CONVENTIONAL, 4421ba19a6eSNaohiro Aota }, 4431ba19a6eSNaohiro Aota .last_alloc = BTRFS_STRIPE_LEN * 7, 4441ba19a6eSNaohiro Aota .expected_result = -EIO, 4451ba19a6eSNaohiro Aota }, 4461ba19a6eSNaohiro Aota 4471ba19a6eSNaohiro Aota /* RAID10 */ 4481ba19a6eSNaohiro Aota /* Normal case */ 4491ba19a6eSNaohiro Aota { 4501ba19a6eSNaohiro Aota .description = "RAID10: initial partial write", 4511ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 4521ba19a6eSNaohiro Aota .num_stripes = 4, 4531ba19a6eSNaohiro Aota .alloc_offsets = { 4541ba19a6eSNaohiro Aota HALF_STRIPE_LEN, HALF_STRIPE_LEN, 0, 0, 4551ba19a6eSNaohiro Aota }, 4561ba19a6eSNaohiro Aota .expected_alloc_offset = HALF_STRIPE_LEN, 4571ba19a6eSNaohiro Aota }, 4581ba19a6eSNaohiro Aota { 4591ba19a6eSNaohiro Aota .description = "RAID10: while in second stripe", 4601ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 4611ba19a6eSNaohiro Aota .num_stripes = 8, 4621ba19a6eSNaohiro Aota .alloc_offsets = { 4631ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 4641ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN + HALF_STRIPE_LEN, 4651ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN + HALF_STRIPE_LEN, 4661ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 4671ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 4681ba19a6eSNaohiro Aota }, 4691ba19a6eSNaohiro Aota .expected_alloc_offset = BTRFS_STRIPE_LEN * 5 + HALF_STRIPE_LEN, 4701ba19a6eSNaohiro Aota }, 4711ba19a6eSNaohiro Aota { 4721ba19a6eSNaohiro Aota .description = "RAID10: one stripe advanced", 4731ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 4741ba19a6eSNaohiro Aota .num_stripes = 4, 4751ba19a6eSNaohiro Aota .alloc_offsets = { 4761ba19a6eSNaohiro Aota SZ_1M + BTRFS_STRIPE_LEN, SZ_1M + BTRFS_STRIPE_LEN, 4771ba19a6eSNaohiro Aota SZ_1M, SZ_1M, 4781ba19a6eSNaohiro Aota }, 4791ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_2M + BTRFS_STRIPE_LEN, 4801ba19a6eSNaohiro Aota }, 4811ba19a6eSNaohiro Aota { 4821ba19a6eSNaohiro Aota .description = "RAID10: one stripe advanced, with conventional zone", 4831ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 4841ba19a6eSNaohiro Aota .num_stripes = 4, 4851ba19a6eSNaohiro Aota .alloc_offsets = { 4861ba19a6eSNaohiro Aota SZ_1M + BTRFS_STRIPE_LEN, WP_CONVENTIONAL, 4871ba19a6eSNaohiro Aota WP_CONVENTIONAL, SZ_1M, 4881ba19a6eSNaohiro Aota }, 4891ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_2M + BTRFS_STRIPE_LEN, 4901ba19a6eSNaohiro Aota }, 4911ba19a6eSNaohiro Aota /* Error case: having different write pointers. */ 4921ba19a6eSNaohiro Aota { 4931ba19a6eSNaohiro Aota .description = "RAID10: fail: disordered stripes", 4941ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 4951ba19a6eSNaohiro Aota .num_stripes = 8, 4961ba19a6eSNaohiro Aota .alloc_offsets = { 4971ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 4981ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 4991ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 5001ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 5011ba19a6eSNaohiro Aota }, 5021ba19a6eSNaohiro Aota .expected_result = -EIO, 5031ba19a6eSNaohiro Aota }, 5041ba19a6eSNaohiro Aota { 5051ba19a6eSNaohiro Aota .description = "RAID10: fail: far distance", 5061ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 5071ba19a6eSNaohiro Aota .num_stripes = 8, 5081ba19a6eSNaohiro Aota .alloc_offsets = { 5091ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 3, BTRFS_STRIPE_LEN * 3, 5101ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 5111ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 5121ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 5131ba19a6eSNaohiro Aota }, 5141ba19a6eSNaohiro Aota .expected_result = -EIO, 5151ba19a6eSNaohiro Aota }, 5161ba19a6eSNaohiro Aota { 5171ba19a6eSNaohiro Aota .description = "RAID10: fail: too many partial write", 5181ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 5191ba19a6eSNaohiro Aota .num_stripes = 8, 5201ba19a6eSNaohiro Aota .alloc_offsets = { 5211ba19a6eSNaohiro Aota HALF_STRIPE_LEN, HALF_STRIPE_LEN, 5221ba19a6eSNaohiro Aota HALF_STRIPE_LEN, HALF_STRIPE_LEN, 5231ba19a6eSNaohiro Aota 0, 0, 0, 0, 5241ba19a6eSNaohiro Aota }, 5251ba19a6eSNaohiro Aota .expected_result = -EIO, 5261ba19a6eSNaohiro Aota }, 5271ba19a6eSNaohiro Aota /* 5281ba19a6eSNaohiro Aota * Error case: Partial missing device in RAID0 level is not allowed even on 5291ba19a6eSNaohiro Aota * non-DEGRADED mount. 5301ba19a6eSNaohiro Aota */ 5311ba19a6eSNaohiro Aota { 5321ba19a6eSNaohiro Aota .description = "RAID10: fail: missing device on DEGRADED", 5331ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 5341ba19a6eSNaohiro Aota .num_stripes = 4, 5351ba19a6eSNaohiro Aota .alloc_offsets = { 5361ba19a6eSNaohiro Aota SZ_1M, SZ_1M, 5371ba19a6eSNaohiro Aota WP_MISSING_DEV, WP_MISSING_DEV, 5381ba19a6eSNaohiro Aota }, 5391ba19a6eSNaohiro Aota .degraded = true, 5401ba19a6eSNaohiro Aota .expected_result = -EIO, 5411ba19a6eSNaohiro Aota }, 5421ba19a6eSNaohiro Aota 5431ba19a6eSNaohiro Aota /* 5441ba19a6eSNaohiro Aota * One sequential zone and one conventional zone, having matching 5451ba19a6eSNaohiro Aota * last_alloc. 5461ba19a6eSNaohiro Aota */ 5471ba19a6eSNaohiro Aota { 5481ba19a6eSNaohiro Aota .description = "RAID10: seq zone and conv zone, partially written stripe", 5491ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 5501ba19a6eSNaohiro Aota .num_stripes = 4, 5511ba19a6eSNaohiro Aota .alloc_offsets = { 5521ba19a6eSNaohiro Aota SZ_1M, SZ_1M, 5531ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 5541ba19a6eSNaohiro Aota }, 5551ba19a6eSNaohiro Aota .last_alloc = SZ_2M - SZ_4K, 5561ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_2M - SZ_4K, 5571ba19a6eSNaohiro Aota }, 5581ba19a6eSNaohiro Aota { 5591ba19a6eSNaohiro Aota .description = "RAID10: conv zone and seq zone, partially written stripe", 5601ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 5611ba19a6eSNaohiro Aota .num_stripes = 4, 5621ba19a6eSNaohiro Aota .alloc_offsets = { 5631ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 5641ba19a6eSNaohiro Aota SZ_1M, SZ_1M, 5651ba19a6eSNaohiro Aota }, 5661ba19a6eSNaohiro Aota .last_alloc = SZ_2M + SZ_4K, 5671ba19a6eSNaohiro Aota .expected_alloc_offset = SZ_2M + SZ_4K, 5681ba19a6eSNaohiro Aota }, 5691ba19a6eSNaohiro Aota /* 5701ba19a6eSNaohiro Aota * Error case: one sequential and one conventional zone, but having larger 5711ba19a6eSNaohiro Aota * last_alloc than write pointer. 5721ba19a6eSNaohiro Aota */ 5731ba19a6eSNaohiro Aota { 5741ba19a6eSNaohiro Aota .description = "RAID10: fail: seq zone and conv zone, larger last_alloc", 5751ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 5761ba19a6eSNaohiro Aota .num_stripes = 4, 5771ba19a6eSNaohiro Aota .alloc_offsets = { 5781ba19a6eSNaohiro Aota SZ_1M, SZ_1M, 5791ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 5801ba19a6eSNaohiro Aota }, 5811ba19a6eSNaohiro Aota .last_alloc = SZ_2M + BTRFS_STRIPE_LEN * 2, 5821ba19a6eSNaohiro Aota .expected_result = -EIO, 5831ba19a6eSNaohiro Aota }, 5841ba19a6eSNaohiro Aota 5851ba19a6eSNaohiro Aota /* RAID10, 4 stripes with seq zones and conv zones. */ 5861ba19a6eSNaohiro Aota { 5871ba19a6eSNaohiro Aota .description = "RAID10: stripes [2, 2, ?, ?] last_alloc = 6", 5881ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 5891ba19a6eSNaohiro Aota .num_stripes = 8, 5901ba19a6eSNaohiro Aota .alloc_offsets = { 5911ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 5921ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 5931ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 5941ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 5951ba19a6eSNaohiro Aota }, 5961ba19a6eSNaohiro Aota .last_alloc = BTRFS_STRIPE_LEN * 6, 5971ba19a6eSNaohiro Aota .expected_alloc_offset = BTRFS_STRIPE_LEN * 6, 5981ba19a6eSNaohiro Aota }, 5991ba19a6eSNaohiro Aota { 6001ba19a6eSNaohiro Aota .description = "RAID10: stripes [2, 2, ?, ?] last_alloc = 7.5", 6011ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 6021ba19a6eSNaohiro Aota .num_stripes = 8, 6031ba19a6eSNaohiro Aota .alloc_offsets = { 6041ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 6051ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 6061ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 6071ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 6081ba19a6eSNaohiro Aota }, 6091ba19a6eSNaohiro Aota .last_alloc = BTRFS_STRIPE_LEN * 7 + HALF_STRIPE_LEN, 6101ba19a6eSNaohiro Aota .expected_alloc_offset = BTRFS_STRIPE_LEN * 7 + HALF_STRIPE_LEN, 6111ba19a6eSNaohiro Aota }, 6121ba19a6eSNaohiro Aota { 6131ba19a6eSNaohiro Aota .description = "RAID10: stripes [3, ?, ?, ?] last_alloc = 1", 6141ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 6151ba19a6eSNaohiro Aota .num_stripes = 8, 6161ba19a6eSNaohiro Aota .alloc_offsets = { 6171ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 3, BTRFS_STRIPE_LEN * 3, 6181ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 6191ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 6201ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 6211ba19a6eSNaohiro Aota }, 6221ba19a6eSNaohiro Aota .last_alloc = BTRFS_STRIPE_LEN, 6231ba19a6eSNaohiro Aota .expected_alloc_offset = BTRFS_STRIPE_LEN * 9, 6241ba19a6eSNaohiro Aota }, 6251ba19a6eSNaohiro Aota { 6261ba19a6eSNaohiro Aota .description = "RAID10: stripes [2, ?, 1, ?] last_alloc = 5", 6271ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 6281ba19a6eSNaohiro Aota .num_stripes = 8, 6291ba19a6eSNaohiro Aota .alloc_offsets = { 6301ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 6311ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 6321ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 6331ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 6341ba19a6eSNaohiro Aota }, 6351ba19a6eSNaohiro Aota .last_alloc = BTRFS_STRIPE_LEN * 5, 6361ba19a6eSNaohiro Aota .expected_alloc_offset = BTRFS_STRIPE_LEN * 5, 6371ba19a6eSNaohiro Aota }, 6381ba19a6eSNaohiro Aota { 6391ba19a6eSNaohiro Aota .description = "RAID10: fail: stripes [2, ?, 1, ?] last_alloc = 7", 6401ba19a6eSNaohiro Aota .raid_type = BTRFS_BLOCK_GROUP_RAID10, 6411ba19a6eSNaohiro Aota .num_stripes = 8, 6421ba19a6eSNaohiro Aota .alloc_offsets = { 6431ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN * 2, BTRFS_STRIPE_LEN * 2, 6441ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 6451ba19a6eSNaohiro Aota BTRFS_STRIPE_LEN, BTRFS_STRIPE_LEN, 6461ba19a6eSNaohiro Aota WP_CONVENTIONAL, WP_CONVENTIONAL, 6471ba19a6eSNaohiro Aota }, 6481ba19a6eSNaohiro Aota .last_alloc = BTRFS_STRIPE_LEN * 7, 6491ba19a6eSNaohiro Aota .expected_result = -EIO, 6501ba19a6eSNaohiro Aota }, 6511ba19a6eSNaohiro Aota }; 6521ba19a6eSNaohiro Aota 6531ba19a6eSNaohiro Aota int btrfs_test_zoned(void) 6541ba19a6eSNaohiro Aota { 6551ba19a6eSNaohiro Aota struct btrfs_fs_info *fs_info __free(btrfs_free_dummy_fs_info) = NULL; 6561ba19a6eSNaohiro Aota int ret; 6571ba19a6eSNaohiro Aota 6581ba19a6eSNaohiro Aota test_msg("running zoned tests (error messages are expected)"); 6591ba19a6eSNaohiro Aota 6601ba19a6eSNaohiro Aota fs_info = btrfs_alloc_dummy_fs_info(PAGE_SIZE, PAGE_SIZE); 6611ba19a6eSNaohiro Aota if (!fs_info) { 6621ba19a6eSNaohiro Aota test_std_err(TEST_ALLOC_FS_INFO); 6631ba19a6eSNaohiro Aota return -ENOMEM; 6641ba19a6eSNaohiro Aota } 6651ba19a6eSNaohiro Aota 6661ba19a6eSNaohiro Aota for (int i = 0; i < ARRAY_SIZE(load_zone_info_tests); i++) { 6671ba19a6eSNaohiro Aota ret = test_load_zone_info(fs_info, &load_zone_info_tests[i]); 6681ba19a6eSNaohiro Aota if (ret) { 6691ba19a6eSNaohiro Aota test_err("test case \"%s\" failed", load_zone_info_tests[i].description); 6701ba19a6eSNaohiro Aota return ret; 6711ba19a6eSNaohiro Aota } 6721ba19a6eSNaohiro Aota } 6731ba19a6eSNaohiro Aota 6741ba19a6eSNaohiro Aota return 0; 6751ba19a6eSNaohiro Aota } 676