pr_err("started %s\n", devname);
} else if (runstop < 0){
struct map_ent *map = NULL;
- struct stat stb;
struct mdinfo *mdi;
char devnm[32];
+ char container[32];
int err;
int count;
/* If this is an mdmon managed array, just write 'inactive'
/* Get EXCL access first. If this fails, then attempting
* to stop is probably a bad idea.
*/
+ mdi = sysfs_read(fd, NULL, GET_LEVEL|GET_VERSION);
+ if (mdi && is_subarray(mdi->text_version)) {
+ char *sl;
+ strncpy(container, mdi->text_version+1, sizeof(container));
+ container[sizeof(container)-1] = 0;
+ sl = strchr(container, '/');
+ if (sl)
+ *sl = 0;
+ } else
+ container[0] = 0;
close(fd);
- if (devnm[0] == '/')
- fd = open(devname, O_RDONLY|O_EXCL);
- else
- fd = open_dev_flags(devnm, O_RDONLY|O_EXCL);
+ count = 5;
+ while (((fd = ((devnm[0] == '/')
+ ?open(devname, O_RDONLY|O_EXCL)
+ :open_dev_flags(devnm, O_RDONLY|O_EXCL))) < 0
+ || strcmp(fd2devnm(fd), devnm) != 0)
+ && container[0]
+ && mdmon_running(container)
+ && count) {
+ if (fd >= 0)
+ close(fd);
+ flush_mdmon(container);
+ count--;
+ }
if (fd < 0 || strcmp(fd2devnm(fd), devnm) != 0) {
if (fd >= 0)
close(fd);
devname);
return 1;
}
- mdi = sysfs_read(fd, NULL, GET_LEVEL|GET_VERSION);
if (mdi &&
mdi->array.level > 0 &&
is_subarray(mdi->text_version)) {
if (mdi)
sysfs_uevent(mdi, "change");
- if (devnm[0] &&
- (stat("/dev/.udev", &stb) != 0 ||
- check_env("MDADM_NO_UDEV"))) {
+ if (devnm[0] && use_udev()) {
struct map_ent *mp = map_by_devnm(&map, devnm);
remove_devices(devnm, mp ? mp->path : NULL);
}
}
}
+static void add_set(struct mddev_dev *dv, int fd, char set_char)
+{
+ mdu_array_info_t array;
+ mdu_disk_info_t disk;
+ int remaining_disks;
+ int copies, set;
+ int i;
+
+ if (ioctl(fd, GET_ARRAY_INFO, &array) != 0)
+ return;
+ if (array.level != 10)
+ return;
+ copies = ((array.layout & 0xff) *
+ ((array.layout >> 8) & 0xff));
+ if (array.raid_disks % copies)
+ return;
+
+ remaining_disks = array.nr_disks;
+ for (i = 0; i < MAX_DISKS && remaining_disks > 0; i++) {
+ char buf[40];
+ disk.number = i;
+ if (ioctl(fd, GET_DISK_INFO, &disk) != 0)
+ continue;
+ if (disk.major == 0 && disk.minor == 0)
+ continue;
+ remaining_disks--;
+ set = disk.raid_disk % copies;
+ if (set_char != set + 'A')
+ continue;
+ sprintf(buf, "%d:%d", disk.major, disk.minor);
+ dv = add_one(dv, buf, dv->disposition);
+ }
+}
+
int attempt_re_add(int fd, int tfd, struct mddev_dev *dv,
struct supertype *dev_st, struct supertype *tst,
unsigned long rdev,
continue;
}
+ if (strncmp(dv->devname, "set-", 4) == 0 &&
+ strlen(dv->devname) == 5) {
+ int copies;
+
+ if (dv->disposition != 'r' &&
+ dv->disposition != 'f') {
+ pr_err("'%s' only meaningful with -r or -f\n",
+ dv->devname);
+ goto abort;
+ }
+ if (array.level != 10) {
+ pr_err("'%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 ||
+ dv->devname[4] < 'A' ||
+ dv->devname[4] >= 'A' + copies ||
+ copies > 26) {
+ pr_err("'%s' not meaningful with this array\n",
+ dv->devname);
+ goto abort;
+ }
+ add_set(dv, fd, dv->devname[4]);
+ continue;
+ }
+
if (strchr(dv->devname, '/') == NULL &&
strchr(dv->devname, ':') == NULL &&
strlen(dv->devname) < 50) {