diff options
author | NeilBrown <neilb@suse.de> | 2012-04-18 14:19:49 +1000 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2012-04-18 14:19:49 +1000 |
commit | 0a999759b54f94fd63ac0ee298a549acef6f7d6f (patch) | |
tree | 546f209a9b8829e64d052d9b836644e79de26af4 | |
parent | c2ecf5f61aca2d73b7d5a6cb3a26973916d5c0d1 (diff) | |
download | mdadm-0a999759b54f94fd63ac0ee298a549acef6f7d6f.tar.gz |
Relax restrictions on when --add is permitted.
The restriction that --add was not allowed on a device which
looked like a recent member of an array was overly harsh.
The real requirement was to avoid using --add when the array had
failed, and the device being added might contain necessary
information which can only be incorporated by stopping and
re-assembling with --force.
So change the test to reflect the need.
Reported-by: Doug Ledford <dledford@redhat.com>
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | Manage.c | 35 |
1 files changed, 26 insertions, 9 deletions
@@ -448,7 +448,7 @@ int Manage_subdevs(char *devname, int fd, char *dnprintable = dv->devname; char *add_dev = dv->devname; int err; - int re_add_failed = 0; + int array_failed; next = dv->next; jnext = 0; @@ -851,9 +851,8 @@ int Manage_subdevs(char *devname, int fd, continue; goto abort; } - skip_re_add: - re_add_failed = 1; } + skip_re_add: st->ss->free_super(st); } if (add_dev != dv->devname) { @@ -875,12 +874,30 @@ int Manage_subdevs(char *devname, int fd, dv->devname, devname); goto abort; } - if (re_add_failed) { - fprintf(stderr, Name ": %s reports being an active member for %s, but a --re-add fails.\n", - dv->devname, devname); - fprintf(stderr, Name ": not performing --add as that would convert %s in to a spare.\n", - dv->devname); - fprintf(stderr, Name ": To make this a spare, use \"mdadm --zero-superblock %s\" first.\n", + if (array.active_disks < array.raid_disks) { + char *avail = calloc(array.raid_disks, 1); + int d; + int found = 0; + + for (d = 0; d < MAX_DISKS && found < array.active_disks; d++) { + disc.number = d; + if (ioctl(fd, GET_DISK_INFO, &disc)) + continue; + if (disc.major == 0 && disc.minor == 0) + continue; + if (!(disc.state & (1<<MD_DISK_SYNC))) + continue; + avail[disc.raid_disk] = 1; + found++; + } + array_failed = !enough(array.level, array.raid_disks, + array.layout, 1, avail); + } else + array_failed = 0; + if (array_failed) { + fprintf(stderr, Name ": %s has failed so using --add cannot work and might destroy\n", + devname); + fprintf(stderr, Name ": data on %s. You should stop the array and re-assemble it.\n", dv->devname); if (tfd >= 0) close(tfd); |