diff options
author | NeilBrown <neilb@suse.de> | 2011-03-15 15:35:04 +1100 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-03-15 15:35:04 +1100 |
commit | 88b496c2697ed531ffecf2f8ced76f437297e5fe (patch) | |
tree | 59eaa8dc9f7fd06f8bf54191c0c790e332c02768 /super-ddf.c | |
parent | e26c926209d84683815275bf8a3850b00731937e (diff) | |
parent | 666bba9b5011150ff01de421dd44b06c0a6610a5 (diff) | |
download | mdadm-88b496c2697ed531ffecf2f8ced76f437297e5fe.tar.gz |
Merge branch 'master' into devel-3.2
Conflicts:
Manage.c
managemon.c
super-ddf.c
super-intel.c
Diffstat (limited to 'super-ddf.c')
-rw-r--r-- | super-ddf.c | 73 |
1 files changed, 66 insertions, 7 deletions
diff --git a/super-ddf.c b/super-ddf.c index bdce4a7..72b87ff 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -3211,7 +3211,8 @@ static void ddf_set_disk(struct active_array *a, int n, int state) /* and find the 'dl' entry corresponding to that. */ for (dl = ddf->dlist; dl; dl = dl->next) - if (mdi->disk.major == dl->major && + if (mdi->state_fd >= 0 && + mdi->disk.major == dl->major && mdi->disk.minor == dl->minor) break; if (!dl) @@ -3273,6 +3274,8 @@ static void ddf_set_disk(struct active_array *a, int n, int state) case DDF_RAID1: if (working == 0) state = DDF_state_failed; + else if (working == 2 && state == DDF_state_degraded) + state = DDF_state_part_optimal; break; case DDF_RAID4: case DDF_RAID5: @@ -3356,6 +3359,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); @@ -3466,17 +3470,38 @@ 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; unsigned int vn = 0; + int in_degraded = 0; for (vcl = ddf->conflist; vcl ; vcl = vcl->next) for (dn=0; dn < ddf->mppe ; dn++) if (vcl->conf.phys_refnum[dn] == dl->disk.refnum) { + 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; + if (vstate == DDF_state_degraded || + vstate == DDF_state_part_optimal) + in_degraded = 1; break; } while (vn < ddf->max_part) @@ -3484,8 +3509,14 @@ static void ddf_process_update(struct supertype *st, if (dl->vlist[0]) { ddf->phys->entries[dl->pdnum].type &= ~__cpu_to_be16(DDF_Global_Spare); - ddf->phys->entries[dl->pdnum].type |= - __cpu_to_be16(DDF_Active_in_VD); + if (!(ddf->phys->entries[dl->pdnum].type & + __cpu_to_be16(DDF_Active_in_VD))) { + ddf->phys->entries[dl->pdnum].type |= + __cpu_to_be16(DDF_Active_in_VD); + if (in_degraded) + ddf->phys->entries[dl->pdnum].state |= + __cpu_to_be16(DDF_Rebuilding); + } } if (dl->spare) { ddf->phys->entries[dl->pdnum].type &= @@ -3501,6 +3532,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: @@ -3657,13 +3715,14 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, esize = ex[j].start - pos; if (esize >= a->info.component_size) break; - pos = ex[i].start + ex[i].size; - i++; - } while (ex[i-1].size); + pos = ex[j].start + ex[j].size; + j++; + } while (ex[j-1].size); free(ex); if (esize < a->info.component_size) { - dprintf("%x:%x has no room: %llu %llu\n", dl->major, dl->minor, + dprintf("%x:%x has no room: %llu %llu\n", + dl->major, dl->minor, esize, a->info.component_size); /* No room */ continue; |