DDF: layout_md2ddf: new md->DDF layout conversion
Support for RAID 10 makes it necessary to rewrite the algorithm for deriving DDF layout from MD layout. The functions level_to_prl and layout_to_rlq are combined in a single function that takes md layout parameters and converts them to DDF. Signed-off-by: Martin Wilck <mwilck@arcor.de> Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
8a2848a700
commit
a3163bf069
199
super-ddf.c
199
super-ddf.c
|
@ -484,6 +484,110 @@ static unsigned int calc_crc(void *buf, int len)
|
||||||
return __cpu_to_be32(newcrc);
|
return __cpu_to_be32(newcrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DDF_INVALID_LEVEL 0xff
|
||||||
|
#define DDF_NO_SECONDARY 0xff
|
||||||
|
static int err_bad_md_layout(const mdu_array_info_t *array)
|
||||||
|
{
|
||||||
|
pr_err("RAID%d layout %x with %d disks is unsupported for DDF\n",
|
||||||
|
array->level, array->layout, array->raid_disks);
|
||||||
|
return DDF_INVALID_LEVEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int layout_md2ddf(const mdu_array_info_t *array,
|
||||||
|
struct vd_config *conf)
|
||||||
|
{
|
||||||
|
__u16 prim_elmnt_count = __cpu_to_be16(array->raid_disks);
|
||||||
|
__u8 prl = DDF_INVALID_LEVEL, rlq = 0;
|
||||||
|
__u8 sec_elmnt_count = 1;
|
||||||
|
__u8 srl = DDF_NO_SECONDARY;
|
||||||
|
|
||||||
|
switch (array->level) {
|
||||||
|
case LEVEL_LINEAR:
|
||||||
|
prl = DDF_CONCAT;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
rlq = DDF_RAID0_SIMPLE;
|
||||||
|
prl = DDF_RAID0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
switch (array->raid_disks) {
|
||||||
|
case 2:
|
||||||
|
rlq = DDF_RAID1_SIMPLE;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
rlq = DDF_RAID1_MULTI;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return err_bad_md_layout(array);
|
||||||
|
}
|
||||||
|
prl = DDF_RAID1;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (array->layout != 0)
|
||||||
|
return err_bad_md_layout(array);
|
||||||
|
rlq = DDF_RAID4_N;
|
||||||
|
prl = DDF_RAID4;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
switch (array->layout) {
|
||||||
|
case ALGORITHM_LEFT_ASYMMETRIC:
|
||||||
|
rlq = DDF_RAID5_N_RESTART;
|
||||||
|
break;
|
||||||
|
case ALGORITHM_RIGHT_ASYMMETRIC:
|
||||||
|
rlq = DDF_RAID5_0_RESTART;
|
||||||
|
break;
|
||||||
|
case ALGORITHM_LEFT_SYMMETRIC:
|
||||||
|
rlq = DDF_RAID5_N_CONTINUE;
|
||||||
|
break;
|
||||||
|
case ALGORITHM_RIGHT_SYMMETRIC:
|
||||||
|
/* not mentioned in standard */
|
||||||
|
default:
|
||||||
|
return err_bad_md_layout(array);
|
||||||
|
}
|
||||||
|
prl = DDF_RAID5;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
switch (array->layout) {
|
||||||
|
case ALGORITHM_ROTATING_N_RESTART:
|
||||||
|
rlq = DDF_RAID5_N_RESTART;
|
||||||
|
break;
|
||||||
|
case ALGORITHM_ROTATING_ZERO_RESTART:
|
||||||
|
rlq = DDF_RAID6_0_RESTART;
|
||||||
|
break;
|
||||||
|
case ALGORITHM_ROTATING_N_CONTINUE:
|
||||||
|
rlq = DDF_RAID5_N_CONTINUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return err_bad_md_layout(array);
|
||||||
|
}
|
||||||
|
prl = DDF_RAID6;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
if (array->raid_disks % 2 == 0 && array->layout == 0x102) {
|
||||||
|
rlq = DDF_RAID1_SIMPLE;
|
||||||
|
prim_elmnt_count = __cpu_to_be16(2);
|
||||||
|
sec_elmnt_count = array->raid_disks / 2;
|
||||||
|
} else if (array->raid_disks % 3 == 0
|
||||||
|
&& array->layout == 0x103) {
|
||||||
|
rlq = DDF_RAID1_MULTI;
|
||||||
|
prim_elmnt_count = __cpu_to_be16(3);
|
||||||
|
sec_elmnt_count = array->raid_disks / 3;
|
||||||
|
} else
|
||||||
|
return err_bad_md_layout(array);
|
||||||
|
srl = DDF_2SPANNED;
|
||||||
|
prl = DDF_RAID1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return err_bad_md_layout(array);
|
||||||
|
}
|
||||||
|
conf->prl = prl;
|
||||||
|
conf->prim_elmnt_count = prim_elmnt_count;
|
||||||
|
conf->rlq = rlq;
|
||||||
|
conf->srl = srl;
|
||||||
|
conf->sec_elmnt_count = sec_elmnt_count;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int err_bad_ddf_layout(const struct vd_config *conf)
|
static int err_bad_ddf_layout(const struct vd_config *conf)
|
||||||
{
|
{
|
||||||
pr_err("DDF RAID %u qualifier %u with %u disks is unsupported\n",
|
pr_err("DDF RAID %u qualifier %u with %u disks is unsupported\n",
|
||||||
|
@ -1128,24 +1232,6 @@ static mapping_t ddf_sec_level[] = {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct num_mapping {
|
|
||||||
int num1, num2;
|
|
||||||
};
|
|
||||||
static struct num_mapping ddf_level_num[] = {
|
|
||||||
{ DDF_RAID0, 0 },
|
|
||||||
{ DDF_RAID1, 1 },
|
|
||||||
{ DDF_RAID3, LEVEL_UNSUPPORTED },
|
|
||||||
{ DDF_RAID4, 4 },
|
|
||||||
{ DDF_RAID5, 5 },
|
|
||||||
{ DDF_RAID1E, LEVEL_UNSUPPORTED },
|
|
||||||
{ DDF_JBOD, LEVEL_UNSUPPORTED },
|
|
||||||
{ DDF_CONCAT, LEVEL_LINEAR },
|
|
||||||
{ DDF_RAID5E, LEVEL_UNSUPPORTED },
|
|
||||||
{ DDF_RAID5EE, LEVEL_UNSUPPORTED },
|
|
||||||
{ DDF_RAID6, 6},
|
|
||||||
{ MAXINT, MAXINT }
|
|
||||||
};
|
|
||||||
|
|
||||||
static int all_ff(const char *guid)
|
static int all_ff(const char *guid)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -2168,59 +2254,6 @@ static int chunk_to_shift(int chunksize)
|
||||||
return ffs(chunksize/512)-1;
|
return ffs(chunksize/512)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int level_to_prl(int level)
|
|
||||||
{
|
|
||||||
switch (level) {
|
|
||||||
case LEVEL_LINEAR: return DDF_CONCAT;
|
|
||||||
case 0: return DDF_RAID0;
|
|
||||||
case 1: return DDF_RAID1;
|
|
||||||
case 4: return DDF_RAID4;
|
|
||||||
case 5: return DDF_RAID5;
|
|
||||||
case 6: return DDF_RAID6;
|
|
||||||
default: return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int layout_to_rlq(int level, int layout, int raiddisks)
|
|
||||||
{
|
|
||||||
switch(level) {
|
|
||||||
case 0:
|
|
||||||
return DDF_RAID0_SIMPLE;
|
|
||||||
case 1:
|
|
||||||
switch(raiddisks) {
|
|
||||||
case 2: return DDF_RAID1_SIMPLE;
|
|
||||||
case 3: return DDF_RAID1_MULTI;
|
|
||||||
default: return -1;
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
switch(layout) {
|
|
||||||
case 0: return DDF_RAID4_N;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
switch(layout) {
|
|
||||||
case ALGORITHM_LEFT_ASYMMETRIC:
|
|
||||||
return DDF_RAID5_N_RESTART;
|
|
||||||
case ALGORITHM_RIGHT_ASYMMETRIC:
|
|
||||||
return DDF_RAID5_0_RESTART;
|
|
||||||
case ALGORITHM_LEFT_SYMMETRIC:
|
|
||||||
return DDF_RAID5_N_CONTINUE;
|
|
||||||
case ALGORITHM_RIGHT_SYMMETRIC:
|
|
||||||
return -1; /* not mentioned in standard */
|
|
||||||
}
|
|
||||||
case 6:
|
|
||||||
switch(layout) {
|
|
||||||
case ALGORITHM_ROTATING_N_RESTART:
|
|
||||||
return DDF_RAID5_N_RESTART;
|
|
||||||
case ALGORITHM_ROTATING_ZERO_RESTART:
|
|
||||||
return DDF_RAID6_0_RESTART;
|
|
||||||
case ALGORITHM_ROTATING_N_CONTINUE:
|
|
||||||
return DDF_RAID5_N_CONTINUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef MDASSEMBLE
|
#ifndef MDASSEMBLE
|
||||||
struct extent {
|
struct extent {
|
||||||
unsigned long long start, size;
|
unsigned long long start, size;
|
||||||
|
@ -2338,13 +2371,15 @@ static int init_super_ddf_bvd(struct supertype *st,
|
||||||
vc->timestamp = __cpu_to_be32(time(0)-DECADE);
|
vc->timestamp = __cpu_to_be32(time(0)-DECADE);
|
||||||
vc->seqnum = __cpu_to_be32(1);
|
vc->seqnum = __cpu_to_be32(1);
|
||||||
memset(vc->pad0, 0xff, 24);
|
memset(vc->pad0, 0xff, 24);
|
||||||
vc->prim_elmnt_count = __cpu_to_be16(info->raid_disks);
|
|
||||||
vc->chunk_shift = chunk_to_shift(info->chunk_size);
|
vc->chunk_shift = chunk_to_shift(info->chunk_size);
|
||||||
vc->prl = level_to_prl(info->level);
|
if (layout_md2ddf(info, vc) == -1 ||
|
||||||
vc->rlq = layout_to_rlq(info->level, info->layout, info->raid_disks);
|
__be16_to_cpu(vc->prim_elmnt_count) > ddf->mppe) {
|
||||||
vc->sec_elmnt_count = 1;
|
pr_err("%s: unsupported RAID level/layout %d/%d with %d disks\n",
|
||||||
|
__func__, info->level, info->layout, info->raid_disks);
|
||||||
|
free(vcl);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
vc->sec_elmnt_seq = 0;
|
vc->sec_elmnt_seq = 0;
|
||||||
vc->srl = 0;
|
|
||||||
vc->blocks = __cpu_to_be64(info->size * 2);
|
vc->blocks = __cpu_to_be64(info->size * 2);
|
||||||
vc->array_blocks = __cpu_to_be64(
|
vc->array_blocks = __cpu_to_be64(
|
||||||
calc_array_size(info->level, info->raid_disks, info->layout,
|
calc_array_size(info->level, info->raid_disks, info->layout,
|
||||||
|
@ -3008,12 +3043,12 @@ static int validate_geometry_ddf(struct supertype *st,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
/* Initial sanity check. Exclude illegal levels. */
|
mdu_array_info_t array = {
|
||||||
int i;
|
.level = level, .layout = layout,
|
||||||
for (i=0; ddf_level_num[i].num1 != MAXINT; i++)
|
.raid_disks = raiddisks
|
||||||
if (ddf_level_num[i].num2 == level)
|
};
|
||||||
break;
|
struct vd_config conf;
|
||||||
if (ddf_level_num[i].num1 == MAXINT) {
|
if (layout_md2ddf(&array, &conf) == -1) {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
pr_err("DDF does not support level %d arrays\n",
|
pr_err("DDF does not support level %d arrays\n",
|
||||||
level);
|
level);
|
||||||
|
|
Loading…
Reference in New Issue