diff options
Diffstat (limited to 'fs/btrfs/scrub.c')
-rw-r--r-- | fs/btrfs/scrub.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 3d29d60bdaf8..28db5dcde0aa 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -2312,8 +2312,8 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2312 | key_start.type = BTRFS_EXTENT_ITEM_KEY; | 2312 | key_start.type = BTRFS_EXTENT_ITEM_KEY; |
2313 | key_start.offset = (u64)0; | 2313 | key_start.offset = (u64)0; |
2314 | key_end.objectid = base + offset + nstripes * increment; | 2314 | key_end.objectid = base + offset + nstripes * increment; |
2315 | key_end.type = BTRFS_EXTENT_ITEM_KEY; | 2315 | key_end.type = BTRFS_METADATA_ITEM_KEY; |
2316 | key_end.offset = (u64)0; | 2316 | key_end.offset = (u64)-1; |
2317 | reada1 = btrfs_reada_add(root, &key_start, &key_end); | 2317 | reada1 = btrfs_reada_add(root, &key_start, &key_end); |
2318 | 2318 | ||
2319 | key_start.objectid = BTRFS_EXTENT_CSUM_OBJECTID; | 2319 | key_start.objectid = BTRFS_EXTENT_CSUM_OBJECTID; |
@@ -2401,6 +2401,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2401 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 2401 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
2402 | if (ret < 0) | 2402 | if (ret < 0) |
2403 | goto out; | 2403 | goto out; |
2404 | |||
2404 | if (ret > 0) { | 2405 | if (ret > 0) { |
2405 | ret = btrfs_previous_item(root, path, 0, | 2406 | ret = btrfs_previous_item(root, path, 0, |
2406 | BTRFS_EXTENT_ITEM_KEY); | 2407 | BTRFS_EXTENT_ITEM_KEY); |
@@ -2418,6 +2419,8 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2418 | } | 2419 | } |
2419 | 2420 | ||
2420 | while (1) { | 2421 | while (1) { |
2422 | u64 bytes; | ||
2423 | |||
2421 | l = path->nodes[0]; | 2424 | l = path->nodes[0]; |
2422 | slot = path->slots[0]; | 2425 | slot = path->slots[0]; |
2423 | if (slot >= btrfs_header_nritems(l)) { | 2426 | if (slot >= btrfs_header_nritems(l)) { |
@@ -2431,14 +2434,21 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2431 | } | 2434 | } |
2432 | btrfs_item_key_to_cpu(l, &key, slot); | 2435 | btrfs_item_key_to_cpu(l, &key, slot); |
2433 | 2436 | ||
2434 | if (key.objectid + key.offset <= logical) | 2437 | if (key.type != BTRFS_EXTENT_ITEM_KEY && |
2438 | key.type != BTRFS_METADATA_ITEM_KEY) | ||
2439 | goto next; | ||
2440 | |||
2441 | if (key.type == BTRFS_METADATA_ITEM_KEY) | ||
2442 | bytes = root->leafsize; | ||
2443 | else | ||
2444 | bytes = key.offset; | ||
2445 | |||
2446 | if (key.objectid + bytes <= logical) | ||
2435 | goto next; | 2447 | goto next; |
2436 | 2448 | ||
2437 | if (key.objectid >= logical + map->stripe_len) | 2449 | if (key.objectid >= logical + map->stripe_len) |
2438 | break; | 2450 | break; |
2439 | 2451 | ||
2440 | if (btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY) | ||
2441 | goto next; | ||
2442 | 2452 | ||
2443 | extent = btrfs_item_ptr(l, slot, | 2453 | extent = btrfs_item_ptr(l, slot, |
2444 | struct btrfs_extent_item); | 2454 | struct btrfs_extent_item); |
@@ -2459,18 +2469,18 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2459 | * trim extent to this stripe | 2469 | * trim extent to this stripe |
2460 | */ | 2470 | */ |
2461 | if (key.objectid < logical) { | 2471 | if (key.objectid < logical) { |
2462 | key.offset -= logical - key.objectid; | 2472 | bytes -= logical - key.objectid; |
2463 | key.objectid = logical; | 2473 | key.objectid = logical; |
2464 | } | 2474 | } |
2465 | if (key.objectid + key.offset > | 2475 | if (key.objectid + bytes > |
2466 | logical + map->stripe_len) { | 2476 | logical + map->stripe_len) { |
2467 | key.offset = logical + map->stripe_len - | 2477 | bytes = logical + map->stripe_len - |
2468 | key.objectid; | 2478 | key.objectid; |
2469 | } | 2479 | } |
2470 | 2480 | ||
2471 | extent_logical = key.objectid; | 2481 | extent_logical = key.objectid; |
2472 | extent_physical = key.objectid - logical + physical; | 2482 | extent_physical = key.objectid - logical + physical; |
2473 | extent_len = key.offset; | 2483 | extent_len = bytes; |
2474 | extent_dev = scrub_dev; | 2484 | extent_dev = scrub_dev; |
2475 | extent_mirror_num = mirror_num; | 2485 | extent_mirror_num = mirror_num; |
2476 | if (is_dev_replace) | 2486 | if (is_dev_replace) |