@@ -3642,6 +3642,149 @@ static int sync_write_pointer_for_zoned(struct scrub_ctx *sctx, u64 logical,
3642
3642
return ret ;
3643
3643
}
3644
3644
3645
+ static void fill_one_extent_info (struct btrfs_fs_info * fs_info ,
3646
+ struct scrub_stripe * stripe ,
3647
+ u64 extent_start , u64 extent_len ,
3648
+ u64 extent_flags , u64 extent_gen )
3649
+ {
3650
+ for (u64 cur_logical = max (stripe -> logical , extent_start );
3651
+ cur_logical < min (stripe -> logical + BTRFS_STRIPE_LEN ,
3652
+ extent_start + extent_len );
3653
+ cur_logical += fs_info -> sectorsize ) {
3654
+ const int nr_sector = (cur_logical - stripe -> logical ) >>
3655
+ fs_info -> sectorsize_bits ;
3656
+ struct scrub_sector_verification * sector =
3657
+ & stripe -> sectors [nr_sector ];
3658
+
3659
+ set_bit (nr_sector , & stripe -> extent_sector_bitmap );
3660
+ if (extent_flags & BTRFS_EXTENT_FLAG_TREE_BLOCK ) {
3661
+ sector -> is_metadata = true;
3662
+ sector -> generation = extent_gen ;
3663
+ }
3664
+ }
3665
+ }
3666
+
3667
+ static void scrub_stripe_reset_bitmaps (struct scrub_stripe * stripe )
3668
+ {
3669
+ stripe -> extent_sector_bitmap = 0 ;
3670
+ stripe -> init_error_bitmap = 0 ;
3671
+ stripe -> error_bitmap = 0 ;
3672
+ stripe -> io_error_bitmap = 0 ;
3673
+ stripe -> csum_error_bitmap = 0 ;
3674
+ stripe -> meta_error_bitmap = 0 ;
3675
+ }
3676
+
3677
+ /*
3678
+ * Locate one stripe which has at least one extent in its range.
3679
+ *
3680
+ * Return 0 if found such stripe, and store its info into @stripe.
3681
+ * Return >0 if there is no such stripe in the specified range.
3682
+ * Return <0 for error.
3683
+ */
3684
+ int scrub_find_fill_first_stripe (struct btrfs_block_group * bg ,
3685
+ struct btrfs_device * dev , u64 physical ,
3686
+ int mirror_num , u64 logical_start ,
3687
+ u32 logical_len , struct scrub_stripe * stripe )
3688
+ {
3689
+ struct btrfs_fs_info * fs_info = bg -> fs_info ;
3690
+ struct btrfs_root * extent_root = btrfs_extent_root (fs_info , bg -> start );
3691
+ struct btrfs_root * csum_root = btrfs_csum_root (fs_info , bg -> start );
3692
+ const u64 logical_end = logical_start + logical_len ;
3693
+ struct btrfs_path path = { 0 };
3694
+ u64 cur_logical = logical_start ;
3695
+ u64 stripe_end ;
3696
+ u64 extent_start ;
3697
+ u64 extent_len ;
3698
+ u64 extent_flags ;
3699
+ u64 extent_gen ;
3700
+ int ret ;
3701
+
3702
+ memset (stripe -> sectors , 0 , sizeof (struct scrub_sector_verification ) *
3703
+ stripe -> nr_sectors );
3704
+ scrub_stripe_reset_bitmaps (stripe );
3705
+
3706
+ /* The range must be inside the bg. */
3707
+ ASSERT (logical_start >= bg -> start && logical_end <= bg -> start + bg -> length );
3708
+
3709
+ path .search_commit_root = 1 ;
3710
+ path .skip_locking = 1 ;
3711
+
3712
+ ret = find_first_extent_item (extent_root , & path , logical_start , logical_len );
3713
+ /* Either error or not found. */
3714
+ if (ret )
3715
+ goto out ;
3716
+ get_extent_info (& path , & extent_start , & extent_len , & extent_flags , & extent_gen );
3717
+ cur_logical = max (extent_start , cur_logical );
3718
+
3719
+ /*
3720
+ * Round down to stripe boundary.
3721
+ *
3722
+ * The extra calculation against bg->start is to handle block groups
3723
+ * whose logical bytenr is not BTRFS_STRIPE_LEN aligned.
3724
+ */
3725
+ stripe -> logical = round_down (cur_logical - bg -> start , BTRFS_STRIPE_LEN ) +
3726
+ bg -> start ;
3727
+ stripe -> physical = physical + stripe -> logical - logical_start ;
3728
+ stripe -> dev = dev ;
3729
+ stripe -> bg = bg ;
3730
+ stripe -> mirror_num = mirror_num ;
3731
+ stripe_end = stripe -> logical + BTRFS_STRIPE_LEN - 1 ;
3732
+
3733
+ /* Fill the first extent info into stripe->sectors[] array. */
3734
+ fill_one_extent_info (fs_info , stripe , extent_start , extent_len ,
3735
+ extent_flags , extent_gen );
3736
+ cur_logical = extent_start + extent_len ;
3737
+
3738
+ /* Fill the extent info for the remaining sectors. */
3739
+ while (cur_logical <= stripe_end ) {
3740
+ ret = find_first_extent_item (extent_root , & path , cur_logical ,
3741
+ stripe_end - cur_logical + 1 );
3742
+ if (ret < 0 )
3743
+ goto out ;
3744
+ if (ret > 0 ) {
3745
+ ret = 0 ;
3746
+ break ;
3747
+ }
3748
+ get_extent_info (& path , & extent_start , & extent_len ,
3749
+ & extent_flags , & extent_gen );
3750
+ fill_one_extent_info (fs_info , stripe , extent_start , extent_len ,
3751
+ extent_flags , extent_gen );
3752
+ cur_logical = extent_start + extent_len ;
3753
+ }
3754
+
3755
+ /* Now fill the data csum. */
3756
+ if (bg -> flags & BTRFS_BLOCK_GROUP_DATA ) {
3757
+ int sector_nr ;
3758
+ unsigned long csum_bitmap = 0 ;
3759
+
3760
+ /* Csum space should have already been allocated. */
3761
+ ASSERT (stripe -> csums );
3762
+
3763
+ /*
3764
+ * Our csum bitmap should be large enough, as BTRFS_STRIPE_LEN
3765
+ * should contain at most 16 sectors.
3766
+ */
3767
+ ASSERT (BITS_PER_LONG >= BTRFS_STRIPE_LEN >> fs_info -> sectorsize_bits );
3768
+
3769
+ ret = btrfs_lookup_csums_bitmap (csum_root , stripe -> logical ,
3770
+ stripe_end , stripe -> csums ,
3771
+ & csum_bitmap , true);
3772
+ if (ret < 0 )
3773
+ goto out ;
3774
+ if (ret > 0 )
3775
+ ret = 0 ;
3776
+
3777
+ for_each_set_bit (sector_nr , & csum_bitmap , stripe -> nr_sectors ) {
3778
+ stripe -> sectors [sector_nr ].csum = stripe -> csums +
3779
+ sector_nr * fs_info -> csum_size ;
3780
+ }
3781
+ }
3782
+ set_bit (SCRUB_STRIPE_FLAG_INITIALIZED , & stripe -> state );
3783
+ out :
3784
+ btrfs_release_path (& path );
3785
+ return ret ;
3786
+ }
3787
+
3645
3788
/*
3646
3789
* Scrub one range which can only has simple mirror based profile.
3647
3790
* (Including all range in SINGLE/DUP/RAID1/RAID1C*, and each stripe in
0 commit comments