Skip to content

Commit 625f1c8

Browse files
Liu BoJosef Bacik
authored andcommitted
Btrfs: improve the loop of scrub_stripe
1) Right now scrub_stripe() is looping in some unnecessary cases: * when the found extent item's objectid has been out of the dev extent's range but we haven't finish scanning all the range within the dev extent * when all the items has been processed but we haven't finish scanning all the range within the dev extent In both cases, we can just finish the loop to save costs. 2) Besides, when the found extent item's length is larger than the stripe len(64k), we don't have to release the path and search again as it'll get at the same key used in the last loop, we can instead increase the logical cursor in place till all space of the extent is scanned. 3) And we use 0 as the key's offset to search btree, then get to previous item to find a smaller item, and again have to move to the next one to get the right item. Setting offset=-1 and previous_item() is the correct way. 4) As we won't find any checksum at offset unless this 'offset' is in a data extent, we can just find checksum when we're really going to scrub an extent. Signed-off-by: Liu Bo <[email protected]> Signed-off-by: Josef Bacik <[email protected]>
1 parent 55793c0 commit 625f1c8

File tree

1 file changed

+57
-26
lines changed

1 file changed

+57
-26
lines changed

fs/btrfs/scrub.c

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2233,12 +2233,12 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
22332233
u64 flags;
22342234
int ret;
22352235
int slot;
2236-
int i;
22372236
u64 nstripes;
22382237
struct extent_buffer *l;
22392238
struct btrfs_key key;
22402239
u64 physical;
22412240
u64 logical;
2241+
u64 logic_end;
22422242
u64 generation;
22432243
int mirror_num;
22442244
struct reada_control *reada1;
@@ -2252,6 +2252,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
22522252
u64 extent_len;
22532253
struct btrfs_device *extent_dev;
22542254
int extent_mirror_num;
2255+
int stop_loop;
22552256

22562257
if (map->type & (BTRFS_BLOCK_GROUP_RAID5 |
22572258
BTRFS_BLOCK_GROUP_RAID6)) {
@@ -2351,8 +2352,9 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
23512352
*/
23522353
logical = base + offset;
23532354
physical = map->stripes[num].physical;
2355+
logic_end = logical + increment * nstripes;
23542356
ret = 0;
2355-
for (i = 0; i < nstripes; ++i) {
2357+
while (logical < logic_end) {
23562358
/*
23572359
* canceled?
23582360
*/
@@ -2388,15 +2390,9 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
23882390
wake_up(&fs_info->scrub_pause_wait);
23892391
}
23902392

2391-
ret = btrfs_lookup_csums_range(csum_root, logical,
2392-
logical + map->stripe_len - 1,
2393-
&sctx->csum_list, 1);
2394-
if (ret)
2395-
goto out;
2396-
23972393
key.objectid = logical;
23982394
key.type = BTRFS_EXTENT_ITEM_KEY;
2399-
key.offset = (u64)0;
2395+
key.offset = (u64)-1;
24002396

24012397
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
24022398
if (ret < 0)
@@ -2418,6 +2414,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
24182414
}
24192415
}
24202416

2417+
stop_loop = 0;
24212418
while (1) {
24222419
u64 bytes;
24232420

@@ -2430,14 +2427,11 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
24302427
if (ret < 0)
24312428
goto out;
24322429

2430+
stop_loop = 1;
24332431
break;
24342432
}
24352433
btrfs_item_key_to_cpu(l, &key, slot);
24362434

2437-
if (key.type != BTRFS_EXTENT_ITEM_KEY &&
2438-
key.type != BTRFS_METADATA_ITEM_KEY)
2439-
goto next;
2440-
24412435
if (key.type == BTRFS_METADATA_ITEM_KEY)
24422436
bytes = root->leafsize;
24432437
else
@@ -2446,9 +2440,16 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
24462440
if (key.objectid + bytes <= logical)
24472441
goto next;
24482442

2449-
if (key.objectid >= logical + map->stripe_len)
2450-
break;
2443+
if (key.type != BTRFS_EXTENT_ITEM_KEY &&
2444+
key.type != BTRFS_METADATA_ITEM_KEY)
2445+
goto next;
24512446

2447+
if (key.objectid >= logical + map->stripe_len) {
2448+
/* out of this device extent */
2449+
if (key.objectid >= logic_end)
2450+
stop_loop = 1;
2451+
break;
2452+
}
24522453

24532454
extent = btrfs_item_ptr(l, slot,
24542455
struct btrfs_extent_item);
@@ -2465,45 +2466,75 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
24652466
goto next;
24662467
}
24672468

2469+
again:
2470+
extent_logical = key.objectid;
2471+
extent_len = bytes;
2472+
24682473
/*
24692474
* trim extent to this stripe
24702475
*/
2471-
if (key.objectid < logical) {
2472-
bytes -= logical - key.objectid;
2473-
key.objectid = logical;
2476+
if (extent_logical < logical) {
2477+
extent_len -= logical - extent_logical;
2478+
extent_logical = logical;
24742479
}
2475-
if (key.objectid + bytes >
2480+
if (extent_logical + extent_len >
24762481
logical + map->stripe_len) {
2477-
bytes = logical + map->stripe_len -
2478-
key.objectid;
2482+
extent_len = logical + map->stripe_len -
2483+
extent_logical;
24792484
}
24802485

2481-
extent_logical = key.objectid;
2482-
extent_physical = key.objectid - logical + physical;
2483-
extent_len = bytes;
2486+
extent_physical = extent_logical - logical + physical;
24842487
extent_dev = scrub_dev;
24852488
extent_mirror_num = mirror_num;
24862489
if (is_dev_replace)
24872490
scrub_remap_extent(fs_info, extent_logical,
24882491
extent_len, &extent_physical,
24892492
&extent_dev,
24902493
&extent_mirror_num);
2494+
2495+
ret = btrfs_lookup_csums_range(csum_root, logical,
2496+
logical + map->stripe_len - 1,
2497+
&sctx->csum_list, 1);
2498+
if (ret)
2499+
goto out;
2500+
24912501
ret = scrub_extent(sctx, extent_logical, extent_len,
24922502
extent_physical, extent_dev, flags,
24932503
generation, extent_mirror_num,
2494-
key.objectid - logical + physical);
2504+
extent_physical);
24952505
if (ret)
24962506
goto out;
24972507

2508+
if (extent_logical + extent_len <
2509+
key.objectid + bytes) {
2510+
logical += increment;
2511+
physical += map->stripe_len;
2512+
2513+
if (logical < key.objectid + bytes) {
2514+
cond_resched();
2515+
goto again;
2516+
}
2517+
2518+
if (logical >= logic_end) {
2519+
stop_loop = 1;
2520+
break;
2521+
}
2522+
}
24982523
next:
24992524
path->slots[0]++;
25002525
}
25012526
btrfs_release_path(path);
25022527
logical += increment;
25032528
physical += map->stripe_len;
25042529
spin_lock(&sctx->stat_lock);
2505-
sctx->stat.last_physical = physical;
2530+
if (stop_loop)
2531+
sctx->stat.last_physical = map->stripes[num].physical +
2532+
length;
2533+
else
2534+
sctx->stat.last_physical = physical;
25062535
spin_unlock(&sctx->stat_lock);
2536+
if (stop_loop)
2537+
break;
25072538
}
25082539
out:
25092540
/* push queued extents */

0 commit comments

Comments
 (0)