aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorZheng Yan <zheng.yan@oracle.com>2008-09-26 10:09:34 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-26 10:09:34 -0400
commit1a40e23b95da45051ee4d74374c58ae87a14051c (patch)
tree77faffd3f9d3a26c22e6cf03b83762c95d687596 /fs/btrfs/disk-io.c
parent5b21f2ed3f2947b5195b65c9fdbdd9e52904cc03 (diff)
Btrfs: update space balancing code
This patch updates the space balancing code to utilize the new backref format. Before, btrfs-vol -b would break any COW links on data blocks or metadata. This was slow and caused the amount of space used to explode if a large number of snapshots were present. The new code can keeps the sharing of all data extents and most of the tree blocks. To maintain the sharing of data extents, the space balance code uses a seperate inode hold data extent pointers, then updates the references to point to the new location. To maintain the sharing of tree blocks, the space balance code uses reloc trees to relocate tree blocks in reference counted roots. There is one reloc tree for each subvol, and all reloc trees share same root key objectid. Reloc trees are snapshots of the latest committed roots of subvols (root->commit_root). To relocate a tree block referenced by a subvol, there are two steps. COW the block through subvol's reloc tree, then update block pointer in the subvol to point to the new block. Since all reloc trees share same root key objectid, doing special handing for tree blocks owned by them is easy. Once a tree block has been COWed in one reloc tree, we can use the resulting new block directly when the same block is required to COW again through other reloc trees. In this way, relocated tree blocks are shared between reloc trees, so they are also shared between subvols. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 8969fee2331..45bc3132b05 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1406,6 +1406,10 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1406 fs_info->btree_inode->i_mapping, GFP_NOFS); 1406 fs_info->btree_inode->i_mapping, GFP_NOFS);
1407 fs_info->do_barriers = 1; 1407 fs_info->do_barriers = 1;
1408 1408
1409 extent_io_tree_init(&fs_info->reloc_mapping_tree,
1410 fs_info->btree_inode->i_mapping, GFP_NOFS);
1411 INIT_LIST_HEAD(&fs_info->dead_reloc_roots);
1412 btrfs_leaf_ref_tree_init(&fs_info->reloc_ref_tree);
1409 btrfs_leaf_ref_tree_init(&fs_info->shared_ref_tree); 1413 btrfs_leaf_ref_tree_init(&fs_info->shared_ref_tree);
1410 1414
1411 BTRFS_I(fs_info->btree_inode)->root = tree_root; 1415 BTRFS_I(fs_info->btree_inode)->root = tree_root;
@@ -1421,6 +1425,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1421 mutex_init(&fs_info->transaction_kthread_mutex); 1425 mutex_init(&fs_info->transaction_kthread_mutex);
1422 mutex_init(&fs_info->cleaner_mutex); 1426 mutex_init(&fs_info->cleaner_mutex);
1423 mutex_init(&fs_info->volume_mutex); 1427 mutex_init(&fs_info->volume_mutex);
1428 mutex_init(&fs_info->tree_reloc_mutex);
1424 init_waitqueue_head(&fs_info->transaction_throttle); 1429 init_waitqueue_head(&fs_info->transaction_throttle);
1425 init_waitqueue_head(&fs_info->transaction_wait); 1430 init_waitqueue_head(&fs_info->transaction_wait);
1426 init_waitqueue_head(&fs_info->async_submit_wait); 1431 init_waitqueue_head(&fs_info->async_submit_wait);
@@ -1627,6 +1632,10 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1627 ret = btrfs_recover_log_trees(log_tree_root); 1632 ret = btrfs_recover_log_trees(log_tree_root);
1628 BUG_ON(ret); 1633 BUG_ON(ret);
1629 } 1634 }
1635
1636 ret = btrfs_cleanup_reloc_trees(tree_root);
1637 BUG_ON(ret);
1638
1630 fs_info->last_trans_committed = btrfs_super_generation(disk_super); 1639 fs_info->last_trans_committed = btrfs_super_generation(disk_super);
1631 return tree_root; 1640 return tree_root;
1632 1641