aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c33
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);