diff options
author | NeilBrown <neilb@suse.de> | 2010-07-05 15:06:27 +1000 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2010-07-06 12:06:11 +1000 |
commit | a4e13010df574a1ce597efe9cb15ed6d6003b8bb (patch) | |
tree | 154ff9e2a4a201ef07e53f09a92ee2f25dfa4266 | |
parent | 3a6ec29ad5695e23723fe18cb0ce3c49cd675fa2 (diff) | |
download | mdadm-a4e13010df574a1ce597efe9cb15ed6d6003b8bb.tar.gz mdadm-a4e13010df574a1ce597efe9cb15ed6d6003b8bb.tar.xz mdadm-a4e13010df574a1ce597efe9cb15ed6d6003b8bb.zip |
Add support for "--re-add missing"
If the device name "missing" is given for --re-add, then mdadm will
attempt to find any device which should be a member of the array but
currently isn't and will --re-add it to the array.
This can be useful if a device disappeared due to a cabling problem,
and was then re-connected.
The appropriate sequence would be
mdadm /dev/mdX --fail detached
mdadm /dev/mdX --remove detached
mdadm /dev/mdX --re-add missing
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | Manage.c | 75 | ||||
-rw-r--r-- | mdadm.8.in | 26 |
2 files changed, 81 insertions, 20 deletions
@@ -342,6 +342,7 @@ int Manage_subdevs(char *devname, int fd, * For 'f' and 'r', the device can also be a kernel-internal * name such as 'sdb'. */ + mddev_dev_t add_devlist = NULL; mdu_array_info_t array; mdu_disk_info_t disc; unsigned long long array_size; @@ -381,6 +382,7 @@ int Manage_subdevs(char *devname, int fd, unsigned long long ldsize; char dvname[20]; char *dnprintable = dv->devname; + char *add_dev = dv->devname; int err; next = dv->next; @@ -458,6 +460,24 @@ int Manage_subdevs(char *devname, int fd, } if (jnext == 0) continue; + } else if (strcmp(dv->devname, "missing") == 0) { + if (dv->disposition != 'a' || dv->re_add == 0) { + fprintf(stderr, Name ": 'missing' only meaningful " + "with --re-add\n"); + return 1; + } + if (add_devlist == NULL) + add_devlist = conf_get_devs(); + if (add_devlist == NULL) { + fprintf(stderr, Name ": no devices to scan for missing members."); + continue; + } + add_dev = add_devlist->devname; + add_devlist = add_devlist->next; + if (add_devlist != NULL) + next = dv; + if (stat(add_dev, &stb) < 0) + continue; } else if (strchr(dv->devname, '/') == NULL && strlen(dv->devname) < 50) { /* Assume this is a kernel-internal name like 'sda1' */ @@ -533,39 +553,44 @@ int Manage_subdevs(char *devname, int fd, return 1; } /* Make sure it isn't in use (in 2.6 or later) */ - tfd = dev_open(dv->devname, O_RDONLY|O_EXCL|O_DIRECT); + tfd = dev_open(add_dev, O_RDONLY|O_EXCL|O_DIRECT); + if (tfd < 0 && add_dev != dv->devname) + continue; if (tfd < 0) { fprintf(stderr, Name ": Cannot open %s: %s\n", dv->devname, strerror(errno)); return 1; } - remove_partitions(tfd); st = dup_super(tst); if (array.not_persistent==0) st->ss->load_super(st, tfd, NULL); - if (!get_dev_size(tfd, dv->devname, &ldsize)) { + if (add_dev == dv->devname) { + if (!get_dev_size(tfd, dv->devname, &ldsize)) { + close(tfd); + return 1; + } + } else if (!get_dev_size(tfd, NULL, &ldsize)) { close(tfd); - return 1; + continue; } - close(tfd); - if (!tst->ss->external && array.major_version == 0 && md_get_version(fd)%100 < 2) { + close(tfd); if (ioctl(fd, HOT_ADD_DISK, (unsigned long)stb.st_rdev)==0) { if (verbose >= 0) fprintf(stderr, Name ": hot added %s\n", - dv->devname); + add_dev); continue; } fprintf(stderr, Name ": hot add failed for %s: %s\n", - dv->devname, strerror(errno)); + add_dev, strerror(errno)); return 1; } @@ -576,7 +601,9 @@ int Manage_subdevs(char *devname, int fd, * For 'external' array (well, container based), * We can just load the metadata for the array. */ - if (tst->ss->external) { + if (tst->sb) + /* already loaded */; + else if (tst->ss->external) { tst->ss->load_super(tst, fd, NULL); } else for (j = 0; j < tst->max_devs; j++) { char *dev; @@ -602,6 +629,7 @@ int Manage_subdevs(char *devname, int fd, } /* FIXME this is a bad test to be using */ if (!tst->sb) { + close(tfd); fprintf(stderr, Name ": cannot find valid superblock in this array - HELP\n"); return 1; } @@ -609,6 +637,9 @@ int Manage_subdevs(char *devname, int fd, /* Make sure device is large enough */ if (tst->ss->avail_size(tst, ldsize/512) < array_size) { + close(tfd); + if (add_dev != dv->devname) + continue; fprintf(stderr, Name ": %s not large enough to join array\n", dv->devname); return 1; @@ -644,23 +675,40 @@ int Manage_subdevs(char *devname, int fd, disc.state |= 1 << MD_DISK_WRITEMOSTLY; if (dv->writemostly == 2) disc.state &= ~(1 << MD_DISK_WRITEMOSTLY); + remove_partitions(tfd); + close(tfd); + 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 (verbose >= 0) - fprintf(stderr, Name ": re-added %s\n", dv->devname); + fprintf(stderr, Name ": re-added %s\n", add_dev); continue; } if (errno == ENOMEM || errno == EROFS) { + close(tfd); fprintf(stderr, Name ": add new device failed for %s: %s\n", - dv->devname, strerror(errno)); + add_dev, strerror(errno)); + if (add_dev != dv->devname) + continue; return 1; } /* fall back on normal-add */ } } + if (add_dev != dv->devname) { + if (verbose > 0) + fprintf(stderr, Name + ": --re-add for %s to %s is not possible\n", + add_dev, devname); + if (tfd >= 0) + close(tfd); + continue; + } if (dv->re_add) { + if (tfd >= 0) + close(tfd); fprintf(stderr, Name ": --re-add for %s to %s is not possible\n", dv->devname, devname); @@ -676,6 +724,11 @@ int Manage_subdevs(char *devname, int fd, return 1; } } + /* committed to really trying this device now*/ + if (tfd >= 0) { + remove_partitions(tfd); + close(tfd); + } /* in 2.6.17 and earlier, version-1 superblocks won't * use the number we write, but will choose a free number. * we must choose the same free number, which requires @@ -1018,16 +1018,24 @@ immediately start recovering data on to one of these spares. .TP .BR \-\-re\-add -re-add a device that was recently removed from an array. This is only -needed for arrays that have be built (i.e. with +re\-add a device that was recently removed from an array. This is +normally only needed for arrays that have be built (i.e. with .BR --build ). -For created arrays, devices are always re-added if that is possible. -When re-adding a device, if nothing has changed on the array since the +For created arrays, devices are always re\-added if that is possible, +however using \-\-re\-add will ensure the device isn't made into a +spare if the \-\-re\-add failed. + +When re\-adding a device, if nothing has changed on the array since the device was removed, no recovery is performed. Also, if the array has -a write-intent bitmap, then the recovery performed after a re-add will +a write-intent bitmap, then the recovery performed after a re\-add will be limited to those blocks which, according to the bitmap, might have changed since the device was removed. +If the device name given is +.B missing +then mdadm will try to find any device that looks like it should be +part of the array but isn't and will try to re\-add all such devices. + .TP .BR \-r ", " \-\-remove remove listed devices. They must not be active. i.e. they should @@ -1062,12 +1070,12 @@ same as .TP .BR \-\-write\-mostly -Subsequent devices that are added or re-added will have the 'write-mostly' +Subsequent devices that are added or re\-added will have the 'write-mostly' flag set. This is only valid for RAID1 and means that the 'md' driver will avoid reading from these devices if possible. .TP .BR \-\-readwrite -Subsequent devices that are added or re-added will have the 'write-mostly' +Subsequent devices that are added or re\-added will have the 'write-mostly' flag cleared. .P @@ -1082,7 +1090,7 @@ Each operation applies to all devices listed until the next operation. If an array is using a write-intent bitmap, then devices which have -been removed can be re-added in a way that avoids a full +been removed can be re\-added in a way that avoids a full reconstruction but instead just updates the blocks that have changed since the device was removed. For arrays with persistent metadata (superblocks) this is done automatically. For arrays created with @@ -1691,7 +1699,7 @@ command. When a device is added to an active array, mdadm checks to see if it has metadata on it which suggests that it was recently a member of the -array. If it does, it tried to "re-add" the device. If there have +array. If it does, it tries to "re\-add" the device. If there have been no changes since the device was removed, or if the array has a write-intent bitmap which has recorded whatever changes there were, then the device will immediately become a full member of the array and |