@@ -175,6 +175,7 @@ struct scrub_ctx {
175175 struct scrub_stripe stripes [SCRUB_STRIPES_PER_SCTX ];
176176 struct scrub_stripe * raid56_data_stripes ;
177177 struct btrfs_fs_info * fs_info ;
178+ struct btrfs_path extent_path ;
178179 int first_free ;
179180 int cur_stripe ;
180181 atomic_t cancel_req ;
@@ -339,6 +340,8 @@ static noinline_for_stack struct scrub_ctx *scrub_setup_ctx(
339340 refcount_set (& sctx -> refs , 1 );
340341 sctx -> is_dev_replace = is_dev_replace ;
341342 sctx -> fs_info = fs_info ;
343+ sctx -> extent_path .search_commit_root = 1 ;
344+ sctx -> extent_path .skip_locking = 1 ;
342345 for (i = 0 ; i < SCRUB_STRIPES_PER_SCTX ; i ++ ) {
343346 int ret ;
344347
@@ -1467,6 +1470,7 @@ static void scrub_stripe_reset_bitmaps(struct scrub_stripe *stripe)
14671470 * Return <0 for error.
14681471 */
14691472static int scrub_find_fill_first_stripe (struct btrfs_block_group * bg ,
1473+ struct btrfs_path * extent_path ,
14701474 struct btrfs_device * dev , u64 physical ,
14711475 int mirror_num , u64 logical_start ,
14721476 u32 logical_len ,
@@ -1476,7 +1480,6 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
14761480 struct btrfs_root * extent_root = btrfs_extent_root (fs_info , bg -> start );
14771481 struct btrfs_root * csum_root = btrfs_csum_root (fs_info , bg -> start );
14781482 const u64 logical_end = logical_start + logical_len ;
1479- struct btrfs_path path = { 0 };
14801483 u64 cur_logical = logical_start ;
14811484 u64 stripe_end ;
14821485 u64 extent_start ;
@@ -1492,14 +1495,13 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
14921495 /* The range must be inside the bg. */
14931496 ASSERT (logical_start >= bg -> start && logical_end <= bg -> start + bg -> length );
14941497
1495- path .search_commit_root = 1 ;
1496- path .skip_locking = 1 ;
1497-
1498- ret = find_first_extent_item (extent_root , & path , logical_start , logical_len );
1498+ ret = find_first_extent_item (extent_root , extent_path , logical_start ,
1499+ logical_len );
14991500 /* Either error or not found. */
15001501 if (ret )
15011502 goto out ;
1502- get_extent_info (& path , & extent_start , & extent_len , & extent_flags , & extent_gen );
1503+ get_extent_info (extent_path , & extent_start , & extent_len , & extent_flags ,
1504+ & extent_gen );
15031505 if (extent_flags & BTRFS_EXTENT_FLAG_TREE_BLOCK )
15041506 stripe -> nr_meta_extents ++ ;
15051507 if (extent_flags & BTRFS_EXTENT_FLAG_DATA )
@@ -1527,15 +1529,15 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
15271529
15281530 /* Fill the extent info for the remaining sectors. */
15291531 while (cur_logical <= stripe_end ) {
1530- ret = find_first_extent_item (extent_root , & path , cur_logical ,
1532+ ret = find_first_extent_item (extent_root , extent_path , cur_logical ,
15311533 stripe_end - cur_logical + 1 );
15321534 if (ret < 0 )
15331535 goto out ;
15341536 if (ret > 0 ) {
15351537 ret = 0 ;
15361538 break ;
15371539 }
1538- get_extent_info (& path , & extent_start , & extent_len ,
1540+ get_extent_info (extent_path , & extent_start , & extent_len ,
15391541 & extent_flags , & extent_gen );
15401542 if (extent_flags & BTRFS_EXTENT_FLAG_TREE_BLOCK )
15411543 stripe -> nr_meta_extents ++ ;
@@ -1575,7 +1577,6 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
15751577 }
15761578 set_bit (SCRUB_STRIPE_FLAG_INITIALIZED , & stripe -> state );
15771579out :
1578- btrfs_release_path (& path );
15791580 return ret ;
15801581}
15811582
@@ -1765,8 +1766,9 @@ static int queue_scrub_stripe(struct scrub_ctx *sctx, struct btrfs_block_group *
17651766
17661767 /* We can queue one stripe using the remaining slot. */
17671768 scrub_reset_stripe (stripe );
1768- ret = scrub_find_fill_first_stripe (bg , dev , physical , mirror_num ,
1769- logical , length , stripe );
1769+ ret = scrub_find_fill_first_stripe (bg , & sctx -> extent_path , dev ,
1770+ physical , mirror_num , logical ,
1771+ length , stripe );
17701772 /* Either >0 as no more extents or <0 for error. */
17711773 if (ret )
17721774 return ret ;
@@ -1784,6 +1786,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
17841786 struct btrfs_fs_info * fs_info = sctx -> fs_info ;
17851787 struct btrfs_raid_bio * rbio ;
17861788 struct btrfs_io_context * bioc = NULL ;
1789+ struct btrfs_path extent_path = { 0 };
17871790 struct bio * bio ;
17881791 struct scrub_stripe * stripe ;
17891792 bool all_empty = true;
@@ -1794,6 +1797,14 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
17941797
17951798 ASSERT (sctx -> raid56_data_stripes );
17961799
1800+ /*
1801+ * For data stripe search, we cannot re-use the same extent path, as
1802+ * the data stripe bytenr may be smaller than previous extent. Thus we
1803+ * have to use our own extent path.
1804+ */
1805+ extent_path .search_commit_root = 1 ;
1806+ extent_path .skip_locking = 1 ;
1807+
17971808 for (int i = 0 ; i < data_stripes ; i ++ ) {
17981809 int stripe_index ;
17991810 int rot ;
@@ -1808,7 +1819,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
18081819
18091820 scrub_reset_stripe (stripe );
18101821 set_bit (SCRUB_STRIPE_FLAG_NO_REPORT , & stripe -> state );
1811- ret = scrub_find_fill_first_stripe (bg ,
1822+ ret = scrub_find_fill_first_stripe (bg , & extent_path ,
18121823 map -> stripes [stripe_index ].dev , physical , 1 ,
18131824 full_stripe_start + btrfs_stripe_nr_to_offset (i ),
18141825 BTRFS_STRIPE_LEN , stripe );
@@ -1936,6 +1947,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
19361947 bio_put (bio );
19371948 btrfs_bio_counter_dec (fs_info );
19381949
1950+ btrfs_release_path (& extent_path );
19391951out :
19401952 return ret ;
19411953}
@@ -2103,6 +2115,9 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
21032115 u64 stripe_logical ;
21042116 int stop_loop = 0 ;
21052117
2118+ /* Extent_path should be released by now. */
2119+ ASSERT (sctx -> extent_path .nodes [0 ] == NULL );
2120+
21062121 scrub_blocked_if_needed (fs_info );
21072122
21082123 if (sctx -> is_dev_replace &&
@@ -2221,6 +2236,8 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
22212236 ret2 = flush_scrub_stripes (sctx );
22222237 if (!ret )
22232238 ret = ret2 ;
2239+ btrfs_release_path (& sctx -> extent_path );
2240+
22242241 if (sctx -> raid56_data_stripes ) {
22252242 for (int i = 0 ; i < nr_data_stripes (map ); i ++ )
22262243 release_scrub_stripe (& sctx -> raid56_data_stripes [i ]);
0 commit comments