aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-06-22 14:16:25 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-06-22 14:16:25 -0400
commit5eda7b5e9b0bed864dd18284c7df9b3c8207dad7 (patch)
tree9efe48de46e77f2b7b97a2ce3ee93c9da6451671 /fs/btrfs/disk-io.c
parent54aa1f4dfdacd60a19c4471220b24e581be6f774 (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.c44
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
329struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, 329struct 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);
384insert: 380insert:
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
390struct 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
541static int free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) 557int 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}