From: NeilBrown Allow a whole 'side' of a RAID10 to be failed at once. This is useful if separate code detects that the path to one set of devices have disappeared. The naming of sides match the "set-A", "set-B" etc reported by "mdadm --detail". So mdadm /dev/md0 --fail set-A will remove half of the devices on a typical RAID10 Signed-off-by: NeilBrown --- Manage.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) --- mdadm-3.2.6.orig/Manage.c +++ mdadm-3.2.6/Manage.c @@ -550,6 +550,59 @@ int Manage_subdevs(char *devname, int fd next = dv; if (stat(add_dev, &stb) < 0) continue; + } else if (strncmp(dv->devname, "set-", 4) == 0) { + int copies, set; + char setname[10]; + int remaining_disks = array.nr_disks; + + if (dv->disposition != 'r' && + dv->disposition != 'f') { + fprintf(stderr, Name ": %s only meaningful " + "with -r or -f\n", dv->devname); + goto abort; + } + if (array.level != 10) { + fprintf(stderr, Name ": %s only meaningful " + "with RAID10 arrays\n", dv->devname); + goto abort; + } + copies = ((array.layout & 0xff) * + ((array.layout >> 8) & 0xff)); + if (array.raid_disks % copies != 0 || + copies > 26) { + fprintf(stderr, Name ": %s not meaningful " + "with this array\n", dv->devname); + goto abort; + } + for (;j < MAX_DISKS && remaining_disks > 0; j++) { + unsigned dev; + disc.number = j; + if (ioctl(fd, GET_DISK_INFO, &disc)) + continue; + if (disc.major == 0 && disc.minor == 0) + continue; + remaining_disks --; + if ((disc.state & 1) == 1) /* faulty */ + continue; + set = disc.raid_disk % copies; + sprintf(setname, "set-%c", set + 'A'); + if (strcmp(setname, dv->devname) != 0) + continue; + dev = makedev(disc.major, disc.minor); + if (stb.st_rdev == dev) + /* already did that one */ + continue; + stb.st_rdev = dev; + next = dv; + /* same slot again next time - things might + * have reshuffled */ + jnext = j; + sprintf(dvname,"%d:%d", disc.major, disc.minor); + dnprintable = dvname; + break; + } + if (next != dv) + continue; } else if (strchr(dv->devname, '/') == NULL && strchr(dv->devname, ':') == NULL && strlen(dv->devname) < 50) {