]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - config.c
Remove subarray field in supertype.
[thirdparty/mdadm.git] / config.c
index 275ca21865fd4f98a3cfb8b73327e231d0533d76..bc450f9430280521054d6df69ed3c3c32f4a3be1 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"
@@ -80,7 +75,7 @@ char DefaultConfFile[] = CONFFILE;
 char DefaultAltConfFile[] = CONFFILE2;
 
 enum linetype { Devices, Array, Mailaddr, Mailfrom, Program, CreateDev,
-               Homehost, AutoMode, LTEnd };
+               Homehost, AutoMode, Policy, PartPolicy, LTEnd };
 char *keywords[] = {
        [Devices]  = "devices",
        [Array]    = "array",
@@ -90,6 +85,8 @@ char *keywords[] = {
        [CreateDev]= "create",
        [Homehost] = "homehost",
        [AutoMode] = "auto",
+       [Policy]   = "policy",
+       [PartPolicy]="part-policy",
        [LTEnd]    = NULL
 };
 
@@ -529,12 +526,13 @@ void arrayline(char *line)
                                        w);
                        else {
                                char *endptr;
-                               mis.super_minor= strtol(w+12, &endptr, 10);
-                               if (w[12]==0 || endptr[0]!=0 || mis.super_minor < 0) {
+                               int minor = strtol(w+12, &endptr, 10);
+
+                               if (w[12]==0 || endptr[0]!=0 || minor < 0)
                                        fprintf(stderr, Name ": invalid super-minor number: %s\n",
                                                w);
-                                       mis.super_minor = UnSet;
-                               }
+                               else
+                                       mis.super_minor = minor;
                        }
                } else if (strncasecmp(w, "name=", 5)==0) {
                        if (mis.name[0])
@@ -679,15 +677,113 @@ void homehostline(char *line)
        }
 }
 
-static char *auto_options = NULL;
+char auto_yes[] = "yes";
+char auto_no[] = "no";
+char auto_homehost[] = "homehost";
+
+static int auto_seen = 0;
 void autoline(char *line)
 {
-       if (auto_options) {
+       char *w;
+       char *seen;
+       int super_cnt;
+       char *dflt = auto_yes;
+       int homehost = 0;
+       int i;
+
+       if (auto_seen) {
                fprintf(stderr, Name ": AUTO line may only be give once."
                        "  Subsequent lines ignored\n");
                return;
        }
-       auto_options = line;            
+       /* Parse the 'auto' line creating policy statements for the 'auto' policy.
+        *
+        * The default is 'yes' but the 'auto' line might over-ride that.
+        * Words in the line are processed in order with the first
+        * match winning.
+        * word can be:
+        *   +version   - that version can be assembled
+        *   -version   - that version cannot be auto-assembled
+        *   yes or +all - any other version can be assembled
+        *   no or -all  - no other version can be assembled.
+        *   homehost   - any array associated by 'homehost' to this
+        *                host can be assembled.
+        *
+        * Thus:
+        *   +ddf -0.90 homehost -all
+        * will auto-assemble any ddf array, no 0.90 array, and
+        * any other array (imsm, 1.x) if and only if it is identified
+        * as belonging to this host.
+        *
+        * We translate that to policy by creating 'auto=yes' when we see
+        * a '+version' line, 'auto=no' if we see '-version' before 'homehost',
+        * or 'auto=homehost' if we see '-version' after 'homehost'.
+        * When we see yes, no, +all or -all we stop an any version that hasn't
+        * been seen gets an appropriate auto= entry.
+        */
+
+       for (super_cnt = 0; superlist[super_cnt]; super_cnt++)
+               ;
+       seen = calloc(super_cnt, 1);
+
+       for (w = dl_next(line); w != line ; w = dl_next(w)) {
+               char *val;
+
+               if (strcasecmp(w, "yes") == 0) {
+                       dflt = auto_yes;
+                       break;
+               }
+               if (strcasecmp(w, "no") == 0) {
+                       if (homehost)
+                               dflt = auto_homehost;
+                       else
+                               dflt = auto_no;
+                       break;
+               }
+               if (strcasecmp(w, "homehost") == 0) {
+                       homehost = 1;
+                       continue;
+               }
+               if (w[0] == '+')
+                       val = auto_yes;
+               else if (w[0] == '-') {
+                       if (homehost)
+                               val = auto_homehost;
+                       else
+                               val = auto_no;
+               } else
+                       continue;
+
+               if (strcasecmp(w+1, "all") == 0) {
+                       dflt = val;
+                       break;
+               }
+               for (i = 0; superlist[i]; i++) {
+                       const char *version = superlist[i]->name;
+                       if (strcasecmp(w+1, version) == 0)
+                               break;
+                       /* 1 matches 1.x, 0 matches 0.90 */
+                       if (version[1] == '.' &&
+                           strlen(w+1) == 1 &&
+                           w[1] == version[0])
+                               break;
+                       /* 1.anything matches 1.x */
+                       if (strcmp(version, "1.x") == 0 &&
+                           strncmp(w+1, "1.", 2) == 0)
+                               break;
+               }
+               if (superlist[i] == NULL)
+                       /* ignore this word */
+                       continue;
+               if (seen[i])
+                       /* already know about this metadata */
+                       continue;
+               policy_add(rule_policy, pol_auto, val, pol_metadata, superlist[i]->name, NULL);
+               seen[i] = 1;
+       }
+       for (i = 0; i < super_cnt; i++)
+               if (!seen[i])
+                       policy_add(rule_policy, pol_auto, dflt, pol_metadata, superlist[i]->name, NULL);
 }
 
 int loaded = 0;
@@ -762,6 +858,12 @@ void load_conffile(void)
                case AutoMode:
                        autoline(line);
                        break;
+               case Policy:
+                       policyline(line, rule_policy);
+                       break;
+               case PartPolicy:
+                       policyline(line, rule_part);
+                       break;
                default:
                        fprintf(stderr, Name ": Unknown keyword %s\n", line);
                }
