aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/root-tree.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/btrfs/root-tree.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'fs/btrfs/root-tree.c')
-rw-r--r--fs/btrfs/root-tree.c87
1 files changed, 31 insertions, 56 deletions
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
index 2d958be761c8..ebe45443de06 100644
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -22,53 +22,6 @@
22#include "print-tree.h" 22#include "print-tree.h"
23 23
24/* 24/*
25 * search forward for a root, starting with objectid 'search_start'
26 * if a root key is found, the objectid we find is filled into 'found_objectid'
27 * and 0 is returned. < 0 is returned on error, 1 if there is nothing
28 * left in the tree.
29 */
30int btrfs_search_root(struct btrfs_root *root, u64 search_start,
31 u64 *found_objectid)
32{
33 struct btrfs_path *path;
34 struct btrfs_key search_key;
35 int ret;
36
37 root = root->fs_info->tree_root;
38 search_key.objectid = search_start;
39 search_key.type = (u8)-1;
40 search_key.offset = (u64)-1;
41
42 path = btrfs_alloc_path();
43 BUG_ON(!path);
44again:
45 ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
46 if (ret < 0)
47 goto out;
48 if (ret == 0) {
49 ret = 1;
50 goto out;
51 }
52 if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) {
53 ret = btrfs_next_leaf(root, path);
54 if (ret)
55 goto out;
56 }
57 btrfs_item_key_to_cpu(path->nodes[0], &search_key, path->slots[0]);
58 if (search_key.type != BTRFS_ROOT_ITEM_KEY) {
59 search_key.offset++;
60 btrfs_release_path(root, path);
61 goto again;
62 }
63 ret = 0;
64 *found_objectid = search_key.objectid;
65
66out:
67 btrfs_free_path(path);
68 return ret;
69}
70
71/*
72 * lookup the root with the highest offset for a given objectid. The key we do 25 * lookup the root with the highest offset for a given objectid. The key we do
73 * find is copied into 'key'. If we find something return 0, otherwise 1, < 0 26 * find is copied into 'key'. If we find something return 0, otherwise 1, < 0
74 * on error. 27 * on error.
@@ -88,7 +41,8 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
88 search_key.offset = (u64)-1; 41 search_key.offset = (u64)-1;
89 42
90 path = btrfs_alloc_path(); 43 path = btrfs_alloc_path();
91 BUG_ON(!path); 44 if (!path)
45 return -ENOMEM;
92 ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); 46 ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
93 if (ret < 0) 47 if (ret < 0)
94 goto out; 48 goto out;
@@ -181,7 +135,6 @@ int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
181int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid) 135int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid)
182{ 136{
183 struct btrfs_root *dead_root; 137 struct btrfs_root *dead_root;
184 struct btrfs_item *item;
185 struct btrfs_root_item *ri; 138 struct btrfs_root_item *ri;
186 struct btrfs_key key; 139 struct btrfs_key key;
187 struct btrfs_key found_key; 140 struct btrfs_key found_key;
@@ -214,7 +167,6 @@ again:
214 nritems = btrfs_header_nritems(leaf); 167 nritems = btrfs_header_nritems(leaf);
215 slot = path->slots[0]; 168 slot = path->slots[0];
216 } 169 }
217 item = btrfs_item_nr(leaf, slot);
218 btrfs_item_key_to_cpu(leaf, &key, slot); 170 btrfs_item_key_to_cpu(leaf, &key, slot);
219 if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY) 171 if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY)
220 goto next; 172 goto next;
@@ -231,7 +183,7 @@ again:
231 183
232 memcpy(&found_key, &key, sizeof(key)); 184 memcpy(&found_key, &key, sizeof(key));
233 key.offset++; 185 key.offset++;
234 btrfs_release_path(root, path); 186 btrfs_release_path(path);
235 dead_root = 187 dead_root =
236 btrfs_read_fs_root_no_radix(root->fs_info->tree_root, 188 btrfs_read_fs_root_no_radix(root->fs_info->tree_root,
237 &found_key); 189 &found_key);
@@ -293,7 +245,7 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
293 } 245 }
294 246
295 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 247 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
296 btrfs_release_path(tree_root, path); 248 btrfs_release_path(path);
297 249
298 if (key.objectid != BTRFS_ORPHAN_OBJECTID || 250 if (key.objectid != BTRFS_ORPHAN_OBJECTID ||
299 key.type != BTRFS_ORPHAN_ITEM_KEY) 251 key.type != BTRFS_ORPHAN_ITEM_KEY)
@@ -334,7 +286,8 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
334 struct extent_buffer *leaf; 286 struct extent_buffer *leaf;
335 287
336 path = btrfs_alloc_path(); 288 path = btrfs_alloc_path();
337 BUG_ON(!path); 289 if (!path)
290 return -ENOMEM;
338 ret = btrfs_search_slot(trans, root, key, path, -1, 1); 291 ret = btrfs_search_slot(trans, root, key, path, -1, 1);
339 if (ret < 0) 292 if (ret < 0)
340 goto out; 293 goto out;
@@ -385,18 +338,22 @@ again:
385 *sequence = btrfs_root_ref_sequence(leaf, ref); 338 *sequence = btrfs_root_ref_sequence(leaf, ref);
386 339
387 ret = btrfs_del_item(trans, tree_root, path); 340 ret = btrfs_del_item(trans, tree_root, path);
388 BUG_ON(ret); 341 if (ret) {
342 err = ret;
343 goto out;
344 }
389 } else 345 } else
390 err = -ENOENT; 346 err = -ENOENT;
391 347
392 if (key.type == BTRFS_ROOT_BACKREF_KEY) { 348 if (key.type == BTRFS_ROOT_BACKREF_KEY) {
393 btrfs_release_path(tree_root, path); 349 btrfs_release_path(path);
394 key.objectid = ref_id; 350 key.objectid = ref_id;
395 key.type = BTRFS_ROOT_REF_KEY; 351 key.type = BTRFS_ROOT_REF_KEY;
396 key.offset = root_id; 352 key.offset = root_id;
397 goto again; 353 goto again;
398 } 354 }
399 355
356out:
400 btrfs_free_path(path); 357 btrfs_free_path(path);
401 return err; 358 return err;
402} 359}
@@ -463,7 +420,7 @@ again:
463 btrfs_mark_buffer_dirty(leaf); 420 btrfs_mark_buffer_dirty(leaf);
464 421
465 if (key.type == BTRFS_ROOT_BACKREF_KEY) { 422 if (key.type == BTRFS_ROOT_BACKREF_KEY) {
466 btrfs_release_path(tree_root, path); 423 btrfs_release_path(path);
467 key.objectid = ref_id; 424 key.objectid = ref_id;
468 key.type = BTRFS_ROOT_REF_KEY; 425 key.type = BTRFS_ROOT_REF_KEY;
469 key.offset = root_id; 426 key.offset = root_id;
@@ -473,3 +430,21 @@ again:
473 btrfs_free_path(path); 430 btrfs_free_path(path);
474 return 0; 431 return 0;
475} 432}
433
434/*
435 * Old btrfs forgets to init root_item->flags and root_item->byte_limit
436 * for subvolumes. To work around this problem, we steal a bit from
437 * root_item->inode_item->flags, and use it to indicate if those fields
438 * have been properly initialized.
439 */
440void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item)
441{
442 u64 inode_flags = le64_to_cpu(root_item->inode.flags);
443
444 if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) {
445 inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT;
446 root_item->inode.flags = cpu_to_le64(inode_flags);
447 root_item->flags = 0;
448 root_item->byte_limit = 0;
449 }
450}