diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index a872b48be0ae..1411b99555a4 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -3324,12 +3324,14 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
3324 | stripe_size = devices_info[ndevs-1].max_avail; | 3324 | stripe_size = devices_info[ndevs-1].max_avail; |
3325 | num_stripes = ndevs * dev_stripes; | 3325 | num_stripes = ndevs * dev_stripes; |
3326 | 3326 | ||
3327 | if (stripe_size * num_stripes > max_chunk_size * ncopies) { | 3327 | if (stripe_size * ndevs > max_chunk_size * ncopies) { |
3328 | stripe_size = max_chunk_size * ncopies; | 3328 | stripe_size = max_chunk_size * ncopies; |
3329 | do_div(stripe_size, num_stripes); | 3329 | do_div(stripe_size, ndevs); |
3330 | } | 3330 | } |
3331 | 3331 | ||
3332 | do_div(stripe_size, dev_stripes); | 3332 | do_div(stripe_size, dev_stripes); |
3333 | |||
3334 | /* align to BTRFS_STRIPE_LEN */ | ||
3333 | do_div(stripe_size, BTRFS_STRIPE_LEN); | 3335 | do_div(stripe_size, BTRFS_STRIPE_LEN); |
3334 | stripe_size *= BTRFS_STRIPE_LEN; | 3336 | stripe_size *= BTRFS_STRIPE_LEN; |
3335 | 3337 | ||
@@ -3805,10 +3807,11 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
3805 | else if (mirror_num) | 3807 | else if (mirror_num) |
3806 | stripe_index += mirror_num - 1; | 3808 | stripe_index += mirror_num - 1; |
3807 | else { | 3809 | else { |
3810 | int old_stripe_index = stripe_index; | ||
3808 | stripe_index = find_live_mirror(map, stripe_index, | 3811 | stripe_index = find_live_mirror(map, stripe_index, |
3809 | map->sub_stripes, stripe_index + | 3812 | map->sub_stripes, stripe_index + |
3810 | current->pid % map->sub_stripes); | 3813 | current->pid % map->sub_stripes); |
3811 | mirror_num = stripe_index + 1; | 3814 | mirror_num = stripe_index - old_stripe_index + 1; |
3812 | } | 3815 | } |
3813 | } else { | 3816 | } else { |
3814 | /* | 3817 | /* |
@@ -3833,6 +3836,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
3833 | int sub_stripes = 0; | 3836 | int sub_stripes = 0; |
3834 | u64 stripes_per_dev = 0; | 3837 | u64 stripes_per_dev = 0; |
3835 | u32 remaining_stripes = 0; | 3838 | u32 remaining_stripes = 0; |
3839 | u32 last_stripe = 0; | ||
3836 | 3840 | ||
3837 | if (map->type & | 3841 | if (map->type & |
3838 | (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID10)) { | 3842 | (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID10)) { |
@@ -3846,6 +3850,8 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
3846 | stripe_nr_orig, | 3850 | stripe_nr_orig, |
3847 | factor, | 3851 | factor, |
3848 | &remaining_stripes); | 3852 | &remaining_stripes); |
3853 | div_u64_rem(stripe_nr_end - 1, factor, &last_stripe); | ||
3854 | last_stripe *= sub_stripes; | ||
3849 | } | 3855 | } |
3850 | 3856 | ||
3851 | for (i = 0; i < num_stripes; i++) { | 3857 | for (i = 0; i < num_stripes; i++) { |
@@ -3858,16 +3864,29 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
3858 | BTRFS_BLOCK_GROUP_RAID10)) { | 3864 | BTRFS_BLOCK_GROUP_RAID10)) { |
3859 | bbio->stripes[i].length = stripes_per_dev * | 3865 | bbio->stripes[i].length = stripes_per_dev * |
3860 | map->stripe_len; | 3866 | map->stripe_len; |
3867 | |||
3861 | if (i / sub_stripes < remaining_stripes) | 3868 | if (i / sub_stripes < remaining_stripes) |
3862 | bbio->stripes[i].length += | 3869 | bbio->stripes[i].length += |
3863 | map->stripe_len; | 3870 | map->stripe_len; |
3871 | |||
3872 | /* | ||
3873 | * Special for the first stripe and | ||
3874 | * the last stripe: | ||
3875 | * | ||
3876 | * |-------|...|-------| | ||
3877 | * |----------| | ||
3878 | * off end_off | ||
3879 | */ | ||
3864 | if (i < sub_stripes) | 3880 | if (i < sub_stripes) |
3865 | bbio->stripes[i].length -= | 3881 | bbio->stripes[i].length -= |
3866 | stripe_offset; | 3882 | stripe_offset; |
3867 | if ((i / sub_stripes + 1) % | 3883 | |
3868 | sub_stripes == remaining_stripes) | 3884 | if (stripe_index >= last_stripe && |
3885 | stripe_index <= (last_stripe + | ||
3886 | sub_stripes - 1)) | ||
3869 | bbio->stripes[i].length -= | 3887 | bbio->stripes[i].length -= |
3870 | stripe_end_offset; | 3888 | stripe_end_offset; |
3889 | |||
3871 | if (i == sub_stripes - 1) | 3890 | if (i == sub_stripes - 1) |
3872 | stripe_offset = 0; | 3891 | stripe_offset = 0; |
3873 | } else | 3892 | } else |
@@ -4334,8 +4353,10 @@ static int open_seed_devices(struct btrfs_root *root, u8 *fsid) | |||
4334 | 4353 | ||
4335 | ret = __btrfs_open_devices(fs_devices, FMODE_READ, | 4354 | ret = __btrfs_open_devices(fs_devices, FMODE_READ, |
4336 | root->fs_info->bdev_holder); | 4355 | root->fs_info->bdev_holder); |
4337 | if (ret) | 4356 | if (ret) { |
4357 | free_fs_devices(fs_devices); | ||
4338 | goto out; | 4358 | goto out; |
4359 | } | ||
4339 | 4360 | ||
4340 | if (!fs_devices->seeding) { | 4361 | if (!fs_devices->seeding) { |
4341 | __btrfs_close_devices(fs_devices); | 4362 | __btrfs_close_devices(fs_devices); |