From a5c7adb310a233d6d69c95071862624ed104d203 Mon Sep 17 00:00:00 2001 From: "mwilck@arcor.de" Date: Fri, 1 Mar 2013 23:28:28 +0100 Subject: [PATCH] DDF: container_content_ddf: check for secondary RAID Check for supportable secondary RAID configurations. There is currently only one: RAID 10, if the stripe sizes and Basic volume sizes are all equal. With this patch, mdadm will not try to start unsupported secondary RAID level configurations any more. Signed-off-by: Martin Wilck Signed-off-by: NeilBrown --- super-ddf.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/super-ddf.c b/super-ddf.c index 89465582..adad75ff 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -3050,6 +3050,74 @@ static int load_container_ddf(struct supertype *st, int fd, #endif /* MDASSEMBLE */ +static int check_secondary(const struct vcl *vc) +{ + const struct vd_config *conf = &vc->conf; + int i; + + /* The only DDF secondary RAID level md can support is + * RAID 10, if the stripe sizes and Basic volume sizes + * are all equal. + * Other configurations could in theory be supported by exposing + * the BVDs to user space and using device mapper for the secondary + * mapping. So far we don't support that. + */ + + __u64 sec_elements[4] = {0, 0, 0, 0}; +#define __set_sec_seen(n) (sec_elements[(n)>>6] |= (1<<((n)&63))) +#define __was_sec_seen(n) ((sec_elements[(n)>>6] & (1<<((n)&63))) != 0) + + if (vc->other_bvds == NULL) { + pr_err("No BVDs for secondary RAID found\n"); + return -1; + } + if (conf->prl != DDF_RAID1) { + pr_err("Secondary RAID level only supported for mirrored BVD\n"); + return -1; + } + if (conf->srl != DDF_2STRIPED && conf->srl != DDF_2SPANNED) { + pr_err("Secondary RAID level %d is unsupported\n", + conf->srl); + return -1; + } + __set_sec_seen(conf->sec_elmnt_seq); + for (i = 0; i < conf->sec_elmnt_count-1; i++) { + const struct vd_config *bvd = vc->other_bvds[i]; + if (bvd == NULL) { + pr_err("BVD %d is missing", i+1); + return -1; + } + if (bvd->srl != conf->srl) { + pr_err("Inconsistent secondary RAID level across BVDs\n"); + return -1; + } + if (bvd->prl != conf->prl) { + pr_err("Different RAID levels for BVDs are unsupported\n"); + return -1; + } + if (bvd->prim_elmnt_count != conf->prim_elmnt_count) { + pr_err("All BVDs must have the same number of primary elements\n"); + return -1; + } + if (bvd->chunk_shift != conf->chunk_shift) { + pr_err("Different strip sizes for BVDs are unsupported\n"); + return -1; + } + if (bvd->array_blocks != conf->array_blocks) { + pr_err("Different BVD sizes are unsupported\n"); + return -1; + } + __set_sec_seen(bvd->sec_elmnt_seq); + } + for (i = 0; i < conf->sec_elmnt_count; i++) { + if (!__was_sec_seen(i)) { + pr_err("BVD %d is missing\n", i); + return -1; + } + } + return 0; +} + #define NO_SUCH_REFNUM (0xFFFFFFFF) static unsigned int get_pd_index_from_refnum(const struct vcl *vc, __u32 refnum, unsigned int nmax) @@ -3089,6 +3157,11 @@ static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray *ep != '\0')) continue; + if (vc->conf.sec_elmnt_count > 1) { + if (check_secondary(vc) != 0) + continue; + } + this = xcalloc(1, sizeof(*this)); this->next = rest; rest = this; -- 2.39.2