aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-04-09 16:28:12 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:01 -0400
commitcea9e4452ebaf18dd0951e90dc84d82a5dee40b2 (patch)
tree94f6a3c4fa25ebdff1f46d8b41ab58ee92723609
parentd18a2c447524751137a12cc8ccaf9d1e0b7fa1b3 (diff)
Change btrfs_map_block to return a structure with mappings for all stripes
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/ctree.c4
-rw-r--r--fs/btrfs/inode.c8
-rw-r--r--fs/btrfs/volumes.c135
-rw-r--r--fs/btrfs/volumes.h25
4 files changed, 103 insertions, 69 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 3c7891cf0d72..c92c6b0ee582 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 a8ae68c6fbb8..7ae677d8a6de 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 b9294e3c05f0..008d3640e8c2 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
29struct stripe {
30 struct btrfs_device *dev;
31 u64 physical;
32};
33
34struct multi_bio {
35 atomic_t stripes;
36 bio_end_io_t *end_io;
37 void *private;
38 int error;
39};
40
41struct map_lookup { 29struct 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
54static DEFINE_MUTEX(uuid_mutex); 42static DEFINE_MUTEX(uuid_mutex);
55static LIST_HEAD(fs_uuids); 43static LIST_HEAD(fs_uuids);
@@ -801,8 +789,8 @@ void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree)
801} 789}
802 790
803int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, 791int 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 }
809again:
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;
902out:
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 35dec3efd78c..10ca0104750c 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
22struct btrfs_device { 24struct 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
74struct btrfs_bio_stripe {
75 struct btrfs_device *dev;
76 u64 physical;
77};
78
79struct 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
72int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, 91int 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);
75int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, int stripe_nr, 94int 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);
78int btrfs_read_sys_array(struct btrfs_root *root); 97int btrfs_read_sys_array(struct btrfs_root *root);
79int btrfs_read_chunk_tree(struct btrfs_root *root); 98int btrfs_read_chunk_tree(struct btrfs_root *root);
80int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, 99int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,