aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.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/transaction.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/transaction.c')
-rw-r--r--fs/btrfs/transaction.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 8c83cf464c83..444abe0796ae 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -477,6 +477,7 @@ static noinline int add_dirty_roots(struct btrfs_trans_handle *trans,
477 dirty = root->dirty_root; 477 dirty = root->dirty_root;
478 478
479 btrfs_free_log(trans, root); 479 btrfs_free_log(trans, root);
480 btrfs_free_reloc_root(root);
480 481
481 if (root->commit_root == root->node) { 482 if (root->commit_root == root->node) {
482 WARN_ON(root->node->start != 483 WARN_ON(root->node->start !=
@@ -855,6 +856,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
855 * with the tree-log code. 856 * with the tree-log code.
856 */ 857 */
857 mutex_lock(&root->fs_info->tree_log_mutex); 858 mutex_lock(&root->fs_info->tree_log_mutex);
859 /*
860 * keep tree reloc code from adding new reloc trees
861 */
862 mutex_lock(&root->fs_info->tree_reloc_mutex);
863
858 864
859 ret = add_dirty_roots(trans, &root->fs_info->fs_roots_radix, 865 ret = add_dirty_roots(trans, &root->fs_info->fs_roots_radix,
860 &dirty_fs_roots); 866 &dirty_fs_roots);
@@ -865,6 +871,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
865 */ 871 */
866 btrfs_free_log_root_tree(trans, root->fs_info); 872 btrfs_free_log_root_tree(trans, root->fs_info);
867 873
874 btrfs_free_reloc_mappings(root);
875
868 ret = btrfs_commit_tree_roots(trans, root); 876 ret = btrfs_commit_tree_roots(trans, root);
869 BUG_ON(ret); 877 BUG_ON(ret);
870 878
@@ -910,10 +918,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
910 mutex_unlock(&root->fs_info->tree_log_mutex); 918 mutex_unlock(&root->fs_info->tree_log_mutex);
911 919
912 btrfs_finish_extent_commit(trans, root, pinned_copy); 920 btrfs_finish_extent_commit(trans, root, pinned_copy);
913 mutex_lock(&root->fs_info->trans_mutex);
914
915 kfree(pinned_copy); 921 kfree(pinned_copy);
916 922
923 btrfs_drop_dead_reloc_roots(root);
924 mutex_unlock(&root->fs_info->tree_reloc_mutex);
925
926 mutex_lock(&root->fs_info->trans_mutex);
927
917 cur_trans->commit_done = 1; 928 cur_trans->commit_done = 1;
918 root->fs_info->last_trans_committed = cur_trans->transid; 929 root->fs_info->last_trans_committed = cur_trans->transid;
919 wake_up(&cur_trans->commit_wait); 930 wake_up(&cur_trans->commit_wait);