summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2011-03-15 15:02:49 +1100
committerNeilBrown <neilb@suse.de>2011-03-15 15:02:49 +1100
commitc7079c84412848c11d21b99bd3702701fa5ca5d6 (patch)
tree59f85960659466f1497c70cb0b170514deda2c99
parent8401644c3a8b2a15bfed25cedc3c4ec0beff07c2 (diff)
downloadmdadm-c7079c84412848c11d21b99bd3702701fa5ca5d6.tar.gz
ddf: remove failed devices that are no longer in use.
The DDF spec requires we have a phys disk record for every physically attached device. But it isn't clear what that means in the case of soft raid in a general purpose Linux computer. So remove phys disk records for any failed device that is not active in any array. Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--super-ddf.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/super-ddf.c b/super-ddf.c
index 505a5b3..6f162b9 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -3337,6 +3337,7 @@ static void ddf_process_update(struct supertype *st,
struct dl *dl;
unsigned int mppe;
unsigned int ent;
+ unsigned int pdnum, pd2;
dprintf("Process update %x\n", *magic);
@@ -3428,6 +3429,14 @@ static void ddf_process_update(struct supertype *st,
}
ddf->conflist = vcl;
}
+ /* Set DDF_Transition on all Failed devices - to help
+ * us detect those that are no longer in use
+ */
+ for (pdnum = 0; pdnum < __be16_to_cpu(ddf->phys->used_pdes); pdnum++)
+ if (ddf->phys->entries[pdnum].state
+ & __be16_to_cpu(DDF_Failed))
+ ddf->phys->entries[pdnum].state
+ |= __be16_to_cpu(DDF_Transition);
/* Now make sure vlist is correct for each dl. */
for (dl = ddf->dlist; dl; dl = dl->next) {
unsigned int dn;
@@ -3440,6 +3449,12 @@ static void ddf_process_update(struct supertype *st,
int vstate;
dprintf("dev %d has %p at %d\n",
dl->pdnum, vcl, vn);
+ /* Clear the Transition flag */
+ if (ddf->phys->entries[dl->pdnum].state
+ & __be16_to_cpu(DDF_Failed))
+ ddf->phys->entries[dl->pdnum].state &=
+ ~__be16_to_cpu(DDF_Transition);
+
dl->vlist[vn++] = vcl;
vstate = ddf->virt->entries[vcl->vcnum].state
& DDF_state_mask;
@@ -3476,6 +3491,33 @@ static void ddf_process_update(struct supertype *st,
DDF_Active_in_VD);
}
}
+
+ /* Now remove any 'Failed' devices that are not part
+ * of any VD. They will have the Transition flag set.
+ * Once done, we need to update all dl->pdnum numbers.
+ */
+ pd2 = 0;
+ for (pdnum = 0; pdnum < __be16_to_cpu(ddf->phys->used_pdes); pdnum++)
+ if ((ddf->phys->entries[pdnum].state
+ & __be16_to_cpu(DDF_Failed))
+ && (ddf->phys->entries[pdnum].state
+ & __be16_to_cpu(DDF_Transition)))
+ /* skip this one */;
+ else if (pdnum == pd2)
+ pd2++;
+ else {
+ ddf->phys->entries[pd2] = ddf->phys->entries[pdnum];
+ for (dl = ddf->dlist; dl; dl = dl->next)
+ if (dl->pdnum == (int)pdnum)
+ dl->pdnum = pd2;
+ pd2++;
+ }
+ ddf->phys->used_pdes = __cpu_to_be16(pd2);
+ while (pd2 < pdnum) {
+ memset(ddf->phys->entries[pd2].guid, 0xff, DDF_GUID_LEN);
+ pd2++;
+ }
+
ddf->updates_pending = 1;
break;
case DDF_SPARE_ASSIGN_MAGIC: