diff options
author | Stefan Behrens <sbehrens@giantdisaster.de> | 2013-08-15 11:11:19 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2013-09-01 08:15:54 -0400 |
commit | f7a81ea4cc6bdb51d8267d2f3ff485f0b4070074 (patch) | |
tree | 61fd4fd144fae34736eb2cda2ed6b351c82d9b54 /fs | |
parent | 8f8ae8e213300378d2506b68d581c80d9dfd2faf (diff) |
Btrfs: create UUID tree if required
This tree is not created by mkfs.btrfs. Therefore when a filesystem
is mounted writable and the UUID tree does not exist, this tree is
created if required. The tree is also added to the fs_info structure
and initialized, but this commit does not yet read or write UUID tree
elements.
Signed-off-by: Stefan Behrens <sbehrens@giantdisaster.de>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ctree.h | 1 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 34 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 3 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 26 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 1 |
5 files changed, 65 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 429c54ac1a65..c03e61ef7230 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1306,6 +1306,7 @@ struct btrfs_fs_info { | |||
1306 | struct btrfs_root *fs_root; | 1306 | struct btrfs_root *fs_root; |
1307 | struct btrfs_root *csum_root; | 1307 | struct btrfs_root *csum_root; |
1308 | struct btrfs_root *quota_root; | 1308 | struct btrfs_root *quota_root; |
1309 | struct btrfs_root *uuid_root; | ||
1309 | 1310 | ||
1310 | /* the log root tree is a directory of all the other log roots */ | 1311 | /* the log root tree is a directory of all the other log roots */ |
1311 | struct btrfs_root *log_root_tree; | 1312 | struct btrfs_root *log_root_tree; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index f96a237bb40a..80bd63738c6d 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1586,6 +1586,9 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, | |||
1586 | if (location->objectid == BTRFS_QUOTA_TREE_OBJECTID) | 1586 | if (location->objectid == BTRFS_QUOTA_TREE_OBJECTID) |
1587 | return fs_info->quota_root ? fs_info->quota_root : | 1587 | return fs_info->quota_root ? fs_info->quota_root : |
1588 | ERR_PTR(-ENOENT); | 1588 | ERR_PTR(-ENOENT); |
1589 | if (location->objectid == BTRFS_UUID_TREE_OBJECTID) | ||
1590 | return fs_info->uuid_root ? fs_info->uuid_root : | ||
1591 | ERR_PTR(-ENOENT); | ||
1589 | again: | 1592 | again: |
1590 | root = btrfs_lookup_fs_root(fs_info, location->objectid); | 1593 | root = btrfs_lookup_fs_root(fs_info, location->objectid); |
1591 | if (root) | 1594 | if (root) |
@@ -2044,6 +2047,12 @@ static void free_root_pointers(struct btrfs_fs_info *info, int chunk_root) | |||
2044 | info->quota_root->node = NULL; | 2047 | info->quota_root->node = NULL; |
2045 | info->quota_root->commit_root = NULL; | 2048 | info->quota_root->commit_root = NULL; |
2046 | } | 2049 | } |
2050 | if (info->uuid_root) { | ||
2051 | free_extent_buffer(info->uuid_root->node); | ||
2052 | free_extent_buffer(info->uuid_root->commit_root); | ||
2053 | info->uuid_root->node = NULL; | ||
2054 | info->uuid_root->commit_root = NULL; | ||
2055 | } | ||
2047 | if (chunk_root) { | 2056 | if (chunk_root) { |
2048 | free_extent_buffer(info->chunk_root->node); | 2057 | free_extent_buffer(info->chunk_root->node); |
2049 | free_extent_buffer(info->chunk_root->commit_root); | 2058 | free_extent_buffer(info->chunk_root->commit_root); |
@@ -2104,11 +2113,13 @@ int open_ctree(struct super_block *sb, | |||
2104 | struct btrfs_root *chunk_root; | 2113 | struct btrfs_root *chunk_root; |
2105 | struct btrfs_root *dev_root; | 2114 | struct btrfs_root *dev_root; |
2106 | struct btrfs_root *quota_root; | 2115 | struct btrfs_root *quota_root; |
2116 | struct btrfs_root *uuid_root; | ||
2107 | struct btrfs_root *log_tree_root; | 2117 | struct btrfs_root *log_tree_root; |
2108 | int ret; | 2118 | int ret; |
2109 | int err = -EINVAL; | 2119 | int err = -EINVAL; |
2110 | int num_backups_tried = 0; | 2120 | int num_backups_tried = 0; |
2111 | int backup_index = 0; | 2121 | int backup_index = 0; |
2122 | bool create_uuid_tree = false; | ||
2112 | 2123 | ||
2113 | tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info); | 2124 | tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info); |
2114 | chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info); | 2125 | chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info); |
@@ -2704,6 +2715,18 @@ retry_root_backup: | |||
2704 | fs_info->quota_root = quota_root; | 2715 | fs_info->quota_root = quota_root; |
2705 | } | 2716 | } |
2706 | 2717 | ||
2718 | location.objectid = BTRFS_UUID_TREE_OBJECTID; | ||
2719 | uuid_root = btrfs_read_tree_root(tree_root, &location); | ||
2720 | if (IS_ERR(uuid_root)) { | ||
2721 | ret = PTR_ERR(uuid_root); | ||
2722 | if (ret != -ENOENT) | ||
2723 | goto recovery_tree_root; | ||
2724 | create_uuid_tree = true; | ||
2725 | } else { | ||
2726 | uuid_root->track_dirty = 1; | ||
2727 | fs_info->uuid_root = uuid_root; | ||
2728 | } | ||
2729 | |||
2707 | fs_info->generation = generation; | 2730 | fs_info->generation = generation; |
2708 | fs_info->last_trans_committed = generation; | 2731 | fs_info->last_trans_committed = generation; |
2709 | 2732 | ||
@@ -2890,6 +2913,17 @@ retry_root_backup: | |||
2890 | 2913 | ||
2891 | btrfs_qgroup_rescan_resume(fs_info); | 2914 | btrfs_qgroup_rescan_resume(fs_info); |
2892 | 2915 | ||
2916 | if (create_uuid_tree) { | ||
2917 | pr_info("btrfs: creating UUID tree\n"); | ||
2918 | ret = btrfs_create_uuid_tree(fs_info); | ||
2919 | if (ret) { | ||
2920 | pr_warn("btrfs: failed to create the UUID tree %d\n", | ||
2921 | ret); | ||
2922 | close_ctree(tree_root); | ||
2923 | return ret; | ||
2924 | } | ||
2925 | } | ||
2926 | |||
2893 | return 0; | 2927 | return 0; |
2894 | 2928 | ||
2895 | fail_qgroup: | 2929 | fail_qgroup: |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index f1c1694d34b7..8cb1d41ba501 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -4361,6 +4361,9 @@ static struct btrfs_block_rsv *get_block_rsv( | |||
4361 | if (root == root->fs_info->csum_root && trans->adding_csums) | 4361 | if (root == root->fs_info->csum_root && trans->adding_csums) |
4362 | block_rsv = trans->block_rsv; | 4362 | block_rsv = trans->block_rsv; |
4363 | 4363 | ||
4364 | if (root == root->fs_info->uuid_root) | ||
4365 | block_rsv = trans->block_rsv; | ||
4366 | |||
4364 | if (!block_rsv) | 4367 | if (!block_rsv) |
4365 | block_rsv = root->block_rsv; | 4368 | block_rsv = root->block_rsv; |
4366 | 4369 | ||
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 306547b51a13..e084218c09d2 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -3429,6 +3429,32 @@ int btrfs_cancel_balance(struct btrfs_fs_info *fs_info) | |||
3429 | return 0; | 3429 | return 0; |
3430 | } | 3430 | } |
3431 | 3431 | ||
3432 | int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info) | ||
3433 | { | ||
3434 | struct btrfs_trans_handle *trans; | ||
3435 | struct btrfs_root *tree_root = fs_info->tree_root; | ||
3436 | struct btrfs_root *uuid_root; | ||
3437 | |||
3438 | /* | ||
3439 | * 1 - root node | ||
3440 | * 1 - root item | ||
3441 | */ | ||
3442 | trans = btrfs_start_transaction(tree_root, 2); | ||
3443 | if (IS_ERR(trans)) | ||
3444 | return PTR_ERR(trans); | ||
3445 | |||
3446 | uuid_root = btrfs_create_tree(trans, fs_info, | ||
3447 | BTRFS_UUID_TREE_OBJECTID); | ||
3448 | if (IS_ERR(uuid_root)) { | ||
3449 | btrfs_abort_transaction(trans, tree_root, | ||
3450 | PTR_ERR(uuid_root)); | ||
3451 | return PTR_ERR(uuid_root); | ||
3452 | } | ||
3453 | |||
3454 | fs_info->uuid_root = uuid_root; | ||
3455 | |||
3456 | return btrfs_commit_transaction(trans, tree_root); | ||
3457 | } | ||
3432 | /* | 3458 | /* |
3433 | * shrinking a device means finding all of the device extents past | 3459 | * shrinking a device means finding all of the device extents past |
3434 | * the new size, and then following the back refs to the chunks. | 3460 | * the new size, and then following the back refs to the chunks. |
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 08c44d9059b1..7071b2988305 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -322,6 +322,7 @@ int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info); | |||
322 | int btrfs_recover_balance(struct btrfs_fs_info *fs_info); | 322 | int btrfs_recover_balance(struct btrfs_fs_info *fs_info); |
323 | int btrfs_pause_balance(struct btrfs_fs_info *fs_info); | 323 | int btrfs_pause_balance(struct btrfs_fs_info *fs_info); |
324 | int btrfs_cancel_balance(struct btrfs_fs_info *fs_info); | 324 | int btrfs_cancel_balance(struct btrfs_fs_info *fs_info); |
325 | int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info); | ||
325 | int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset); | 326 | int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset); |
326 | int find_free_dev_extent(struct btrfs_trans_handle *trans, | 327 | int find_free_dev_extent(struct btrfs_trans_handle *trans, |
327 | struct btrfs_device *device, u64 num_bytes, | 328 | struct btrfs_device *device, u64 num_bytes, |