aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-04-16 10:49:51 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:01 -0400
commit321aecc65671ae8136bd2ca6879b56f0221f8ac8 (patch)
tree9e397c5a6b4750703e60d70c0b588c463aaf376c /fs/btrfs/volumes.c
parente17cade25ff8074101d653557a78df09c16ca276 (diff)
Btrfs: Add RAID10 support
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c46
1 files changed, 41 insertions, 5 deletions
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 }
661again: 670again:
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);