From c7079c84412848c11d21b99bd3702701fa5ca5d6 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 15 Mar 2011 15:02:49 +1100 Subject: 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 --- super-ddf.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) 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: -- cgit v1.2.1