aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/relocation.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/relocation.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/relocation.c')
-rw-r--r--fs/btrfs/relocation.c73
1 files changed, 58 insertions, 15 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index b67171e6d688..86f192ffc212 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -619,10 +619,13 @@ static noinline_for_stack
619int find_inline_backref(struct extent_buffer *leaf, int slot, 619int find_inline_backref(struct extent_buffer *leaf, int slot,
620 unsigned long *ptr, unsigned long *end) 620 unsigned long *ptr, unsigned long *end)
621{ 621{
622 struct btrfs_key key;
622 struct btrfs_extent_item *ei; 623 struct btrfs_extent_item *ei;
623 struct btrfs_tree_block_info *bi; 624 struct btrfs_tree_block_info *bi;
624 u32 item_size; 625 u32 item_size;
625 626
627 btrfs_item_key_to_cpu(leaf, &key, slot);
628
626 item_size = btrfs_item_size_nr(leaf, slot); 629 item_size = btrfs_item_size_nr(leaf, slot);
627#ifdef BTRFS_COMPAT_EXTENT_TREE_V0 630#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
628 if (item_size < sizeof(*ei)) { 631 if (item_size < sizeof(*ei)) {
@@ -634,13 +637,18 @@ int find_inline_backref(struct extent_buffer *leaf, int slot,
634 WARN_ON(!(btrfs_extent_flags(leaf, ei) & 637 WARN_ON(!(btrfs_extent_flags(leaf, ei) &
635 BTRFS_EXTENT_FLAG_TREE_BLOCK)); 638 BTRFS_EXTENT_FLAG_TREE_BLOCK));
636 639
637 if (item_size <= sizeof(*ei) + sizeof(*bi)) { 640 if (key.type == BTRFS_EXTENT_ITEM_KEY &&
641 item_size <= sizeof(*ei) + sizeof(*bi)) {
638 WARN_ON(item_size < sizeof(*ei) + sizeof(*bi)); 642 WARN_ON(item_size < sizeof(*ei) + sizeof(*bi));
639 return 1; 643 return 1;
640 } 644 }
641 645
642 bi = (struct btrfs_tree_block_info *)(ei + 1); 646 if (key.type == BTRFS_EXTENT_ITEM_KEY) {
643 *ptr = (unsigned long)(bi + 1); 647 bi = (struct btrfs_tree_block_info *)(ei + 1);
648 *ptr = (unsigned long)(bi + 1);
649 } else {
650 *ptr = (unsigned long)(ei + 1);
651 }
644 *end = (unsigned long)ei + item_size; 652 *end = (unsigned long)ei + item_size;
645 return 0; 653 return 0;
646} 654}
@@ -708,7 +716,7 @@ again:
708 end = 0; 716 end = 0;
709 ptr = 0; 717 ptr = 0;
710 key.objectid = cur->bytenr; 718 key.objectid = cur->bytenr;
711 key.type = BTRFS_EXTENT_ITEM_KEY; 719 key.type = BTRFS_METADATA_ITEM_KEY;
712 key.offset = (u64)-1; 720 key.offset = (u64)-1;
713 721
714 path1->search_commit_root = 1; 722 path1->search_commit_root = 1;
@@ -766,7 +774,8 @@ again:
766 break; 774 break;
767 } 775 }
768 776
769 if (key.type == BTRFS_EXTENT_ITEM_KEY) { 777 if (key.type == BTRFS_EXTENT_ITEM_KEY ||
778 key.type == BTRFS_METADATA_ITEM_KEY) {
770 ret = find_inline_backref(eb, path1->slots[0], 779 ret = find_inline_backref(eb, path1->slots[0],
771 &ptr, &end); 780 &ptr, &end);
772 if (ret) 781 if (ret)
@@ -2768,8 +2777,13 @@ static int reada_tree_block(struct reloc_control *rc,
2768 struct tree_block *block) 2777 struct tree_block *block)
2769{ 2778{
2770 BUG_ON(block->key_ready); 2779 BUG_ON(block->key_ready);
2771 readahead_tree_block(rc->extent_root, block->bytenr, 2780 if (block->key.type == BTRFS_METADATA_ITEM_KEY)
2772 block->key.objectid, block->key.offset); 2781 readahead_tree_block(rc->extent_root, block->bytenr,
2782 block->key.objectid,
2783 rc->extent_root->leafsize);
2784 else
2785 readahead_tree_block(rc->extent_root, block->bytenr,
2786 block->key.objectid, block->key.offset);
2773 return 0; 2787 return 0;
2774} 2788}
2775 2789
@@ -3176,12 +3190,17 @@ static int add_tree_block(struct reloc_control *rc,
3176 eb = path->nodes[0]; 3190 eb = path->nodes[0];
3177 item_size = btrfs_item_size_nr(eb, path->slots[0]); 3191 item_size = btrfs_item_size_nr(eb, path->slots[0]);
3178 3192
3179 if (item_size >= sizeof(*ei) + sizeof(*bi)) { 3193 if (extent_key->type == BTRFS_METADATA_ITEM_KEY ||
3194 item_size >= sizeof(*ei) + sizeof(*bi)) {
3180 ei = btrfs_item_ptr(eb, path->slots[0], 3195 ei = btrfs_item_ptr(eb, path->slots[0],
3181 struct btrfs_extent_item); 3196 struct btrfs_extent_item);
3182 bi = (struct btrfs_tree_block_info *)(ei + 1); 3197 if (extent_key->type == BTRFS_EXTENT_ITEM_KEY) {
3198 bi = (struct btrfs_tree_block_info *)(ei + 1);
3199 level = btrfs_tree_block_level(eb, bi);
3200 } else {
3201 level = (int)extent_key->offset;
3202 }
3183 generation = btrfs_extent_generation(eb, ei); 3203 generation = btrfs_extent_generation(eb, ei);
3184 level = btrfs_tree_block_level(eb, bi);
3185 } else { 3204 } else {
3186#ifdef BTRFS_COMPAT_EXTENT_TREE_V0 3205#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
3187 u64 ref_owner; 3206 u64 ref_owner;
@@ -3210,7 +3229,7 @@ static int add_tree_block(struct reloc_control *rc,
3210 return -ENOMEM; 3229 return -ENOMEM;
3211 3230
3212 block->bytenr = extent_key->objectid; 3231 block->bytenr = extent_key->objectid;
3213 block->key.objectid = extent_key->offset; 3232 block->key.objectid = rc->extent_root->leafsize;
3214 block->key.offset = generation; 3233 block->key.offset = generation;
3215 block->level = level; 3234 block->level = level;
3216 block->key_ready = 0; 3235 block->key_ready = 0;
@@ -3252,9 +3271,15 @@ static int __add_tree_block(struct reloc_control *rc,
3252 ret = btrfs_search_slot(NULL, rc->extent_root, &key, path, 0, 0); 3271 ret = btrfs_search_slot(NULL, rc->extent_root, &key, path, 0, 0);
3253 if (ret < 0) 3272 if (ret < 0)
3254 goto out; 3273 goto out;
3255 BUG_ON(ret);
3256 3274
3257 btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); 3275 btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
3276 if (ret > 0) {
3277 if (key.objectid == bytenr &&
3278 key.type == BTRFS_METADATA_ITEM_KEY)
3279 ret = 0;
3280 }
3281 BUG_ON(ret);
3282
3258 ret = add_tree_block(rc, &key, path, blocks); 3283 ret = add_tree_block(rc, &key, path, blocks);
3259out: 3284out:
3260 btrfs_free_path(path); 3285 btrfs_free_path(path);
@@ -3275,7 +3300,8 @@ static int block_use_full_backref(struct reloc_control *rc,
3275 return 1; 3300 return 1;
3276 3301
3277 ret = btrfs_lookup_extent_info(NULL, rc->extent_root, 3302 ret = btrfs_lookup_extent_info(NULL, rc->extent_root,
3278 eb->start, eb->len, NULL, &flags); 3303 eb->start, btrfs_header_level(eb), 1,
3304 NULL, &flags);
3279 BUG_ON(ret); 3305 BUG_ON(ret);
3280 3306
3281 if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) 3307 if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)
@@ -3644,12 +3670,25 @@ next:
3644 break; 3670 break;
3645 } 3671 }
3646 3672
3647 if (key.type != BTRFS_EXTENT_ITEM_KEY || 3673 if (key.type != BTRFS_EXTENT_ITEM_KEY &&
3674 key.type != BTRFS_METADATA_ITEM_KEY) {
3675 path->slots[0]++;
3676 goto next;
3677 }
3678
3679 if (key.type == BTRFS_EXTENT_ITEM_KEY &&
3648 key.objectid + key.offset <= rc->search_start) { 3680 key.objectid + key.offset <= rc->search_start) {
3649 path->slots[0]++; 3681 path->slots[0]++;
3650 goto next; 3682 goto next;
3651 } 3683 }
3652 3684
3685 if (key.type == BTRFS_METADATA_ITEM_KEY &&
3686 key.objectid + rc->extent_root->leafsize <=
3687 rc->search_start) {
3688 path->slots[0]++;
3689 goto next;
3690 }
3691
3653 ret = find_first_extent_bit(&rc->processed_blocks, 3692 ret = find_first_extent_bit(&rc->processed_blocks,
3654 key.objectid, &start, &end, 3693 key.objectid, &start, &end,
3655 EXTENT_DIRTY, NULL); 3694 EXTENT_DIRTY, NULL);
@@ -3658,7 +3697,11 @@ next:
3658 btrfs_release_path(path); 3697 btrfs_release_path(path);
3659 rc->search_start = end + 1; 3698 rc->search_start = end + 1;
3660 } else { 3699 } else {
3661 rc->search_start = key.objectid + key.offset; 3700 if (key.type == BTRFS_EXTENT_ITEM_KEY)
3701 rc->search_start = key.objectid + key.offset;
3702 else
3703 rc->search_start = key.objectid +
3704 rc->extent_root->leafsize;
3662 memcpy(extent_key, &key, sizeof(key)); 3705 memcpy(extent_key, &key, sizeof(key));
3663 return 0; 3706 return 0;
3664 } 3707 }