summaryrefslogtreecommitdiff
path: root/fs/btrfs/scrub.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-03-07 23:22:04 +0400
committerJosef Bacik <jbacik@fusionio.com>2013-05-06 23:54:18 +0400
commit3173a18f70554fe7880bb2d85c7da566e364eb3c (patch)
tree0a23b42a8d275d3499fac2b90ded76276c64c1c1 /fs/btrfs/scrub.c
parentbe283b2e674a09457d4563729015adb637ce7cc1 (diff)
downloadlinux-3173a18f70554fe7880bb2d85c7da566e364eb3c.tar.xz
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,
key_start.type = BTRFS_EXTENT_ITEM_KEY;
key_start.offset = (u64)0;
key_end.objectid = base + offset + nstripes * increment;
- key_end.type = BTRFS_EXTENT_ITEM_KEY;
- key_end.offset = (u64)0;
+ key_end.type = BTRFS_METADATA_ITEM_KEY;
+ key_end.offset = (u64)-1;
reada1 = btrfs_reada_add(root, &key_start, &key_end);
key_start.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
@@ -2401,6 +2401,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (ret < 0)
goto out;
+
if (ret > 0) {
ret = btrfs_previous_item(root, path, 0,
BTRFS_EXTENT_ITEM_KEY);
@@ -2418,6 +2419,8 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
}
while (1) {
+ u64 bytes;
+
l = path->nodes[0];
slot = path->slots[0];
if (slot >= btrfs_header_nritems(l)) {
@@ -2431,14 +2434,21 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
}
btrfs_item_key_to_cpu(l, &key, slot);
- if (key.objectid + key.offset <= logical)
+ if (key.type != BTRFS_EXTENT_ITEM_KEY &&
+ key.type != BTRFS_METADATA_ITEM_KEY)
+ goto next;
+
+ if (key.type == BTRFS_METADATA_ITEM_KEY)
+ bytes = root->leafsize;
+ else
+ bytes = key.offset;
+
+ if (key.objectid + bytes <= logical)
goto next;
if (key.objectid >= logical + map->stripe_len)
break;
- if (btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY)
- goto next;
extent = btrfs_item_ptr(l, slot,
struct btrfs_extent_item);
@@ -2459,18 +2469,18 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
* trim extent to this stripe
*/
if (key.objectid < logical) {
- key.offset -= logical - key.objectid;
+ bytes -= logical - key.objectid;
key.objectid = logical;
}
- if (key.objectid + key.offset >
+ if (key.objectid + bytes >
logical + map->stripe_len) {
- key.offset = logical + map->stripe_len -
- key.objectid;
+ bytes = logical + map->stripe_len -
+ key.objectid;
}
extent_logical = key.objectid;
extent_physical = key.objectid - logical + physical;
- extent_len = key.offset;
+ extent_len = bytes;
extent_dev = scrub_dev;
extent_mirror_num = mirror_num;
if (is_dev_replace)