summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2014-04-02 15:26:35 +1100
committerNeilBrown <neilb@suse.de>2014-04-02 15:26:35 +1100
commitf43f5b32991c7f5a188940b00989c27f87feee81 (patch)
treef0a4809492263b4f655f06220f3e66495bb7cc2b
parent188d31ed2b6dc195a4be1f5620ce2e5185d4e789 (diff)
DDF: Don't fail compare_super_ddf due to re-configure changes.
It is possible that one device has seem some reconfig but the other hasn't. In that case they are still the "same" DDF, even though one might be older. Such age will be detected by 'seq' differences. If A is new and B is old, then it is import that mdadm -I B mdadm -I A doesn't get confused because A has the same uuid as B, but compare_super fails. So: if the seq numbers are different, then just accept as two different superblocks. If they are the same, then look to copy data from new to old. Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--super-ddf.c44
1 files changed, 11 insertions, 33 deletions
diff --git a/super-ddf.c b/super-ddf.c
index 8530e98c..37ef665a 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -3946,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,