]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Incremental.c
util: make env checking more generic
[thirdparty/mdadm.git] / Incremental.c
index d7eeafc17da594e4064949440217bfdf360fc3de..08960a5f5fde3664197b7b65d96603eace4a6f59 100644 (file)
@@ -85,12 +85,12 @@ int Incremental(char *devname, int verbose, int runstop,
        int dfd, mdfd;
        char *avail;
        int active_disks;
-
+       int uuid_for_name = 0;
+       char *name_to_use;
+       char nbuf[64];
 
        struct createinfo *ci = conf_get_create_info();
 
-       if (autof == 0)
-               autof = ci->autof;
 
        /* 1/ Check if device is permitted by mdadm.conf */
 
@@ -214,27 +214,47 @@ int Incremental(char *devname, int verbose, int runstop,
                match = array_list;
        }
 
-       /* 3a/ if not, check for homehost match.  If no match, reject. */
+       /* 3a/ if not, check for homehost match.  If no match, continue
+        * but don't trust the 'name' in the array. Thus a 'random' minor
+        * number will be assigned, and the device name will be based
+        * on that. */
        if (!match) {
                if (homehost == NULL ||
-                   st->ss->match_home(st, homehost) == 0) {
-                       if (verbose >= 0)
-                               fprintf(stderr, Name
-             ": not found in mdadm.conf and not identified by homehost.\n");
-                       return 2;
-               }
+                      st->ss->match_home(st, homehost) != 1)
+                       uuid_for_name = 1;
        }
        /* 4/ Determine device number. */
-       /* - If in mdadm.conf with std name, use that */
-       /* - UUID in /var/run/mdadm.map  use that */
+       /* - If in mdadm.conf with std name, get number from name. */
+       /* - UUID in /var/run/mdadm.map  get number from mapping */
        /* - If name is suggestive, use that. unless in use with */
        /*           different uuid. */
        /* - Choose a free, high number. */
        /* - Use a partitioned device unless strong suggestion not to. */
        /*         e.g. auto=md */
