diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-06-22 14:16:25 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-06-22 14:16:25 -0400 |
commit | 5eda7b5e9b0bed864dd18284c7df9b3c8207dad7 (patch) | |
tree | 9efe48de46e77f2b7b97a2ce3ee93c9da6451671 /fs/btrfs/disk-io.c | |
parent | 54aa1f4dfdacd60a19c4471220b24e581be6f774 (diff) |
Btrfs: Add the ability to find and remove dead roots after a crash.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 865a284aa06c..d7615e1578cc 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -326,8 +326,8 @@ static int find_and_setup_root(int blocksize, | |||
326 | return 0; | 326 | return 0; |
327 | } | 327 | } |
328 | 328 | ||
329 | struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, | 329 | struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, |
330 | struct btrfs_key *location) | 330 | struct btrfs_key *location) |
331 | { | 331 | { |
332 | struct btrfs_root *root; | 332 | struct btrfs_root *root; |
333 | struct btrfs_root *tree_root = fs_info->tree_root; | 333 | struct btrfs_root *tree_root = fs_info->tree_root; |
@@ -336,11 +336,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, | |||
336 | u64 highest_inode; | 336 | u64 highest_inode; |
337 | int ret = 0; | 337 | int ret = 0; |
338 | 338 | ||
339 | root = radix_tree_lookup(&fs_info->fs_roots_radix, | 339 | root = kzalloc(sizeof(*root), GFP_NOFS); |
340 | (unsigned long)location->objectid); | ||
341 | if (root) | ||
342 | return root; | ||
343 | root = kmalloc(sizeof(*root), GFP_NOFS); | ||
344 | if (!root) | 340 | if (!root) |
345 | return ERR_PTR(-ENOMEM); | 341 | return ERR_PTR(-ENOMEM); |
346 | if (location->offset == (u64)-1) { | 342 | if (location->offset == (u64)-1) { |
@@ -383,6 +379,28 @@ out: | |||
383 | BUG_ON(!root->node); | 379 | BUG_ON(!root->node); |
384 | insert: | 380 | insert: |
385 | root->ref_cows = 1; | 381 | root->ref_cows = 1; |
382 | ret = btrfs_find_highest_inode(root, &highest_inode); | ||
383 | if (ret == 0) { | ||
384 | root->highest_inode = highest_inode; | ||
385 | root->last_inode_alloc = highest_inode; | ||
386 | } | ||
387 | return root; | ||
388 | } | ||
389 | |||
390 | struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, | ||
391 | struct btrfs_key *location) | ||
392 | { | ||
393 | struct btrfs_root *root; | ||
394 | int ret; | ||
395 | |||
396 | root = radix_tree_lookup(&fs_info->fs_roots_radix, | ||
397 | (unsigned long)location->objectid); | ||
398 | if (root) | ||
399 | return root; | ||
400 | |||
401 | root = btrfs_read_fs_root_no_radix(fs_info, location); | ||
402 | if (IS_ERR(root)) | ||
403 | return root; | ||
386 | ret = radix_tree_insert(&fs_info->fs_roots_radix, | 404 | ret = radix_tree_insert(&fs_info->fs_roots_radix, |
387 | (unsigned long)root->root_key.objectid, | 405 | (unsigned long)root->root_key.objectid, |
388 | root); | 406 | root); |
@@ -391,11 +409,6 @@ insert: | |||
391 | kfree(root); | 409 | kfree(root); |
392 | return ERR_PTR(ret); | 410 | return ERR_PTR(ret); |
393 | } | 411 | } |
394 | ret = btrfs_find_highest_inode(root, &highest_inode); | ||
395 | if (ret == 0) { | ||
396 | root->highest_inode = highest_inode; | ||
397 | root->last_inode_alloc = highest_inode; | ||
398 | } | ||
399 | return root; | 412 | return root; |
400 | } | 413 | } |
401 | 414 | ||
@@ -489,6 +502,9 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
489 | btrfs_read_block_groups(extent_root); | 502 | btrfs_read_block_groups(extent_root); |
490 | 503 | ||
491 | fs_info->generation = btrfs_super_generation(disk_super) + 1; | 504 | fs_info->generation = btrfs_super_generation(disk_super) + 1; |
505 | ret = btrfs_find_dead_roots(tree_root); | ||
506 | if (ret) | ||
507 | goto fail_tree_root; | ||
492 | mutex_unlock(&fs_info->fs_mutex); | 508 | mutex_unlock(&fs_info->fs_mutex); |
493 | return tree_root; | 509 | return tree_root; |
494 | 510 | ||
@@ -538,7 +554,7 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | |||
538 | return 0; | 554 | return 0; |
539 | } | 555 | } |
540 | 556 | ||
541 | static int free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) | 557 | int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) |
542 | { | 558 | { |
543 | radix_tree_delete(&fs_info->fs_roots_radix, | 559 | radix_tree_delete(&fs_info->fs_roots_radix, |
544 | (unsigned long)root->root_key.objectid); | 560 | (unsigned long)root->root_key.objectid); |
@@ -565,7 +581,7 @@ static int del_fs_roots(struct btrfs_fs_info *fs_info) | |||
565 | if (!ret) | 581 | if (!ret) |
566 | break; | 582 | break; |
567 | for (i = 0; i < ret; i++) | 583 | for (i = 0; i < ret; i++) |
568 | free_fs_root(fs_info, gang[i]); | 584 | btrfs_free_fs_root(fs_info, gang[i]); |
569 | } | 585 | } |
570 | return 0; | 586 | return 0; |
571 | } | 587 | } |