Skip to content

Commit bf2e2eb

Browse files
lorddoskiaskdave
authored andcommitted
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 <[email protected]> Reviewed-by: David Sterba <[email protected]> [ update changelog ] Signed-off-by: David Sterba <[email protected]>
1 parent b3ad2c1 commit bf2e2eb

File tree

1 file changed

+153
-1
lines changed

1 file changed

+153
-1
lines changed

fs/btrfs/tests/extent-map-tests.c

Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
#include <linux/types.h>
77
#include "btrfs-tests.h"
88
#include "../ctree.h"
9+
#include "../volumes.h"
10+
#include "../disk-io.h"
11+
#include "../block-group.h"
912

1013
static void free_extent_map_tree(struct extent_map_tree *em_tree)
1114
{
@@ -437,11 +440,153 @@ static int test_case_4(struct btrfs_fs_info *fs_info,
437440
return ret;
438441
}
439442

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

446591
test_msg("running extent_map tests");
447592

@@ -474,6 +619,13 @@ int btrfs_test_extent_map(void)
474619
goto out;
475620
ret = test_case_4(fs_info, em_tree);
476621

622+
test_msg("running rmap tests");
623+
for (i = 0; i < ARRAY_SIZE(rmap_tests); i++) {
624+
ret = test_rmap_block(fs_info, &rmap_tests[i]);
625+
if (ret)
626+
goto out;
627+
}
628+
477629
out:
478630
kfree(em_tree);
479631
btrfs_free_dummy_fs_info(fs_info);

0 commit comments

Comments
 (0)