diff --git a/Assemble.c b/Assemble.c index 6ca54f9..23e3583 100644 --- a/Assemble.c +++ b/Assemble.c @@ -656,7 +656,9 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, continue; } info.events = devices[most_recent].events; - st->ss->update_super(&info, super, "force", devices[chosen_drive].devname, verbose, 0, NULL); + st->ss->update_super(&info, super, "force-one", + devices[chosen_drive].devname, verbose, + 0, NULL); if (st->ss->store_super(st, fd, super)) { close(fd); @@ -752,10 +754,10 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, } #endif } - if (force && okcnt == info.array.raid_disks-1) { - /* FIXME check event count */ - change += st->ss->update_super(&info, super, "force", - devices[chosen_drive].devname, verbose, 0, NULL); + if (force && okcnt < info.array.raid_disks) { + change += st->ss->update_super(&info, super, "force-array", + devices[chosen_drive].devname, verbose, + 0, NULL); } if (change) { diff --git a/ChangeLog b/ChangeLog index 81d51d3..6ea0c3b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,10 @@ Changes Prior to this release - Fixed UUID printing in "--detail --brief" for version1 metadata. - --update=resync did exactly the wrong thing for version1 metadata. It caused a resync to not happen, rather than to happen. + - Allow --assemble --force to mark a raid6 clean when it has two + missing devices (which is needed else if won't assemble. + Without this fix it would only assemble if one or zero + missing devices. Changes Prior to 2.5.6 release - Fix bug which meant "bitmap=xxx" in mdadm.conf was not handled diff --git a/super0.c b/super0.c index 9e83193..2060e93 100644 --- a/super0.c +++ b/super0.c @@ -411,13 +411,21 @@ static int update_super0(struct mdinfo *info, void *sbv, char *update, } else if (i >= sb->raid_disks && sb->disks[i].number == 0) sb->disks[i].state = 0; } - if (strcmp(update, "force")==0) { + if (strcmp(update, "force-one")==0) { + /* Not enough devices for a working array, so + * bring this one up-to-date. + */ __u32 ehi = sb->events_hi, elo = sb->events_lo; sb->events_hi = (info->events>>32) & 0xFFFFFFFF; sb->events_lo = (info->events) & 0xFFFFFFFF; if (sb->events_hi != ehi || sb->events_lo != elo) rv = 1; + } + if (strcmp(update, "force-array")==0) { + /* degraded array and 'force' requested, so + * maybe need to mark it 'clean' + */ if ((sb->level == 5 || sb->level == 4 || sb->level == 6) && (sb->state & (1 << MD_SB_CLEAN)) == 0) { /* need to force clean */ diff --git a/super1.c b/super1.c index c8d63cf..bf26cfa 100644 --- a/super1.c +++ b/super1.c @@ -485,10 +485,18 @@ static int update_super1(struct mdinfo *info, void *sbv, char *update, int rv = 0; struct mdp_superblock_1 *sb = sbv; - if (strcmp(update, "force")==0) { + if (strcmp(update, "force-one")==0) { + /* Not enough devices for a working array, + * so bring this one up-to-date + */ if (sb->events != __cpu_to_le64(info->events)) rv = 1; sb->events = __cpu_to_le64(info->events); + } + if (strcmp(update, "force-array")==0) { + /* Degraded array and 'force' requests to + * maybe need to mark it 'clean'. + */ switch(__le32_to_cpu(sb->level)) { case 5: case 4: case 6: /* need to force clean */ diff --git a/tests/06update-uuid b/tests/06update-uuid new file mode 100644 index 0000000..e69de29