@@ -887,50 +989,30 @@ int conf_test_dev(char *devname)
        return 0;
 }
 
-int conf_test_metadata(const char *version)
+int conf_test_metadata(const char *version, struct dev_policy *pol, int is_homehost)
 {
-       /* Check if the given metadata version is allowed
-        * to be auto-assembled.
-        * The default is 'yes' but the 'auto' line might over-ride that.
-        * Word in auto_options are processed in order with the first
-        * match winning.
-        * word can be:
-        *   +version   - that version can be assembled
-        *   -version   - that version cannot be auto-assembled
-        *   yes or +all - any other version can be assembled
-        *   no or -all  - no other version can be assembled.
+       /* If anyone said 'yes', that sticks.
+        * else if homehost applies, use that
+        * else if there is a 'no', say 'no'.
+        * else 'yes'.
         */
-       char *w;
+       struct dev_policy *p;
+       int no=0, found_auto=0;
        load_conffile();
-       if (!auto_options)
-               return 1;
-       for (w = dl_next(auto_options); w != auto_options; w = dl_next(w)) {
-               int rv;
-               if (strcasecmp(w, "yes") == 0)
+
+       pol = pol_find(pol, pol_auto);
+       pol_for_each(p, pol, version) {
+               if (strcmp(p->value, "yes") == 0)
                        return 1;
-               if (strcasecmp(w, "no") == 0)
-                       return 0;
-               if (w[0] == '+')
-                       rv = 1;
-               else if (w[0] == '-')
-                       rv = 0;
-               else continue;
-
-               if (strcasecmp(w+1, "all") == 0)
-                       return rv;
-               if (strcasecmp(w+1, version) == 0)
-                       return rv;
-               /* allow  '0' to match version '0.90'
-                * and 1 or 1.whatever to match version '1.x'
-                */
-               if (version[1] == '.' &&
-                   strlen(w+1) == 1 &&
-                   w[1] == version[0])
-                       return rv;
-               if (version[1] == '.' && version[2] == 'x' &&
-                   strncmp(w+1, version, 2) == 0)
-                       return rv;
+               if (strcmp(p->value, "auto") == 0)
+                       found_auto = 1;
+               if (strcmp(p->value, "no") == 0)
+                       no = 1;
        }
+       if (is_homehost && found_auto)
+               return 1;
+       if (no)
+               return 0;
        return 1;
 }
 
@@ -940,7 +1022,6 @@ int match_oneof(char *devices, char *devname)
      * matches devname
      */
 
-
     while (devices && *devices) {
        char patn[1024];
        char *p = devices;