]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - config.c
Detail: export MD_UUID from mapfile
[thirdparty/mdadm.git] / config.c
index 0d5b3f9aac7a929e523224ef241ebdbf858cde67..c962afdaaed829d0122550166ce0f072d9ccea97 100644 (file)
--- a/config.c
+++ b/config.c
@@ -1,7 +1,7 @@
 /*
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  *    Author: Neil Brown
- *    Email: <neilb@cse.unsw.edu.au>
- *    Paper: Neil Brown
- *           School of Computer Science and Engineering
- *           The University of New South Wales
- *           Sydney, 2052
- *           Australia
+ *    Email: <neilb@suse.de>
  */
 
 #include       "mdadm.h"
@@ -448,6 +443,17 @@ void devline(char *line)
 mddev_ident_t mddevlist = NULL;
 mddev_ident_t *mddevlp = &mddevlist;
 
+static int is_number(char *w)
+{
+       /* check if there are 1 or more digits and nothing else */
+       int digits = 0;
+       while (*w && isdigit(*w)) {
+               digits++;
+               w++;
+       }
+       return (digits && ! *w);
+}
+
 void arrayline(char *line)
 {
        char *w;
@@ -473,11 +479,35 @@ void arrayline(char *line)
        mis.member = NULL;
 
        for (w=dl_next(line); w!=line; w=dl_next(w)) {
-               if (w[0] == '/' || strcasecmp(w, "<ignore>") == 0) {
-                       if (mis.devname)
-                               fprintf(stderr, Name ": only give one device per ARRAY line: %s and %s\n",
-                                       mis.devname, w);
-                       else mis.devname = w;
+               if (w[0] == '/' || strchr(w, '=') == NULL) {
+                       /* This names the device, or is '<ignore>'.
+                        * The rules match those in create_mddev.
+                        * 'w' must be:
+                        *  /dev/md/{anything}
+                        *  /dev/mdNN
+                        *  /dev/md_dNN
+                        *  <ignore>
+                        *  or anything that doesn't start '/' or '<'
+                        */
+                       if (strcasecmp(w, "<ignore>") == 0 ||
+                           strncmp(w, "/dev/md/", 8) == 0 ||
+                           (w[0] != '/' && w[0] != '<') ||
+                           (strncmp(w, "/dev/md", 7) == 0 && 
+                            is_number(w+7)) ||
+                           (strncmp(w, "/dev/md_d", 9) == 0 &&
+                            is_number(w+9))
+                               ) {
+                               /* This is acceptable */;
+                               if (mis.devname)
+                                       fprintf(stderr, Name ": only give one "
+                                               "device per ARRAY line: %s and %s\n",
+                                               mis.devname, w);
+                               else
+                                       mis.devname = w;
+                       }else {
+                               fprintf(stderr, Name ": %s is an invalid name for "
+                                       "an md device - ignored.\n", w);
+                       }
                } else if (strncasecmp(w, "uuid=", 5)==0 ) {
                        if (mis.uuid_set)
                                fprintf(stderr, Name ": only specify uuid once, %s ignored.\n",
@@ -567,7 +597,7 @@ void arrayline(char *line)
        }
        if (mis.uuid_set == 0 && mis.devices == NULL &&
            mis.super_minor == UnSet && mis.name[0] == 0 &&
-           (mis.container == NULL && mis.member == NULL))
+           (mis.container == NULL || mis.member == NULL))
                fprintf(stderr, Name ": ARRAY line %s has no identity information.\n", mis.devname);
        else {
                mi = malloc(sizeof(*mi));
@@ -628,12 +658,15 @@ void programline(char *line)
 }
 
 static char *home_host = NULL;
+static int require_homehost = 1;
 void homehostline(char *line)
 {
        char *w;
 
        for (w=dl_next(line); w != line ; w=dl_next(w)) {
-               if (home_host == NULL)
+               if (strcasecmp(w, "<ignore>")==0)
+                       require_homehost = 0;
+               else if (home_host == NULL)
                        home_host = strdup(w);
                else
                        fprintf(stderr, Name ": excess host name on HOMEHOST line: %s - ignored\n",
@@ -753,9 +786,11 @@ char *conf_get_program(void)
        return alert_program;
 }
 
-char *conf_get_homehost(void)
+char *conf_get_homehost(int *require_homehostp)
 {
        load_conffile();
+       if (require_homehostp)
+               *require_homehostp = require_homehost;
        return home_host;
 }
 
@@ -771,7 +806,7 @@ mddev_ident_t conf_get_ident(char *dev)
        load_conffile();
        rv = mddevlist;
        while (dev && rv && (rv->devname == NULL
-                            || strcmp(dev, rv->devname)!=0))
+                            || !devname_matches(dev, rv->devname)))
                rv = rv->next;
        return rv;
 }
@@ -918,3 +953,128 @@ int match_oneof(char *devices, char *devname)
     }
     return 0;
 }
+
+int devname_matches(char *name, char *match)
+{
+       /* See if the given array name matches the
+        * given match from config file.
+        *
+        * First strip and /dev/md/ or /dev/, then
+        * see if there might be a numeric match of
+        *  mdNN with NN
+        * then just strcmp
+        */
+       if (strncmp(name, "/dev/md/", 8) == 0)
+               name += 8;
+       else if (strncmp(name, "/dev/", 5) == 0)
+               name += 5;
+
+       if (strncmp(match, "/dev/md/", 8) == 0)
+               match += 8;
+       else if (strncmp(match, "/dev/", 5) == 0)
+               match += 5;
+
+
+       if (strncmp(name, "md", 2) == 0 &&
+           isdigit(name[2]))
+               name += 2;
+       if (strncmp(match, "md", 2) == 0 &&
+           isdigit(match[2]))
+               match += 2;
+
+       return (strcmp(name, match) == 0);
+}
+
+int conf_name_is_free(char *name)
+{
+       /* Check if this name is already take by an ARRAY entry in
+        * the config file.
+        * It can be taken either by a match on devname, name, or
+        * even super-minor.
+        */
+       mddev_ident_t dev;
+
+       load_conffile();
+       for (dev = mddevlist; dev; dev = dev->next) {
+               char nbuf[100];
+               if (dev->devname && devname_matches(name, dev->devname))
+                       return 0;
+               if (dev->name[0] && devname_matches(name, dev->name))
+                       return 0;
+               sprintf(nbuf, "%d", dev->super_minor);
+               if (dev->super_minor != UnSet &&
+                   devname_matches(name, nbuf))
+                       return 0;
+       }
+       return 1;
+}
+
+struct mddev_ident_s *conf_match(struct mdinfo *info, struct supertype *st)
+{
+       struct mddev_ident_s *array_list, *match;
+       int verbose = 0;
+       char *devname = NULL;
+       array_list = conf_get_ident(NULL);
+       match = NULL;
+       for (; array_list; array_list = array_list->next) {
+               if (array_list->uuid_set &&
+                   same_uuid(array_list->uuid, info->uuid, st->ss->swapuuid)
+                   == 0) {
+                       if (verbose >= 2 && array_list->devname)
+                               fprintf(stderr, Name
+                                       ": UUID differs from %s.\n",
+                                       array_list->devname);
+                       continue;
+               }
+               if (array_list->name[0] &&
+                   strcasecmp(array_list->name, info->name) != 0) {
+                       if (verbose >= 2 && array_list->devname)
+                               fprintf(stderr, Name
+                                       ": Name differs from %s.\n",
+                                       array_list->devname);
+                       continue;
+               }
+               if (array_list->devices && devname &&
+                   !match_oneof(array_list->devices, devname)) {
+                       if (verbose >= 2 && array_list->devname)
+                               fprintf(stderr, Name
+                                       ": Not a listed device for %s.\n",
+                                       array_list->devname);
+                       continue;
+               }
+               if (array_list->super_minor != UnSet &&
+                   array_list->super_minor != info->array.md_minor) {
+                       if (verbose >= 2 && array_list->devname)
+                               fprintf(stderr, Name
+                                       ": Different super-minor to %s.\n",
+                                       array_list->devname);
+                       continue;
+               }
+               if (!array_list->uuid_set &&
+                   !array_list->name[0] &&
+                   !array_list->devices &&
+                   array_list->super_minor == UnSet) {
+                       if (verbose >= 2 && array_list->devname)
+                               fprintf(stderr, Name
+                            ": %s doesn't have any identifying information.\n",
+                                       array_list->devname);
+                       continue;
+               }
+               /* FIXME, should I check raid_disks and level too?? */
+
+               if (match) {
+                       if (verbose >= 0) {
+                               if (match->devname && array_list->devname)
+                                       fprintf(stderr, Name
+                  ": we match both %s and %s - cannot decide which to use.\n",
+                                               match->devname, array_list->devname);
+                               else
+                                       fprintf(stderr, Name
+                                               ": multiple lines in mdadm.conf match\n");
+                       }
+                       return NULL;
+               }
+               match = array_list;
+       }
+       return match;
+}