Change btrfs_map_block to return a structure with mappings for all stripes

master
Chris Mason 2008-04-09 16:28:12 -04:00 committed by David Woodhouse
parent 97864fa126
commit 1b74adf90b
4 changed files with 97 additions and 52 deletions

View File

@ -1928,8 +1928,10 @@ again:
root->root_key.objectid,
root_gen, disk_key.objectid, 0,
l->start, 0);
if (IS_ERR(right))
if (IS_ERR(right)) {
BUG_ON(1);
return PTR_ERR(right);
}
memset_extent_buffer(right, 0, 0, sizeof(struct btrfs_header));
btrfs_set_header_bytenr(right, right->start);

View File

@ -97,11 +97,10 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize)
{
int ret;
int total_devs = 1;
int dev_nr;
struct extent_buffer *eb;
u64 physical;
u64 length;
struct btrfs_multi_bio *multi = NULL;
struct btrfs_device *device;
eb = btrfs_find_tree_block(root, bytenr, blocksize);
@ -111,13 +110,15 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize)
}
dev_nr = 0;
ret = btrfs_map_block(&root->fs_info->mapping_tree, READ, dev_nr,
bytenr, &physical, &length, &device,
&total_devs);
length = blocksize;
ret = btrfs_map_block(&root->fs_info->mapping_tree, READ,
bytenr, &length, &multi);
BUG_ON(ret);
device = multi->stripes[0].dev;
device->total_ios++;
blocksize = min(blocksize, (u32)(64 * 1024));
readahead(device->fd, physical, blocksize);
readahead(device->fd, multi->stripes[0].physical, blocksize);
kfree(multi);
return 0;
}
@ -125,11 +126,10 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
u32 blocksize)
{
int ret;
int total_devs = 1;
int dev_nr;
struct extent_buffer *eb;
u64 physical;
u64 length;
struct btrfs_multi_bio *multi = NULL;
struct btrfs_device *device;
eb = btrfs_find_create_tree_block(root, bytenr, blocksize);
@ -140,19 +140,21 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
return eb;
dev_nr = 0;
ret = btrfs_map_block(&root->fs_info->mapping_tree, READ, dev_nr,
eb->start, &physical, &length, &device,
&total_devs);
length = blocksize;
ret = btrfs_map_block(&root->fs_info->mapping_tree, READ,
eb->start, &length, &multi);
BUG_ON(ret);
device = multi->stripes[0].dev;
eb->fd = device->fd;
device->total_ios++;
eb->dev_bytenr = physical;
eb->dev_bytenr = multi->stripes[0].physical;
ret = read_extent_from_disk(eb);
if (ret) {
free_extent_buffer(eb);
return NULL;
}
btrfs_set_buffer_uptodate(eb);
kfree(multi);
return eb;
}
@ -160,11 +162,9 @@ int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct extent_buffer *eb)
{
int ret;
int total_devs = 1;
int dev_nr;
u64 physical;
u64 length;
struct btrfs_device *device;
struct btrfs_multi_bio *multi = NULL;
if (check_tree_block(root, eb))
BUG();
@ -175,18 +175,19 @@ int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
csum_tree_block(root, eb, 0);
dev_nr = 0;
while(dev_nr < total_devs) {
ret = btrfs_map_block(&root->fs_info->mapping_tree, WRITE,
dev_nr, eb->start, &physical, &length,
&device, &total_devs);
length = eb->len;
ret = btrfs_map_block(&root->fs_info->mapping_tree, WRITE,
eb->start, &length, &multi);
while(dev_nr < multi->num_stripes) {
BUG_ON(ret);
eb->fd = device->fd;
eb->dev_bytenr = physical;
eb->fd = multi->stripes[dev_nr].dev->fd;
eb->dev_bytenr = multi->stripes[dev_nr].physical;
multi->stripes[dev_nr].dev->total_ios++;
dev_nr++;
device->total_ios++;
ret = write_extent_to_disk(eb);
BUG_ON(ret);
}
kfree(multi);
return 0;
}

View File

@ -43,11 +43,11 @@ struct map_lookup {
int stripe_len;
int sector_size;
int num_stripes;
struct stripe stripes[];
struct btrfs_bio_stripe stripes[];
};
#define map_lookup_size(n) (sizeof(struct map_lookup) + \
(sizeof(struct stripe) * (n)))
(sizeof(struct btrfs_bio_stripe) * (n)))
static LIST_HEAD(fs_uuids);
@ -733,15 +733,29 @@ void btrfs_mapping_init(struct btrfs_mapping_tree *tree)
}
int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
int dev_nr, u64 logical, u64 *phys, u64 *length,
struct btrfs_device **dev, int *total_devs)
u64 logical, u64 *length,
struct btrfs_multi_bio **multi_ret)
{
struct cache_extent *ce;
struct map_lookup *map;
u64 offset;
u64 stripe_offset;
u64 stripe_nr;
int stripes_allocated = 8;
int stripe_index;
int i;
struct btrfs_multi_bio *multi = NULL;
if (multi_ret && rw == READ) {
stripes_allocated = 1;
}
again:
if (multi_ret) {
multi = kzalloc(btrfs_multi_bio_size(stripes_allocated),
GFP_NOFS);
if (!multi)
return -ENOMEM;
}
ce = find_first_cache_extent(&map_tree->cache_tree, logical);
BUG_ON(!ce);
@ -749,6 +763,15 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
map = container_of(ce, struct map_lookup, ce);
offset = logical - ce->start;
/* if our multi bio struct is too small, back off and try again */
if (multi_ret && (rw == WRITE) &&
stripes_allocated < map->num_stripes &&
((map->type & BTRFS_BLOCK_GROUP_RAID1) ||
(map->type & BTRFS_BLOCK_GROUP_DUP))) {
stripes_allocated = map->num_stripes;
kfree(multi);
goto again;
}
stripe_nr = offset;
/*
* stripe_nr counts the total number of stripes we have to stride
@ -762,22 +785,28 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
/* stripe_offset is the offset of this block in its stripe*/
stripe_offset = offset - stripe_offset;
if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
BTRFS_BLOCK_GROUP_DUP)) {
/* we limit the length of each bio to what fits in a stripe */
*length = min_t(u64, ce->size - offset,
map->stripe_len - stripe_offset);
} else {
*length = ce->size - offset;
}
if (!multi_ret)
goto out;
multi->num_stripes = 1;
stripe_index = 0;
if (map->type & BTRFS_BLOCK_GROUP_RAID1) {
stripe_index = dev_nr;
if (rw == WRITE)
*total_devs = map->num_stripes;
else {
multi->num_stripes = map->num_stripes;
else
stripe_index = stripe_nr % map->num_stripes;
*total_devs = 1;
}
} else if (map->type & BTRFS_BLOCK_GROUP_DUP) {
if (rw == WRITE) {
*total_devs = map->num_stripes;
stripe_index = dev_nr;
} else {
stripe_index = 0;
*total_devs = 1;
}
if (rw == WRITE)
multi->num_stripes = map->num_stripes;
} else {
/*
* after this do_div call, stripe_nr is the number of stripes
@ -788,18 +817,17 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
stripe_nr = stripe_nr / map->num_stripes;
}
BUG_ON(stripe_index >= map->num_stripes);
*phys = map->stripes[stripe_index].physical + stripe_offset +
stripe_nr * map->stripe_len;
if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
BTRFS_BLOCK_GROUP_DUP)) {
/* we limit the length of each bio to what fits in a stripe */
*length = min_t(u64, ce->size - offset,
map->stripe_len - stripe_offset);
} else {
*length = ce->size - offset;
BUG_ON(stripe_index != 0 && multi->num_stripes > 1);
for (i = 0; i < multi->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++;
}
*dev = map->stripes[stripe_index].dev;
*multi_ret = multi;
out:
return 0;
}

View File

@ -66,12 +66,26 @@ struct btrfs_fs_devices {
struct list_head list;
};
struct btrfs_bio_stripe {
struct btrfs_device *dev;
u64 physical;
};
struct btrfs_multi_bio {
int error;
int num_stripes;
struct btrfs_bio_stripe stripes[];
};
#define btrfs_multi_bio_size(n) (sizeof(struct btrfs_multi_bio) + \
(sizeof(struct btrfs_bio_stripe) * (n)))
int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
struct btrfs_device *device,
u64 owner, u64 num_bytes, u64 *start);
int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, int stripe_nr,
u64 logical, u64 *phys, u64 *length,
struct btrfs_device **dev, int *total_stripes);
int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
u64 logical, u64 *length,
struct btrfs_multi_bio **multi_ret);
int btrfs_read_sys_array(struct btrfs_root *root);
int btrfs_read_chunk_tree(struct btrfs_root *root);
int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,