summaryrefslogtreecommitdiff
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2008-12-09 00:46:26 +0300
committerChris Mason <chris.mason@oracle.com>2008-12-09 00:46:26 +0300
commita512bbf855ff0af474257475f2e6da7acd854f52 (patch)
tree1b2cfcf4152e09f32a6cb0bcbd798d5dab2f5490 /fs/btrfs/extent-tree.c
parentd20f7043fa65659136c1a7c3c456eeeb5c6f431f (diff)
downloadlinux-a512bbf855ff0af474257475f2e6da7acd854f52.tar.xz
Btrfs: superblock duplication
This patch implements superblock duplication. Superblocks are stored at offset 16K, 64M and 256G on every devices. Spaces used by superblocks are preserved by the allocator, which uses a reverse mapping function to find the logical addresses that correspond to superblocks. Thank you, Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c54
1 files changed, 28 insertions, 26 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index d15638529389..803647bc8400 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -189,6 +189,29 @@ static int add_new_free_space(struct btrfs_block_group_cache *block_group,
return 0;
}
+static int remove_sb_from_cache(struct btrfs_root *root,
+ struct btrfs_block_group_cache *cache)
+{
+ u64 bytenr;
+ u64 *logical;
+ int stripe_len;
+ int i, nr, ret;
+
+ for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
+ bytenr = btrfs_sb_offset(i);
+ ret = btrfs_rmap_block(&root->fs_info->mapping_tree,
+ cache->key.objectid, bytenr, 0,
+ &logical, &nr, &stripe_len);
+ BUG_ON(ret);
+ while (nr--) {
+ btrfs_remove_free_space(cache, logical[nr],
+ stripe_len);
+ }
+ kfree(logical);
+ }
+ return 0;
+}
+
static int cache_block_group(struct btrfs_root *root,
struct btrfs_block_group_cache *block_group)
{
@@ -197,9 +220,7 @@ static int cache_block_group(struct btrfs_root *root,
struct btrfs_key key;
struct extent_buffer *leaf;
int slot;
- u64 last = 0;
- u64 first_free;
- int found = 0;
+ u64 last = block_group->key.objectid;
if (!block_group)
return 0;
@@ -220,23 +241,13 @@ static int cache_block_group(struct btrfs_root *root,
* skip the locking here
*/
path->skip_locking = 1;
- first_free = max_t(u64, block_group->key.objectid,
- BTRFS_SUPER_INFO_OFFSET + BTRFS_SUPER_INFO_SIZE);
- key.objectid = block_group->key.objectid;
+ key.objectid = last;
key.offset = 0;
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (ret < 0)
goto err;
- ret = btrfs_previous_item(root, path, 0, BTRFS_EXTENT_ITEM_KEY);
- if (ret < 0)
- goto err;
- if (ret == 0) {
- leaf = path->nodes[0];
- btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
- if (key.objectid + key.offset > first_free)
- first_free = key.objectid + key.offset;
- }
+
while(1) {
leaf = path->nodes[0];
slot = path->slots[0];
@@ -258,11 +269,6 @@ static int cache_block_group(struct btrfs_root *root,
break;
if (btrfs_key_type(&key) == BTRFS_EXTENT_ITEM_KEY) {
- if (!found) {
- last = first_free;
- found = 1;
- }
-
add_new_free_space(block_group, root->fs_info, last,
key.objectid);
@@ -272,13 +278,11 @@ next:
path->slots[0]++;
}
- if (!found)
- last = first_free;
-
add_new_free_space(block_group, root->fs_info, last,
block_group->key.objectid +
block_group->key.offset);
+ remove_sb_from_cache(root, block_group);
block_group->cached = 1;
ret = 0;
err:
@@ -1974,10 +1978,8 @@ static int update_block_group(struct btrfs_trans_handle *trans,
if (alloc) {
old_val += num_bytes;
cache->space_info->bytes_used += num_bytes;
- if (cache->ro) {
+ if (cache->ro)
cache->space_info->bytes_readonly -= num_bytes;
- WARN_ON(1);
- }
btrfs_set_block_group_used(&cache->item, old_val);
spin_unlock(&cache->lock);
spin_unlock(&cache->space_info->lock);