return __cpu_to_be32(newcrc);
}
+static int err_bad_ddf_layout(const struct vd_config *conf)
+{
+ pr_err("DDF RAID %u qualifier %u with %u disks is unsupported\n",
+ conf->prl, conf->rlq, __be16_to_cpu(conf->prim_elmnt_count));
+ return -1;
+}
+
+static int layout_ddf2md(const struct vd_config *conf,
+ mdu_array_info_t *array)
+{
+ int level = LEVEL_UNSUPPORTED;
+ int layout = 0;
+ int raiddisks = __be16_to_cpu(conf->prim_elmnt_count);
+
+ if (conf->sec_elmnt_count > 1) {
+ /* see also check_secondary() */
+ if (conf->prl != DDF_RAID1 ||
+ (conf->srl != DDF_2STRIPED && conf->srl != DDF_2SPANNED)) {
+ pr_err("Unsupported secondary RAID level %u/%u\n",
+ conf->prl, conf->srl);
+ return -1;
+ }
+ if (raiddisks == 2 && conf->rlq == DDF_RAID1_SIMPLE)
+ layout = 0x102;
+ else if (raiddisks == 3 && conf->rlq == DDF_RAID1_MULTI)
+ layout = 0x103;
+ else
+ return err_bad_ddf_layout(conf);
+ raiddisks *= conf->sec_elmnt_count;
+ level = 10;
+ goto good;
+ }
+
+ switch (conf->prl) {
+ case DDF_CONCAT:
+ level = LEVEL_LINEAR;
+ break;
+ case DDF_RAID0:
+ if (conf->rlq != DDF_RAID0_SIMPLE)
+ return err_bad_ddf_layout(conf);
+ level = 0;
+ break;
+ case DDF_RAID1:
+ if (!((conf->rlq == DDF_RAID1_SIMPLE && raiddisks == 2) ||
+ (conf->rlq == DDF_RAID1_MULTI && raiddisks == 3)))
+ return err_bad_ddf_layout(conf);
+ level = 1;
+ break;
+ case DDF_RAID4:
+ if (conf->rlq != DDF_RAID4_N)
+ return err_bad_ddf_layout(conf);
+ level = 4;
+ break;
+ case DDF_RAID5:
+ switch (conf->rlq) {
+ case DDF_RAID5_N_RESTART:
+ layout = ALGORITHM_LEFT_ASYMMETRIC;
+ break;
+ case DDF_RAID5_0_RESTART:
+ layout = ALGORITHM_RIGHT_ASYMMETRIC;
+ break;
+ case DDF_RAID5_N_CONTINUE:
+ layout = ALGORITHM_LEFT_SYMMETRIC;
+ break;
+ default:
+ return err_bad_ddf_layout(conf);
+ }
+ level = 5;
+ break;
+ case DDF_RAID6:
+ switch (conf->rlq) {
+ case DDF_RAID5_N_RESTART:
+ layout = ALGORITHM_ROTATING_N_RESTART;
+ break;
+ case DDF_RAID6_0_RESTART:
+ layout = ALGORITHM_ROTATING_ZERO_RESTART;
+ break;
+ case DDF_RAID5_N_CONTINUE:
+ layout = ALGORITHM_ROTATING_N_CONTINUE;
+ break;
+ default:
+ return err_bad_ddf_layout(conf);
+ }
+ level = 6;
+ break;
+ default:
+ return err_bad_ddf_layout(conf);
+ };
+
+good:
+ array->level = level;
+ array->layout = layout;
+ array->raid_disks = raiddisks;
+ return 0;
+}
+
static int load_ddf_header(int fd, unsigned long long lba,
unsigned long long size,
int type,
{ MAXINT, MAXINT }
};
-static int map_num1(struct num_mapping *map, int num)
-{
- int i;
- for (i=0 ; map[i].num1 != MAXINT; i++)
- if (map[i].num1 == num)
- break;
- return map[i].num2;
-}
-
static int all_ff(const char *guid)
{
int i;
}
}
-static int rlq_to_layout(int rlq, int prl, int raiddisks);
-
static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, char *map)
{
struct ddf_super *ddf = st->sb;
__u32 *cptr;
memset(info, 0, sizeof(*info));
- /* FIXME this returns BVD info - what if we want SVD ?? */
-
- info->array.raid_disks = __be16_to_cpu(vc->conf.prim_elmnt_count);
- info->array.level = map_num1(ddf_level_num, vc->conf.prl);
- info->array.layout = rlq_to_layout(vc->conf.rlq, vc->conf.prl,
- info->array.raid_disks);
+ if (layout_ddf2md(&vc->conf, &info->array) == -1)
+ return;
info->array.md_minor = -1;
cptr = (__u32 *)(vc->conf.guid + 16);
info->array.ctime = DECADE + __be32_to_cpu(*cptr);
return -1;
}
-static int rlq_to_layout(int rlq, int prl, int raiddisks)
-{
- switch(prl) {
- case DDF_RAID0:
- return 0; /* hopefully rlq == DDF_RAID0_SIMPLE */
- case DDF_RAID1:
- return 0; /* hopefully rlq == SIMPLE or MULTI depending
- on raiddisks*/
- case DDF_RAID4:
- switch(rlq) {
- case DDF_RAID4_N:
- return 0;
- default:
- /* not supported */
- return -1; /* FIXME this isn't checked */
- }
- case DDF_RAID5:
- switch(rlq) {
- case DDF_RAID5_N_RESTART:
- return ALGORITHM_LEFT_ASYMMETRIC;
- case DDF_RAID5_0_RESTART:
- return ALGORITHM_RIGHT_ASYMMETRIC;
- case DDF_RAID5_N_CONTINUE:
- return ALGORITHM_LEFT_SYMMETRIC;
- default:
- return -1;
- }
- case DDF_RAID6:
- switch(rlq) {
- case DDF_RAID5_N_RESTART:
- return ALGORITHM_ROTATING_N_RESTART;
- case DDF_RAID6_0_RESTART:
- return ALGORITHM_ROTATING_ZERO_RESTART;
- case DDF_RAID5_N_CONTINUE:
- return ALGORITHM_ROTATING_N_CONTINUE;
- default:
- return -1;
- }
- }
- return -1;
-}
-
#ifndef MDASSEMBLE
struct extent {
unsigned long long start, size;
this->next = rest;
rest = this;
- if (vc->conf.sec_elmnt_count == 1) {
- this->array.level = map_num1(ddf_level_num,
- vc->conf.prl);
- this->array.raid_disks =
- __be16_to_cpu(vc->conf.prim_elmnt_count);
- this->array.layout =
- rlq_to_layout(vc->conf.rlq, vc->conf.prl,
- this->array.raid_disks);
- } else {
- /* The only supported layout is RAID 10.
- * Compatibility has been checked in check_secondary()
- * above.
- */
- this->array.level = 10;
- this->array.raid_disks =
- __be16_to_cpu(vc->conf.prim_elmnt_count)
- * vc->conf.sec_elmnt_count;
- this->array.layout = 0x100 |
- __be16_to_cpu(vc->conf.prim_elmnt_count);
- }
+ if (layout_ddf2md(&vc->conf, &this->array))
+ continue;
this->array.md_minor = -1;
this->array.major_version = -1;
this->array.minor_version = -2;