+ infos = malloc(sizeof(*infos) * total_slots);
+
+ for (pass=1; pass <=2 ; pass++) {
+ mddev_dev_t moved_disk = NULL; /* the disk that was moved out of the insert point */
+
+ for (dnum=0, dv = devlist ; dv ;
+ dv=(dv->next)?(dv->next):moved_disk, dnum++) {
+ int fd;
+ struct stat stb;
+ struct mdinfo *inf = &infos[dnum];
+
+ if (dnum >= total_slots)
+ abort();
+ if (dnum == insert_point) {
+ moved_disk = dv;
+ }
+ if (dnum == insert_point ||
+ strcasecmp(dv->devname, "missing")==0)
+ continue;
+
+ switch(pass) {
+ case 1:
+ *inf = info;
+
+ inf->disk.number = dnum;
+ inf->disk.raid_disk = dnum;
+ if (inf->disk.raid_disk < raiddisks)
+ inf->disk.state = (1<<MD_DISK_ACTIVE) |
+ (1<<MD_DISK_SYNC);
+ else
+ inf->disk.state = 0;
+
+ if (dv->writemostly)
+ inf->disk.state |= (1<<MD_DISK_WRITEMOSTLY);
+
+ if (st->ss->external && st->subarray[0])
+ fd = open(dv->devname, O_RDWR, 0);
+ else
+ fd = open(dv->devname, O_RDWR|O_EXCL,0);
+
+ if (fd < 0) {
+ fprintf(stderr, Name ": failed to open %s "
+ "after earlier success - aborting\n",
+ dv->devname);
+ return 1;
+ }
+ fstat(fd, &stb);
+ inf->disk.major = major(stb.st_rdev);
+ inf->disk.minor = minor(stb.st_rdev);
+
+ remove_partitions(fd);
+ st->ss->add_to_super(st, &inf->disk,
+ fd, dv->devname);
+ st->ss->getinfo_super(st, inf);
+
+ /* getinfo_super might have lost these ... */
+ inf->disk.major = major(stb.st_rdev);
+ inf->disk.minor = minor(stb.st_rdev);
+ break;
+ case 2:
+ inf->errors = 0;
+ rv = 0;
+
+ if (st->ss->external)
+ rv = sysfs_add_disk(sra, inf);
+ else
+ rv = ioctl(mdfd, ADD_NEW_DISK,
+ &inf->disk);
+
+ if (rv) {
+ fprintf(stderr,
+ Name ": ADD_NEW_DISK for %s "
+ "failed: %s\n",
+ dv->devname, strerror(errno));
+ st->ss->free_super(st);
+ return 1;
+ }
+ break;
+ }
+ if (dv == moved_disk && dnum != insert_point) break;
+ }
+ if (pass == 1) {
+ st->ss->write_init_super(st);
+ flush_metadata_updates(st);
+ }
+ }
+ free(infos);
+ st->ss->free_super(st);
+