@@ -2626,33 +2626,16 @@ static int find_live_mirror(struct map_lookup *map, int first, int num,
return optimal;
}
-int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
- u64 logical, u64 *length,
- struct btrfs_multi_bio **multi_ret,
- int mirror_num)
+void btrfs_map_to_stripe(struct extent_map *em, int rw, int mirror_num,
+ u64 logical, u64 *length,
+ struct btrfs_stripe_info *stripe_info)
{
- struct extent_map *em;
struct map_lookup *map;
- struct extent_map_tree *em_tree = &map_tree->map_tree;
u64 offset;
u64 stripe_offset;
u64 stripe_nr;
int stripe_index;
- int i;
int num_stripes;
- int max_errors;
- struct btrfs_multi_bio *multi;
-
- read_lock(&em_tree->lock);
- em = lookup_extent_mapping(em_tree, logical, *length);
- read_unlock(&em_tree->lock);
-
- if (!em) {
- printk(KERN_CRIT "unable to find logical %llu len %llu\n",
- (unsigned long long)logical,
- (unsigned long long)*length);
- BUG();
- }
BUG_ON(em->start > logical || em->start + em->len < logical);
map = (struct map_lookup *)em->bdev;
@@ -2682,19 +2665,19 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
*length = min(*length, em->len - offset);
}
- if (!multi_ret)
- goto out;
+ if (!stripe_info)
+ return;
if (mirror_num > map->num_stripes)
mirror_num = 0;
- max_errors = 0;
+ stripe_info->max_errors = 0;
if (rw & (1 << BIO_RW)) {
if (map->type & (BTRFS_BLOCK_GROUP_RAID1 |
BTRFS_BLOCK_GROUP_DUP))
- max_errors = 1;
+ stripe_info->max_errors = 1;
else if (map->type & BTRFS_BLOCK_GROUP_RAID10)
- max_errors = 1;
+ stripe_info->max_errors = 1;
}
num_stripes = 1;
@@ -2741,22 +2724,58 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
}
BUG_ON(stripe_index >= map->num_stripes);
- multi = kzalloc(btrfs_multi_bio_size(num_stripes), GFP_NOFS);
+ stripe_info->num_stripes = num_stripes;
+ stripe_info->stripe_index = stripe_index;
+ stripe_info->phys_offset = stripe_offset + stripe_nr * map->stripe_len;
+}
+
+int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
+ u64 logical, u64 *length,
+ struct btrfs_multi_bio **multi_ret, int mirror_num)
+{
+ struct extent_map *em;
+ struct map_lookup *map;
+ struct extent_map_tree *em_tree = &map_tree->map_tree;
+ struct btrfs_multi_bio *multi;
+ struct btrfs_stripe_info stripe_info;
+ int i;
+
+ read_lock(&em_tree->lock);
+ em = lookup_extent_mapping(em_tree, logical, *length);
+ read_unlock(&em_tree->lock);
+
+ if (!em) {
+ printk(KERN_CRIT "unable to find logical %llu len %llu\n",
+ (unsigned long long)logical,
+ (unsigned long long)*length);
+ BUG();
+ }
+
+ btrfs_map_to_stripe(em, rw, mirror_num, logical, length,
+ multi_ret ? &stripe_info : NULL);
+ if (!multi_ret)
+ goto out;
+
+ multi = kzalloc(btrfs_multi_bio_size(stripe_info.num_stripes),
+ GFP_NOFS);
if (!multi)
return -ENOMEM;
*multi_ret = multi;
atomic_set(&multi->error, 0);
- multi->num_stripes = num_stripes;
- multi->max_errors = max_errors;
+ multi->num_stripes = stripe_info.num_stripes;
+ multi->max_errors = stripe_info.max_errors;
- for (i = 0; i < num_stripes; i++) {
+ map = (struct map_lookup *)em->bdev;
+ for (i = 0; i < stripe_info.num_stripes; i++) {
multi->stripes[i].physical =
- map->stripes[stripe_index].physical +
- stripe_offset + stripe_nr * map->stripe_len;
- multi->stripes[i].dev = map->stripes[stripe_index].dev;
- stripe_index++;
+ map->stripes[stripe_info.stripe_index].physical +
+ stripe_info.phys_offset;
+ multi->stripes[i].dev =
+ map->stripes[stripe_info.stripe_index].dev;
+ stripe_info.stripe_index++;
}
+
out:
free_extent_map(em);
return 0;
@@ -135,6 +135,13 @@ struct btrfs_multi_bio {
struct btrfs_bio_stripe stripes[];
};
+struct btrfs_stripe_info {
+ int num_stripes;
+ int max_errors;
+ int stripe_index;
+ u64 phys_offset;
+};
+
#define btrfs_multi_bio_size(n) (sizeof(struct btrfs_multi_bio) + \
(sizeof(struct btrfs_bio_stripe) * (n)))
@@ -142,6 +149,9 @@ int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
struct btrfs_device *device,
u64 chunk_tree, u64 chunk_objectid,
u64 chunk_offset, u64 start, u64 num_bytes);
+void btrfs_map_to_stripe(struct extent_map *em, int rw, int mirror_num,
+ u64 logical, u64 *length,
+ struct btrfs_stripe_info *stripe_info);
int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
u64 logical, u64 *length,
struct btrfs_multi_bio **multi_ret, int mirror_num);