* 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;
unsigned long long ldsize;
char dvname[20];
char *dnprintable = dv->devname;
+ char *add_dev = dv->devname;
int err;
next = dv->next;
}
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' */
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;
}
* 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;
}
/* 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;
}
/* 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;
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);
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
.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
.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
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
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