aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/scrub.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-03-07 14:22:04 -0500
committerJosef Bacik <jbacik@fusionio.com>2013-05-06 15:54:18 -0400
commit3173a18f70554fe7880bb2d85c7da566e364eb3c (patch)
tree0a23b42a8d275d3499fac2b90ded76276c64c1c1 /fs/btrfs/scrub.c
parentbe283b2e674a09457d4563729015adb637ce7cc1 (diff)
Btrfs: add a incompatible format change for smaller metadata extent refs
We currently store the first key of the tree block inside the reference for the tree block in the extent tree. This takes up quite a bit of space. Make a new key type for metadata which holds the level as the offset and completely removes storing the btrfs_tree_block_info inside the extent ref. This reduces the size from 51 bytes to 33 bytes per extent reference for each tree block. In practice this results in a 30-35% decrease in the size of our extent tree, which means we COW less and can keep more of the extent tree in memory which makes our heavy metadata operations go much faster. This is not an automatic format change, you must enable it at mkfs time or with btrfstune. This patch deals with having metadata stored as either the old format or the new format so it is easy to convert. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
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)