diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-04-21 10:03:05 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:02 -0400 |
commit | f2d8d74d7874f8f81222363cd6459a365796e35a (patch) | |
tree | 2d081c85d9e88006f084cc17fc1ffa262b885e37 /fs/btrfs/volumes.c | |
parent | 4ef64eae288a3644d1f8b748eb075426701e96d1 (diff) |
Btrfs: Make an unplug function that doesn't unplug every spindle
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 79 |
1 files changed, 57 insertions, 22 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 4fc92cf813d8..460240706505 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/bio.h> | 19 | #include <linux/bio.h> |
20 | #include <linux/buffer_head.h> | 20 | #include <linux/buffer_head.h> |
21 | #include <linux/blkdev.h> | ||
21 | #include <asm/div64.h> | 22 | #include <asm/div64.h> |
22 | #include "ctree.h" | 23 | #include "ctree.h" |
23 | #include "extent_map.h" | 24 | #include "extent_map.h" |
@@ -930,9 +931,10 @@ int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len) | |||
930 | return ret; | 931 | return ret; |
931 | } | 932 | } |
932 | 933 | ||
933 | int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | 934 | static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, |
934 | u64 logical, u64 *length, | 935 | u64 logical, u64 *length, |
935 | struct btrfs_multi_bio **multi_ret, int mirror_num) | 936 | struct btrfs_multi_bio **multi_ret, |
937 | int mirror_num, struct page *unplug_page) | ||
936 | { | 938 | { |
937 | struct extent_map *em; | 939 | struct extent_map *em; |
938 | struct map_lookup *map; | 940 | struct map_lookup *map; |
@@ -944,6 +946,7 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
944 | int stripes_required = 1; | 946 | int stripes_required = 1; |
945 | int stripe_index; | 947 | int stripe_index; |
946 | int i; | 948 | int i; |
949 | int num_stripes; | ||
947 | struct btrfs_multi_bio *multi = NULL; | 950 | struct btrfs_multi_bio *multi = NULL; |
948 | 951 | ||
949 | if (multi_ret && !(rw & (1 << BIO_RW))) { | 952 | if (multi_ret && !(rw & (1 << BIO_RW))) { |
@@ -960,10 +963,14 @@ again: | |||
960 | spin_lock(&em_tree->lock); | 963 | spin_lock(&em_tree->lock); |
961 | em = lookup_extent_mapping(em_tree, logical, *length); | 964 | em = lookup_extent_mapping(em_tree, logical, *length); |
962 | spin_unlock(&em_tree->lock); | 965 | spin_unlock(&em_tree->lock); |
966 | |||
967 | if (!em && unplug_page) | ||
968 | return 0; | ||
969 | |||
963 | if (!em) { | 970 | if (!em) { |
964 | printk("unable to find logical %Lu\n", logical); | 971 | printk("unable to find logical %Lu\n", logical); |
972 | BUG(); | ||
965 | } | 973 | } |
966 | BUG_ON(!em); | ||
967 | 974 | ||
968 | BUG_ON(em->start > logical || em->start + em->len < logical); | 975 | BUG_ON(em->start > logical || em->start + em->len < logical); |
969 | map = (struct map_lookup *)em->bdev; | 976 | map = (struct map_lookup *)em->bdev; |
@@ -1010,14 +1017,15 @@ again: | |||
1010 | } else { | 1017 | } else { |
1011 | *length = em->len - offset; | 1018 | *length = em->len - offset; |
1012 | } | 1019 | } |
1013 | if (!multi_ret) | 1020 | |
1021 | if (!multi_ret && !unplug_page) | ||
1014 | goto out; | 1022 | goto out; |
1015 | 1023 | ||
1016 | multi->num_stripes = 1; | 1024 | num_stripes = 1; |
1017 | stripe_index = 0; | 1025 | stripe_index = 0; |
1018 | if (map->type & BTRFS_BLOCK_GROUP_RAID1) { | 1026 | if (map->type & BTRFS_BLOCK_GROUP_RAID1) { |
1019 | if (rw & (1 << BIO_RW)) | 1027 | if (unplug_page || (rw & (1 << BIO_RW))) |
1020 | multi->num_stripes = map->num_stripes; | 1028 | num_stripes = map->num_stripes; |
1021 | else if (mirror_num) { | 1029 | else if (mirror_num) { |
1022 | stripe_index = mirror_num - 1; | 1030 | stripe_index = mirror_num - 1; |
1023 | } else { | 1031 | } else { |
@@ -1037,7 +1045,7 @@ again: | |||
1037 | } | 1045 | } |
1038 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { | 1046 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { |
1039 | if (rw & (1 << BIO_RW)) | 1047 | if (rw & (1 << BIO_RW)) |
1040 | multi->num_stripes = map->num_stripes; | 1048 | num_stripes = map->num_stripes; |
1041 | else if (mirror_num) | 1049 | else if (mirror_num) |
1042 | stripe_index = mirror_num - 1; | 1050 | stripe_index = mirror_num - 1; |
1043 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { | 1051 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { |
@@ -1047,8 +1055,8 @@ again: | |||
1047 | stripe_index = do_div(stripe_nr, factor); | 1055 | stripe_index = do_div(stripe_nr, factor); |
1048 | stripe_index *= map->sub_stripes; | 1056 | stripe_index *= map->sub_stripes; |
1049 | 1057 | ||
1050 | if (rw & (1 << BIO_RW)) | 1058 | if (unplug_page || (rw & (1 << BIO_RW))) |
1051 | multi->num_stripes = map->sub_stripes; | 1059 | num_stripes = map->sub_stripes; |
1052 | else if (mirror_num) | 1060 | else if (mirror_num) |
1053 | stripe_index += mirror_num - 1; | 1061 | stripe_index += mirror_num - 1; |
1054 | else | 1062 | else |
@@ -1063,19 +1071,50 @@ again: | |||
1063 | } | 1071 | } |
1064 | BUG_ON(stripe_index >= map->num_stripes); | 1072 | BUG_ON(stripe_index >= map->num_stripes); |
1065 | 1073 | ||
1066 | for (i = 0; i < multi->num_stripes; i++) { | 1074 | for (i = 0; i < num_stripes; i++) { |
1067 | multi->stripes[i].physical = | 1075 | if (unplug_page) { |
1068 | map->stripes[stripe_index].physical + stripe_offset + | 1076 | struct btrfs_device *device; |
1069 | stripe_nr * map->stripe_len; | 1077 | struct backing_dev_info *bdi; |
1070 | multi->stripes[i].dev = map->stripes[stripe_index].dev; | 1078 | |
1079 | device = map->stripes[stripe_index].dev; | ||
1080 | bdi = blk_get_backing_dev_info(device->bdev); | ||
1081 | if (bdi->unplug_io_fn) { | ||
1082 | bdi->unplug_io_fn(bdi, unplug_page); | ||
1083 | } | ||
1084 | } else { | ||
1085 | multi->stripes[i].physical = | ||
1086 | map->stripes[stripe_index].physical + | ||
1087 | stripe_offset + stripe_nr * map->stripe_len; | ||
1088 | multi->stripes[i].dev = map->stripes[stripe_index].dev; | ||
1089 | } | ||
1071 | stripe_index++; | 1090 | stripe_index++; |
1072 | } | 1091 | } |
1073 | *multi_ret = multi; | 1092 | if (multi_ret) { |
1093 | *multi_ret = multi; | ||
1094 | multi->num_stripes = num_stripes; | ||
1095 | } | ||
1074 | out: | 1096 | out: |
1075 | free_extent_map(em); | 1097 | free_extent_map(em); |
1076 | return 0; | 1098 | return 0; |
1077 | } | 1099 | } |
1078 | 1100 | ||
1101 | int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | ||
1102 | u64 logical, u64 *length, | ||
1103 | struct btrfs_multi_bio **multi_ret, int mirror_num) | ||
1104 | { | ||
1105 | return __btrfs_map_block(map_tree, rw, logical, length, multi_ret, | ||
1106 | mirror_num, NULL); | ||
1107 | } | ||
1108 | |||
1109 | int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree, | ||
1110 | u64 logical, struct page *page) | ||
1111 | { | ||
1112 | u64 length = PAGE_CACHE_SIZE; | ||
1113 | return __btrfs_map_block(map_tree, READ, logical, &length, | ||
1114 | NULL, 0, page); | ||
1115 | } | ||
1116 | |||
1117 | |||
1079 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23) | 1118 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23) |
1080 | static void end_bio_multi_stripe(struct bio *bio, int err) | 1119 | static void end_bio_multi_stripe(struct bio *bio, int err) |
1081 | #else | 1120 | #else |
@@ -1122,16 +1161,12 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, | |||
1122 | u64 logical = bio->bi_sector << 9; | 1161 | u64 logical = bio->bi_sector << 9; |
1123 | u64 length = 0; | 1162 | u64 length = 0; |
1124 | u64 map_length; | 1163 | u64 map_length; |
1125 | struct bio_vec *bvec; | ||
1126 | struct btrfs_multi_bio *multi = NULL; | 1164 | struct btrfs_multi_bio *multi = NULL; |
1127 | int i; | ||
1128 | int ret; | 1165 | int ret; |
1129 | int dev_nr = 0; | 1166 | int dev_nr = 0; |
1130 | int total_devs = 1; | 1167 | int total_devs = 1; |
1131 | 1168 | ||
1132 | bio_for_each_segment(bvec, bio, i) { | 1169 | length = bio->bi_size; |
1133 | length += bvec->bv_len; | ||
1134 | } | ||
1135 | 1170 | ||
1136 | map_tree = &root->fs_info->mapping_tree; | 1171 | map_tree = &root->fs_info->mapping_tree; |
1137 | map_length = length; | 1172 | map_length = length; |