]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Manage.c
Allow domain_test to report that no domains were found.
[thirdparty/mdadm.git] / Manage.c
index a203ec9b90062f7ca78b847cd4cfffb10ea684a8..481c16541bc381a04318ae87813d8108093deb58 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -325,7 +325,8 @@ int Manage_resize(char *devname, int fd, long long size, int raid_disks)
 }
 
 int Manage_subdevs(char *devname, int fd,
-                  struct mddev_dev *devlist, int verbose, int test)
+                  struct mddev_dev *devlist, int verbose, int test,
+                  char *update)
 {
        /* do something to each dev.
         * devmode can be
@@ -691,6 +692,24 @@ int Manage_subdevs(char *devname, int fd,
                                                remove_partitions(tfd);
                                                close(tfd);
                                                tfd = -1;
+                                               if (update) {
+                                                       int rv = -1;
+                                                       tfd = dev_open(dv->devname, O_RDWR);
+
+                                                       if (tfd >= 0)
+                                                               rv = st->ss->update_super(
+                                                                       st, NULL, update,
+                                                                       devname, verbose, 0, NULL);
+                                                       if (rv == 0)
+                                                               rv = tst->ss->store_super(st, tfd);
+                                                       close(tfd);
+                                                       tfd = -1;
+                                                       if (rv != 0) {
+                                                               fprintf(stderr, Name ": failed to update"
+                                                                       " superblock during re-add\n");
+                                                               return 1;
+                                                       }
+                                               }
                                                /* don't even try if disk is marked as faulty */
                                                errno = 0;
                                                if (ioctl(fd, ADD_NEW_DISK, &disc) == 0) {
@@ -709,6 +728,7 @@ int Manage_subdevs(char *devname, int fd,
                                        skip_re_add:
                                                re_add_failed = 1;
                                        }
+                                       st->ss->free_super(st);
                                }
                                if (add_dev != dv->devname) {
                                        if (verbose > 0)
@@ -781,17 +801,18 @@ int Manage_subdevs(char *devname, int fd,
                                if (dv->writemostly == 1)
                                        disc.state |= 1 << MD_DISK_WRITEMOSTLY;
                                dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
+                               if (tst->ss->external &&
+                                   mdmon_running(tst->container_dev))
+                                       tst->update_tail = &tst->updates;
                                if (tst->ss->add_to_super(tst, &disc, dfd,
                                                          dv->devname)) {
                                        close(dfd);
                                        return 1;
                                }
-                               /* write_init_super will close 'dfd' */
-                               if (tst->ss->external)
-                                       /* mdmon will write the metadata */
+                               if (tst->ss->write_init_super(tst)) {
                                        close(dfd);
-                               else if (tst->ss->write_init_super(tst))
                                        return 1;
+                               }
                        } else if (dv->re_add) {
                                /*  this had better be raid1.
                                 * As we are "--re-add"ing we must find a spare slot
@@ -825,9 +846,8 @@ int Manage_subdevs(char *devname, int fd,
                        if (dv->writemostly == 1)
                                disc.state |= (1 << MD_DISK_WRITEMOSTLY);
                        if (tst->ss->external) {
-                               /* add a disk to an external metadata container
-                                * only if mdmon is around to see it
-                                */
+                               /* add a disk
+                                * to an external metadata container */
                                struct mdinfo new_mdi;
                                struct mdinfo *sra;
                                int container_fd;
@@ -838,13 +858,7 @@ int Manage_subdevs(char *devname, int fd,
                                        fprintf(stderr, Name ": add failed for %s:"
                                                " could not get exclusive access to container\n",
                                                dv->devname);
-                                       return 1;
-                               }
-
-                               if (!mdmon_running(devnum)) {
-                                       fprintf(stderr, Name ": add failed for %s: mdmon not running\n",
-                                               dv->devname);
-                                       close(container_fd);
+                                       tst->ss->free_super(tst);
                                        return 1;
                                }
 
@@ -853,6 +867,7 @@ int Manage_subdevs(char *devname, int fd,
                                        fprintf(stderr, Name ": add failed for %s: sysfs_read failed\n",
                                                dv->devname);
                                        close(container_fd);
+                                       tst->ss->free_super(tst);
                                        return 1;
                                }
                                sra->array.level = LEVEL_CONTAINER;
@@ -861,19 +876,26 @@ int Manage_subdevs(char *devname, int fd,
                                new_mdi.disk.major = disc.major;
                                new_mdi.disk.minor = disc.minor;
                                new_mdi.recovery_start = 0;
+                               /* Make sure fds are closed as they are O_EXCL which
+                                * would block add_disk */
+                               tst->ss->free_super(tst);
                                if (sysfs_add_disk(sra, &new_mdi, 0) != 0) {
                                        fprintf(stderr, Name ": add new device to external metadata"
                                                " failed for %s\n", dv->devname);
                                        close(container_fd);
+                                       sysfs_free(sra);
                                        return 1;
                                }
                                ping_monitor(devnum2devname(devnum));
                                sysfs_free(sra);
                                close(container_fd);
-                       } else if (ioctl(fd, ADD_NEW_DISK, &disc)) {
-                               fprintf(stderr, Name ": add new device failed for %s as %d: %s\n",
-                                       dv->devname, j, strerror(errno));
-                               return 1;
+                       } else {
+                               tst->ss->free_super(tst);
+                               if (ioctl(fd, ADD_NEW_DISK, &disc)) {
+                                       fprintf(stderr, Name ": add new device failed for %s as %d: %s\n",
+                                               dv->devname, j, strerror(errno));
+                                       return 1;
+                               }
                        }
                        if (verbose >= 0)
                                fprintf(stderr, Name ": added %s\n", dv->devname);
@@ -1077,4 +1099,48 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident
 
        return rv;
 }
+
+/* Move spare from one array to another
+ * If adding to destination array fails
+ * add back to original array
+ * Returns 1 on success, 0 on failure */
+int move_spare(char *from_devname, char *to_devname, dev_t devid)
+{
+       struct mddev_dev devlist;
+       char devname[20];
+
+       /* try to remove and add */
+       int fd1 = open(to_devname, O_RDONLY);
+       int fd2 = open(from_devname, O_RDONLY);
+
+       if (fd1 < 0 || fd2 < 0) {
+               if (fd1>=0) close(fd1);
+               if (fd2>=0) close(fd2);
+               return 0;
+       }
+
+       devlist.next = NULL;
+       devlist.used = 0;
+       devlist.re_add = 0;
+       devlist.writemostly = 0;
+       devlist.devname = devname;
+       sprintf(devname, "%d:%d", major(devid), minor(devid));
+
+       devlist.disposition = 'r';
+       if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL) == 0) {
+               devlist.disposition = 'a';
+               if (Manage_subdevs(to_devname, fd1, &devlist, -1, 0, NULL) == 0) {
+                       /* make sure manager is aware of changes */
+                       ping_manager(to_devname);
+                       ping_manager(from_devname);
+                       close(fd1);
+                       close(fd2);
+                       return 1;
+               }
+               else Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL);
+       }
+       close(fd1);
+       close(fd2);
+       return 0;
+}
 #endif