@@ -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+
711846struct 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