summaryrefslogtreecommitdiff
path: root/Manage.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-11-28 10:19:52 +1100
committerNeilBrown <neilb@suse.de>2012-11-28 10:19:52 +1100
commit262e3b7fe88d5bb7a29ace6a077bd3a2505820f1 (patch)
treef24a5eab97c7d327b8075fb9cb21af2260a1b45c /Manage.c
parent5fe7f5f7c8c4c02e108d48aec5463329870ff71b (diff)
Manage: Add support for --re-add faulty
mdadm /dev/mdXX --re-add faulty will identify any faulty devices in the array, remove them, and --re-add them. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'Manage.c')
-rw-r--r--Manage.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/Manage.c b/Manage.c
index 3d713a32..4d9c0d2f 100644
--- a/Manage.c
+++ b/Manage.c
@@ -1084,6 +1084,8 @@ int Manage_subdevs(char *devname, int fd,
* it must be unpaired, and is an error.
* 'M' - this is created by a 'missing' target. It is a slight
* variant on 'A'
+ * 'F' - Another variant of 'A', where the device was faulty
+ * so must be removed from the array first.
*
* For 'f' and 'r', the device can also be a kernel-internal
* name such as 'sdb'.
@@ -1128,13 +1130,15 @@ int Manage_subdevs(char *devname, int fd,
if (strcmp(dv->devname, "failed") == 0 ||
strcmp(dv->devname, "faulty") == 0) {
- if (dv->disposition != 'r') {
+ if (dv->disposition != 'A'
+ && dv->disposition != 'r') {
pr_err("%s only meaningful "
- "with -r, not -%c\n",
+ "with -r or --re-add, not -%c\n",
dv->devname, dv->disposition);
goto abort;
}
- add_faulty(dv, fd, 'r');
+ add_faulty(dv, fd, (dv->disposition == 'A'
+ ? 'F' : 'r'));
continue;
}
if (strcmp(dv->devname, "detached") == 0) {
@@ -1245,7 +1249,8 @@ int Manage_subdevs(char *devname, int fd,
goto abort;
case 'a':
case 'A':
- case 'M':
+ case 'M': /* --re-add missing */
+ case 'F': /* --re-add faulty */
/* add the device */
if (subarray) {
pr_err("Cannot add disks to a"
@@ -1253,6 +1258,10 @@ int Manage_subdevs(char *devname, int fd,
" operation on the parent container\n");
goto abort;
}
+ if (dv->disposition == 'F')
+ /* Need to remove first */
+ ioctl(fd, HOT_REMOVE_DISK,
+ (unsigned long)stb.st_rdev);
/* Make sure it isn't in use (in 2.6 or later) */
tfd = dev_open(dv->devname, O_RDONLY|O_EXCL);
if (tfd >= 0) {