]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Initial implementation of auto-assembly
authorNeil Brown <neilb@suse.de>
Fri, 26 May 2006 00:50:15 +0000 (00:50 +0000)
committerNeil Brown <neilb@suse.de>
Fri, 26 May 2006 00:50:15 +0000 (00:50 +0000)
This basically works, but needs various improvements and some tests.

Signed-off-by: Neil Brown <neilb@suse.de>
Assemble.c
config.c
mdadm.c

index 46ec9bc0bb96e6d24e4d3811d16c3f8db34d95a9..6d89a242b379df468fca8765421ede03218e249c 100644 (file)
@@ -180,11 +180,15 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
        }
        if (devlist == NULL)
                devlist = conf_get_devs(conffile);
-       else inargv = 1;
+       else if (mdfd >= 0)
+               inargv = 1;
 
        tmpdev = devlist; num_devs = 0;
        while (tmpdev) {
-               num_devs++;
+               if (tmpdev->used)
+                       tmpdev->used = 2;
+               else
+                       num_devs++;
                tmpdev = tmpdev->next;
        }
        devices = malloc(num_devs * sizeof(*devices));
@@ -207,6 +211,8 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                struct stat stb;
                struct supertype *tst = st;
 
+               if (tmpdev->used > 1) continue;
+
                if (ident->devices &&
                    !match_oneof(ident->devices, devname)) {
                        if ((inargv && verbose>=0) || verbose > 0)
@@ -224,16 +230,21 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                        if ((inargv && verbose >= 0) || verbose > 0)
                                fprintf(stderr, Name ": cannot open device %s: %s\n",
                                        devname, strerror(errno));
+                       tmpdev->used = 2;
                } else if (fstat(dfd, &stb)< 0) {
                        /* Impossible! */
                        fprintf(stderr, Name ": fstat failed for %s: %s\n",
                                devname, strerror(errno));
+                       tmpdev->used = 2;
                } else if ((stb.st_mode & S_IFMT) != S_IFBLK) {
                        fprintf(stderr, Name ": %s is not a block device.\n",
                                devname);
+                       tmpdev->used = 2;
                } else if (!tst && (tst = guess_super(dfd)) == NULL) {
                        if ((inargv && verbose >= 0) || verbose > 0)
-                               fprintf(stderr, Name ": no recogniseable superblock\n");
+                               fprintf(stderr, Name ": no recogniseable superblock on %s\n",
+                                       devname);
+                       tmpdev->used = 2;
                } else if (tst->ss->load_super(tst,dfd, &super, NULL)) {
                        if ((inargv && verbose >= 0) || verbose > 0)
                                fprintf( stderr, Name ": no RAID superblock on %s\n",
@@ -278,7 +289,17 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                                        devname);
                        continue;
                }
-
+               if (mdfd < 0) {
+                       if (tst == NULL || super == NULL)
+                               continue;
+                       if (tst->ss->match_home(super, homehost)==0) {
+                               if ((inargv && verbose >= 0) || verbose > 0)
+                                       fprintf(stderr, Name ": %s is not built for host %s.\n",
+                                               devname, homehost);
+                               /* Auto-assemble, and this is not a usable host */
+                               continue;
+                       }
+               }
                /* If we are this far, then we are nearly commited to this device.
                 * If the super_block doesn't exist, or doesn't match others,
                 * then we probably cannot continue
@@ -299,8 +320,12 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                    st->minor_version != tst->minor_version ||
                    st->ss->compare_super(&first_super, super) != 0) {
                        /* Some mismatch. If exactly one array matches this host,
-                        * we can resolve on that one
+                        * we can resolve on that one.
+                        * Or, if we are auto assembling, we just ignore the second
+                        * for now.
                         */
+                       if (mdfd < 0)
+                               continue;
                        if (homehost) {
                                int first = st->ss->match_home(first_super, homehost);
                                int last = tst->ss->match_home(super, homehost);
@@ -339,14 +364,29 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                 * We create a name '/dev/md/XXX' based on the info in the
                 * superblock, and call open_mddev on that
                 */
-               asprintf(&mddev, "/dev/md/%s", info.name);
-               mdfd = open_mddev(mddev, 0);
+               mdu_array_info_t inf;
+               char *c;
+               if (!first_super) {
+                       return 1;
+               }
+               st->ss->getinfo_super(&info, first_super);
+               c = strchr(info.name, ':');
+               if (c) c++; else c= info.name;
+               asprintf(&mddev, "/dev/md/%s", c);
+               mdfd = open_mddev(mddev, ident->autof);
                if (mdfd < 0)
                        return mdfd;
+               vers = md_get_version(mdfd);
+               if (ioctl(mdfd, GET_ARRAY_INFO, &inf)==0) {
+                       fprintf(stderr, Name ": %s already active, cannot restart it!\n", mddev);
+                       close(mdfd);
+                       free(first_super);
+                       return 1;
+               }
        }
 
        /* Ok, no bad inconsistancy, we can try updating etc */