-       if (match && is_standard(match->devname, &devnum))
-               /* We have devnum now */;
-       else if ((mp = map_by_uuid(&map, info.uuid)) != NULL)
+       mp = map_by_uuid(&map, info.uuid);
+
+       if (uuid_for_name && ! mp) {
+               name_to_use = fname_from_uuid(st, &info, nbuf, '-');
+               if (verbose >= 0)
+                       fprintf(stderr, Name
+               ": not found in mdadm.conf and not identified by homehost"
+                               " - using uuid based name\n");
+       } else
+               name_to_use = info.name;
+
+       /* There are three possible sources for 'autof':  command line,
+        * ARRAY line in mdadm.conf, or CREATE line in mdadm.conf.
+        * ARRAY takes precedence, then command line, then
+        * CREATE.
+        */
+       if (match && match->autof)
+               autof = match->autof;
+       if (autof == 0)
+               autof = ci->autof;
+
+       if (match && (rv = is_standard(match->devname, &devnum))) {
+               devnum = (rv > 0) ? (-1-devnum) : devnum;
+       } else if (mp != NULL)
                devnum = mp->devnum;
        else {
                /* Have to guess a bit. */
@@ -247,11 +267,11 @@ int Incremental(char *devname, int verbose, int runstop,
                        use_partitions = 0;
                if (st->ss->external)
                        use_partitions = 0;
-               np = strchr(info.name, ':');
+               np = strchr(name_to_use, ':');
                if (np)
                        np++;
                else
-                       np = info.name;
+                       np = name_to_use;
                devnum = strtoul(np, &ep, 10);
                if (ep > np && *ep == 0) {
                        /* This is a number.  Let check that it is unused. */
@@ -290,9 +310,10 @@ int Incremental(char *devname, int verbose, int runstop,
                } else
                        devnum = use_partitions ? (-1-devnum) : devnum;
        }
-       mdfd = open_mddev_devnum(match ? match->devname : NULL,
+
+       mdfd = create_mddev_devnum(match ? match->devname : mp ? mp->path : NULL,
                                 devnum,
-                                info.name,
+                                name_to_use,
                                 chosen_name, autof >> 3);
        if (mdfd < 0) {
                fprintf(stderr, Name ": failed to open %s: %s.\n",
@@ -480,7 +501,8 @@ int Incremental(char *devname, int verbose, int runstop,
                        close(bmfd);
                }
                sra = sysfs_read(mdfd, devnum, 0);
-               if (sra == NULL || active_disks >= info.array.working_disks)
+               if ((sra == NULL || active_disks >= info.array.working_disks)
+                   && uuid_for_name == 0)
                        rv = ioctl(mdfd, RUN_ARRAY, NULL);
                else
                        rv = sysfs_set_str(sra, NULL,
@@ -577,12 +599,18 @@ static int count_active(struct supertype *st, int mdfd, char **availp,
                if (ok != 0)
                        continue;
                st->ss->getinfo_super(st, &info);
+               if (!avail) {
+                       avail = malloc(info.array.raid_disks);
+                       if (!avail) {
+                               fprintf(stderr, Name ": out of memory.\n");
+                               exit(1);
+                       }
+                       memset(avail, 0, info.array.raid_disks);
+                       *availp = avail;
+               }
+
                if (info.disk.state & (1<<MD_DISK_SYNC))
                {
-                       if (avail == NULL) {
-                               avail = malloc(info.array.raid_disks);
-                               memset(avail, 0, info.array.raid_disks);
-                       }
                        if (cnt == 0) {
                                cnt++;
                                max_events = info.events;
@@ -686,7 +714,7 @@ int IncrementalScan(int verbose)
                mdu_array_info_t array;
                mdu_bitmap_file_t bmf;
                struct mdinfo *sra;
-               int mdfd = open_mddev_devnum(me->path, me->devnum,
+               int mdfd = create_mddev_devnum(me->path, me->devnum,
                                             NULL, path, 0);
                if (mdfd < 0)
                        continue;
@@ -743,19 +771,6 @@ int IncrementalScan(int verbose)
        return rv;
 }
 
-static char *container2devname(char *devname)
-{
-       int fd = open(devname, O_RDONLY);
-       char *mdname = NULL;
-
-       if (fd >= 0) {
-               mdname = devnum2devname(fd2devnum(fd));
-               close(fd);
-       }
-
-       return mdname;
-}
-
 int Incremental_container(struct supertype *st, char *devname, int verbose,
                          int runstop, int autof)
 {
@@ -765,15 +780,9 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
 
        struct mdinfo *list = st->ss->container_content(st);
        struct mdinfo *ra;
-       char *mdname = container2devname(devname);
-
-       if (!mdname) {
-               fprintf(stderr, Name": failed to determine device name\n");
-               return 2;
-       }
 
        for (ra = list ; ra ; ra = ra->next) {
-               struct mdinfo *dev;
+               struct mdinfo *dev, *sra;
                int devnum = -1;
                int mdfd;
                char chosen_name[1024];
@@ -781,23 +790,81 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
                char *n;
                int working = 0, preexist = 0;
                struct map_ent *mp, *map = NULL;
+               char nbuf[64];
+               char *name_to_use;
+               struct mddev_ident_s *match = NULL;
 
                if ((autof&7) == 3 || (autof&7) == 5)
                        usepart = 0;
 
                mp = map_by_uuid(&map, ra->uuid);
-               if (mp)
+
+               name_to_use = ra->name;
+               if (! name_to_use ||
+                   ! *name_to_use ||
+                   (*devname != '/' || strncmp("UUID-", strrchr(devname,'/')+1,5) == 0)
+                       )
+                       name_to_use = fname_from_uuid(st, ra, nbuf, '-');
+                   
+               if (!mp) {
+
+                       /* Check in mdadm.conf for devices == devname and
+                        * member == ra->text_version after second slash.
+                        */
+                       char *sub = strchr(ra->text_version+1, '/');
+                       struct mddev_ident_s *array_list;
+                       if (sub) {
+                               sub++;
+                               array_list = conf_get_ident(NULL);
+                       } else
+                               array_list = NULL;
+                       for(; array_list ; array_list = array_list->next) {
+                               int fd;
+                               char *dn;
+                               if (array_list->member == NULL ||
+                                   array_list->container == NULL)
+                                       continue;
+                               if (strcmp(array_list->member, sub) != 0)
+                                       continue;
+                               if (array_list->uuid_set &&
+                                   !same_uuid(ra->uuid, array_list->uuid, st->ss->swapuuid))
+                                       continue;
+                               fd = open(array_list->container, O_RDONLY);
+                               if (fd < 0)
+                                       continue;
+                               dn = devnum2devname(fd2devnum(fd));
+                               close(fd);
+                               if (strncmp(dn, ra->text_version+1,
+                                           strlen(dn)) != 0 ||
+                                   ra->text_version[strlen(dn)+1] != '/') {
+                                       free(dn);
+                                       continue;
+                               }
+                               free(dn);
+                               /* we have a match */
+                               match = array_list;
+                               if (verbose>0)
+                                       fprintf(stderr, Name ": match found for member %s\n",
+                                               array_list->member);
+                               break;
+                       }
+               }
+
+               if (match && is_standard(match->devname, &devnum))
+                       /* we have devnum now */;
+               else if (mp)
                        devnum = mp->devnum;
+               else if (is_standard(name_to_use, &devnum))
+                       /* have devnum */;
                else {
-
-                       n = ra->name;
+                       n = name_to_use;
                        if (*n == 'd')
                                n++;
                        if (*n && devnum < 0) {
                                devnum = strtoul(n, &n, 10);
                                if (devnum >= 0 && (*n == 0 || *n == ' ')) {
                                        /* Use this devnum */
-                                       usepart = (ra->name[0] == 'd');
+                                       usepart = (name_to_use[0] == 'd');
                                        if (mddev_busy(usepart ? (-1-devnum) : devnum))
                                                devnum = -1;
                                } else
@@ -805,7 +872,7 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
                        }
 
                        if (devnum < 0) {
-                               char *nm = ra->name;
+                               char *nm = name_to_use;
                                char nbuf[1024];
                                struct stat stb;
                                if (strchr(nm, ':'))
@@ -831,7 +898,8 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
                        else
                                devnum = find_free_devnum(usepart);
                }
-               mdfd = open_mddev_devnum(mp ? mp->path : NULL, devnum, ra->name,
+               mdfd = create_mddev_devnum(mp ? mp->path : match ? match->devname : NULL,
+                                        devnum, name_to_use,
                                         chosen_name, autof>>3);
 
                if (mdfd < 0) {
@@ -840,8 +908,16 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
                        return 2;
                }
 
+
                sysfs_init(ra, mdfd, 0);
-               sysfs_set_array(ra, md_get_version(mdfd));
+
+               sra = sysfs_read(mdfd, 0, GET_VERSION);
+               if (sra == NULL || strcmp(sra->text_version, ra->text_version) != 0)
+                       if (sysfs_set_array(ra, md_get_version(mdfd)) != 0)
+                               return 1;
+               if (sra)
+                       sysfs_free(sra);
+
                for (dev = ra->devs; dev; dev = dev->next)
                        if (sysfs_add_disk(ra, dev) == 0)
                                working++;
@@ -870,7 +946,7 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
                        sysfs_set_safemode(ra, ra->safe_mode_delay);
                        if (verbose >= 0) {
                                fprintf(stderr, Name
-                                       "Started %s with %d devices",
+                                       "Started %s with %d devices",
                                        chosen_name, working + preexist);
                                if (preexist)
                                        fprintf(stderr, " (%d new)", working);
@@ -880,7 +956,7 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
                } else
                        if (verbose >= 0)
                                fprintf(stderr, Name
-                                       "%s assembled with %d devices but "
+                                       "%s assembled with %d devices but "
                                        "not started\n",
                                        chosen_name, working);
                close(mdfd);