diff options
author | Yan Zheng <zheng.yan@oracle.com> | 2008-12-08 16:46:26 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-12-08 16:46:26 -0500 |
commit | a512bbf855ff0af474257475f2e6da7acd854f52 (patch) | |
tree | 1b2cfcf4152e09f32a6cb0bcbd798d5dab2f5490 /fs/btrfs/extent-tree.c | |
parent | d20f7043fa65659136c1a7c3c456eeeb5c6f431f (diff) |
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.c | 54 |
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, | |||
189 | return 0; | 189 | return 0; |
190 | } | 190 | } |
191 | 191 | ||
192 | static int remove_sb_from_cache(struct btrfs_root *root, | ||
193 | struct btrfs_block_group_cache *cache) | ||
194 | { | ||
195 | u64 bytenr; | ||
196 | u64 *logical; | ||
197 | int stripe_len; | ||
198 | int i, nr, ret; | ||
199 | |||
200 | for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { | ||
201 | bytenr = btrfs_sb_offset(i); | ||
202 | ret = btrfs_rmap_block(&root->fs_info->mapping_tree, | ||
203 | cache->key.objectid, bytenr, 0, | ||
204 | &logical, &nr, &stripe_len); | ||
205 | BUG_ON(ret); | ||
206 | while (nr--) { | ||
207 | btrfs_remove_free_space(cache, logical[nr], | ||
208 | stripe_len); | ||
209 | } | ||
210 | kfree(logical); | ||
211 | } | ||
212 | return 0; | ||
213 | } | ||
214 | |||
192 | static int cache_block_group(struct btrfs_root *root, | 215 | static int cache_block_group(struct btrfs_root *root, |
193 | struct btrfs_block_group_cache *block_group) | 216 | struct btrfs_block_group_cache *block_group) |
194 | { | 217 | { |
@@ -197,9 +220,7 @@ static int cache_block_group(struct btrfs_root *root, | |||
197 | struct btrfs_key key; | 220 | struct btrfs_key key; |
198 | struct extent_buffer *leaf; | 221 | struct extent_buffer *leaf; |
199 | int slot; | 222 | int slot; |
200 | u64 last = 0; | 223 | u64 last = block_group->key.objectid; |
201 | u64 first_free; | ||
202 | int found = 0; | ||
203 | 224 | ||
204 | if (!block_group) | 225 | if (!block_group) |
205 | return 0; | 226 | return 0; |
@@ -220,23 +241,13 @@ static int cache_block_group(struct btrfs_root *root, | |||
220 | * skip the locking here | 241 | * skip the locking here |
221 | */ | 242 | */ |
222 | path->skip_locking = 1; | 243 | path->skip_locking = 1; |
223 | first_free = max_t(u64, block_group->key.objectid, | 244 | key.objectid = last; |
224 | BTRFS_SUPER_INFO_OFFSET + BTRFS_SUPER_INFO_SIZE); | ||
225 | key.objectid = block_group->key.objectid; | ||
226 | key.offset = 0; | 245 | key.offset = 0; |
227 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 246 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
228 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 247 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
229 | if (ret < 0) | 248 | if (ret < 0) |
230 | goto err; | 249 | goto err; |
231 | ret = btrfs_previous_item(root, path, 0, BTRFS_EXTENT_ITEM_KEY); | 250 | |
232 | if (ret < 0) | ||
233 | goto err; | ||
234 | if (ret == 0) { | ||
235 | leaf = path->nodes[0]; | ||
236 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
237 | if (key.objectid + key.offset > first_free) | ||
238 | first_free = key.objectid + key.offset; | ||
239 | } | ||
240 | while(1) { | 251 | while(1) { |
241 | leaf = path->nodes[0]; | 252 | leaf = path->nodes[0]; |
242 | slot = path->slots[0]; | 253 | slot = path->slots[0]; |
@@ -258,11 +269,6 @@ static int cache_block_group(struct btrfs_root *root, | |||
258 | break; | 269 | break; |
259 | 270 | ||
260 | if (btrfs_key_type(&key) == BTRFS_EXTENT_ITEM_KEY) { | 271 | if (btrfs_key_type(&key) == BTRFS_EXTENT_ITEM_KEY) { |
261 | if (!found) { | ||
262 | last = first_free; | ||
263 | found = 1; | ||
264 | } | ||
265 | |||
266 | add_new_free_space(block_group, root->fs_info, last, | 272 | add_new_free_space(block_group, root->fs_info, last, |
267 | key.objectid); | 273 | key.objectid); |
268 | 274 | ||
@@ -272,13 +278,11 @@ next: | |||
272 | path->slots[0]++; | 278 | path->slots[0]++; |
273 | } | 279 | } |
274 | 280 | ||
275 | if (!found) | ||
276 | last = first_free; | ||
277 | |||
278 | add_new_free_space(block_group, root->fs_info, last, | 281 | add_new_free_space(block_group, root->fs_info, last, |
279 | block_group->key.objectid + | 282 | block_group->key.objectid + |
280 | block_group->key.offset); | 283 | block_group->key.offset); |
281 | 284 | ||
285 | remove_sb_from_cache(root, block_group); | ||
282 | block_group->cached = 1; | 286 | block_group->cached = 1; |
283 | ret = 0; | 287 | ret = 0; |
284 | err: | 288 | err: |
@@ -1974,10 +1978,8 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
1974 | if (alloc) { | 1978 | if (alloc) { |
1975 | old_val += num_bytes; | 1979 | old_val += num_bytes; |
1976 | cache->space_info->bytes_used += num_bytes; | 1980 | cache->space_info->bytes_used += num_bytes; |
1977 | if (cache->ro) { | 1981 | if (cache->ro) |
1978 | cache->space_info->bytes_readonly -= num_bytes; | 1982 | cache->space_info->bytes_readonly -= num_bytes; |
1979 | WARN_ON(1); | ||
1980 | } | ||
1981 | btrfs_set_block_group_used(&cache->item, old_val); | 1983 | btrfs_set_block_group_used(&cache->item, old_val); |
1982 | spin_unlock(&cache->lock); | 1984 | spin_unlock(&cache->lock); |
1983 | spin_unlock(&cache->space_info->lock); | 1985 | spin_unlock(&cache->space_info->lock); |