summaryrefslogtreecommitdiffstats
path: root/Manage.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2010-11-22 19:35:25 +1100
committerNeilBrown <neilb@suse.de>2011-03-10 17:25:40 +1100
commitd6508f0cfb60edf07b36f1532eae4d9cddf7178b (patch)
treef0169e472ef9b1344bfcb9fe61f180e46d80a08b /Manage.c
parent37e430d163f71417f50371cb2871e4828490ed7a (diff)
downloadmdadm-d6508f0cfb60edf07b36f1532eae4d9cddf7178b.tar.gz
Manage: be more careful about --add attempts.
If an --add is requested and a re-add looks promising but fails or cannot possibly succeed, then don't try the add. This avoids inadvertently turning devices into spares when an array is failed but the devices seem to actually work. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'Manage.c')
-rw-r--r--Manage.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/Manage.c b/Manage.c
index 1b474798..7ed47310 100644
--- a/Manage.c
+++ b/Manage.c
@@ -383,6 +383,7 @@ int Manage_subdevs(char *devname, int fd,
char *dnprintable = dv->devname;
char *add_dev = dv->devname;
int err;
+ int re_add_failed = 0;
next = dv->next;
jnext = 0;
@@ -662,14 +663,20 @@ int Manage_subdevs(char *devname, int fd,
get_linux_version() <= 2006018)
;
else if (st->sb) {
+ struct mdinfo mdi;
+ st->ss->getinfo_super(st, &mdi);
st->ss->uuid_from_super(st, ouuid);
- if (memcmp(duuid, ouuid, sizeof(ouuid))==0) {
- /* looks close enough for now. Kernel
- * will worry about whether a bitmap
- * based reconstruction is possible.
+ if ((mdi.disk.state & (1<<MD_DISK_ACTIVE)) &&
+ !(mdi.disk.state & (1<<MD_DISK_FAULTY)) &&
+ memcmp(duuid, ouuid, sizeof(ouuid))==0) {
+ /* look like it is worth a try. Need to
+ * make sure kernel will accept it though.
*/
- struct mdinfo mdi;
- st->ss->getinfo_super(st, &mdi);
+ disc.number = mdi.disk.number;
+ if (ioctl(fd, GET_DISK_INFO, &disc) != 0
+ || disc.major != 0 || disc.minor != 0
+ || !enough_fd(fd))
+ goto skip_re_add;
disc.major = major(stb.st_rdev);
disc.minor = minor(stb.st_rdev);
disc.number = mdi.disk.number;
@@ -684,8 +691,7 @@ int Manage_subdevs(char *devname, int fd,
tfd = -1;
/* don't even try if disk is marked as faulty */
errno = 0;
- if ((disc.state & 1) == 0 &&
- ioctl(fd, ADD_NEW_DISK, &disc) == 0) {
+ if (ioctl(fd, ADD_NEW_DISK, &disc) == 0) {
if (verbose >= 0)
fprintf(stderr, Name ": re-added %s\n", add_dev);
count++;
@@ -698,7 +704,8 @@ int Manage_subdevs(char *devname, int fd,
continue;
return 1;
}
- /* fall back on normal-add */
+ skip_re_add:
+ re_add_failed = 1;
}
}
if (add_dev != dv->devname) {
@@ -720,6 +727,17 @@ int Manage_subdevs(char *devname, int fd,
dv->devname, devname);
return 1;
}
+ 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",
+ dv->devname);
+ if (tfd >= 0)
+ close(tfd);
+ return 1;
+ }
} else {
/* non-persistent. Must ensure that new drive
* is at least array.size big.