diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index ff2b35114972..0144790e296e 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -4879,13 +4879,15 @@ static inline int parity_smaller(u64 a, u64 b) | |||
4879 | static void sort_parity_stripes(struct btrfs_bio *bbio, u64 *raid_map) | 4879 | static void sort_parity_stripes(struct btrfs_bio *bbio, u64 *raid_map) |
4880 | { | 4880 | { |
4881 | struct btrfs_bio_stripe s; | 4881 | struct btrfs_bio_stripe s; |
4882 | int real_stripes = bbio->num_stripes - bbio->num_tgtdevs; | ||
4882 | int i; | 4883 | int i; |
4883 | u64 l; | 4884 | u64 l; |
4884 | int again = 1; | 4885 | int again = 1; |
4886 | int m; | ||
4885 | 4887 | ||
4886 | while (again) { | 4888 | while (again) { |
4887 | again = 0; | 4889 | again = 0; |
4888 | for (i = 0; i < bbio->num_stripes - 1; i++) { | 4890 | for (i = 0; i < real_stripes - 1; i++) { |
4889 | if (parity_smaller(raid_map[i], raid_map[i+1])) { | 4891 | if (parity_smaller(raid_map[i], raid_map[i+1])) { |
4890 | s = bbio->stripes[i]; | 4892 | s = bbio->stripes[i]; |
4891 | l = raid_map[i]; | 4893 | l = raid_map[i]; |
@@ -4893,6 +4895,14 @@ static void sort_parity_stripes(struct btrfs_bio *bbio, u64 *raid_map) | |||
4893 | raid_map[i] = raid_map[i+1]; | 4895 | raid_map[i] = raid_map[i+1]; |
4894 | bbio->stripes[i+1] = s; | 4896 | bbio->stripes[i+1] = s; |
4895 | raid_map[i+1] = l; | 4897 | raid_map[i+1] = l; |
4898 | |||
4899 | if (bbio->tgtdev_map) { | ||
4900 | m = bbio->tgtdev_map[i]; | ||
4901 | bbio->tgtdev_map[i] = | ||
4902 | bbio->tgtdev_map[i + 1]; | ||
4903 | bbio->tgtdev_map[i + 1] = m; | ||
4904 | } | ||
4905 | |||
4896 | again = 1; | 4906 | again = 1; |
4897 | } | 4907 | } |
4898 | } | 4908 | } |
@@ -4921,6 +4931,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, | |||
4921 | int ret = 0; | 4931 | int ret = 0; |
4922 | int num_stripes; | 4932 | int num_stripes; |
4923 | int max_errors = 0; | 4933 | int max_errors = 0; |
4934 | int tgtdev_indexes = 0; | ||
4924 | struct btrfs_bio *bbio = NULL; | 4935 | struct btrfs_bio *bbio = NULL; |
4925 | struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace; | 4936 | struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace; |
4926 | int dev_replace_is_ongoing = 0; | 4937 | int dev_replace_is_ongoing = 0; |
@@ -5159,15 +5170,14 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, | |||
5159 | BTRFS_BLOCK_GROUP_RAID6)) { | 5170 | BTRFS_BLOCK_GROUP_RAID6)) { |
5160 | u64 tmp; | 5171 | u64 tmp; |
5161 | 5172 | ||
5162 | if (bbio_ret && ((rw & REQ_WRITE) || mirror_num > 1) | 5173 | if (raid_map_ret && |
5163 | && raid_map_ret) { | 5174 | ((rw & (REQ_WRITE | REQ_GET_READ_MIRRORS)) || |
5175 | mirror_num > 1)) { | ||
5164 | int i, rot; | 5176 | int i, rot; |
5165 | 5177 | ||
5166 | /* push stripe_nr back to the start of the full stripe */ | 5178 | /* push stripe_nr back to the start of the full stripe */ |
5167 | stripe_nr = raid56_full_stripe_start; | 5179 | stripe_nr = raid56_full_stripe_start; |
5168 | do_div(stripe_nr, stripe_len); | 5180 | do_div(stripe_nr, stripe_len * nr_data_stripes(map)); |
5169 | |||
5170 | stripe_index = do_div(stripe_nr, nr_data_stripes(map)); | ||
5171 | 5181 | ||
5172 | /* RAID[56] write or recovery. Return all stripes */ | 5182 | /* RAID[56] write or recovery. Return all stripes */ |
5173 | num_stripes = map->num_stripes; | 5183 | num_stripes = map->num_stripes; |
@@ -5233,14 +5243,19 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, | |||
5233 | num_alloc_stripes <<= 1; | 5243 | num_alloc_stripes <<= 1; |
5234 | if (rw & REQ_GET_READ_MIRRORS) | 5244 | if (rw & REQ_GET_READ_MIRRORS) |
5235 | num_alloc_stripes++; | 5245 | num_alloc_stripes++; |
5246 | tgtdev_indexes = num_stripes; | ||
5236 | } | 5247 | } |
5237 | bbio = kzalloc(btrfs_bio_size(num_alloc_stripes), GFP_NOFS); | 5248 | |
5249 | bbio = kzalloc(btrfs_bio_size(num_alloc_stripes, tgtdev_indexes), | ||
5250 | GFP_NOFS); | ||
5238 | if (!bbio) { | 5251 | if (!bbio) { |
5239 | kfree(raid_map); | 5252 | kfree(raid_map); |
5240 | ret = -ENOMEM; | 5253 | ret = -ENOMEM; |
5241 | goto out; | 5254 | goto out; |
5242 | } | 5255 | } |
5243 | atomic_set(&bbio->error, 0); | 5256 | atomic_set(&bbio->error, 0); |
5257 | if (dev_replace_is_ongoing) | ||
5258 | bbio->tgtdev_map = (int *)(bbio->stripes + num_alloc_stripes); | ||
5244 | 5259 | ||
5245 | if (rw & REQ_DISCARD) { | 5260 | if (rw & REQ_DISCARD) { |
5246 | int factor = 0; | 5261 | int factor = 0; |
@@ -5325,6 +5340,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, | |||
5325 | if (rw & (REQ_WRITE | REQ_GET_READ_MIRRORS)) | 5340 | if (rw & (REQ_WRITE | REQ_GET_READ_MIRRORS)) |
5326 | max_errors = btrfs_chunk_max_errors(map); | 5341 | max_errors = btrfs_chunk_max_errors(map); |
5327 | 5342 | ||
5343 | tgtdev_indexes = 0; | ||
5328 | if (dev_replace_is_ongoing && (rw & (REQ_WRITE | REQ_DISCARD)) && | 5344 | if (dev_replace_is_ongoing && (rw & (REQ_WRITE | REQ_DISCARD)) && |
5329 | dev_replace->tgtdev != NULL) { | 5345 | dev_replace->tgtdev != NULL) { |
5330 | int index_where_to_add; | 5346 | int index_where_to_add; |
@@ -5353,8 +5369,10 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, | |||
5353 | new->physical = old->physical; | 5369 | new->physical = old->physical; |
5354 | new->length = old->length; | 5370 | new->length = old->length; |
5355 | new->dev = dev_replace->tgtdev; | 5371 | new->dev = dev_replace->tgtdev; |
5372 | bbio->tgtdev_map[i] = index_where_to_add; | ||
5356 | index_where_to_add++; | 5373 | index_where_to_add++; |
5357 | max_errors++; | 5374 | max_errors++; |
5375 | tgtdev_indexes++; | ||
5358 | } | 5376 | } |
5359 | } | 5377 | } |
5360 | num_stripes = index_where_to_add; | 5378 | num_stripes = index_where_to_add; |
@@ -5400,7 +5418,9 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, | |||
5400 | tgtdev_stripe->length = | 5418 | tgtdev_stripe->length = |
5401 | bbio->stripes[index_srcdev].length; | 5419 | bbio->stripes[index_srcdev].length; |
5402 | tgtdev_stripe->dev = dev_replace->tgtdev; | 5420 | tgtdev_stripe->dev = dev_replace->tgtdev; |
5421 | bbio->tgtdev_map[index_srcdev] = num_stripes; | ||
5403 | 5422 | ||
5423 | tgtdev_indexes++; | ||
5404 | num_stripes++; | 5424 | num_stripes++; |
5405 | } | 5425 | } |
5406 | } | 5426 | } |
@@ -5410,6 +5430,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, | |||
5410 | bbio->num_stripes = num_stripes; | 5430 | bbio->num_stripes = num_stripes; |
5411 | bbio->max_errors = max_errors; | 5431 | bbio->max_errors = max_errors; |
5412 | bbio->mirror_num = mirror_num; | 5432 | bbio->mirror_num = mirror_num; |
5433 | bbio->num_tgtdevs = tgtdev_indexes; | ||
5413 | 5434 | ||
5414 | /* | 5435 | /* |
5415 | * this is the case that REQ_READ && dev_replace_is_ongoing && | 5436 | * this is the case that REQ_READ && dev_replace_is_ongoing && |
@@ -5441,6 +5462,16 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, | |||
5441 | mirror_num, NULL); | 5462 | mirror_num, NULL); |
5442 | } | 5463 | } |
5443 | 5464 | ||
5465 | /* For Scrub/replace */ | ||
5466 | int btrfs_map_sblock(struct btrfs_fs_info *fs_info, int rw, | ||
5467 | u64 logical, u64 *length, | ||
5468 | struct btrfs_bio **bbio_ret, int mirror_num, | ||
5469 | u64 **raid_map_ret) | ||
5470 | { | ||
5471 | return __btrfs_map_block(fs_info, rw, logical, length, bbio_ret, | ||
5472 | mirror_num, raid_map_ret); | ||
5473 | } | ||
5474 | |||
5444 | int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, | 5475 | int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, |
5445 | u64 chunk_start, u64 physical, u64 devid, | 5476 | u64 chunk_start, u64 physical, u64 devid, |
5446 | u64 **logical, int *naddrs, int *stripe_len) | 5477 | u64 **logical, int *naddrs, int *stripe_len) |
@@ -5810,12 +5841,9 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, | |||
5810 | } else { | 5841 | } else { |
5811 | ret = raid56_parity_recover(root, bio, bbio, | 5842 | ret = raid56_parity_recover(root, bio, bbio, |
5812 | raid_map, map_length, | 5843 | raid_map, map_length, |
5813 | mirror_num); | 5844 | mirror_num, 1); |
5814 | } | 5845 | } |
5815 | /* | 5846 | |
5816 | * FIXME, replace dosen't support raid56 yet, please fix | ||
5817 | * it in the future. | ||
5818 | */ | ||
5819 | btrfs_bio_counter_dec(root->fs_info); | 5847 | btrfs_bio_counter_dec(root->fs_info); |
5820 | return ret; | 5848 | return ret; |
5821 | } | 5849 | } |