Skip to content

Commit f82d02d

Browse files
Yan Zhengchrismason-xx
authored andcommitted
Btrfs: Improve space balancing code
This patch improves the space balancing code to keep more sharing of tree blocks. The only case that breaks sharing of tree blocks is data extents get fragmented during balancing. The main changes in this patch are: Add a 'drop sub-tree' function. This solves the problem in old code that BTRFS_HEADER_FLAG_WRITTEN check breaks sharing of tree block. Remove relocation mapping tree. Relocation mappings are stored in struct btrfs_ref_path and updated dynamically during walking up/down the reference path. This reduces CPU usage and simplifies code. This patch also fixes a bug. Root items for reloc trees should be updated in btrfs_free_reloc_root. Signed-off-by: Yan Zheng <[email protected]>
1 parent c8b9781 commit f82d02d

File tree

5 files changed

+277
-199
lines changed

5 files changed

+277
-199
lines changed

fs/btrfs/ctree.c

Lines changed: 47 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ int noinline __btrfs_cow_block(struct btrfs_trans_handle *trans,
287287
/*
288288
* There are only two places that can drop reference to
289289
* tree blocks owned by living reloc trees, one is here,
290-
* the other place is btrfs_merge_path. In both places,
290+
* the other place is btrfs_drop_subtree. In both places,
291291
* we check reference count while tree block is locked.
292292
* Furthermore, if reference count is one, it won't get
293293
* increased by someone else.
@@ -312,9 +312,6 @@ int noinline __btrfs_cow_block(struct btrfs_trans_handle *trans,
312312
}
313313

314314
if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) {
315-
ret = btrfs_add_reloc_mapping(root, buf->start,
316-
buf->len, cow->start);
317-
BUG_ON(ret);
318315
ret = btrfs_reloc_tree_cache_ref(trans, root, cow, buf->start);
319316
WARN_ON(ret);
320317
}
@@ -1627,61 +1624,57 @@ int btrfs_merge_path(struct btrfs_trans_handle *trans,
16271624
btrfs_node_key_to_cpu(eb, &key, slot);
16281625
key_match = !memcmp(&key, &node_keys[level - 1], sizeof(key));
16291626

1627+
if (generation == trans->transid) {
1628+
eb = read_tree_block(root, bytenr, blocksize,
1629+
generation);
1630+
btrfs_tree_lock(eb);
1631+
}
1632+
16301633
/*
16311634
* if node keys match and node pointer hasn't been modified
16321635
* in the running transaction, we can merge the path. for
1633-
* reloc trees, the node pointer check is skipped, this is
1634-
* because the reloc trees are fully controlled by the space
1635-
* balance code, no one else can modify them.
1636+
* blocks owened by reloc trees, the node pointer check is
1637+
* skipped, this is because these blocks are fully controlled
1638+
* by the space balance code, no one else can modify them.
16361639
*/
16371640
if (!nodes[level - 1] || !key_match ||
16381641
(generation == trans->transid &&
1639-
root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID)) {
1640-
next_level:
1641-
if (level == 1 || level == lowest_level + 1)
1642+
btrfs_header_owner(eb) != BTRFS_TREE_RELOC_OBJECTID)) {
1643+
if (level == 1 || level == lowest_level + 1) {
1644+
if (generation == trans->transid) {
1645+
btrfs_tree_unlock(eb);
1646+
free_extent_buffer(eb);
1647+
}
16421648
break;
1649+
}
16431650

1644-
eb = read_tree_block(root, bytenr, blocksize,
1645-
generation);
1646-
btrfs_tree_lock(eb);
1651+
if (generation != trans->transid) {
1652+
eb = read_tree_block(root, bytenr, blocksize,
1653+
generation);
1654+
btrfs_tree_lock(eb);
1655+
}
16471656

16481657
ret = btrfs_cow_block(trans, root, eb, parent, slot,
16491658
&eb, 0);
16501659
BUG_ON(ret);
16511660

1661+
if (root->root_key.objectid ==
1662+
BTRFS_TREE_RELOC_OBJECTID) {
1663+
if (!nodes[level - 1]) {
1664+
nodes[level - 1] = eb->start;
1665+
memcpy(&node_keys[level - 1], &key,
1666+
sizeof(node_keys[0]));
1667+
} else {
1668+
WARN_ON(1);
1669+
}
1670+
}
1671+
16521672
btrfs_tree_unlock(parent);
16531673
free_extent_buffer(parent);
16541674
parent = eb;
16551675
continue;
16561676
}
16571677

