Skip to content

Commit 92e1229

Browse files
josefbacikkdave
authored andcommitted
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 <[email protected]> Signed-off-by: Josef Bacik <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent f345dbd commit 92e1229

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

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

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,141 @@ static int test_case_6(struct btrfs_fs_info *fs_info, struct extent_map_tree *em
708708
return ret;
709709
}
710710

711+
/*
712+
* Regression test for btrfs_drop_extent_map_range. Calling with skip_pinned ==
713+
* true would mess up the start/end calculations and subsequent splits would be
714+
* incorrect.
715+
*/
716+
static int test_case_7(void)
717+
{
718+
struct extent_map_tree *em_tree;
719+
struct extent_map *em;
720+
struct inode *inode;
721+
int ret;
722+
723+
test_msg("Running btrfs_drop_extent_cache with pinned");
724+
725+
inode = btrfs_new_test_inode();
726+
if (!inode) {
727+
test_std_err(TEST_ALLOC_INODE);
728+
return -ENOMEM;
729+
}
730+
731+
em_tree = &BTRFS_I(inode)->extent_tree;
732+
733+
em = alloc_extent_map();
734+
if (!em) {
735+
test_std_err(TEST_ALLOC_EXTENT_MAP);
736+
ret = -ENOMEM;
737+
goto out;
738+
}
739+
740+
/* [0, 16K), pinned */
741+
em->start = 0;
742+
em->len = SZ_16K;
743+
em->block_start = 0;
744+
em->block_len = SZ_4K;
745+
set_bit(EXTENT_FLAG_PINNED, &em->flags);
746+
write_lock(&em_tree->lock);
747+
ret = add_extent_mapping(em_tree, em, 0);
748+
write_unlock(&em_tree->lock);
749+
if (ret < 0) {
750+
test_err("couldn't add extent map");
751+
goto out;
752+
}
753+
free_extent_map(em);
754+
755+
em = alloc_extent_map();
756+
if (!em) {
757+
test_std_err(TEST_ALLOC_EXTENT_MAP);
758+
ret = -ENOMEM;
759+
goto out;
760+
}
761+
762+
/* [32K, 48K), not pinned */
763+
em->start = SZ_32K;
764+
em->len = SZ_16K;
765+
em->block_start = SZ_32K;
766+
em->block_len = SZ_16K;
767+
write_lock(&em_tree->lock);
768+
ret = add_extent_mapping(em_tree, em, 0);
769+
write_unlock(&em_tree->lock);
770+
if (ret < 0) {
771+
test_err("couldn't add extent map");
772+
goto out;
773+
}
774+
free_extent_map(em);
775+
776+
/*
777+
* Drop [0, 36K) This should skip the [0, 4K) extent and then split the
778+
* [32K, 48K) extent.
779+
*/
780+
btrfs_drop_extent_map_range(BTRFS_I(inode), 0, (36 * SZ_1K) - 1, true);
781+
782+
/* Make sure our extent maps look sane. */
783+
ret = -EINVAL;
784+
785+
em = lookup_extent_mapping(em_tree, 0, SZ_16K);
786+
if (!em) {
787+
test_err("didn't find an em at 0 as expected");
788+
goto out;
789+
}
790+
791+
if (em->start != 0) {
792+
test_err("em->start is %llu, expected 0", em->start);
793+
goto out;
794+
}
795+
796+
if (em->len != SZ_16K) {
797+
test_err("em->len is %llu, expected 16K", em->len);
798+
goto out;
799+
}
800+
801+
free_extent_map(em);
802+
803+
read_lock(&em_tree->lock);
804+
em = lookup_extent_mapping(em_tree, SZ_16K, SZ_16K);
805+
read_unlock(&em_tree->lock);
806+
if (em) {
807+
test_err("found an em when we weren't expecting one");
808+
goto out;
809+
}
810+
811+
read_lock(&em_tree->lock);
812+
em = lookup_extent_mapping(em_tree, SZ_32K, SZ_16K);
813+
read_unlock(&em_tree->lock);
814+
if (!em) {
815+
test_err("didn't find an em at 32K as expected");
816+
goto out;
817+
}
818+
819+
if (em->start != (36 * SZ_1K)) {
820+
test_err("em->start is %llu, expected 36K", em->start);
821+
goto out;
822+
}
823+
824+
if (em->len != (12 * SZ_1K)) {
825+
test_err("em->len is %llu, expected 12K", em->len);
826+
goto out;
827+
}
828+
829+
free_extent_map(em);
830+
831+
read_lock(&em_tree->lock);
832+
em = lookup_extent_mapping(em_tree, 48 * SZ_1K, (u64)-1);
833+
read_unlock(&em_tree->lock);
834+
if (em) {
835+
test_err("found an unexpected em above 48K");
836+
goto out;
837+
}
838+
839+
ret = 0;
840+
out:
841+
free_extent_map(em);
842+
iput(inode);
843+
return ret;
844+
}
845+
711846
struct rmap_test_vector {
712847
u64 raid_type;
713848
u64 physical_start;
@@ -891,6 +1026,9 @@ int btrfs_test_extent_map(void)
8911026
if (ret)
8921027
goto out;
8931028
ret = test_case_6(fs_info, em_tree);
1029+
if (ret)
1030+
goto out;
1031+
ret = test_case_7();
8941032
if (ret)
8951033
goto out;
8961034

0 commit comments

Comments
 (0)