diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 185 |
1 files changed, 66 insertions, 119 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 9489a2aca47b..e0b7bb92a170 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -830,7 +830,6 @@ out: | |||
830 | 830 | ||
831 | /* | 831 | /* |
832 | * find_free_dev_extent - find free space in the specified device | 832 | * find_free_dev_extent - find free space in the specified device |
833 | * @trans: transaction handler | ||
834 | * @device: the device which we search the free space in | 833 | * @device: the device which we search the free space in |
835 | * @num_bytes: the size of the free space that we need | 834 | * @num_bytes: the size of the free space that we need |
836 | * @start: store the start of the free space. | 835 | * @start: store the start of the free space. |
@@ -849,8 +848,7 @@ out: | |||
849 | * But if we don't find suitable free space, it is used to store the size of | 848 | * But if we don't find suitable free space, it is used to store the size of |
850 | * the max free space. | 849 | * the max free space. |
851 | */ | 850 | */ |
852 | int find_free_dev_extent(struct btrfs_trans_handle *trans, | 851 | int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes, |
853 | struct btrfs_device *device, u64 num_bytes, | ||
854 | u64 *start, u64 *len) | 852 | u64 *start, u64 *len) |
855 | { | 853 | { |
856 | struct btrfs_key key; | 854 | struct btrfs_key key; |
@@ -894,7 +892,7 @@ int find_free_dev_extent(struct btrfs_trans_handle *trans, | |||
894 | key.offset = search_start; | 892 | key.offset = search_start; |
895 | key.type = BTRFS_DEV_EXTENT_KEY; | 893 | key.type = BTRFS_DEV_EXTENT_KEY; |
896 | 894 | ||
897 | ret = btrfs_search_slot(trans, root, &key, path, 0, 0); | 895 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
898 | if (ret < 0) | 896 | if (ret < 0) |
899 | goto out; | 897 | goto out; |
900 | if (ret > 0) { | 898 | if (ret > 0) { |
@@ -1468,8 +1466,7 @@ error_undo: | |||
1468 | /* | 1466 | /* |
1469 | * does all the dirty work required for changing file system's UUID. | 1467 | * does all the dirty work required for changing file system's UUID. |
1470 | */ | 1468 | */ |
1471 | static int btrfs_prepare_sprout(struct btrfs_trans_handle *trans, | 1469 | static int btrfs_prepare_sprout(struct btrfs_root *root) |
1472 | struct btrfs_root *root) | ||
1473 | { | 1470 | { |
1474 | struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices; | 1471 | struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices; |
1475 | struct btrfs_fs_devices *old_devices; | 1472 | struct btrfs_fs_devices *old_devices; |
@@ -1693,7 +1690,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1693 | 1690 | ||
1694 | if (seeding_dev) { | 1691 | if (seeding_dev) { |
1695 | sb->s_flags &= ~MS_RDONLY; | 1692 | sb->s_flags &= ~MS_RDONLY; |
1696 | ret = btrfs_prepare_sprout(trans, root); | 1693 | ret = btrfs_prepare_sprout(root); |
1697 | BUG_ON(ret); | 1694 | BUG_ON(ret); |
1698 | } | 1695 | } |
1699 | 1696 | ||
@@ -3044,8 +3041,7 @@ done: | |||
3044 | return ret; | 3041 | return ret; |
3045 | } | 3042 | } |
3046 | 3043 | ||
3047 | static int btrfs_add_system_chunk(struct btrfs_trans_handle *trans, | 3044 | static int btrfs_add_system_chunk(struct btrfs_root *root, |
3048 | struct btrfs_root *root, | ||
3049 | struct btrfs_key *key, | 3045 | struct btrfs_key *key, |
3050 | struct btrfs_chunk *chunk, int item_size) | 3046 | struct btrfs_chunk *chunk, int item_size) |
3051 | { | 3047 | { |
@@ -3221,7 +3217,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
3221 | if (total_avail == 0) | 3217 | if (total_avail == 0) |
3222 | continue; | 3218 | continue; |
3223 | 3219 | ||
3224 | ret = find_free_dev_extent(trans, device, | 3220 | ret = find_free_dev_extent(device, |
3225 | max_stripe_size * dev_stripes, | 3221 | max_stripe_size * dev_stripes, |
3226 | &dev_offset, &max_avail); | 3222 | &dev_offset, &max_avail); |
3227 | if (ret && ret != -ENOSPC) | 3223 | if (ret && ret != -ENOSPC) |
@@ -3412,7 +3408,7 @@ static int __finish_chunk_alloc(struct btrfs_trans_handle *trans, | |||
3412 | BUG_ON(ret); | 3408 | BUG_ON(ret); |
3413 | 3409 | ||
3414 | if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) { | 3410 | if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) { |
3415 | ret = btrfs_add_system_chunk(trans, chunk_root, &key, chunk, | 3411 | ret = btrfs_add_system_chunk(chunk_root, &key, chunk, |
3416 | item_size); | 3412 | item_size); |
3417 | BUG_ON(ret); | 3413 | BUG_ON(ret); |
3418 | } | 3414 | } |
@@ -3624,26 +3620,13 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
3624 | u64 stripe_nr; | 3620 | u64 stripe_nr; |
3625 | u64 stripe_nr_orig; | 3621 | u64 stripe_nr_orig; |
3626 | u64 stripe_nr_end; | 3622 | u64 stripe_nr_end; |
3627 | int stripes_allocated = 8; | ||
3628 | int stripes_required = 1; | ||
3629 | int stripe_index; | 3623 | int stripe_index; |
3630 | int i; | 3624 | int i; |
3625 | int ret = 0; | ||
3631 | int num_stripes; | 3626 | int num_stripes; |
3632 | int max_errors = 0; | 3627 | int max_errors = 0; |
3633 | struct btrfs_bio *bbio = NULL; | 3628 | struct btrfs_bio *bbio = NULL; |
3634 | 3629 | ||
3635 | if (bbio_ret && !(rw & (REQ_WRITE | REQ_DISCARD))) | ||
3636 | stripes_allocated = 1; | ||
3637 | again: | ||
3638 | if (bbio_ret) { | ||
3639 | bbio = kzalloc(btrfs_bio_size(stripes_allocated), | ||
3640 | GFP_NOFS); | ||
3641 | if (!bbio) | ||
3642 | return -ENOMEM; | ||
3643 | |||
3644 | atomic_set(&bbio->error, 0); | ||
3645 | } | ||
3646 | |||
3647 | read_lock(&em_tree->lock); | 3630 | read_lock(&em_tree->lock); |
3648 | em = lookup_extent_mapping(em_tree, logical, *length); | 3631 | em = lookup_extent_mapping(em_tree, logical, *length); |
3649 | read_unlock(&em_tree->lock); | 3632 | read_unlock(&em_tree->lock); |
@@ -3662,28 +3645,6 @@ again: | |||
3662 | if (mirror_num > map->num_stripes) | 3645 | if (mirror_num > map->num_stripes) |
3663 | mirror_num = 0; | 3646 | mirror_num = 0; |
3664 | 3647 | ||
3665 | /* if our btrfs_bio struct is too small, back off and try again */ | ||
3666 | if (rw & REQ_WRITE) { | ||
3667 | if (map->type & (BTRFS_BLOCK_GROUP_RAID1 | | ||
3668 | BTRFS_BLOCK_GROUP_DUP)) { | ||
3669 | stripes_required = map->num_stripes; | ||
3670 | max_errors = 1; | ||
3671 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { | ||
3672 | stripes_required = map->sub_stripes; | ||
3673 | max_errors = 1; | ||
3674 | } | ||
3675 | } | ||
3676 | if (rw & REQ_DISCARD) { | ||
3677 | if (map->type & BTRFS_BLOCK_GROUP_PROFILE_MASK) | ||
3678 | stripes_required = map->num_stripes; | ||
3679 | } | ||
3680 | if (bbio_ret && (rw & (REQ_WRITE | REQ_DISCARD)) && | ||
3681 | stripes_allocated < stripes_required) { | ||
3682 | stripes_allocated = map->num_stripes; | ||
3683 | free_extent_map(em); | ||
3684 | kfree(bbio); | ||
3685 | goto again; | ||
3686 | } | ||
3687 | stripe_nr = offset; | 3648 | stripe_nr = offset; |
3688 | /* | 3649 | /* |
3689 | * stripe_nr counts the total number of stripes we have to stride | 3650 | * stripe_nr counts the total number of stripes we have to stride |
@@ -3775,81 +3736,55 @@ again: | |||
3775 | } | 3736 | } |
3776 | BUG_ON(stripe_index >= map->num_stripes); | 3737 | BUG_ON(stripe_index >= map->num_stripes); |
3777 | 3738 | ||
3739 | bbio = kzalloc(btrfs_bio_size(num_stripes), GFP_NOFS); | ||
3740 | if (!bbio) { | ||
3741 | ret = -ENOMEM; | ||
3742 | goto out; | ||
3743 | } | ||
3744 | atomic_set(&bbio->error, 0); | ||
3745 | |||
3778 | if (rw & REQ_DISCARD) { | 3746 | if (rw & REQ_DISCARD) { |
3747 | int factor = 0; | ||
3748 | int sub_stripes = 0; | ||
3749 | u64 stripes_per_dev = 0; | ||
3750 | u32 remaining_stripes = 0; | ||
3751 | |||
3752 | if (map->type & | ||
3753 | (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID10)) { | ||
3754 | if (map->type & BTRFS_BLOCK_GROUP_RAID0) | ||
3755 | sub_stripes = 1; | ||
3756 | else | ||
3757 | sub_stripes = map->sub_stripes; | ||
3758 | |||
3759 | factor = map->num_stripes / sub_stripes; | ||
3760 | stripes_per_dev = div_u64_rem(stripe_nr_end - | ||
3761 | stripe_nr_orig, | ||
3762 | factor, | ||
3763 | &remaining_stripes); | ||
3764 | } | ||
3765 | |||
3779 | for (i = 0; i < num_stripes; i++) { | 3766 | for (i = 0; i < num_stripes; i++) { |
3780 | bbio->stripes[i].physical = | 3767 | bbio->stripes[i].physical = |
3781 | map->stripes[stripe_index].physical + | 3768 | map->stripes[stripe_index].physical + |
3782 | stripe_offset + stripe_nr * map->stripe_len; | 3769 | stripe_offset + stripe_nr * map->stripe_len; |
3783 | bbio->stripes[i].dev = map->stripes[stripe_index].dev; | 3770 | bbio->stripes[i].dev = map->stripes[stripe_index].dev; |
3784 | 3771 | ||
3785 | if (map->type & BTRFS_BLOCK_GROUP_RAID0) { | 3772 | if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | |
3786 | u64 stripes; | 3773 | BTRFS_BLOCK_GROUP_RAID10)) { |
3787 | u32 last_stripe = 0; | 3774 | bbio->stripes[i].length = stripes_per_dev * |
3788 | int j; | 3775 | map->stripe_len; |
3789 | 3776 | if (i / sub_stripes < remaining_stripes) | |
3790 | div_u64_rem(stripe_nr_end - 1, | 3777 | bbio->stripes[i].length += |
3791 | map->num_stripes, | 3778 | map->stripe_len; |
3792 | &last_stripe); | 3779 | if (i < sub_stripes) |
3793 | |||
3794 | for (j = 0; j < map->num_stripes; j++) { | ||
3795 | u32 test; | ||
3796 | |||
3797 | div_u64_rem(stripe_nr_end - 1 - j, | ||
3798 | map->num_stripes, &test); | ||
3799 | if (test == stripe_index) | ||
3800 | break; | ||
3801 | } | ||
3802 | stripes = stripe_nr_end - 1 - j; | ||
3803 | do_div(stripes, map->num_stripes); | ||
3804 | bbio->stripes[i].length = map->stripe_len * | ||
3805 | (stripes - stripe_nr + 1); | ||
3806 | |||
3807 | if (i == 0) { | ||
3808 | bbio->stripes[i].length -= | ||
3809 | stripe_offset; | ||
3810 | stripe_offset = 0; | ||
3811 | } | ||
3812 | if (stripe_index == last_stripe) | ||
3813 | bbio->stripes[i].length -= | ||
3814 | stripe_end_offset; | ||
3815 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { | ||
3816 | u64 stripes; | ||
3817 | int j; | ||
3818 | int factor = map->num_stripes / | ||
3819 | map->sub_stripes; | ||
3820 | u32 last_stripe = 0; | ||
3821 | |||
3822 | div_u64_rem(stripe_nr_end - 1, | ||
3823 | factor, &last_stripe); | ||
3824 | last_stripe *= map->sub_stripes; | ||
3825 | |||
3826 | for (j = 0; j < factor; j++) { | ||
3827 | u32 test; | ||
3828 | |||
3829 | div_u64_rem(stripe_nr_end - 1 - j, | ||
3830 | factor, &test); | ||
3831 | |||
3832 | if (test == | ||
3833 | stripe_index / map->sub_stripes) | ||
3834 | break; | ||
3835 | } | ||
3836 | stripes = stripe_nr_end - 1 - j; | ||
3837 | do_div(stripes, factor); | ||
3838 | bbio->stripes[i].length = map->stripe_len * | ||
3839 | (stripes - stripe_nr + 1); | ||
3840 | |||
3841 | if (i < map->sub_stripes) { | ||
3842 | bbio->stripes[i].length -= | 3780 | bbio->stripes[i].length -= |
3843 | stripe_offset; | 3781 | stripe_offset; |
3844 | if (i == map->sub_stripes - 1) | 3782 | if ((i / sub_stripes + 1) % |
3845 | stripe_offset = 0; | 3783 | sub_stripes == remaining_stripes) |
3846 | } | ||
3847 | if (stripe_index >= last_stripe && | ||
3848 | stripe_index <= (last_stripe + | ||
3849 | map->sub_stripes - 1)) { | ||
3850 | bbio->stripes[i].length -= | 3784 | bbio->stripes[i].length -= |
3851 | stripe_end_offset; | 3785 | stripe_end_offset; |
3852 | } | 3786 | if (i == sub_stripes - 1) |
3787 | stripe_offset = 0; | ||
3853 | } else | 3788 | } else |
3854 | bbio->stripes[i].length = *length; | 3789 | bbio->stripes[i].length = *length; |
3855 | 3790 | ||
@@ -3871,15 +3806,22 @@ again: | |||
3871 | stripe_index++; | 3806 | stripe_index++; |
3872 | } | 3807 | } |
3873 | } | 3808 | } |
3874 | if (bbio_ret) { | 3809 | |
3875 | *bbio_ret = bbio; | 3810 | if (rw & REQ_WRITE) { |
3876 | bbio->num_stripes = num_stripes; | 3811 | if (map->type & (BTRFS_BLOCK_GROUP_RAID1 | |
3877 | bbio->max_errors = max_errors; | 3812 | BTRFS_BLOCK_GROUP_RAID10 | |
3878 | bbio->mirror_num = mirror_num; | 3813 | BTRFS_BLOCK_GROUP_DUP)) { |
3814 | max_errors = 1; | ||
3815 | } | ||
3879 | } | 3816 | } |
3817 | |||
3818 | *bbio_ret = bbio; | ||
3819 | bbio->num_stripes = num_stripes; | ||
3820 | bbio->max_errors = max_errors; | ||
3821 | bbio->mirror_num = mirror_num; | ||
3880 | out: | 3822 | out: |
3881 | free_extent_map(em); | 3823 | free_extent_map(em); |
3882 | return 0; | 3824 | return ret; |
3883 | } | 3825 | } |
3884 | 3826 | ||
3885 | int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | 3827 | int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, |
@@ -4284,7 +4226,7 @@ static int open_seed_devices(struct btrfs_root *root, u8 *fsid) | |||
4284 | struct btrfs_fs_devices *fs_devices; | 4226 | struct btrfs_fs_devices *fs_devices; |
4285 | int ret; | 4227 | int ret; |
4286 | 4228 | ||
4287 | mutex_lock(&uuid_mutex); | 4229 | BUG_ON(!mutex_is_locked(&uuid_mutex)); |
4288 | 4230 | ||
4289 | fs_devices = root->fs_info->fs_devices->seed; | 4231 | fs_devices = root->fs_info->fs_devices->seed; |
4290 | while (fs_devices) { | 4232 | while (fs_devices) { |
@@ -4322,7 +4264,6 @@ static int open_seed_devices(struct btrfs_root *root, u8 *fsid) | |||
4322 | fs_devices->seed = root->fs_info->fs_devices->seed; | 4264 | fs_devices->seed = root->fs_info->fs_devices->seed; |
4323 | root->fs_info->fs_devices->seed = fs_devices; | 4265 | root->fs_info->fs_devices->seed = fs_devices; |
4324 | out: | 4266 | out: |
4325 | mutex_unlock(&uuid_mutex); | ||
4326 | return ret; | 4267 | return ret; |
4327 | } | 4268 | } |
4328 | 4269 | ||
@@ -4465,6 +4406,9 @@ int btrfs_read_chunk_tree(struct btrfs_root *root) | |||
4465 | if (!path) | 4406 | if (!path) |
4466 | return -ENOMEM; | 4407 | return -ENOMEM; |
4467 | 4408 | ||
4409 | mutex_lock(&uuid_mutex); | ||
4410 | lock_chunks(root); | ||
4411 | |||
4468 | /* first we search for all of the device items, and then we | 4412 | /* first we search for all of the device items, and then we |
4469 | * read in all of the chunk items. This way we can create chunk | 4413 | * read in all of the chunk items. This way we can create chunk |
4470 | * mappings that reference all of the devices that are afound | 4414 | * mappings that reference all of the devices that are afound |
@@ -4515,6 +4459,9 @@ again: | |||
4515 | } | 4459 | } |
4516 | ret = 0; | 4460 | ret = 0; |
4517 | error: | 4461 | error: |
4462 | unlock_chunks(root); | ||
4463 | mutex_unlock(&uuid_mutex); | ||
4464 | |||
4518 | btrfs_free_path(path); | 4465 | btrfs_free_path(path); |
4519 | return ret; | 4466 | return ret; |
4520 | } | 4467 | } |