1658-
if (generation == trans->transid) {
1659-
u32 refs;
1660-
BUG_ON(btrfs_header_owner(eb) !=
1661-
BTRFS_TREE_RELOC_OBJECTID);
1662-
/*
1663-
* lock the block to keep __btrfs_cow_block from
1664-
* changing the reference count.
1665-
*/
1666-
eb = read_tree_block(root, bytenr, blocksize,
1667-
generation);
1668-
btrfs_tree_lock(eb);
1669-
1670-
ret = btrfs_lookup_extent_ref(trans, root, bytenr,
1671-
blocksize, &refs);
1672-
BUG_ON(ret);
1673-
/*
1674-
* if replace block whose reference count is one,
1675-
* we have to "drop the subtree". so skip it for
1676-
* simplicity
1677-
*/
1678-
if (refs == 1) {
1679-
btrfs_tree_unlock(eb);
1680-
free_extent_buffer(eb);
1681-
goto next_level;
1682-
}
1683-
}
1684-
16851678
btrfs_set_node_blockptr(parent, slot, nodes[level - 1]);
16861679
btrfs_set_node_ptr_generation(parent, slot, trans->transid);
16871680
btrfs_mark_buffer_dirty(parent);
@@ -1693,16 +1686,24 @@ int btrfs_merge_path(struct btrfs_trans_handle *trans,
16931686
btrfs_header_generation(parent),
16941687
level - 1);
16951688
BUG_ON(ret);
1696-
ret = btrfs_free_extent(trans, root, bytenr,
1697-
blocksize, parent->start,
1698-
btrfs_header_owner(parent),
1699-
btrfs_header_generation(parent),
1700-
level - 1, 1);
1701-
BUG_ON(ret);
17021689

1690+
/*
1691+
* If the block was created in the running transaction,
1692+
* it's possible this is the last reference to it, so we
1693+
* should drop the subtree.
1694+
*/
17031695
if (generation == trans->transid) {
1696+
ret = btrfs_drop_subtree(trans, root, eb, parent);
1697+
BUG_ON(ret);
17041698
btrfs_tree_unlock(eb);
17051699
free_extent_buffer(eb);
1700+
} else {
1701+
ret = btrfs_free_extent(trans, root, bytenr,
1702+
blocksize, parent->start,
1703+
btrfs_header_owner(parent),
1704+
btrfs_header_generation(parent),
1705+
level - 1, 1);
1706+
BUG_ON(ret);
17061707
}
17071708
break;
17081709
}

fs/btrfs/ctree.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,6 @@ struct btrfs_fs_info {
684684
int thread_pool_size;
685685

686686
/* tree relocation relocated fields */
687-
struct extent_io_tree reloc_mapping_tree;
688687
struct list_head dead_reloc_roots;
689688
struct btrfs_leaf_ref_tree reloc_ref_tree;
690689
struct btrfs_leaf_ref_tree shared_ref_tree;
@@ -1636,13 +1635,9 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
16361635
int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
16371636
struct btrfs_root *root, u64 group_start);
16381637
int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start);
1639-
int btrfs_free_reloc_root(struct btrfs_root *root);
1638+
int btrfs_free_reloc_root(struct btrfs_trans_handle *trans,
1639+
struct btrfs_root *root);
16401640
int btrfs_drop_dead_reloc_roots(struct btrfs_root *root);
1641-
int btrfs_add_reloc_mapping(struct btrfs_root *root, u64 orig_bytenr,
1642-
u64 num_bytes, u64 new_bytenr);
1643-
int btrfs_get_reloc_mapping(struct btrfs_root *root, u64 orig_bytenr,
1644-
u64 num_bytes, u64 *new_bytenr);
1645-
void btrfs_free_reloc_mappings(struct btrfs_root *root);
16461641
int btrfs_reloc_tree_cache_ref(struct btrfs_trans_handle *trans,
16471642
struct btrfs_root *root,
16481643
struct extent_buffer *buf, u64 orig_start);
@@ -1726,6 +1721,10 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
17261721
int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf);
17271722
int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
17281723
*root);
1724+
int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
1725+
struct btrfs_root *root,
1726+
struct extent_buffer *node,
1727+
struct extent_buffer *parent);
17291728
/* root-item.c */
17301729
int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
17311730
struct btrfs_key *key);

fs/btrfs/disk-io.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,8 +1448,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
14481448
fs_info->btree_inode->i_mapping, GFP_NOFS);
14491449
fs_info->do_barriers = 1;
14501450

1451-
extent_io_tree_init(&fs_info->reloc_mapping_tree,
1452-
fs_info->btree_inode->i_mapping, GFP_NOFS);
14531451
INIT_LIST_HEAD(&fs_info->dead_reloc_roots);
14541452
btrfs_leaf_ref_tree_init(&fs_info->reloc_ref_tree);
14551453
btrfs_leaf_ref_tree_init(&fs_info->shared_ref_tree);

0 commit comments

Comments
 (0)