+ /* If an array has active < raid && spare == 0 && spare_group != NULL
+ * Look for another array with spare > 0 and active == raid and same spare_group
+ * if found, choose a device and hotremove/hotadd
+ */
+ for (st = statelist; st; st=st->next)
+ if (st->active < st->raid &&
+ st->spare == 0 &&
+ st->spare_group != NULL) {
+ struct state *st2;
+ for (st2=statelist ; st2 ; st2=st2->next)
+ if (st2 != st &&
+ st2->spare > 0 &&
+ st2->active == st2->raid &&
+ st2->spare_group != NULL &&
+ strcmp(st->spare_group, st2->spare_group) == 0) {
+ /* try to remove and add */
+ int fd1 = open(st->devname, O_RDONLY);
+ int fd2 = open(st2->devname, O_RDONLY);
+ int dev = -1;
+ int d;
+ if (fd1 < 0 || fd2 < 0) {
+ if (fd1>=0) close(fd1);
+ if (fd2>=0) close(fd2);
+ continue;
+ }
+ for (d=st2->raid; d < MaxDisks; d++) {
+ if (st2->devid[d] > 0 &&
+ st2->devstate[d] == 0) {
+ dev = st2->devid[d];
+ break;
+ }
+ }
+ if (dev > 0) {
+ if (ioctl(fd2, HOT_REMOVE_DISK,
+ (unsigned long)dev) == 0) {
+ if (ioctl(fd1, HOT_ADD_DISK,
+ (unsigned long)dev) == 0) {
+ alert("MoveSpare", st->devname, st2->devname, mailaddr, mailfrom, alert_cmd, dosyslog);
+ close(fd1);
+ close(fd2);
+ break;
+ }
+ else ioctl(fd2, HOT_ADD_DISK, (unsigned long) dev);
+ }
+ }
+ close(fd1);
+ close(fd2);
+ }
+ }
+ if (!new_found) {
+ if (oneshot)
+ break;
+ else
+ mdstat_wait(period);
+ }
+ test = 0;