aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.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/volumes.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/volumes.c')
-rw-r--r--fs/btrfs/volumes.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index ddf89626498a..51f113119b25 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1268,7 +1268,7 @@ int btrfs_relocate_chunk(struct btrfs_root *root,
1268 em_tree = &root->fs_info->mapping_tree.map_tree; 1268 em_tree = &root->fs_info->mapping_tree.map_tree;
1269 1269
1270 /* step one, relocate all the extents inside this chunk */ 1270 /* step one, relocate all the extents inside this chunk */
1271 ret = btrfs_shrink_extent_tree(extent_root, chunk_offset); 1271 ret = btrfs_relocate_block_group(extent_root, chunk_offset);
1272 BUG_ON(ret); 1272 BUG_ON(ret);
1273 1273
1274 trans = btrfs_start_transaction(root, 1); 1274 trans = btrfs_start_transaction(root, 1);
@@ -1308,15 +1308,18 @@ int btrfs_relocate_chunk(struct btrfs_root *root,
1308 BUG_ON(ret); 1308 BUG_ON(ret);
1309 } 1309 }
1310 1310
1311 ret = btrfs_remove_block_group(trans, extent_root, chunk_offset);
1312 BUG_ON(ret);
1313
1311 spin_lock(&em_tree->lock); 1314 spin_lock(&em_tree->lock);
1312 remove_extent_mapping(em_tree, em); 1315 remove_extent_mapping(em_tree, em);
1316 spin_unlock(&em_tree->lock);
1317
1313 kfree(map); 1318 kfree(map);
1314 em->bdev = NULL; 1319 em->bdev = NULL;
1315 1320
1316 /* once for the tree */ 1321 /* once for the tree */
1317 free_extent_map(em); 1322 free_extent_map(em);
1318 spin_unlock(&em_tree->lock);
1319
1320 /* once for us */ 1323 /* once for us */
1321 free_extent_map(em); 1324 free_extent_map(em);
1322 1325