-       for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used) {
+       for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) {
                char *devname = tmpdev->devname;
                struct stat stb;
                /* looks like a good enough match to update the super block if needed */
@@ -401,6 +441,18 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                        if (strcmp(update, "uuid")==0 &&
                            ident->bitmap_fd)
                                bitmap_update_uuid(ident->bitmap_fd, info.uuid);
+               } else {
+                       int dfd;
+                       dfd = dev_open(devname, O_RDWR|O_EXCL);
+
+                       if (super) {
+                               free(super);
+                               super = NULL;
+                       }
+
+                       st->ss->load_super(st, dfd, &super, NULL);
+                       st->ss->getinfo_super(&info, super);
+                       close(dfd);
                }
 
                stat(devname, &stb);
index 8382cdfe44174c6ea81b42bd49ff62e7c01bae27..d753f54114e16b3bbee931854380d3700678f633 100644 (file)
--- a/config.c
+++ b/config.c
@@ -246,6 +246,7 @@ mddev_dev_t load_partitions(void)
                d = malloc(sizeof(*d));
                d->devname = strdup(name);
                d->next = rv;
+               d->used = 0;
                rv = d;
        }
        fclose(f);
@@ -716,6 +717,7 @@ mddev_dev_t conf_get_devs(char *conffile)
                        mddev_dev_t t = malloc(sizeof(*t));
                        t->devname = strdup(globbuf.gl_pathv[i]);
                        t->next = dlist;
+                       t->used = 0;
                        dlist = t;
 /*     printf("one dev is %s\n", t->devname);*/
                }
diff --git a/mdadm.c b/mdadm.c
index 0df73691fb8b0117fd925023bda393e5b59a45e3..6c30058baad6051b78b8497af0e70f9ccbda0a94 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -237,6 +237,7 @@ int main(int argc, char *argv[])
                                        dv->disposition = devmode;
                                        dv->writemostly = writemostly;
                                        dv->re_add = re_add;
+                                       dv->used = 0;
                                        dv->next = NULL;
                                        *devlistend = dv;
                                        devlistend = &dv->next;
@@ -981,36 +982,63 @@ int main(int argc, char *argv[])
                        }
                } else {
                        mddev_ident_t array_list =  conf_get_ident(configfile, NULL);
-                       if (!array_list) {
-                               fprintf(stderr, Name ": No arrays found in config file\n");
-                               rv = 1;
-                       } else
-                               if (update) {
-                                       fprintf(stderr, Name ": --update not meaningful with a --scan assembly.\n");
-                                       exit(1);
+                       mddev_dev_t devlist = conf_get_devs(configfile);
+                       int cnt = 0;
+                       if (devlist == NULL) {
+                               fprintf(stderr, Name ": No devices listed in conf file were found.\n");
+                               exit(1);
+                       }
+                       if (update) {
+                               fprintf(stderr, Name ": --update not meaningful with a --scan assembly.\n");
+                               exit(1);
+                       }
+                       if (backup_file) {
+                               fprintf(stderr, Name ": --backup_file not meaningful with a --scan assembly.\n");
+                               exit(1);
+                       }
+                       for (; array_list; array_list = array_list->next) {
+                               mdu_array_info_t array;
+                               mdfd = open_mddev(array_list->devname,
+                                                 array_list->autof ? array_list->autof : autof);
+                               if (mdfd < 0) {
+                                       rv |= 1;
+                                       continue;
                                }
-                               if (backup_file) {
-                                       fprintf(stderr, Name ": --backup_file not meaningful with a --scan assembly.\n");
-                                       exit(1);
+                               if (ioctl(mdfd, GET_ARRAY_INFO, &array)>=0)
+                                       /* already assembled, skip */
+                                       ;
+                               else {
+                                       rv |= Assemble(ss, array_list->devname, mdfd,
+                                                      array_list, configfile,
+                                                      devlist, NULL,
+                                                      readonly, runstop, NULL, homehost, verbose-quiet, force);
+                                       if (rv == 0) cnt++;
                                }
-                               for (; array_list; array_list = array_list->next) {
-                                       mdu_array_info_t array;
-                                       mdfd = open_mddev(array_list->devname, 
-                                                         array_list->autof ? array_list->autof : autof);
-                                       if (mdfd < 0) {
-                                               rv |= 1;
-                                               continue;
-                                       }
-                                       if (ioctl(mdfd, GET_ARRAY_INFO, &array)>=0)
-                                               /* already assembled, skip */
-                                               ;
-                                       else
-                                               rv |= Assemble(ss, array_list->devname, mdfd,
-                                                              array_list, configfile,
-                                                              NULL, NULL,
-                                                              readonly, runstop, NULL, homehost, verbose-quiet, force);
-                                       close(mdfd);
+                               close(mdfd);
+                       }
+                       if (homehost) {
+                               /* Maybe we can auto-assemble something.
+                                * Repeatedly call Assemble in auto-assmble mode
+                                * until it fails
+                                */
+                               int rv2;
+                               do {
+                                       ident.autof = autof;
+                                       rv2 = Assemble(ss, NULL, -1,
+                                                      &ident, configfile,
+                                                      devlist, NULL,
+                                                      readonly, runstop, NULL, homehost, verbose-quiet, force);
+                                       if (rv2==0)
+                                               cnt++;
+                               } while (rv2==0);
+                               if (cnt == 0 && rv == 0) {
+                                       fprintf(stderr, Name ": No arrays found in config file or automatically\n");
+                                       rv = 1;
                                }
+                       } else if (cnt == 0 && rv == 0) {
+                               fprintf(stderr, Name ": No arrays found in config file\n");
+                               rv = 1;
+                       }
                }
                break;
        case BUILD: