@@ -708,6 +708,141 @@ static int test_case_6(struct btrfs_fs_info *fs_info, struct extent_map_tree *em
708
708
return ret ;
709
709
}
710
710
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
+
711
846
struct rmap_test_vector {
712
847
u64 raid_type ;
713
848
u64 physical_start ;
@@ -891,6 +1026,9 @@ int btrfs_test_extent_map(void)
891
1026
if (ret )
892
1027
goto out ;
893
1028
ret = test_case_6 (fs_info , em_tree );
1029
+ if (ret )
1030
+ goto out ;
1031
+ ret = test_case_7 ();
894
1032
if (ret )
895
1033
goto out ;
896
1034
0 commit comments