]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
btrfs: Add self-tests for btrfs_rmap_block
authorNikolay Borisov <nborisov@suse.com>
Tue, 10 Dec 2019 18:00:45 +0000 (20:00 +0200)
committerDavid Sterba <dsterba@suse.com>
Thu, 23 Jan 2020 16:24:35 +0000 (17:24 +0100)
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>
fs/btrfs/tests/extent-map-tests.c

index 4a7f796c9900fe40bbe6cab96c6c5b533ba5e716..57379e96ccc9094e01d47e070ee77ab33371af30 100644 (file)
@@ -6,6 +6,9 @@
 #include <linux/types.h>
 #include "btrfs-tests.h"
 #include "../ctree.h"
+#include "../volumes.h"
+#include "../disk-io.h"
+#include "../block-group.h"
 
 static void free_extent_map_tree(struct extent_map_tree *em_tree)
 {
@@ -437,11 +440,153 @@ static int test_case_4(struct btrfs_fs_info *fs_info,
        return ret;
 }
 
+struct rmap_test_vector {
+       u64 raid_type;
+       u64 physical_start;
+       u64 data_stripe_size;
+       u64 num_data_stripes;
+       u64 num_stripes;
+       /* Assume we won't have more than 5 physical stripes */
+       u64 data_stripe_phys_start[5];
+       bool expected_mapped_addr;
+       /* Physical to logical addresses */
+       u64 mapped_logical[5];
+};
+
+static int test_rmap_block(struct btrfs_fs_info *fs_info,
+                          struct rmap_test_vector *test)
+{
+       struct extent_map *em;
+       struct map_lookup *map = NULL;
+       u64 *logical = NULL;
+       int i, out_ndaddrs, out_stripe_len;
+       int ret;
+
+       em = alloc_extent_map();
+       if (!em) {
+               test_std_err(TEST_ALLOC_EXTENT_MAP);
+               return -ENOMEM;
+       }
+
+       map = kmalloc(map_lookup_size(test->num_stripes), GFP_KERNEL);
+       if (!map) {
+               kfree(em);
+               test_std_err(TEST_ALLOC_EXTENT_MAP);
+               return -ENOMEM;
+       }
+
+       set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags);
+       /* Start at 4GiB logical address */
+       em->start = SZ_4G;
+       em->len = test->data_stripe_size * test->num_data_stripes;
+       em->block_len = em->len;
+       em->orig_block_len = test->data_stripe_size;
+       em->map_lookup = map;
+
+       map->num_stripes = test->num_stripes;
+       map->stripe_len = BTRFS_STRIPE_LEN;
+       map->type = test->raid_type;
+
+       for (i = 0; i < map->num_stripes; i++) {
+               struct btrfs_device *dev = btrfs_alloc_dummy_device(fs_info);
+
+               if (IS_ERR(dev)) {
+                       test_err("cannot allocate device");
+                       ret = PTR_ERR(dev);
+                       goto out;
+               }
+               map->stripes[i].dev = dev;
+               map->stripes[i].physical = test->data_stripe_phys_start[i];
+       }
+
+       write_lock(&fs_info->mapping_tree.lock);
+       ret = add_extent_mapping(&fs_info->mapping_tree, em, 0);
+       write_unlock(&fs_info->mapping_tree.lock);
+       if (ret) {
+               test_err("error adding block group mapping to mapping tree");
+               goto out_free;
+       }
+
+       ret = btrfs_rmap_block(fs_info, em->start, btrfs_sb_offset(1),
+                              &logical, &out_ndaddrs, &out_stripe_len);
+       if (ret || (out_ndaddrs == 0 && test->expected_mapped_addr)) {
+               test_err("didn't rmap anything but expected %d",
+                        test->expected_mapped_addr);
+               goto out;
+       }
+
+       if (out_stripe_len != BTRFS_STRIPE_LEN) {
+               test_err("calculated stripe length doesn't match");
+               goto out;
+       }
+
+       if (out_ndaddrs != test->expected_mapped_addr) {
+               for (i = 0; i < out_ndaddrs; i++)
+                       test_msg("mapped %llu", logical[i]);
+               test_err("unexpected number of mapped addresses: %d", out_ndaddrs);
+               goto out;
+       }
+
+       for (i = 0; i < out_ndaddrs; i++) {
+               if (logical[i] != test->mapped_logical[i]) {
+                       test_err("unexpected logical address mapped");
+                       goto out;
+               }
+       }
+
+       ret = 0;
+out:
+       write_lock(&fs_info->mapping_tree.lock);
+       remove_extent_mapping(&fs_info->mapping_tree, em);
+       write_unlock(&fs_info->mapping_tree.lock);
+       /* For us */
+       free_extent_map(em);
+out_free:
+       /* For the tree */
+       free_extent_map(em);
+       kfree(logical);
+       return ret;
+}
+
 int btrfs_test_extent_map(void)
 {
        struct btrfs_fs_info *fs_info = NULL;
        struct extent_map_tree *em_tree;
-       int ret = 0;
+       int ret = 0, i;
+       struct rmap_test_vector rmap_tests[] = {
+               {
+                       /*
+                        * Test a chunk with 2 data stripes one of which
+                        * interesects the physical address of the super block
+                        * is correctly recognised.
+                        */
+                       .raid_type = BTRFS_BLOCK_GROUP_RAID1,
+                       .physical_start = SZ_64M - SZ_4M,
+                       .data_stripe_size = SZ_256M,
+                       .num_data_stripes = 2,
+                       .num_stripes = 2,
+                       .data_stripe_phys_start =
+                               {SZ_64M - SZ_4M, SZ_64M - SZ_4M + SZ_256M},
+                       .expected_mapped_addr = true,
+                       .mapped_logical= {SZ_4G + SZ_4M}
+               },
+               {
+                       /*
+                        * Test that out-of-range physical addresses are
+                        * ignored
+                        */
+
+                        /* SINGLE chunk type */
+                       .raid_type = 0,
+                       .physical_start = SZ_4G,
+                       .data_stripe_size = SZ_256M,
+                       .num_data_stripes = 1,
+                       .num_stripes = 1,
+                       .data_stripe_phys_start = {SZ_256M},
+                       .expected_mapped_addr = false,
+                       .mapped_logical = {0}
+               }
+       };
 
        test_msg("running extent_map tests");
 
@@ -474,6 +619,13 @@ int btrfs_test_extent_map(void)
                goto out;
        ret = test_case_4(fs_info, em_tree);
 
+       test_msg("running rmap tests");
+       for (i = 0; i < ARRAY_SIZE(rmap_tests); i++) {
+               ret = test_rmap_block(fs_info, &rmap_tests[i]);
+               if (ret)
+                       goto out;
+       }
+
 out:
        kfree(em_tree);
        btrfs_free_dummy_fs_info(fs_info);