diff options
-rw-r--r-- | fs/btrfs/ctree.c | 4 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 8 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 135 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 25 |
4 files changed, 103 insertions, 69 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 3c7891cf0d7..c92c6b0ee58 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -2025,8 +2025,10 @@ again: | |||
2025 | root->root_key.objectid, | 2025 | root->root_key.objectid, |
2026 | root_gen, disk_key.objectid, 0, | 2026 | root_gen, disk_key.objectid, 0, |
2027 | l->start, 0); | 2027 | l->start, 0); |
2028 | if (IS_ERR(right)) | 2028 | if (IS_ERR(right)) { |
2029 | BUG_ON(1); | ||
2029 | return PTR_ERR(right); | 2030 | return PTR_ERR(right); |
2031 | } | ||
2030 | 2032 | ||
2031 | memset_extent_buffer(right, 0, 0, sizeof(struct btrfs_header)); | 2033 | memset_extent_buffer(right, 0, 0, sizeof(struct btrfs_header)); |
2032 | btrfs_set_header_bytenr(right, right->start); | 2034 | btrfs_set_header_bytenr(right, right->start); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index a8ae68c6fbb..7ae677d8a6d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -301,12 +301,9 @@ int btrfs_merge_bio_hook(struct page *page, unsigned long offset, | |||
301 | { | 301 | { |
302 | struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; | 302 | struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; |
303 | struct btrfs_mapping_tree *map_tree; | 303 | struct btrfs_mapping_tree *map_tree; |
304 | struct btrfs_device *dev; | ||
305 | u64 logical = bio->bi_sector << 9; | 304 | u64 logical = bio->bi_sector << 9; |
306 | u64 physical; | ||
307 | u64 length = 0; | 305 | u64 length = 0; |
308 | u64 map_length; | 306 | u64 map_length; |
309 | int total_devs; | ||
310 | struct bio_vec *bvec; | 307 | struct bio_vec *bvec; |
311 | int i; | 308 | int i; |
312 | int ret; | 309 | int ret; |
@@ -316,8 +313,9 @@ int btrfs_merge_bio_hook(struct page *page, unsigned long offset, | |||
316 | } | 313 | } |
317 | map_tree = &root->fs_info->mapping_tree; | 314 | map_tree = &root->fs_info->mapping_tree; |
318 | map_length = length; | 315 | map_length = length; |
319 | ret = btrfs_map_block(map_tree, READ, 0, logical, &physical, | 316 | ret = btrfs_map_block(map_tree, READ, logical, |
320 | &map_length, &dev, &total_devs); | 317 | &map_length, NULL); |
318 | |||
321 | if (map_length < length + size) { | 319 | if (map_length < length + size) { |
322 | return 1; | 320 | return 1; |
323 | } | 321 | } |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index b9294e3c05f..008d3640e8c 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -26,18 +26,6 @@ | |||
26 | #include "print-tree.h" | 26 | #include "print-tree.h" |
27 | #include "volumes.h" | 27 | #include "volumes.h" |
28 | 28 | ||
29 | struct stripe { | ||
30 | struct btrfs_device *dev; | ||
31 | u64 physical; | ||
32 | }; | ||
33 | |||
34 | struct multi_bio { | ||
35 | atomic_t stripes; | ||
36 | bio_end_io_t *end_io; | ||
37 | void *private; | ||
38 | int error; | ||
39 | }; | ||
40 | |||
41 | struct map_lookup { | 29 | struct map_lookup { |
42 | u64 type; | 30 | u64 type; |
43 | int io_align; | 31 | int io_align; |
@@ -45,11 +33,11 @@ struct map_lookup { | |||
45 | int stripe_len; | 33 | int stripe_len; |
46 | int sector_size; | 34 | int sector_size; |
47 | int num_stripes; | 35 | int num_stripes; |
48 | struct stripe stripes[]; | 36 | struct btrfs_bio_stripe stripes[]; |
49 | }; | 37 | }; |
50 | 38 | ||
51 | #define map_lookup_size(n) (sizeof(struct map_lookup) + \ | 39 | #define map_lookup_size(n) (sizeof(struct map_lookup) + \ |
52 | (sizeof(struct stripe) * (n))) | 40 | (sizeof(struct btrfs_bio_stripe) * (n))) |
53 | 41 | ||
54 | static DEFINE_MUTEX(uuid_mutex); | 42 | static DEFINE_MUTEX(uuid_mutex); |
55 | static LIST_HEAD(fs_uuids); | 43 | static LIST_HEAD(fs_uuids); |
@@ -801,8 +789,8 @@ void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree) | |||
801 | } | 789 | } |
802 | 790 | ||
803 | int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | 791 | int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, |
804 | int dev_nr, u64 logical, u64 *phys, u64 *length, | 792 | u64 logical, u64 *length, |
805 | struct btrfs_device **dev, int *total_devs) | 793 | struct btrfs_multi_bio **multi_ret) |
806 | { | 794 | { |
807 | struct extent_map *em; | 795 | struct extent_map *em; |
808 | struct map_lookup *map; | 796 | struct map_lookup *map; |
@@ -810,8 +798,21 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
810 | u64 offset; | 798 | u64 offset; |
811 | u64 stripe_offset; | 799 | u64 stripe_offset; |
812 | u64 stripe_nr; | 800 | u64 stripe_nr; |
801 | int stripes_allocated = 8; | ||
813 | int stripe_index; | 802 | int stripe_index; |
803 | int i; | ||
804 | struct btrfs_multi_bio *multi = NULL; | ||
814 | 805 | ||
806 | if (multi_ret && !(rw & (1 << BIO_RW))) { | ||
807 | stripes_allocated = 1; | ||
808 | } | ||
809 | again: | ||
810 | if (multi_ret) { | ||
811 | multi = kzalloc(btrfs_multi_bio_size(stripes_allocated), | ||
812 | GFP_NOFS); | ||
813 | if (!multi) | ||
814 | return -ENOMEM; | ||
815 | } | ||
815 | 816 | ||
816 | spin_lock(&em_tree->lock); | 817 | spin_lock(&em_tree->lock); |
817 | em = lookup_extent_mapping(em_tree, logical, *length); | 818 | em = lookup_extent_mapping(em_tree, logical, *length); |
@@ -821,6 +822,17 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
821 | map = (struct map_lookup *)em->bdev; | 822 | map = (struct map_lookup *)em->bdev; |
822 | offset = logical - em->start; | 823 | offset = logical - em->start; |
823 | 824 | ||
825 | /* if our multi bio struct is too small, back off and try again */ | ||
826 | if (multi_ret && (rw & (1 << BIO_RW)) && | ||
827 | stripes_allocated < map->num_stripes && | ||
828 | ((map->type & BTRFS_BLOCK_GROUP_RAID1) || | ||
829 | (map->type & BTRFS_BLOCK_GROUP_DUP))) { | ||
830 | stripes_allocated = map->num_stripes; | ||
831 | spin_unlock(&em_tree->lock); | ||
832 | free_extent_map(em); | ||
833 | kfree(multi); | ||
834 | goto again; | ||
835 | } | ||
824 | stripe_nr = offset; | 836 | stripe_nr = offset; |
825 | /* | 837 | /* |
826 | * stripe_nr counts the total number of stripes we have to stride | 838 | * stripe_nr counts the total number of stripes we have to stride |
@@ -834,10 +846,22 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
834 | /* stripe_offset is the offset of this block in its stripe*/ | 846 | /* stripe_offset is the offset of this block in its stripe*/ |
835 | stripe_offset = offset - stripe_offset; | 847 | stripe_offset = offset - stripe_offset; |
836 | 848 | ||
849 | if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 | | ||
850 | BTRFS_BLOCK_GROUP_DUP)) { | ||
851 | /* we limit the length of each bio to what fits in a stripe */ | ||
852 | *length = min_t(u64, em->len - offset, | ||
853 | map->stripe_len - stripe_offset); | ||
854 | } else { | ||
855 | *length = em->len - offset; | ||
856 | } | ||
857 | if (!multi_ret) | ||
858 | goto out; | ||
859 | |||
860 | multi->num_stripes = 1; | ||
861 | stripe_index = 0; | ||
837 | if (map->type & BTRFS_BLOCK_GROUP_RAID1) { | 862 | if (map->type & BTRFS_BLOCK_GROUP_RAID1) { |
838 | stripe_index = dev_nr; | ||
839 | if (rw & (1 << BIO_RW)) | 863 | if (rw & (1 << BIO_RW)) |
840 | *total_devs = map->num_stripes; | 864 | multi->num_stripes = map->num_stripes; |
841 | else { | 865 | else { |
842 | int i; | 866 | int i; |
843 | u64 least = (u64)-1; | 867 | u64 least = (u64)-1; |
@@ -852,16 +876,10 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
852 | } | 876 | } |
853 | spin_unlock(&cur->io_lock); | 877 | spin_unlock(&cur->io_lock); |
854 | } | 878 | } |
855 | *total_devs = 1; | ||
856 | } | 879 | } |
857 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { | 880 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { |
858 | if (rw == WRITE) { | 881 | if (rw & (1 << BIO_RW)) |
859 | *total_devs = map->num_stripes; | 882 | multi->num_stripes = map->num_stripes; |
860 | stripe_index = dev_nr; | ||
861 | } else { | ||
862 | stripe_index = 0; | ||
863 | *total_devs = 1; | ||
864 | } | ||
865 | } else { | 883 | } else { |
866 | /* | 884 | /* |
867 | * after this do_div call, stripe_nr is the number of stripes | 885 | * after this do_div call, stripe_nr is the number of stripes |
@@ -871,18 +889,17 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
871 | stripe_index = do_div(stripe_nr, map->num_stripes); | 889 | stripe_index = do_div(stripe_nr, map->num_stripes); |
872 | } | 890 | } |
873 | BUG_ON(stripe_index >= map->num_stripes); | 891 | BUG_ON(stripe_index >= map->num_stripes); |
874 | *phys = map->stripes[stripe_index].physical + stripe_offset + | 892 | BUG_ON(stripe_index != 0 && multi->num_stripes > 1); |
875 | stripe_nr * map->stripe_len; | 893 | |
876 | 894 | for (i = 0; i < multi->num_stripes; i++) { | |
877 | if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 | | 895 | multi->stripes[i].physical = |
878 | BTRFS_BLOCK_GROUP_DUP)) { | 896 | map->stripes[stripe_index].physical + stripe_offset + |
879 | /* we limit the length of each bio to what fits in a stripe */ | 897 | stripe_nr * map->stripe_len; |
880 | *length = min_t(u64, em->len - offset, | 898 | multi->stripes[i].dev = map->stripes[stripe_index].dev; |
881 | map->stripe_len - stripe_offset); | 899 | stripe_index++; |
882 | } else { | ||
883 | *length = em->len - offset; | ||
884 | } | 900 | } |
885 | *dev = map->stripes[stripe_index].dev; | 901 | *multi_ret = multi; |
902 | out: | ||
886 | free_extent_map(em); | 903 | free_extent_map(em); |
887 | spin_unlock(&em_tree->lock); | 904 | spin_unlock(&em_tree->lock); |
888 | return 0; | 905 | return 0; |
@@ -895,7 +912,7 @@ static int end_bio_multi_stripe(struct bio *bio, | |||
895 | unsigned int bytes_done, int err) | 912 | unsigned int bytes_done, int err) |
896 | #endif | 913 | #endif |
897 | { | 914 | { |
898 | struct multi_bio *multi = bio->bi_private; | 915 | struct btrfs_multi_bio *multi = bio->bi_private; |
899 | 916 | ||
900 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) | 917 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) |
901 | if (bio->bi_size) | 918 | if (bio->bi_size) |
@@ -904,7 +921,7 @@ static int end_bio_multi_stripe(struct bio *bio, | |||
904 | if (err) | 921 | if (err) |
905 | multi->error = err; | 922 | multi->error = err; |
906 | 923 | ||
907 | if (atomic_dec_and_test(&multi->stripes)) { | 924 | if (atomic_dec_and_test(&multi->stripes_pending)) { |
908 | bio->bi_private = multi->private; | 925 | bio->bi_private = multi->private; |
909 | bio->bi_end_io = multi->end_io; | 926 | bio->bi_end_io = multi->end_io; |
910 | 927 | ||
@@ -927,11 +944,10 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio) | |||
927 | struct btrfs_device *dev; | 944 | struct btrfs_device *dev; |
928 | struct bio *first_bio = bio; | 945 | struct bio *first_bio = bio; |
929 | u64 logical = bio->bi_sector << 9; | 946 | u64 logical = bio->bi_sector << 9; |
930 | u64 physical; | ||
931 | u64 length = 0; | 947 | u64 length = 0; |
932 | u64 map_length; | 948 | u64 map_length; |
933 | struct bio_vec *bvec; | 949 | struct bio_vec *bvec; |
934 | struct multi_bio *multi = NULL; | 950 | struct btrfs_multi_bio *multi = NULL; |
935 | int i; | 951 | int i; |
936 | int ret; | 952 | int ret; |
937 | int dev_nr = 0; | 953 | int dev_nr = 0; |
@@ -943,26 +959,22 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio) | |||
943 | 959 | ||
944 | map_tree = &root->fs_info->mapping_tree; | 960 | map_tree = &root->fs_info->mapping_tree; |
945 | map_length = length; | 961 | map_length = length; |
962 | |||
963 | ret = btrfs_map_block(map_tree, rw, logical, &map_length, &multi); | ||
964 | BUG_ON(ret); | ||
965 | |||
966 | total_devs = multi->num_stripes; | ||
967 | if (map_length < length) { | ||
968 | printk("mapping failed logical %Lu bio len %Lu " | ||
969 | "len %Lu\n", logical, length, map_length); | ||
970 | BUG(); | ||
971 | } | ||
972 | multi->end_io = first_bio->bi_end_io; | ||
973 | multi->private = first_bio->bi_private; | ||
974 | atomic_set(&multi->stripes_pending, multi->num_stripes); | ||
975 | |||
946 | while(dev_nr < total_devs) { | 976 | while(dev_nr < total_devs) { |
947 | ret = btrfs_map_block(map_tree, rw, dev_nr, logical, | ||
948 | &physical, &map_length, &dev, | ||
949 | &total_devs); | ||
950 | if (map_length < length) { | ||
951 | printk("mapping failed logical %Lu bio len %Lu physical %Lu " | ||
952 | "len %Lu\n", logical, length, physical, map_length); | ||
953 | BUG(); | ||
954 | } | ||
955 | BUG_ON(map_length < length); | ||
956 | if (total_devs > 1) { | 977 | if (total_devs > 1) { |
957 | if (!multi) { | ||
958 | multi = kmalloc(sizeof(*multi), GFP_NOFS); | ||
959 | atomic_set(&multi->stripes, 1); | ||
960 | multi->end_io = bio->bi_end_io; | ||
961 | multi->private = first_bio->bi_private; | ||
962 | multi->error = 0; | ||
963 | } else { | ||
964 | atomic_inc(&multi->stripes); | ||
965 | } | ||
966 | if (dev_nr < total_devs - 1) { | 978 | if (dev_nr < total_devs - 1) { |
967 | bio = bio_clone(first_bio, GFP_NOFS); | 979 | bio = bio_clone(first_bio, GFP_NOFS); |
968 | BUG_ON(!bio); | 980 | BUG_ON(!bio); |
@@ -972,7 +984,8 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio) | |||
972 | bio->bi_private = multi; | 984 | bio->bi_private = multi; |
973 | bio->bi_end_io = end_bio_multi_stripe; | 985 | bio->bi_end_io = end_bio_multi_stripe; |
974 | } | 986 | } |
975 | bio->bi_sector = physical >> 9; | 987 | bio->bi_sector = multi->stripes[dev_nr].physical >> 9; |
988 | dev = multi->stripes[dev_nr].dev; | ||
976 | bio->bi_bdev = dev->bdev; | 989 | bio->bi_bdev = dev->bdev; |
977 | spin_lock(&dev->io_lock); | 990 | spin_lock(&dev->io_lock); |
978 | dev->total_ios++; | 991 | dev->total_ios++; |
@@ -980,6 +993,8 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio) | |||
980 | submit_bio(rw, bio); | 993 | submit_bio(rw, bio); |
981 | dev_nr++; | 994 | dev_nr++; |
982 | } | 995 | } |
996 | if (total_devs == 1) | ||
997 | kfree(multi); | ||
983 | return 0; | 998 | return 0; |
984 | } | 999 | } |
985 | 1000 | ||
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 35dec3efd78..10ca0104750 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -19,6 +19,8 @@ | |||
19 | #ifndef __BTRFS_VOLUMES_ | 19 | #ifndef __BTRFS_VOLUMES_ |
20 | #define __BTRFS_VOLUMES_ | 20 | #define __BTRFS_VOLUMES_ |
21 | 21 | ||
22 | #include <linux/bio.h> | ||
23 | |||
22 | struct btrfs_device { | 24 | struct btrfs_device { |
23 | struct list_head dev_list; | 25 | struct list_head dev_list; |
24 | struct btrfs_root *dev_root; | 26 | struct btrfs_root *dev_root; |
@@ -69,12 +71,29 @@ struct btrfs_fs_devices { | |||
69 | struct list_head list; | 71 | struct list_head list; |
70 | }; | 72 | }; |
71 | 73 | ||
74 | struct btrfs_bio_stripe { | ||
75 | struct btrfs_device *dev; | ||
76 | u64 physical; | ||
77 | }; | ||
78 | |||
79 | struct btrfs_multi_bio { | ||
80 | atomic_t stripes_pending; | ||
81 | bio_end_io_t *end_io; | ||
82 | void *private; | ||
83 | int error; | ||
84 | int num_stripes; | ||
85 | struct btrfs_bio_stripe stripes[]; | ||
86 | }; | ||
87 | |||
88 | #define btrfs_multi_bio_size(n) (sizeof(struct btrfs_multi_bio) + \ | ||
89 | (sizeof(struct btrfs_bio_stripe) * (n))) | ||
90 | |||
72 | int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, | 91 | int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, |
73 | struct btrfs_device *device, | 92 | struct btrfs_device *device, |
74 | u64 owner, u64 num_bytes, u64 *start); | 93 | u64 owner, u64 num_bytes, u64 *start); |
75 | int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, int stripe_nr, | 94 | int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, |
76 | u64 logical, u64 *phys, u64 *length, | 95 | u64 logical, u64 *length, |
77 | struct btrfs_device **dev, int *total_stripes); | 96 | struct btrfs_multi_bio **multi_ret); |
78 | int btrfs_read_sys_array(struct btrfs_root *root); | 97 | int btrfs_read_sys_array(struct btrfs_root *root); |
79 | int btrfs_read_chunk_tree(struct btrfs_root *root); | 98 | int btrfs_read_chunk_tree(struct btrfs_root *root); |
80 | int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | 99 | int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, |