diff options
Diffstat (limited to 'fs/btrfs/root-tree.c')
| -rw-r--r-- | fs/btrfs/root-tree.c | 69 |
1 files changed, 64 insertions, 5 deletions
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 5ef72599a581..9351428f30e2 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
| @@ -94,17 +94,23 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, | |||
| 94 | goto out; | 94 | goto out; |
| 95 | 95 | ||
| 96 | BUG_ON(ret == 0); | 96 | BUG_ON(ret == 0); |
| 97 | if (path->slots[0] == 0) { | ||
| 98 | ret = 1; | ||
| 99 | goto out; | ||
| 100 | } | ||
| 97 | l = path->nodes[0]; | 101 | l = path->nodes[0]; |
| 98 | BUG_ON(path->slots[0] == 0); | ||
| 99 | slot = path->slots[0] - 1; | 102 | slot = path->slots[0] - 1; |
| 100 | btrfs_item_key_to_cpu(l, &found_key, slot); | 103 | btrfs_item_key_to_cpu(l, &found_key, slot); |
| 101 | if (found_key.objectid != objectid) { | 104 | if (found_key.objectid != objectid || |
| 105 | found_key.type != BTRFS_ROOT_ITEM_KEY) { | ||
| 102 | ret = 1; | 106 | ret = 1; |
| 103 | goto out; | 107 | goto out; |
| 104 | } | 108 | } |
| 105 | read_extent_buffer(l, item, btrfs_item_ptr_offset(l, slot), | 109 | if (item) |
| 106 | sizeof(*item)); | 110 | read_extent_buffer(l, item, btrfs_item_ptr_offset(l, slot), |
| 107 | memcpy(key, &found_key, sizeof(found_key)); | 111 | sizeof(*item)); |
| 112 | if (key) | ||
| 113 | memcpy(key, &found_key, sizeof(found_key)); | ||
| 108 | ret = 0; | 114 | ret = 0; |
| 109 | out: | 115 | out: |
| 110 | btrfs_free_path(path); | 116 | btrfs_free_path(path); |
| @@ -249,6 +255,59 @@ err: | |||
| 249 | return ret; | 255 | return ret; |
| 250 | } | 256 | } |
| 251 | 257 | ||
| 258 | int btrfs_find_orphan_roots(struct btrfs_root *tree_root) | ||
| 259 | { | ||
| 260 | struct extent_buffer *leaf; | ||
| 261 | struct btrfs_path *path; | ||
| 262 | struct btrfs_key key; | ||
| 263 | int err = 0; | ||
| 264 | int ret; | ||
| 265 | |||
| 266 | path = btrfs_alloc_path(); | ||
| 267 | if (!path) | ||
| 268 | return -ENOMEM; | ||
| 269 | |||
| 270 | key.objectid = BTRFS_ORPHAN_OBJECTID; | ||
| 271 | key.type = BTRFS_ORPHAN_ITEM_KEY; | ||
| 272 | key.offset = 0; | ||
| 273 | |||
| 274 | while (1) { | ||
| 275 | ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0); | ||
| 276 | if (ret < 0) { | ||
| 277 | err = ret; | ||
| 278 | break; | ||
| 279 | } | ||
| 280 | |||
| 281 | leaf = path->nodes[0]; | ||
| 282 | if (path->slots[0] >= btrfs_header_nritems(leaf)) { | ||
| 283 | ret = btrfs_next_leaf(tree_root, path); | ||
| 284 | if (ret < 0) | ||
| 285 | err = ret; | ||
| 286 | if (ret != 0) | ||
| 287 | break; | ||
| 288 | leaf = path->nodes[0]; | ||
| 289 | } | ||
| 290 | |||
| 291 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
| 292 | btrfs_release_path(tree_root, path); | ||
| 293 | |||
| 294 | if (key.objectid != BTRFS_ORPHAN_OBJECTID || | ||
| 295 | key.type != BTRFS_ORPHAN_ITEM_KEY) | ||
| 296 | break; | ||
| 297 | |||
| 298 | ret = btrfs_find_dead_roots(tree_root, key.offset); | ||
| 299 | if (ret) { | ||
| 300 | err = ret; | ||
| 301 | break; | ||
| 302 | } | ||
| 303 | |||
| 304 | key.offset++; | ||
| 305 | } | ||
| 306 | |||
| 307 | btrfs_free_path(path); | ||
| 308 | return err; | ||
| 309 | } | ||
| 310 | |||
| 252 | /* drop the root item for 'key' from 'root' */ | 311 | /* drop the root item for 'key' from 'root' */ |
| 253 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 312 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
| 254 | struct btrfs_key *key) | 313 | struct btrfs_key *key) |
