Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

btrfs: Add self-tests for btrfs_rmap_block

Add RAID1 and single testcases to verify that data stripes are excluded
from super block locations and that the address mapping is valid.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
[ update changelog ]
Signed-off-by: David Sterba <dsterba@suse.com>

authored by

Nikolay Borisov and committed by
David Sterba
bf2e2eb0 b3ad2c17

+153 -1
+153 -1
fs/btrfs/tests/extent-map-tests.c
··· 6 6 #include <linux/types.h> 7 7 #include "btrfs-tests.h" 8 8 #include "../ctree.h" 9 + #include "../volumes.h" 10 + #include "../disk-io.h" 11 + #include "../block-group.h" 9 12 10 13 static void free_extent_map_tree(struct extent_map_tree *em_tree) 11 14 { ··· 440 437 return ret; 441 438 } 442 439 440 + struct rmap_test_vector { 441 + u64 raid_type; 442 + u64 physical_start; 443 + u64 data_stripe_size; 444 + u64 num_data_stripes; 445 + u64 num_stripes; 446 + /* Assume we won't have more than 5 physical stripes */ 447 + u64 data_stripe_phys_start[5]; 448 + bool expected_mapped_addr; 449 + /* Physical to logical addresses */ 450 + u64 mapped_logical[5]; 451 + }; 452 + 453 + static int test_rmap_block(struct btrfs_fs_info *fs_info, 454 + struct rmap_test_vector *test) 455 + { 456 + struct extent_map *em; 457 + struct map_lookup *map = NULL; 458 + u64 *logical = NULL; 459 + int i, out_ndaddrs, out_stripe_len; 460 + int ret; 461 + 462 + em = alloc_extent_map(); 463 + if (!em) { 464 + test_std_err(TEST_ALLOC_EXTENT_MAP); 465 + return -ENOMEM; 466 + } 467 + 468 + map = kmalloc(map_lookup_size(test->num_stripes), GFP_KERNEL); 469 + if (!map) { 470 + kfree(em); 471 + test_std_err(TEST_ALLOC_EXTENT_MAP); 472 + return -ENOMEM; 473 + } 474 + 475 + set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags); 476 + /* Start at 4GiB logical address */ 477 + em->start = SZ_4G; 478 + em->len = test->data_stripe_size * test->num_data_stripes; 479 + em->block_len = em->len; 480 + em->orig_block_len = test->data_stripe_size; 481 + em->map_lookup = map; 482 + 483 + map->num_stripes = test->num_stripes; 484 + map->stripe_len = BTRFS_STRIPE_LEN; 485 + map->type = test->raid_type; 486 + 487 + for (i = 0; i < map->num_stripes; i++) { 488 + struct btrfs_device *dev = btrfs_alloc_dummy_device(fs_info); 489 + 490 + if (IS_ERR(dev)) { 491 + test_err("cannot allocate device"); 492 + ret = PTR_ERR(dev); 493 + goto out; 494 + } 495 + map->stripes[i].dev = dev; 496 + map->stripes[i].physical = test->data_stripe_phys_start[i]; 497 + } 498 + 499 + write_lock(&fs_info->mapping_tree.lock); 500 + ret = add_extent_mapping(&fs_info->mapping_tree, em, 0); 501 + write_unlock(&fs_info->mapping_tree.lock); 502 + if (ret) { 503 + test_err("error adding block group mapping to mapping tree"); 504 + goto out_free; 505 + } 506 + 507 + ret = btrfs_rmap_block(fs_info, em->start, btrfs_sb_offset(1), 508 + &logical, &out_ndaddrs, &out_stripe_len); 509 + if (ret || (out_ndaddrs == 0 && test->expected_mapped_addr)) { 510 + test_err("didn't rmap anything but expected %d", 511 + test->expected_mapped_addr); 512 + goto out; 513 + } 514 + 515 + if (out_stripe_len != BTRFS_STRIPE_LEN) { 516 + test_err("calculated stripe length doesn't match"); 517 + goto out; 518 + } 519 + 520 + if (out_ndaddrs != test->expected_mapped_addr) { 521 + for (i = 0; i < out_ndaddrs; i++) 522 + test_msg("mapped %llu", logical[i]); 523 + test_err("unexpected number of mapped addresses: %d", out_ndaddrs); 524 + goto out; 525 + } 526 + 527 + for (i = 0; i < out_ndaddrs; i++) { 528 + if (logical[i] != test->mapped_logical[i]) { 529 + test_err("unexpected logical address mapped"); 530 + goto out; 531 + } 532 + } 533 + 534 + ret = 0; 535 + out: 536 + write_lock(&fs_info->mapping_tree.lock); 537 + remove_extent_mapping(&fs_info->mapping_tree, em); 538 + write_unlock(&fs_info->mapping_tree.lock); 539 + /* For us */ 540 + free_extent_map(em); 541 + out_free: 542 + /* For the tree */ 543 + free_extent_map(em); 544 + kfree(logical); 545 + return ret; 546 + } 547 + 443 548 int btrfs_test_extent_map(void) 444 549 { 445 550 struct btrfs_fs_info *fs_info = NULL; 446 551 struct extent_map_tree *em_tree; 447 - int ret = 0; 552 + int ret = 0, i; 553 + struct rmap_test_vector rmap_tests[] = { 554 + { 555 + /* 556 + * Test a chunk with 2 data stripes one of which 557 + * interesects the physical address of the super block 558 + * is correctly recognised. 559 + */ 560 + .raid_type = BTRFS_BLOCK_GROUP_RAID1, 561 + .physical_start = SZ_64M - SZ_4M, 562 + .data_stripe_size = SZ_256M, 563 + .num_data_stripes = 2, 564 + .num_stripes = 2, 565 + .data_stripe_phys_start = 566 + {SZ_64M - SZ_4M, SZ_64M - SZ_4M + SZ_256M}, 567 + .expected_mapped_addr = true, 568 + .mapped_logical= {SZ_4G + SZ_4M} 569 + }, 570 + { 571 + /* 572 + * Test that out-of-range physical addresses are 573 + * ignored 574 + */ 575 + 576 + /* SINGLE chunk type */ 577 + .raid_type = 0, 578 + .physical_start = SZ_4G, 579 + .data_stripe_size = SZ_256M, 580 + .num_data_stripes = 1, 581 + .num_stripes = 1, 582 + .data_stripe_phys_start = {SZ_256M}, 583 + .expected_mapped_addr = false, 584 + .mapped_logical = {0} 585 + } 586 + }; 448 587 449 588 test_msg("running extent_map tests"); 450 589 ··· 618 473 if (ret) 619 474 goto out; 620 475 ret = test_case_4(fs_info, em_tree); 476 + 477 + test_msg("running rmap tests"); 478 + for (i = 0; i < ARRAY_SIZE(rmap_tests); i++) { 479 + ret = test_rmap_block(fs_info, &rmap_tests[i]); 480 + if (ret) 481 + goto out; 482 + } 621 483 622 484 out: 623 485 kfree(em_tree);