diff options
-rw-r--r-- | fs/btrfs/ctree.h | 7 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 1 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 46 |
3 files changed, 49 insertions, 5 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 82d67c3db8bc..a22edcf49174 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -197,6 +197,9 @@ struct btrfs_chunk { | |||
197 | * item in the btree | 197 | * item in the btree |
198 | */ | 198 | */ |
199 | __le16 num_stripes; | 199 | __le16 num_stripes; |
200 | |||
201 | /* sub stripes only matter for raid10 */ | ||
202 | __le16 sub_stripes; | ||
200 | struct btrfs_stripe stripe; | 203 | struct btrfs_stripe stripe; |
201 | /* additional stripes go here */ | 204 | /* additional stripes go here */ |
202 | } __attribute__ ((__packed__)); | 205 | } __attribute__ ((__packed__)); |
@@ -444,6 +447,7 @@ struct btrfs_csum_item { | |||
444 | #define BTRFS_BLOCK_GROUP_RAID0 (1 << 3) | 447 | #define BTRFS_BLOCK_GROUP_RAID0 (1 << 3) |
445 | #define BTRFS_BLOCK_GROUP_RAID1 (1 << 4) | 448 | #define BTRFS_BLOCK_GROUP_RAID1 (1 << 4) |
446 | #define BTRFS_BLOCK_GROUP_DUP (1 << 5) | 449 | #define BTRFS_BLOCK_GROUP_DUP (1 << 5) |
450 | #define BTRFS_BLOCK_GROUP_RAID10 (1 << 6) | ||
447 | 451 | ||
448 | 452 | ||
449 | struct btrfs_block_group_item { | 453 | struct btrfs_block_group_item { |
@@ -757,6 +761,7 @@ BTRFS_SETGET_FUNCS(chunk_io_width, struct btrfs_chunk, io_width, 32); | |||
757 | BTRFS_SETGET_FUNCS(chunk_sector_size, struct btrfs_chunk, sector_size, 32); | 761 | BTRFS_SETGET_FUNCS(chunk_sector_size, struct btrfs_chunk, sector_size, 32); |
758 | BTRFS_SETGET_FUNCS(chunk_type, struct btrfs_chunk, type, 64); | 762 | BTRFS_SETGET_FUNCS(chunk_type, struct btrfs_chunk, type, 64); |
759 | BTRFS_SETGET_FUNCS(chunk_num_stripes, struct btrfs_chunk, num_stripes, 16); | 763 | BTRFS_SETGET_FUNCS(chunk_num_stripes, struct btrfs_chunk, num_stripes, 16); |
764 | BTRFS_SETGET_FUNCS(chunk_sub_stripes, struct btrfs_chunk, sub_stripes, 16); | ||
760 | BTRFS_SETGET_FUNCS(stripe_devid, struct btrfs_stripe, devid, 64); | 765 | BTRFS_SETGET_FUNCS(stripe_devid, struct btrfs_stripe, devid, 64); |
761 | BTRFS_SETGET_FUNCS(stripe_offset, struct btrfs_stripe, offset, 64); | 766 | BTRFS_SETGET_FUNCS(stripe_offset, struct btrfs_stripe, offset, 64); |
762 | 767 | ||
@@ -778,6 +783,8 @@ BTRFS_SETGET_STACK_FUNCS(stack_chunk_sector_size, struct btrfs_chunk, | |||
778 | BTRFS_SETGET_STACK_FUNCS(stack_chunk_type, struct btrfs_chunk, type, 64); | 783 | BTRFS_SETGET_STACK_FUNCS(stack_chunk_type, struct btrfs_chunk, type, 64); |
779 | BTRFS_SETGET_STACK_FUNCS(stack_chunk_num_stripes, struct btrfs_chunk, | 784 | BTRFS_SETGET_STACK_FUNCS(stack_chunk_num_stripes, struct btrfs_chunk, |
780 | num_stripes, 16); | 785 | num_stripes, 16); |
786 | BTRFS_SETGET_STACK_FUNCS(stack_chunk_sub_stripes, struct btrfs_chunk, | ||
787 | sub_stripes, 16); | ||
781 | BTRFS_SETGET_STACK_FUNCS(stack_stripe_devid, struct btrfs_stripe, devid, 64); | 788 | BTRFS_SETGET_STACK_FUNCS(stack_stripe_devid, struct btrfs_stripe, devid, 64); |
782 | BTRFS_SETGET_STACK_FUNCS(stack_stripe_offset, struct btrfs_stripe, offset, 64); | 789 | BTRFS_SETGET_STACK_FUNCS(stack_stripe_offset, struct btrfs_stripe, offset, 64); |
783 | 790 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 71f045c63493..4e5bd62e6e1a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1042,6 +1042,7 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | |||
1042 | { | 1042 | { |
1043 | u64 extra_flags = flags & (BTRFS_BLOCK_GROUP_RAID0 | | 1043 | u64 extra_flags = flags & (BTRFS_BLOCK_GROUP_RAID0 | |
1044 | BTRFS_BLOCK_GROUP_RAID1 | | 1044 | BTRFS_BLOCK_GROUP_RAID1 | |
1045 | BTRFS_BLOCK_GROUP_RAID10 | | ||
1045 | BTRFS_BLOCK_GROUP_DUP); | 1046 | BTRFS_BLOCK_GROUP_DUP); |
1046 | if (extra_flags) { | 1047 | if (extra_flags) { |
1047 | if (flags & BTRFS_BLOCK_GROUP_DATA) | 1048 | if (flags & BTRFS_BLOCK_GROUP_DATA) |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 23ebd95b25e0..e6417a573d44 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -33,6 +33,7 @@ struct map_lookup { | |||
33 | int stripe_len; | 33 | int stripe_len; |
34 | int sector_size; | 34 | int sector_size; |
35 | int num_stripes; | 35 | int num_stripes; |
36 | int sub_stripes; | ||
36 | struct btrfs_bio_stripe stripes[]; | 37 | struct btrfs_bio_stripe stripes[]; |
37 | }; | 38 | }; |
38 | 39 | ||
@@ -641,6 +642,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
641 | u64 avail; | 642 | u64 avail; |
642 | u64 max_avail = 0; | 643 | u64 max_avail = 0; |
643 | int num_stripes = 1; | 644 | int num_stripes = 1; |
645 | int sub_stripes = 0; | ||
644 | int looped = 0; | 646 | int looped = 0; |
645 | int ret; | 647 | int ret; |
646 | int index; | 648 | int index; |
@@ -658,6 +660,13 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
658 | num_stripes = min_t(u64, 2, | 660 | num_stripes = min_t(u64, 2, |
659 | btrfs_super_num_devices(&info->super_copy)); | 661 | btrfs_super_num_devices(&info->super_copy)); |
660 | } | 662 | } |
663 | if (type & (BTRFS_BLOCK_GROUP_RAID10)) { | ||
664 | num_stripes = btrfs_super_num_devices(&info->super_copy); | ||
665 | if (num_stripes < 4) | ||
666 | return -ENOSPC; | ||
667 | num_stripes &= ~(u32)1; | ||
668 | sub_stripes = 2; | ||
669 | } | ||
661 | again: | 670 | again: |
662 | INIT_LIST_HEAD(&private_devs); | 671 | INIT_LIST_HEAD(&private_devs); |
663 | cur = dev_list->next; | 672 | cur = dev_list->next; |
@@ -714,6 +723,8 @@ again: | |||
714 | 723 | ||
715 | if (type & (BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_DUP)) | 724 | if (type & (BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_DUP)) |
716 | *num_bytes = calc_size; | 725 | *num_bytes = calc_size; |
726 | else if (type & BTRFS_BLOCK_GROUP_RAID10) | ||
727 | *num_bytes = calc_size * num_stripes / sub_stripes; | ||
717 | else | 728 | else |
718 | *num_bytes = calc_size * num_stripes; | 729 | *num_bytes = calc_size * num_stripes; |
719 | 730 | ||
@@ -760,12 +771,14 @@ printk("alloc chunk start %Lu size %Lu from dev %Lu type %Lu\n", key.offset, cal | |||
760 | btrfs_set_stack_chunk_io_align(chunk, stripe_len); | 771 | btrfs_set_stack_chunk_io_align(chunk, stripe_len); |
761 | btrfs_set_stack_chunk_io_width(chunk, stripe_len); | 772 | btrfs_set_stack_chunk_io_width(chunk, stripe_len); |
762 | btrfs_set_stack_chunk_sector_size(chunk, extent_root->sectorsize); | 773 | btrfs_set_stack_chunk_sector_size(chunk, extent_root->sectorsize); |
774 | btrfs_set_stack_chunk_sub_stripes(chunk, sub_stripes); | ||
763 | map->sector_size = extent_root->sectorsize; | 775 | map->sector_size = extent_root->sectorsize; |
764 | map->stripe_len = stripe_len; | 776 | map->stripe_len = stripe_len; |
765 | map->io_align = stripe_len; | 777 | map->io_align = stripe_len; |
766 | map->io_width = stripe_len; | 778 | map->io_width = stripe_len; |
767 | map->type = type; | 779 | map->type = type; |
768 | map->num_stripes = num_stripes; | 780 | map->num_stripes = num_stripes; |
781 | map->sub_stripes = sub_stripes; | ||
769 | 782 | ||
770 | ret = btrfs_insert_item(trans, chunk_root, &key, chunk, | 783 | ret = btrfs_insert_item(trans, chunk_root, &key, chunk, |
771 | btrfs_chunk_item_size(num_stripes)); | 784 | btrfs_chunk_item_size(num_stripes)); |
@@ -832,6 +845,8 @@ int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len) | |||
832 | map = (struct map_lookup *)em->bdev; | 845 | map = (struct map_lookup *)em->bdev; |
833 | if (map->type & (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1)) | 846 | if (map->type & (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1)) |
834 | ret = map->num_stripes; | 847 | ret = map->num_stripes; |
848 | else if (map->type & BTRFS_BLOCK_GROUP_RAID10) | ||
849 | ret = map->sub_stripes; | ||
835 | else | 850 | else |
836 | ret = 1; | 851 | ret = 1; |
837 | free_extent_map(em); | 852 | free_extent_map(em); |
@@ -849,6 +864,7 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
849 | u64 stripe_offset; | 864 | u64 stripe_offset; |
850 | u64 stripe_nr; | 865 | u64 stripe_nr; |
851 | int stripes_allocated = 8; | 866 | int stripes_allocated = 8; |
867 | int stripes_required = 1; | ||
852 | int stripe_index; | 868 | int stripe_index; |
853 | int i; | 869 | int i; |
854 | struct btrfs_multi_bio *multi = NULL; | 870 | struct btrfs_multi_bio *multi = NULL; |
@@ -877,10 +893,16 @@ again: | |||
877 | mirror_num = 0; | 893 | mirror_num = 0; |
878 | 894 | ||
879 | /* if our multi bio struct is too small, back off and try again */ | 895 | /* if our multi bio struct is too small, back off and try again */ |
880 | if (multi_ret && (rw & (1 << BIO_RW)) && | 896 | if (rw & (1 << BIO_RW)) { |
881 | stripes_allocated < map->num_stripes && | 897 | if (map->type & (BTRFS_BLOCK_GROUP_RAID1 | |
882 | ((map->type & BTRFS_BLOCK_GROUP_RAID1) || | 898 | BTRFS_BLOCK_GROUP_DUP)) { |
883 | (map->type & BTRFS_BLOCK_GROUP_DUP))) { | 899 | stripes_required = map->num_stripes; |
900 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { | ||
901 | stripes_required = map->sub_stripes; | ||
902 | } | ||
903 | } | ||
904 | if (multi_ret && rw == WRITE && | ||
905 | stripes_allocated < stripes_required) { | ||
884 | stripes_allocated = map->num_stripes; | 906 | stripes_allocated = map->num_stripes; |
885 | free_extent_map(em); | 907 | free_extent_map(em); |
886 | kfree(multi); | 908 | kfree(multi); |
@@ -900,6 +922,7 @@ again: | |||
900 | stripe_offset = offset - stripe_offset; | 922 | stripe_offset = offset - stripe_offset; |
901 | 923 | ||
902 | if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 | | 924 | if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 | |
925 | BTRFS_BLOCK_GROUP_RAID10 | | ||
903 | BTRFS_BLOCK_GROUP_DUP)) { | 926 | BTRFS_BLOCK_GROUP_DUP)) { |
904 | /* we limit the length of each bio to what fits in a stripe */ | 927 | /* we limit the length of each bio to what fits in a stripe */ |
905 | *length = min_t(u64, em->len - offset, | 928 | *length = min_t(u64, em->len - offset, |
@@ -937,6 +960,19 @@ again: | |||
937 | multi->num_stripes = map->num_stripes; | 960 | multi->num_stripes = map->num_stripes; |
938 | else if (mirror_num) | 961 | else if (mirror_num) |
939 | stripe_index = mirror_num - 1; | 962 | stripe_index = mirror_num - 1; |
963 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { | ||
964 | int factor = map->num_stripes / map->sub_stripes; | ||
965 | int orig_stripe_nr = stripe_nr; | ||
966 | |||
967 | stripe_index = do_div(stripe_nr, factor); | ||
968 | stripe_index *= map->sub_stripes; | ||
969 | |||
970 | if (rw & (1 << BIO_RW)) | ||
971 | multi->num_stripes = map->sub_stripes; | ||
972 | else if (mirror_num) | ||
973 | stripe_index += mirror_num - 1; | ||
974 | else | ||
975 | stripe_index += orig_stripe_nr % map->sub_stripes; | ||
940 | } else { | 976 | } else { |
941 | /* | 977 | /* |
942 | * after this do_div call, stripe_nr is the number of stripes | 978 | * after this do_div call, stripe_nr is the number of stripes |
@@ -946,7 +982,6 @@ again: | |||
946 | stripe_index = do_div(stripe_nr, map->num_stripes); | 982 | stripe_index = do_div(stripe_nr, map->num_stripes); |
947 | } | 983 | } |
948 | BUG_ON(stripe_index >= map->num_stripes); | 984 | BUG_ON(stripe_index >= map->num_stripes); |
949 | BUG_ON(stripe_index != 0 && multi->num_stripes > 1); | ||
950 | 985 | ||
951 | for (i = 0; i < multi->num_stripes; i++) { | 986 | for (i = 0; i < multi->num_stripes; i++) { |
952 | multi->stripes[i].physical = | 987 | multi->stripes[i].physical = |
@@ -1120,6 +1155,7 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, | |||
1120 | map->sector_size = btrfs_chunk_sector_size(leaf, chunk); | 1155 | map->sector_size = btrfs_chunk_sector_size(leaf, chunk); |
1121 | map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk); | 1156 | map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk); |
1122 | map->type = btrfs_chunk_type(leaf, chunk); | 1157 | map->type = btrfs_chunk_type(leaf, chunk); |
1158 | map->sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); | ||
1123 | for (i = 0; i < num_stripes; i++) { | 1159 | for (i = 0; i < num_stripes; i++) { |
1124 | map->stripes[i].physical = | 1160 | map->stripes[i].physical = |
1125 | btrfs_stripe_offset_nr(leaf, chunk, i); | 1161 | btrfs_stripe_offset_nr(leaf, chunk, i); |