mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
btrfs: tests: test invalid splitting when skipping pinned drop extent_map
This reproduces the bug fixed by "btrfs: fix incorrect splitting in btrfs_drop_extent_map_range", we were improperly calculating the range for the split extent. Add a test that exercises this scenario and validates that we get the correct resulting extent_maps in our tree. Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
f345dbdf2c
commit
92e1229b20
@ -708,6 +708,141 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Regression test for btrfs_drop_extent_map_range. Calling with skip_pinned ==
|
||||
* true would mess up the start/end calculations and subsequent splits would be
|
||||
* incorrect.
|
||||
*/
|
||||
static int test_case_7(void)
|
||||
{
|
||||
struct extent_map_tree *em_tree;
|
||||
struct extent_map *em;
|
||||
struct inode *inode;
|
||||
int ret;
|
||||
|
||||
test_msg("Running btrfs_drop_extent_cache with pinned");
|
||||
|
||||
inode = btrfs_new_test_inode();
|
||||
if (!inode) {
|
||||
test_std_err(TEST_ALLOC_INODE);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
em_tree = &BTRFS_I(inode)->extent_tree;
|
||||
|
||||
em = alloc_extent_map();
|
||||
if (!em) {
|
||||
test_std_err(TEST_ALLOC_EXTENT_MAP);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* [0, 16K), pinned */
|
||||
em->start = 0;
|
||||
em->len = SZ_16K;
|
||||
em->block_start = 0;
|
||||
em->block_len = SZ_4K;
|
||||
set_bit(EXTENT_FLAG_PINNED, &em->flags);
|
||||
write_lock(&em_tree->lock);
|
||||
ret = add_extent_mapping(em_tree, em, 0);
|
||||
write_unlock(&em_tree->lock);
|
||||
if (ret < 0) {
|
||||
test_err("couldn't add extent map");
|
||||
goto out;
|
||||
}
|
||||
free_extent_map(em);
|
||||
|
||||
em = alloc_extent_map();
|
||||
if (!em) {
|
||||
test_std_err(TEST_ALLOC_EXTENT_MAP);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* [32K, 48K), not pinned */
|
||||
em->start = SZ_32K;
|
||||
em->len = SZ_16K;
|
||||
em->block_start = SZ_32K;
|
||||
em->block_len = SZ_16K;
|
||||
write_lock(&em_tree->lock);
|
||||
ret = add_extent_mapping(em_tree, em, 0);
|
||||
write_unlock(&em_tree->lock);
|
||||
if (ret < 0) {
|
||||
test_err("couldn't add extent map");
|
||||
goto out;
|
||||
}
|
||||
free_extent_map(em);
|
||||
|
||||
/*
|
||||
* Drop [0, 36K) This should skip the [0, 4K) extent and then split the
|
||||
* [32K, 48K) extent.
|
||||
*/
|
||||
btrfs_drop_extent_map_range(BTRFS_I(inode), 0, (36 * SZ_1K) - 1, true);
|
||||
|
||||
/* Make sure our extent maps look sane. */
|
||||
ret = -EINVAL;
|
||||
|
||||
em = lookup_extent_mapping(em_tree, 0, SZ_16K);
|
||||
if (!em) {
|
||||
test_err("didn't find an em at 0 as expected");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (em->start != 0) {
|
||||
test_err("em->start is %llu, expected 0", em->start);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (em->len != SZ_16K) {
|
||||
test_err("em->len is %llu, expected 16K", em->len);
|
||||
goto out;
|
||||
}
|
||||
|
||||
free_extent_map(em);
|
||||
|
||||
read_lock(&em_tree->lock);
|
||||
em = lookup_extent_mapping(em_tree, SZ_16K, SZ_16K);
|
||||
read_unlock(&em_tree->lock);
|
||||
if (em) {
|
||||
test_err("found an em when we weren't expecting one");
|
||||
goto out;
|
||||
}
|
||||
|
||||
read_lock(&em_tree->lock);
|
||||
em = lookup_extent_mapping(em_tree, SZ_32K, SZ_16K);
|
||||
read_unlock(&em_tree->lock);
|
||||
if (!em) {
|
||||
test_err("didn't find an em at 32K as expected");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (em->start != (36 * SZ_1K)) {
|
||||
test_err("em->start is %llu, expected 36K", em->start);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (em->len != (12 * SZ_1K)) {
|
||||
test_err("em->len is %llu, expected 12K", em->len);
|
||||
goto out;
|
||||
}
|
||||
|
||||
free_extent_map(em);
|
||||
|
||||
read_lock(&em_tree->lock);
|
||||
em = lookup_extent_mapping(em_tree, 48 * SZ_1K, (u64)-1);
|
||||
read_unlock(&em_tree->lock);
|
||||
if (em) {
|
||||
test_err("found an unexpected em above 48K");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
free_extent_map(em);
|
||||
iput(inode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct rmap_test_vector {
|
||||
u64 raid_type;
|
||||
u64 physical_start;
|
||||
@ -891,6 +1026,9 @@ int btrfs_test_extent_map(void)
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = test_case_6(fs_info, em_tree);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = test_case_7();
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user