summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--Manage.c108
-rw-r--r--mdadm.825
3 files changed, 124 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index 28b5512..caa2539 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Changes Prior to this release
+ - --fail detached and --remove faulty can be used to fail and
+ remove devices that are no longer physically present.
+ - --export option for --detail or present information in a format
+ that can be processed by udev.
+ - fix internal bitmap allocation problems with v1.1, v1.2 metadata.
+ - --help now goes to stdout so you can direct it to a pager.
+ - Various manpage updates.
+
Changes Prior to 2.6.1 release
- --monitor was producing some meaningless warnings due to a bug.
- Fix some compiler warnings.
diff --git a/Manage.c b/Manage.c
index 9193482..3deb8ea 100644
--- a/Manage.c
+++ b/Manage.c
@@ -180,13 +180,17 @@ int Manage_subdevs(char *devname, int fd,
* try HOT_ADD_DISK
* If that fails EINVAL, try ADD_NEW_DISK
* 'r' - remove the device HOT_REMOVE_DISK
+ * device can be 'faulty' or 'detached' in which case all
+ * matching devices are removed.
* 'f' - set the device faulty SET_DISK_FAULTY
+ * device can be 'detached' in which case any device that
+ * is inaccessible will be marked faulty.
*/
mdu_array_info_t array;
mdu_disk_info_t disc;
- mddev_dev_t dv;
+ mddev_dev_t dv, next = NULL;
struct stat stb;
- int j;
+ int j, jnext = 0;
int tfd;
struct supertype *st;
void *dsuper = NULL;
@@ -199,18 +203,86 @@ int Manage_subdevs(char *devname, int fd,
devname);
return 1;
}
- for (dv = devlist ; dv; dv=dv->next) {
+ for (dv = devlist, j=0 ; dv; dv = next, j = jnext) {
unsigned long long ldsize;
+ char dvname[20];
+ char *dnprintable = dv->devname;
- if (stat(dv->devname, &stb)) {
- fprintf(stderr, Name ": cannot find %s: %s\n",
- dv->devname, strerror(errno));
- return 1;
- }
- if ((stb.st_mode & S_IFMT) != S_IFBLK) {
- fprintf(stderr, Name ": %s is not a block device.\n",
- dv->devname);
- return 1;
+ next = dv->next;
+ jnext = 0;
+
+ if (strcmp(dv->devname, "failed")==0 ||
+ strcmp(dv->devname, "faulty")==0) {
+ if (dv->disposition != 'r') {
+ fprintf(stderr, Name ": %s only meaningful "
+ "with -r, not -%c\n",
+ dv->devname, dv->disposition);
+ return 1;
+ }
+ for (; j < array.raid_disks + array.nr_disks ; j++) {
+ disc.number = j;
+ if (ioctl(fd, GET_DISK_INFO, &disc))
+ continue;
+ if (disc.major == 0 && disc.minor == 0)
+ continue;
+ if ((disc.state & 1) == 0) /* faulty */
+ continue;
+ stb.st_rdev = makedev(disc.major, disc.minor);
+ next = dv;
+ jnext = j+1;
+ sprintf(dvname,"%d:%d", disc.major, disc.minor);
+ dnprintable = dvname;
+ break;
+ }
+ if (jnext == 0)
+ continue;
+ } else if (strcmp(dv->devname, "detached") == 0) {
+ if (dv->disposition != 'r' && dv->disposition != 'f') {
+ fprintf(stderr, Name ": %s only meaningful "
+ "with -r of -f, not -%c\n",
+ dv->devname, dv->disposition);
+ return 1;
+ }
+ for (; j < array.raid_disks + array.nr_disks; j++) {
+ int sfd;
+ disc.number = j;
+ if (ioctl(fd, GET_DISK_INFO, &disc))
+ continue;
+ if (disc.major == 0 && disc.minor == 0)
+ continue;
+ sprintf(dvname,"%d:%d", disc.major, disc.minor);
+ sfd = dev_open(dvname, O_RDONLY);
+ if (sfd >= 0) {
+ close(sfd);
+ continue;
+ }
+ if (dv->disposition == 'f' &&
+ (disc.state & 1) == 1) /* already faulty */
+ continue;
+ if (errno != ENXIO)
+ continue;
+ stb.st_rdev = makedev(disc.major, disc.minor);
+ next = dv;
+ jnext = j+1;
+ dnprintable = dvname;
+ break;
+ }
+ if (jnext == 0)
+ continue;
+ } else {
+ j = 0;
+
+ if (stat(dv->devname, &stb)) {
+ fprintf(stderr, Name ": cannot find %s: %s\n",
+ dv->devname, strerror(errno));
+ return 1;
+ }
+ if ((stb.st_mode & S_IFMT) != S_IFBLK) {
+ fprintf(stderr, Name ": %s is not a "
+ "block device.\n",
+ dv->devname);
+ return 1;
+ }
}
switch(dv->disposition){
default:
@@ -409,24 +481,26 @@ int Manage_subdevs(char *devname, int fd,
/* hot remove */
/* FIXME check that it is a current member */
if (ioctl(fd, HOT_REMOVE_DISK, (unsigned long)stb.st_rdev)) {
- fprintf(stderr, Name ": hot remove failed for %s: %s\n",
- dv->devname, strerror(errno));
+ fprintf(stderr, Name ": hot remove failed "
+ "for %s: %s\n", dnprintable,
+ strerror(errno));
return 1;
}
if (verbose >= 0)
- fprintf(stderr, Name ": hot removed %s\n", dv->devname);
+ fprintf(stderr, Name ": hot removed %s\n",
+ dnprintable);
break;
case 'f': /* set faulty */
/* FIXME check current member */
if (ioctl(fd, SET_DISK_FAULTY, (unsigned long) stb.st_rdev)) {
fprintf(stderr, Name ": set device faulty failed for %s: %s\n",
- dv->devname, strerror(errno));
+ dnprintable, strerror(errno));
return 1;
}
if (verbose >= 0)
fprintf(stderr, Name ": set %s faulty in %s\n",
- dv->devname, devname);
+ dnprintable, devname);
break;
}
}
diff --git a/mdadm.8 b/mdadm.8
index 321c1f4..16f71f2 100644
--- a/mdadm.8
+++ b/mdadm.8
@@ -859,11 +859,29 @@ re-add a device that was recently removed from an array.
.TP
.BR \-r ", " \-\-remove
remove listed devices. They must not be active. i.e. they should
-be failed or spare devices.
+be failed or spare devices. As well as the name of a device file
+(e.g.
+.BR /dev/sda1 )
+the words
+.B failed
+and
+.B detached
+can be given to
+.BR \-\-remove .
+The first causes all failed device to be removed. The second causes
+any device which is no longer connected to the system (i.e and open
+returns
+.BR ENXIO )
+to be removed. This will only succeed for devices that are spares or
+have already been marked as failed.
.TP
.BR \-f ", " \-\-fail
mark listed devices as faulty.
+As well as the name of a device file, the word
+.B detached
+can be given. This will cause any device that has been detached from
+the system to be marked as failed. It can then be removed.
.TP
.BR \-\-set\-faulty
@@ -1977,6 +1995,11 @@ appropriate.
Rebuild the array map from any current arrays, and then start any that
can be started.
+.B " mdadm /dev/md4 --fail detached --remove detached"
+.br
+Any devices which are components of /dev/md4 will be marked as faulty
+and then remove from the array.
+
.B " mdadm \-\-create \-\-help"
.br
Provide help about the Create mode.