]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-ddf.c
DDF: Don't fail compare_super_ddf due to re-configure changes.
[thirdparty/mdadm.git] / super-ddf.c
index 55fa03ee1117a1bae6b69591e37e2a39716f12e3..37ef665acd1dafd886b92f597d4d9c9085028cec 100644 (file)
@@ -2490,7 +2490,11 @@ static struct extent *get_extents(struct ddf_super *ddf, struct dl *dl)
        struct extent *rv;
        int n = 0;
        unsigned int i;
-       __u16 state = be16_to_cpu(ddf->phys->entries[dl->pdnum].state);
+       __u16 state;
+
+       if (dl->pdnum < 0)
+               return NULL;
+       state = be16_to_cpu(ddf->phys->entries[dl->pdnum].state);
 
        if ((state & (DDF_Online|DDF_Failed|DDF_Missing)) != DDF_Online)
                return NULL;
@@ -2923,7 +2927,7 @@ static int remove_from_super_ddf(struct supertype *st, mdu_disk_info_t *dk)
                if (dl->major == dk->major &&
                    dl->minor == dk->minor)
                        break;
-       if (!dl)
+       if (!dl || dl->pdnum < 0)
                return -1;
 
        if (st->update_tail) {
@@ -3018,7 +3022,7 @@ static int __write_ddf_structure(struct dl *d, struct ddf_super *ddf, __u8 type)
                                        (const struct vd_config **)&vdc,
                                        &dummy);
                }
-               if (c) {
+               if (vdc) {
                        dprintf("writing conf record %i on disk %08x for %s/%u\n",
                                i, be32_to_cpu(d->disk.refnum),
                                guid_str(vdc->guid),
@@ -3942,47 +3946,25 @@ static int compare_super_ddf(struct supertype *st, struct supertype *tst)
        if (memcmp(first->anchor.guid, second->anchor.guid, DDF_GUID_LEN) != 0)
                return 2;
 
-       if (first->max_part != second->max_part ||
-           !be16_eq(first->phys->used_pdes, second->phys->used_pdes) ||
-           !be16_eq(first->virt->populated_vdes,
-                    second->virt->populated_vdes)) {
-               dprintf("%s: PD/VD number mismatch\n", __func__);
-               return 3;
-       }
-
-       max_pds = be16_to_cpu(first->phys->used_pdes);
-       for (dl2 = second->dlist; dl2; dl2 = dl2->next) {
-               for (pd = 0; pd < max_pds; pd++)
-                       if (be32_eq(first->phys->entries[pd].refnum,
-                                   dl2->disk.refnum))
-                               break;
-               if (pd == max_pds) {
-                       dprintf("%s: no match for disk %08x\n", __func__,
-                               be32_to_cpu(dl2->disk.refnum));
-                       return 3;
-               }
-       }
+       /* It is only OK to compare info in the anchor.  Anything else
+        * could be changing due to a reconfig so must be ignored.
+        * guid really should be enough anyway.
+        */
 
-       max_vds = be16_to_cpu(first->active->max_vd_entries);
-       for (vl2 = second->conflist; vl2; vl2 = vl2->next) {
-               if (!be32_eq(vl2->conf.magic, DDF_VD_CONF_MAGIC))
-                       continue;
-               for (vd = 0; vd < max_vds; vd++)
-                       if (!memcmp(first->virt->entries[vd].guid,
-                                   vl2->conf.guid, DDF_GUID_LEN))
-                               break;
-               if (vd == max_vds) {
-                       dprintf("%s: no match for VD config\n", __func__);
-                       return 3;
-               }
+       if (!be32_eq(first->active->seq, second->active->seq)) {
+               dprintf("%s: sequence number mismatch %u<->%u\n", __func__,
+                       be32_to_cpu(first->active->seq),
+                       be32_to_cpu(second->active->seq));
+               return 0;
        }
-       /* FIXME should I look at anything else? */
 
        /*
         * At this point we are fairly sure that the meta data matches.
         * But the new disk may contain additional local data.
         * Add it to the super block.
         */
+       max_vds = be16_to_cpu(first->active->max_vd_entries);
+       max_pds = be16_to_cpu(first->phys->used_pdes);
        for (vl2 = second->conflist; vl2; vl2 = vl2->next) {
                for (vl1 = first->conflist; vl1; vl1 = vl1->next)
                        if (!memcmp(vl1->conf.guid, vl2->conf.guid,
@@ -4105,7 +4087,7 @@ static int ddf_open_new(struct supertype *c, struct active_array *a, char *inst)
                        if (dl->major == dev->disk.major &&
                            dl->minor == dev->disk.minor)
                                break;
-               if (!dl) {
+               if (!dl || dl->pdnum < 0) {
                        pr_err("%s: device %d/%d of subarray %d not found in meta data\n",
                                __func__, dev->disk.major, dev->disk.minor, n);
                        return -1;
@@ -4733,6 +4715,9 @@ static void ddf_process_update(struct supertype *st,
                for (dl = ddf->dlist; dl; dl = dl->next) {
                        unsigned int vn = 0;
                        int in_degraded = 0;
+
+                       if (dl->pdnum < 0)
+                               continue;
                        for (vcl = ddf->conflist; vcl ; vcl = vcl->next) {
                                unsigned int dn, ibvd;
                                const struct vd_config *conf;
@@ -4996,7 +4981,11 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
                        int is_dedicated = 0;
                        struct extent *ex;
                        unsigned int j;
-                       be16 state = ddf->phys->entries[dl->pdnum].state;
+                       be16 state;
+
+                       if (dl->pdnum < 0)
+                               continue;
+                       state = ddf->phys->entries[dl->pdnum].state;
                        if (be16_and(state,
                                     cpu_to_be16(DDF_Failed|DDF_Missing)) ||
                            !be16_and(state,
@@ -5087,7 +5076,6 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
                        di->recovery_start = 0;
                        di->data_offset = pos;
                        di->component_size = a->info.component_size;
-                       di->container_member = dl->pdnum;
                        di->next = rv;
                        rv = di;
                        dprintf("%x:%x (%08x) to be %d at %llu\n",
@@ -5145,7 +5133,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
                        if (dl->major == di->disk.major
                            && dl->minor == di->disk.minor)
                                break;
-               if (!dl) {
+               if (!dl || dl->pdnum < 0) {
                        pr_err("%s: BUG: can't find disk %d (%d/%d)\n",
                               __func__, di->disk.raid_disk,
                               di->disk.major, di->disk.minor);