aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2008-12-08 16:46:26 -0500
committerChris Mason <chris.mason@oracle.com>2008-12-08 16:46:26 -0500
commita512bbf855ff0af474257475f2e6da7acd854f52 (patch)
tree1b2cfcf4152e09f32a6cb0bcbd798d5dab2f5490 /fs/btrfs/extent-tree.c
parentd20f7043fa65659136c1a7c3c456eeeb5c6f431f (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.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,
189 return 0; 189 return 0;
190} 190}
191 191
192static 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
192static int cache_block_group(struct btrfs_root *root, 215static 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;
284err: 288err:
@@ -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);