@@ -175,6 +175,7 @@ struct scrub_ctx {
175
175
struct scrub_stripe stripes [SCRUB_STRIPES_PER_SCTX ];
176
176
struct scrub_stripe * raid56_data_stripes ;
177
177
struct btrfs_fs_info * fs_info ;
178
+ struct btrfs_path extent_path ;
178
179
int first_free ;
179
180
int cur_stripe ;
180
181
atomic_t cancel_req ;
@@ -339,6 +340,8 @@ static noinline_for_stack struct scrub_ctx *scrub_setup_ctx(
339
340
refcount_set (& sctx -> refs , 1 );
340
341
sctx -> is_dev_replace = is_dev_replace ;
341
342
sctx -> fs_info = fs_info ;
343
+ sctx -> extent_path .search_commit_root = 1 ;
344
+ sctx -> extent_path .skip_locking = 1 ;
342
345
for (i = 0 ; i < SCRUB_STRIPES_PER_SCTX ; i ++ ) {
343
346
int ret ;
344
347
@@ -1467,6 +1470,7 @@ static void scrub_stripe_reset_bitmaps(struct scrub_stripe *stripe)
1467
1470
* Return <0 for error.
1468
1471
*/
1469
1472
static int scrub_find_fill_first_stripe (struct btrfs_block_group * bg ,
1473
+ struct btrfs_path * extent_path ,
1470
1474
struct btrfs_device * dev , u64 physical ,
1471
1475
int mirror_num , u64 logical_start ,
1472
1476
u32 logical_len ,
@@ -1476,7 +1480,6 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
1476
1480
struct btrfs_root * extent_root = btrfs_extent_root (fs_info , bg -> start );
1477
1481
struct btrfs_root * csum_root = btrfs_csum_root (fs_info , bg -> start );
1478
1482
const u64 logical_end = logical_start + logical_len ;
1479
- struct btrfs_path path = { 0 };
1480
1483
u64 cur_logical = logical_start ;
1481
1484
u64 stripe_end ;
1482
1485
u64 extent_start ;
@@ -1492,14 +1495,13 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
1492
1495
/* The range must be inside the bg. */
1493
1496
ASSERT (logical_start >= bg -> start && logical_end <= bg -> start + bg -> length );
1494
1497
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 );
1499
1500
/* Either error or not found. */
1500
1501
if (ret )
1501
1502
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 );
1503
1505
if (extent_flags & BTRFS_EXTENT_FLAG_TREE_BLOCK )
1504
1506
stripe -> nr_meta_extents ++ ;
1505
1507
if (extent_flags & BTRFS_EXTENT_FLAG_DATA )
@@ -1527,15 +1529,15 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
1527
1529
1528
1530
/* Fill the extent info for the remaining sectors. */
1529
1531
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 ,
1531
1533
stripe_end - cur_logical + 1 );
1532
1534
if (ret < 0 )
1533
1535
goto out ;
1534
1536
if (ret > 0 ) {
1535
1537
ret = 0 ;
1536
1538
break ;
1537
1539
}
1538
- get_extent_info (& path , & extent_start , & extent_len ,
1540
+ get_extent_info (extent_path , & extent_start , & extent_len ,
1539
1541
& extent_flags , & extent_gen );
1540
1542
if (extent_flags & BTRFS_EXTENT_FLAG_TREE_BLOCK )
1541
1543
stripe -> nr_meta_extents ++ ;
@@ -1575,7 +1577,6 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
1575
1577
}
1576
1578
set_bit (SCRUB_STRIPE_FLAG_INITIALIZED , & stripe -> state );
1577
1579
out :
1578
- btrfs_release_path (& path );
1579
1580
return ret ;
1580
1581
}
1581
1582
@@ -1765,8 +1766,9 @@ static int queue_scrub_stripe(struct scrub_ctx *sctx, struct btrfs_block_group *
1765
1766
1766
1767
/* We can queue one stripe using the remaining slot. */
1767
1768
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 );
1770
1772
/* Either >0 as no more extents or <0 for error. */
1771
1773
if (ret )
1772
1774
return ret ;
@@ -1784,6 +1786,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
1784
1786
struct btrfs_fs_info * fs_info = sctx -> fs_info ;
1785
1787
struct btrfs_raid_bio * rbio ;
1786
1788
struct btrfs_io_context * bioc = NULL ;
1789
+ struct btrfs_path extent_path = { 0 };
1787
1790
struct bio * bio ;
1788
1791
struct scrub_stripe * stripe ;
1789
1792
bool all_empty = true;
@@ -1794,6 +1797,14 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
1794
1797
1795
1798
ASSERT (sctx -> raid56_data_stripes );
1796
1799
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
+
1797
1808
for (int i = 0 ; i < data_stripes ; i ++ ) {
1798
1809
int stripe_index ;
1799
1810
int rot ;
@@ -1808,7 +1819,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
1808
1819
1809
1820
scrub_reset_stripe (stripe );
1810
1821
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 ,
1812
1823
map -> stripes [stripe_index ].dev , physical , 1 ,
1813
1824
full_stripe_start + btrfs_stripe_nr_to_offset (i ),
1814
1825
BTRFS_STRIPE_LEN , stripe );
@@ -1936,6 +1947,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
1936
1947
bio_put (bio );
1937
1948
btrfs_bio_counter_dec (fs_info );
1938
1949
1950
+ btrfs_release_path (& extent_path );
1939
1951
out :
1940
1952
return ret ;
1941
1953
}
@@ -2103,6 +2115,9 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
2103
2115
u64 stripe_logical ;
2104
2116
int stop_loop = 0 ;
2105
2117
2118
+ /* Extent_path should be released by now. */
2119
+ ASSERT (sctx -> extent_path .nodes [0 ] == NULL );
2120
+
2106
2121
scrub_blocked_if_needed (fs_info );
2107
2122
2108
2123
if (sctx -> is_dev_replace &&
@@ -2221,6 +2236,8 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
2221
2236
ret2 = flush_scrub_stripes (sctx );
2222
2237
if (!ret )
2223
2238
ret = ret2 ;
2239
+ btrfs_release_path (& sctx -> extent_path );
2240
+
2224
2241
if (sctx -> raid56_data_stripes ) {
2225
2242
for (int i = 0 ; i < nr_data_stripes (map ); i ++ )
2226
2243
release_scrub_stripe (& sctx -> raid56_data_stripes [i ]);
0 commit comments