Add raid10 support
This commit is contained in:
parent
951fd7371c
commit
1f81c1b6fc
7
ctree.h
7
ctree.h
|
@ -186,6 +186,9 @@ struct btrfs_chunk {
|
|||
* item in the btree
|
||||
*/
|
||||
__le16 num_stripes;
|
||||
|
||||
/* sub stripes only matter for raid10 */
|
||||
__le16 sub_stripes;
|
||||
struct btrfs_stripe stripe;
|
||||
/* additional stripes go here */
|
||||
} __attribute__ ((__packed__));
|
||||
|
@ -432,6 +435,7 @@ struct btrfs_csum_item {
|
|||
#define BTRFS_BLOCK_GROUP_RAID0 (1 << 3)
|
||||
#define BTRFS_BLOCK_GROUP_RAID1 (1 << 4)
|
||||
#define BTRFS_BLOCK_GROUP_DUP (1 << 5)
|
||||
#define BTRFS_BLOCK_GROUP_RAID10 (1 << 6)
|
||||
|
||||
struct btrfs_block_group_item {
|
||||
__le64 used;
|
||||
|
@ -705,6 +709,7 @@ BTRFS_SETGET_FUNCS(chunk_io_width, struct btrfs_chunk, io_width, 32);
|
|||
BTRFS_SETGET_FUNCS(chunk_sector_size, struct btrfs_chunk, sector_size, 32);
|
||||
BTRFS_SETGET_FUNCS(chunk_type, struct btrfs_chunk, type, 64);
|
||||
BTRFS_SETGET_FUNCS(chunk_num_stripes, struct btrfs_chunk, num_stripes, 16);
|
||||
BTRFS_SETGET_FUNCS(chunk_sub_stripes, struct btrfs_chunk, sub_stripes, 16);
|
||||
BTRFS_SETGET_FUNCS(stripe_devid, struct btrfs_stripe, devid, 64);
|
||||
BTRFS_SETGET_FUNCS(stripe_offset, struct btrfs_stripe, offset, 64);
|
||||
|
||||
|
@ -726,6 +731,8 @@ BTRFS_SETGET_STACK_FUNCS(stack_chunk_sector_size, struct btrfs_chunk,
|
|||
BTRFS_SETGET_STACK_FUNCS(stack_chunk_type, struct btrfs_chunk, type, 64);
|
||||
BTRFS_SETGET_STACK_FUNCS(stack_chunk_num_stripes, struct btrfs_chunk,
|
||||
num_stripes, 16);
|
||||
BTRFS_SETGET_STACK_FUNCS(stack_chunk_sub_stripes, struct btrfs_chunk,
|
||||
sub_stripes, 16);
|
||||
BTRFS_SETGET_STACK_FUNCS(stack_stripe_devid, struct btrfs_stripe, devid, 64);
|
||||
BTRFS_SETGET_STACK_FUNCS(stack_stripe_offset, struct btrfs_stripe, offset, 64);
|
||||
|
||||
|
|
7
mkfs.c
7
mkfs.c
|
@ -203,7 +203,10 @@ static int create_raid_groups(struct btrfs_trans_handle *trans,
|
|||
|
||||
if (num_devices == 1)
|
||||
allowed = BTRFS_BLOCK_GROUP_DUP;
|
||||
else
|
||||
else if (num_devices >= 4) {
|
||||
allowed = BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
|
||||
BTRFS_BLOCK_GROUP_RAID10;
|
||||
} else
|
||||
allowed = BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1;
|
||||
|
||||
if (allowed & metadata_profile) {
|
||||
|
@ -246,6 +249,8 @@ static u64 parse_profile(char *s)
|
|||
return BTRFS_BLOCK_GROUP_RAID0;
|
||||
} else if (strcmp(s, "raid1") == 0) {
|
||||
return BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_DUP;
|
||||
} else if (strcmp(s, "raid10") == 0) {
|
||||
return BTRFS_BLOCK_GROUP_RAID10 | BTRFS_BLOCK_GROUP_DUP;
|
||||
} else if (strcmp(s, "single") == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
|
|
49
volumes.c
49
volumes.c
|
@ -43,6 +43,7 @@ struct map_lookup {
|
|||
int stripe_len;
|
||||
int sector_size;
|
||||
int num_stripes;
|
||||
int sub_stripes;
|
||||
struct btrfs_bio_stripe stripes[];
|
||||
};
|
||||
|
||||
|
@ -594,6 +595,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
|
|||
u64 avail;
|
||||
u64 max_avail = 0;
|
||||
int num_stripes = 1;
|
||||
int sub_stripes = 0;
|
||||
int looped = 0;
|
||||
int ret;
|
||||
int index;
|
||||
|
@ -605,6 +607,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
|
|||
}
|
||||
|
||||
if (type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
|
||||
BTRFS_BLOCK_GROUP_RAID10 |
|
||||
BTRFS_BLOCK_GROUP_DUP)) {
|
||||
if (type & BTRFS_BLOCK_GROUP_SYSTEM)
|
||||
calc_size = 128 * 1024 * 1024;
|
||||
|
@ -619,6 +622,13 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
|
|||
num_stripes = 2;
|
||||
if (type & (BTRFS_BLOCK_GROUP_RAID0))
|
||||
num_stripes = btrfs_super_num_devices(&info->super_copy);
|
||||
if (type & (BTRFS_BLOCK_GROUP_RAID10)) {
|
||||
num_stripes = btrfs_super_num_devices(&info->super_copy);
|
||||
if (num_stripes < 4)
|
||||
return -ENOSPC;
|
||||
num_stripes &= ~(u32)1;
|
||||
sub_stripes = 2;
|
||||
}
|
||||
again:
|
||||
INIT_LIST_HEAD(&private_devs);
|
||||
cur = dev_list->next;
|
||||
|
@ -674,6 +684,8 @@ again:
|
|||
|
||||
if (type & (BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_DUP))
|
||||
*num_bytes = calc_size;
|
||||
else if (type & BTRFS_BLOCK_GROUP_RAID10)
|
||||
*num_bytes = calc_size * num_stripes / sub_stripes;
|
||||
else
|
||||
*num_bytes = calc_size * num_stripes;
|
||||
|
||||
|
@ -723,12 +735,14 @@ printk("\talloc chunk size %llu from dev %llu phys %llu\n",
|
|||
btrfs_set_stack_chunk_io_align(chunk, stripe_len);
|
||||
btrfs_set_stack_chunk_io_width(chunk, stripe_len);
|
||||
btrfs_set_stack_chunk_sector_size(chunk, extent_root->sectorsize);
|
||||
btrfs_set_stack_chunk_sub_stripes(chunk, sub_stripes);
|
||||
map->sector_size = extent_root->sectorsize;
|
||||
map->stripe_len = stripe_len;
|
||||
map->io_align = stripe_len;
|
||||
map->io_width = stripe_len;
|
||||
map->type = type;
|
||||
map->num_stripes = num_stripes;
|
||||
map->sub_stripes = sub_stripes;
|
||||
|
||||
ret = btrfs_insert_item(trans, chunk_root, &key, chunk,
|
||||
btrfs_chunk_item_size(num_stripes));
|
||||
|
@ -773,6 +787,8 @@ int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len)
|
|||
offset = logical - ce->start;
|
||||
if (map->type & (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1))
|
||||
ret = map->num_stripes;
|
||||
else if (map->type & BTRFS_BLOCK_GROUP_RAID10)
|
||||
ret = map->sub_stripes;
|
||||
else
|
||||
ret = 1;
|
||||
return ret;
|
||||
|
@ -788,6 +804,7 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
|
|||
u64 stripe_offset;
|
||||
u64 stripe_nr;
|
||||
int stripes_allocated = 8;
|
||||
int stripes_required = 1;
|
||||
int stripe_index;
|
||||
int i;
|
||||
struct btrfs_multi_bio *multi = NULL;
|
||||
|
@ -809,11 +826,17 @@ again:
|
|||
map = container_of(ce, struct map_lookup, ce);
|
||||
offset = logical - ce->start;
|
||||
|
||||
if (rw == WRITE) {
|
||||
if (map->type & (BTRFS_BLOCK_GROUP_RAID1 |
|
||||
BTRFS_BLOCK_GROUP_DUP)) {
|
||||
stripes_required = map->num_stripes;
|
||||
} else if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
|
||||
stripes_required = map->sub_stripes;
|
||||
}
|
||||
}
|
||||
/* 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))) {
|
||||
if (multi_ret && rw == WRITE &&
|
||||
stripes_allocated < stripes_required) {
|
||||
stripes_allocated = map->num_stripes;
|
||||
kfree(multi);
|
||||
goto again;
|
||||
|
@ -832,6 +855,7 @@ again:
|
|||
stripe_offset = offset - stripe_offset;
|
||||
|
||||
if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
|
||||
BTRFS_BLOCK_GROUP_RAID10 |
|
||||
BTRFS_BLOCK_GROUP_DUP)) {
|
||||
/* we limit the length of each bio to what fits in a stripe */
|
||||
*length = min_t(u64, ce->size - offset,
|
||||
|
@ -852,6 +876,20 @@ again:
|
|||
stripe_index = mirror_num - 1;
|
||||
else
|
||||
stripe_index = stripe_nr % map->num_stripes;
|
||||
} else if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
|
||||
int factor = map->num_stripes / map->sub_stripes;
|
||||
|
||||
stripe_index = stripe_nr % factor;
|
||||
stripe_index *= map->sub_stripes;
|
||||
|
||||
if (rw == WRITE)
|
||||
multi->num_stripes = map->sub_stripes;
|
||||
else if (mirror_num)
|
||||
stripe_index += mirror_num - 1;
|
||||
else
|
||||
stripe_index = stripe_nr % map->sub_stripes;
|
||||
|
||||
stripe_nr = stripe_nr / factor;
|
||||
} else if (map->type & BTRFS_BLOCK_GROUP_DUP) {
|
||||
if (rw == WRITE)
|
||||
multi->num_stripes = map->num_stripes;
|
||||
|
@ -895,6 +933,7 @@ int btrfs_bootstrap_super_map(struct btrfs_mapping_tree *map_tree,
|
|||
u64 logical = BTRFS_SUPER_INFO_OFFSET;
|
||||
u64 length = BTRFS_SUPER_INFO_SIZE;
|
||||
int num_stripes = 0;
|
||||
int sub_stripes = 0;
|
||||
int ret;
|
||||
int i;
|
||||
struct list_head *cur;
|
||||
|
@ -909,6 +948,7 @@ int btrfs_bootstrap_super_map(struct btrfs_mapping_tree *map_tree,
|
|||
map->ce.start = logical;
|
||||
map->ce.size = length;
|
||||
map->num_stripes = num_stripes;
|
||||
map->sub_stripes = sub_stripes;
|
||||
map->io_width = length;
|
||||
map->io_align = length;
|
||||
map->sector_size = length;
|
||||
|
@ -983,6 +1023,7 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
|
|||
map->sector_size = btrfs_chunk_sector_size(leaf, chunk);
|
||||
map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
|
||||
map->type = btrfs_chunk_type(leaf, chunk);
|
||||
map->sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
|
||||
|
||||
for (i = 0; i < num_stripes; i++) {
|
||||
map->stripes[i].physical =
|
||||
|
|
Loading…
Reference in a new issue