aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/scrub.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/scrub.c')
-rw-r--r--fs/btrfs/scrub.c30
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)