1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2024 Western Digital Corporation or its affiliates. 4 */ 5 6 #include <linux/sizes.h> 7 #include "../fs.h" 8 #include "../disk-io.h" 9 #include "../transaction.h" 10 #include "../volumes.h" 11 #include "../raid-stripe-tree.h" 12 #include "btrfs-tests.h" 13 14 #define RST_TEST_NUM_DEVICES (2) 15 #define RST_TEST_RAID1_TYPE (BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_RAID1) 16 17 typedef int (*test_func_t)(struct btrfs_trans_handle *trans); 18 19 static struct btrfs_device *btrfs_device_by_devid(struct btrfs_fs_devices *fs_devices, 20 u64 devid) 21 { 22 struct btrfs_device *dev; 23 24 list_for_each_entry(dev, &fs_devices->devices, dev_list) { 25 if (dev->devid == devid) 26 return dev; 27 } 28 29 return NULL; 30 } 31 32 /* 33 * Test a 64K RST write on a 2 disk RAID1 at a logical address of 1M and then 34 * delete the 1st 32K, making the new start address 1M+32K. 35 */ 36 static int test_front_delete(struct btrfs_trans_handle *trans) 37 { 38 struct btrfs_fs_info *fs_info = trans->fs_info; 39 struct btrfs_io_context *bioc; 40 struct btrfs_io_stripe io_stripe = { 0 }; 41 u64 map_type = RST_TEST_RAID1_TYPE; 42 u64 logical = SZ_1M; 43 u64 len = SZ_64K; 44 int ret; 45 46 bioc = alloc_btrfs_io_context(fs_info, logical, RST_TEST_NUM_DEVICES); 47 if (!bioc) { 48 test_std_err(TEST_ALLOC_IO_CONTEXT); 49 ret = -ENOMEM; 50 goto out; 51 } 52 53 io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0); 54 bioc->map_type = map_type; 55 bioc->size = len; 56 57 for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) { 58 struct btrfs_io_stripe *stripe = &bioc->stripes[i]; 59 60 stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i); 61 if (!stripe->dev) { 62 test_err("cannot find device with devid %d", i); 63 ret = -EINVAL; 64 goto out; 65 } 66 67 stripe->physical = logical + i * SZ_1G; 68 } 69 70 ret = btrfs_insert_one_raid_extent(trans, bioc); 71 if (ret) { 72 test_err("inserting RAID extent failed: %d", ret); 73 goto out; 74 } 75 76 ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe); 77 if (ret) { 78 test_err("lookup of RAID extent [%llu, %llu] failed", logical, 79 logical + len); 80 goto out; 81 } 82 83 if (io_stripe.physical != logical) { 84 test_err("invalid physical address, expected %llu got %llu", 85 logical, io_stripe.physical); 86 ret = -EINVAL; 87 goto out; 88 } 89 90 if (len != SZ_64K) { 91 test_err("invalid stripe length, expected %llu got %llu", 92 (u64)SZ_64K, len); 93 ret = -EINVAL; 94 goto out; 95 } 96 97 ret = btrfs_delete_raid_extent(trans, logical, SZ_32K); 98 if (ret) { 99 test_err("deleting RAID extent [%llu, %llu] failed", logical, 100 logical + SZ_32K); 101 goto out; 102 } 103 104 len = SZ_32K; 105 ret = btrfs_get_raid_extent_offset(fs_info, logical + SZ_32K, &len, 106 map_type, 0, &io_stripe); 107 if (ret) { 108 test_err("lookup of RAID extent [%llu, %llu] failed", 109 logical + SZ_32K, logical + SZ_32K + len); 110 goto out; 111 } 112 113 if (io_stripe.physical != logical + SZ_32K) { 114 test_err("invalid physical address, expected %llu, got %llu", 115 logical + SZ_32K, io_stripe.physical); 116 ret = -EINVAL; 117 goto out; 118 } 119 120 if (len != SZ_32K) { 121 test_err("invalid stripe length, expected %llu, got %llu", 122 (u64)SZ_32K, len); 123 ret = -EINVAL; 124 goto out; 125 } 126 127 ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe); 128 if (!ret) { 129 ret = -EINVAL; 130 test_err("lookup of RAID extent [%llu, %llu] succeeded, should fail", 131 logical, logical + SZ_32K); 132 goto out; 133 } 134 135 ret = btrfs_delete_raid_extent(trans, logical + SZ_32K, SZ_32K); 136 out: 137 btrfs_put_bioc(bioc); 138 return ret; 139 } 140 141 /* 142 * Test a 64K RST write on a 2 disk RAID1 at a logical address of 1M and then 143 * truncate the stripe extent down to 32K. 144 */ 145 static int test_tail_delete(struct btrfs_trans_handle *trans) 146 { 147 struct btrfs_fs_info *fs_info = trans->fs_info; 148 struct btrfs_io_context *bioc; 149 struct btrfs_io_stripe io_stripe = { 0 }; 150 u64 map_type = RST_TEST_RAID1_TYPE; 151 u64 logical = SZ_1M; 152 u64 len = SZ_64K; 153 int ret; 154 155 bioc = alloc_btrfs_io_context(fs_info, logical, RST_TEST_NUM_DEVICES); 156 if (!bioc) { 157 test_std_err(TEST_ALLOC_IO_CONTEXT); 158 ret = -ENOMEM; 159 goto out; 160 } 161 162 io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0); 163 bioc->map_type = map_type; 164 bioc->size = len; 165 166 for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) { 167 struct btrfs_io_stripe *stripe = &bioc->stripes[i]; 168 169 stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i); 170 if (!stripe->dev) { 171 test_err("cannot find device with devid %d", i); 172 ret = -EINVAL; 173 goto out; 174 } 175 176 stripe->physical = logical + i * SZ_1G; 177 } 178 179 ret = btrfs_insert_one_raid_extent(trans, bioc); 180 if (ret) { 181 test_err("inserting RAID extent failed: %d", ret); 182 goto out; 183 } 184 185 io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0); 186 if (!io_stripe.dev) { 187 ret = -EINVAL; 188 goto out; 189 } 190 191 ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe); 192 if (ret) { 193 test_err("lookup of RAID extent [%llu, %llu] failed", logical, 194 logical + len); 195 goto out; 196 } 197 198 if (io_stripe.physical != logical) { 199 test_err("invalid physical address, expected %llu got %llu", 200 logical, io_stripe.physical); 201 ret = -EINVAL; 202 goto out; 203 } 204 205 if (len != SZ_64K) { 206 test_err("invalid stripe length, expected %llu got %llu", 207 (u64)SZ_64K, len); 208 ret = -EINVAL; 209 goto out; 210 } 211 212 ret = btrfs_delete_raid_extent(trans, logical + SZ_32K, SZ_32K); 213 if (ret) { 214 test_err("deleting RAID extent [%llu, %llu] failed", 215 logical + SZ_32K, logical + SZ_64K); 216 goto out; 217 } 218 219 len = SZ_32K; 220 ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe); 221 if (ret) { 222 test_err("lookup of RAID extent [%llu, %llu] failed", logical, 223 logical + len); 224 goto out; 225 } 226 227 if (io_stripe.physical != logical) { 228 test_err("invalid physical address, expected %llu, got %llu", 229 logical, io_stripe.physical); 230 ret = -EINVAL; 231 goto out; 232 } 233 234 if (len != SZ_32K) { 235 test_err("invalid stripe length, expected %llu, got %llu", 236 (u64)SZ_32K, len); 237 ret = -EINVAL; 238 goto out; 239 } 240 241 ret = btrfs_delete_raid_extent(trans, logical, len); 242 if (ret) 243 test_err("deleting RAID extent [%llu, %llu] failed", logical, 244 logical + len); 245 246 out: 247 btrfs_put_bioc(bioc); 248 return ret; 249 } 250 251 /* 252 * Test a 64K RST write on a 2 disk RAID1 at a logical address of 1M and then 253 * overwrite the whole range giving it new physical address at an offset of 1G. 254 * The intent of this test is to exercise the 'update_raid_extent_item()' 255 * function called be btrfs_insert_one_raid_extent(). 256 */ 257 static int test_create_update_delete(struct btrfs_trans_handle *trans) 258 { 259 struct btrfs_fs_info *fs_info = trans->fs_info; 260 struct btrfs_io_context *bioc; 261 struct btrfs_io_stripe io_stripe = { 0 }; 262 u64 map_type = RST_TEST_RAID1_TYPE; 263 u64 logical = SZ_1M; 264 u64 len = SZ_64K; 265 int ret; 266 267 bioc = alloc_btrfs_io_context(fs_info, logical, RST_TEST_NUM_DEVICES); 268 if (!bioc) { 269 test_std_err(TEST_ALLOC_IO_CONTEXT); 270 ret = -ENOMEM; 271 goto out; 272 } 273 274 io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0); 275 bioc->map_type = map_type; 276 bioc->size = len; 277 278 for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) { 279 struct btrfs_io_stripe *stripe = &bioc->stripes[i]; 280 281 stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i); 282 if (!stripe->dev) { 283 test_err("cannot find device with devid %d", i); 284 ret = -EINVAL; 285 goto out; 286 } 287 288 stripe->physical = logical + i * SZ_1G; 289 } 290 291 ret = btrfs_insert_one_raid_extent(trans, bioc); 292 if (ret) { 293 test_err("inserting RAID extent failed: %d", ret); 294 goto out; 295 } 296 297 io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0); 298 if (!io_stripe.dev) { 299 ret = -EINVAL; 300 goto out; 301 } 302 303 ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe); 304 if (ret) { 305 test_err("lookup of RAID extent [%llu, %llu] failed", logical, 306 logical + len); 307 goto out; 308 } 309 310 if (io_stripe.physical != logical) { 311 test_err("invalid physical address, expected %llu got %llu", 312 logical, io_stripe.physical); 313 ret = -EINVAL; 314 goto out; 315 } 316 317 if (len != SZ_64K) { 318 test_err("invalid stripe length, expected %llu got %llu", 319 (u64)SZ_64K, len); 320 ret = -EINVAL; 321 goto out; 322 } 323 324 for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) { 325 struct btrfs_io_stripe *stripe = &bioc->stripes[i]; 326 327 stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i); 328 if (!stripe->dev) { 329 test_err("cannot find device with devid %d", i); 330 ret = -EINVAL; 331 goto out; 332 } 333 334 stripe->physical = SZ_1G + logical + i * SZ_1G; 335 } 336 337 ret = btrfs_insert_one_raid_extent(trans, bioc); 338 if (ret) { 339 test_err("updating RAID extent failed: %d", ret); 340 goto out; 341 } 342 343 ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe); 344 if (ret) { 345 test_err("lookup of RAID extent [%llu, %llu] failed", logical, 346 logical + len); 347 goto out; 348 } 349 350 if (io_stripe.physical != logical + SZ_1G) { 351 test_err("invalid physical address, expected %llu, got %llu", 352 logical + SZ_1G, io_stripe.physical); 353 ret = -EINVAL; 354 goto out; 355 } 356 357 if (len != SZ_64K) { 358 test_err("invalid stripe length, expected %llu, got %llu", 359 (u64)SZ_64K, len); 360 ret = -EINVAL; 361 goto out; 362 } 363 364 ret = btrfs_delete_raid_extent(trans, logical, len); 365 if (ret) 366 test_err("deleting RAID extent [%llu, %llu] failed", logical, 367 logical + len); 368 369 out: 370 btrfs_put_bioc(bioc); 371 return ret; 372 } 373 374 /* 375 * Test a simple 64K RST write on a 2 disk RAID1 at a logical address of 1M. 376 * The "physical" copy on device 0 is at 1M, on device 1 it is at 1G+1M. 377 */ 378 static int test_simple_create_delete(struct btrfs_trans_handle *trans) 379 { 380 struct btrfs_fs_info *fs_info = trans->fs_info; 381 struct btrfs_io_context *bioc; 382 struct btrfs_io_stripe io_stripe = { 0 }; 383 u64 map_type = RST_TEST_RAID1_TYPE; 384 u64 logical = SZ_1M; 385 u64 len = SZ_64K; 386 int ret; 387 388 bioc = alloc_btrfs_io_context(fs_info, logical, RST_TEST_NUM_DEVICES); 389 if (!bioc) { 390 test_std_err(TEST_ALLOC_IO_CONTEXT); 391 ret = -ENOMEM; 392 goto out; 393 } 394 395 bioc->map_type = map_type; 396 bioc->size = SZ_64K; 397 398 for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) { 399 struct btrfs_io_stripe *stripe = &bioc->stripes[i]; 400 401 stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i); 402 if (!stripe->dev) { 403 test_err("cannot find device with devid %d", i); 404 ret = -EINVAL; 405 goto out; 406 } 407 408 stripe->physical = logical + i * SZ_1G; 409 } 410 411 ret = btrfs_insert_one_raid_extent(trans, bioc); 412 if (ret) { 413 test_err("inserting RAID extent failed: %d", ret); 414 goto out; 415 } 416 417 io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0); 418 if (!io_stripe.dev) { 419 ret = -EINVAL; 420 goto out; 421 } 422 423 ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe); 424 if (ret) { 425 test_err("lookup of RAID extent [%llu, %llu] failed", logical, 426 logical + len); 427 goto out; 428 } 429 430 if (io_stripe.physical != logical) { 431 test_err("invalid physical address, expected %llu got %llu", 432 logical, io_stripe.physical); 433 ret = -EINVAL; 434 goto out; 435 } 436 437 if (len != SZ_64K) { 438 test_err("invalid stripe length, expected %llu got %llu", 439 (u64)SZ_64K, len); 440 ret = -EINVAL; 441 goto out; 442 } 443 444 ret = btrfs_delete_raid_extent(trans, logical, len); 445 if (ret) 446 test_err("deleting RAID extent [%llu, %llu] failed", logical, 447 logical + len); 448 449 out: 450 btrfs_put_bioc(bioc); 451 return ret; 452 } 453 454 static const test_func_t tests[] = { 455 test_simple_create_delete, 456 test_create_update_delete, 457 test_tail_delete, 458 test_front_delete, 459 }; 460 461 static int run_test(test_func_t test, u32 sectorsize, u32 nodesize) 462 { 463 struct btrfs_trans_handle trans; 464 struct btrfs_fs_info *fs_info; 465 struct btrfs_root *root = NULL; 466 int ret; 467 468 fs_info = btrfs_alloc_dummy_fs_info(sectorsize, nodesize); 469 if (!fs_info) { 470 test_std_err(TEST_ALLOC_FS_INFO); 471 ret = -ENOMEM; 472 goto out; 473 } 474 475 root = btrfs_alloc_dummy_root(fs_info); 476 if (IS_ERR(root)) { 477 test_std_err(TEST_ALLOC_ROOT); 478 ret = PTR_ERR(root); 479 goto out; 480 } 481 btrfs_set_super_compat_ro_flags(root->fs_info->super_copy, 482 BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE); 483 root->root_key.objectid = BTRFS_RAID_STRIPE_TREE_OBJECTID; 484 root->root_key.type = BTRFS_ROOT_ITEM_KEY; 485 root->root_key.offset = 0; 486 fs_info->stripe_root = root; 487 root->fs_info->tree_root = root; 488 489 root->node = alloc_test_extent_buffer(root->fs_info, nodesize); 490 if (IS_ERR(root->node)) { 491 test_std_err(TEST_ALLOC_EXTENT_BUFFER); 492 ret = PTR_ERR(root->node); 493 goto out; 494 } 495 btrfs_set_header_level(root->node, 0); 496 btrfs_set_header_nritems(root->node, 0); 497 root->alloc_bytenr += 2 * nodesize; 498 499 for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) { 500 struct btrfs_device *dev; 501 502 dev = btrfs_alloc_dummy_device(fs_info); 503 if (IS_ERR(dev)) { 504 test_err("cannot allocate device"); 505 ret = PTR_ERR(dev); 506 goto out; 507 } 508 dev->devid = i; 509 } 510 511 btrfs_init_dummy_trans(&trans, root->fs_info); 512 ret = test(&trans); 513 if (ret) 514 goto out; 515 516 out: 517 btrfs_free_dummy_root(root); 518 btrfs_free_dummy_fs_info(fs_info); 519 520 return ret; 521 } 522 523 int btrfs_test_raid_stripe_tree(u32 sectorsize, u32 nodesize) 524 { 525 int ret = 0; 526 527 test_msg("running raid-stripe-tree tests"); 528 for (int i = 0; i < ARRAY_SIZE(tests); i++) { 529 ret = run_test(tests[i], sectorsize, nodesize); 530 if (ret) { 531 test_err("test-case %ps failed with %d\n", tests[i], ret); 532 goto out; 533 } 534 } 535 536 out: 537 return ret; 538 } 539