Support failing and removed of detached and faulty devices.

This if you unplug a device and udev removes the entry from /dev,
you can still remove the device.
This commit is contained in:
Neil Brown 2007-05-11 16:13:03 +10:00
parent 6f9a21a78f
commit b80da66161
3 changed files with 124 additions and 18 deletions

View File

@ -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.

108
Manage.c
View File

@ -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;
}
}

25
mdadm.8
View File

@ -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.