]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Convert 'auto' config line to policy statements
authorNeilBrown <neilb@suse.de>
Thu, 2 Sep 2010 11:21:36 +0000 (21:21 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 6 Sep 2010 01:26:28 +0000 (11:26 +1000)
Assemble.c
Incremental.c
config.c
mdadm.h
policy.c

index 23d0b826f4304db1c5453cf09795b4ecf75579fe..e115ecac775bca52428f1ba7820f7d0601473a4f 100644 (file)
@@ -230,6 +230,7 @@ int Assemble(struct supertype *st, char *mddev,
                int dfd;
                struct stat stb;
                struct supertype *tst = dup_super(st);
                int dfd;
                struct stat stb;
                struct supertype *tst = dup_super(st);
+               struct dev_policy *pol = NULL;
 
                if (tmpdev->used > 1) continue;
 
 
                if (tmpdev->used > 1) continue;
 
@@ -271,7 +272,7 @@ int Assemble(struct supertype *st, char *mddev,
                        tst->ss->free_super(tst);
                        tmpdev->used = 2;
                } else if (auto_assem && st == NULL &&
                        tst->ss->free_super(tst);
                        tmpdev->used = 2;
                } else if (auto_assem && st == NULL &&
-                          !conf_test_metadata(tst->ss->name,
+                          !conf_test_metadata(tst->ss->name, (pol = devnum_policy(stb.st_rdev)),
                                               tst->ss->match_home(tst, homehost) == 1)) {
                        if (report_missmatch)
                                fprintf(stderr, Name ": %s has metadata type %s for which "
                                               tst->ss->match_home(tst, homehost) == 1)) {
                        if (report_missmatch)
                                fprintf(stderr, Name ": %s has metadata type %s for which "
@@ -403,6 +404,7 @@ int Assemble(struct supertype *st, char *mddev,
                                devname);
                        if (st)
                                st->ss->free_super(st);
                                devname);
                        if (st)
                                st->ss->free_super(st);
+                       dev_policy_free(pol);
                        return 1;
                }
 
                        return 1;
                }
 
@@ -424,6 +426,7 @@ int Assemble(struct supertype *st, char *mddev,
                                content = NULL;
                                if (auto_assem)
                                        goto loop;
                                content = NULL;
                                if (auto_assem)
                                        goto loop;
+                               dev_policy_free(pol);
                                return 1;
                        }
                        if (ident->member && ident->member[0]) {
                                return 1;
                        }
                        if (ident->member && ident->member[0]) {
@@ -447,6 +450,7 @@ int Assemble(struct supertype *st, char *mddev,
                                        "only device given: confused and aborting\n",
                                        devname);
                                st->ss->free_super(st);
                                        "only device given: confused and aborting\n",
                                        devname);
                                st->ss->free_super(st);
+                               dev_policy_free(pol);
                                return 1;
                        }
                        if (verbose > 0)
                                return 1;
                        }
                        if (verbose > 0)
@@ -496,12 +500,15 @@ int Assemble(struct supertype *st, char *mddev,
                                devname);
                        tst->ss->free_super(tst);
                        st->ss->free_super(st);
                                devname);
                        tst->ss->free_super(tst);
                        st->ss->free_super(st);
+                       dev_policy_free(pol);
                        return 1;
                }
 
                tmpdev->used = 1;
 
        loop:
                        return 1;
                }
 
                tmpdev->used = 1;
 
        loop:
+               dev_policy_free(pol);
+               pol = NULL;
                if (tmpdev->content)
                        goto next_member;
                if (tst)
                if (tmpdev->content)
                        goto next_member;
                if (tst)
index 3a41a1e18260950a2948ffe2a64243310b255205..a60be47a749e8377dace2ed7869fca81270beb66 100644 (file)
@@ -246,7 +246,7 @@ int Incremental(char *devname, int verbose, int runstop,
                trustworthy = FOREIGN;
 
 
                trustworthy = FOREIGN;
 
 
-       if (!match && !conf_test_metadata(st->ss->name,
+       if (!match && !conf_test_metadata(st->ss->name, policy,
                                          (trustworthy == LOCAL))) {
                if (verbose >= 1)
                        fprintf(stderr, Name
                                          (trustworthy == LOCAL))) {
                if (verbose >= 1)
                        fprintf(stderr, Name
index 3baf7af45ab031cd938a78d57b8fbe7d335d4bb7..bc450f9430280521054d6df69ed3c3c32f4a3be1 100644 (file)
--- a/config.c
+++ b/config.c
@@ -677,24 +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)
 {
        char *w;
 void autoline(char *line)
 {
        char *w;
+       char *seen;
+       int super_cnt;
+       char *dflt = auto_yes;
+       int homehost = 0;
+       int i;
 
 
-       if (auto_options) {
+       if (auto_seen) {
                fprintf(stderr, Name ": AUTO line may only be give once."
                        "  Subsequent lines ignored\n");
                return;
        }
                fprintf(stderr, Name ": AUTO line may only be give once."
                        "  Subsequent lines ignored\n");
                return;
        }
+       /* 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.
+        */
 
 
-       auto_options = dl_strdup(line);
-       dl_init(auto_options);
+       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 *w2 = dl_strdup(w);
-               dl_add(auto_options, w2);
+       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;
 }
 
 int loaded = 0;
@@ -900,64 +989,30 @@ int conf_test_dev(char *devname)
        return 0;
 }
 
        return 0;
 }
 
-int conf_test_metadata(const char *version, int is_homehost)
+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.
-        * Words 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.
-        *   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.
+       /* 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();
        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;
                        return 1;
-               if (strcasecmp(w, "no") == 0)
-                       return 0;
-               if (strcasecmp(w, "homehost") == 0) {
-                       if (is_homehost)
-                               return 1;
-                       else
-                               continue;
-               }
-               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;
 }
 
        return 1;
 }
 
@@ -967,7 +1022,6 @@ int match_oneof(char *devices, char *devname)
      * matches devname
      */
 
      * matches devname
      */
 
-
     while (devices && *devices) {
        char patn[1024];
        char *p = devices;
     while (devices && *devices) {
        char patn[1024];
        char *p = devices;
diff --git a/mdadm.h b/mdadm.h
index 89705603893922c5a8013a23f48f16f67b94540a..9ad99f046b2103722077ab149b68f970981cf6b8 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -757,7 +757,7 @@ struct dev_policy {
        char *value;
 };
 
        char *value;
 };
 
-extern char pol_act[], pol_domain[], pol_metadata[];
+extern char pol_act[], pol_domain[], pol_metadata[], pol_auto[];
 
 /* iterate over the sublist starting at list, having the same
  * 'name' as 'list', and matching the given metadata (Where
 
 /* iterate over the sublist starting at list, having the same
  * 'name' as 'list', and matching the given metadata (Where
@@ -790,10 +790,12 @@ extern char rule_path[], rule_type[];
 extern char type_part[], type_disk[];
 
 extern void policyline(char *line, char *type);
 extern char type_part[], type_disk[];
 
 extern void policyline(char *line, char *type);
+extern void policy_add(char *type, ...);
 extern void policy_free(void);
 
 extern struct dev_policy *path_policy(char *path, char *type);
 extern struct dev_policy *disk_policy(struct mdinfo *disk);
 extern void policy_free(void);
 
 extern struct dev_policy *path_policy(char *path, char *type);
 extern struct dev_policy *disk_policy(struct mdinfo *disk);
+extern struct dev_policy *devnum_policy(int dev);
 extern void dev_policy_free(struct dev_policy *p);
 
 extern void pol_new(struct dev_policy **pol, char *name, char *val, char *metadata);
 extern void dev_policy_free(struct dev_policy *p);
 
 extern void pol_new(struct dev_policy **pol, char *name, char *val, char *metadata);
@@ -959,7 +961,7 @@ extern int parse_auto(char *str, char *msg, int config);
 extern mddev_ident_t conf_get_ident(char *dev);
 extern mddev_dev_t conf_get_devs(void);
 extern int conf_test_dev(char *devname);
 extern mddev_ident_t conf_get_ident(char *dev);
 extern mddev_dev_t conf_get_devs(void);
 extern int conf_test_dev(char *devname);
-extern int conf_test_metadata(const char *version, int is_homehost);
+extern int conf_test_metadata(const char *version, struct dev_policy *pol, int is_homehost);
 extern struct createinfo *conf_get_create_info(void);
 extern void set_conffile(char *file);
 extern char *conf_get_mailaddr(void);
 extern struct createinfo *conf_get_create_info(void);
 extern void set_conffile(char *file);
 extern char *conf_get_mailaddr(void);
index 8aa4cc8eb3a8116617edcd9cb588961fa5993402..945d37ff6e0007a8d673ad64d824a2709c2f5fb6 100644 (file)
--- a/policy.c
+++ b/policy.c
@@ -389,6 +389,14 @@ struct dev_policy *disk_policy(struct mdinfo *disk)
        return pol;
 }
 
        return pol;
 }
 
+struct dev_policy *devnum_policy(int dev)
+{
+       struct mdinfo disk;
+       disk.disk.major = major(dev);
+       disk.disk.minor = minor(dev);
+       return disk_policy(&disk);
+}
+
 /*
  * process policy rules read from config file.
  */
 /*
  * process policy rules read from config file.
  */
@@ -402,6 +410,7 @@ char rule_part[] = "part-policy";
 char pol_metadata[] = "metadata";
 char pol_act[] = "action";
 char pol_domain[] = "domain";
 char pol_metadata[] = "metadata";
 char pol_act[] = "action";
 char pol_domain[] = "domain";
+char pol_auto[] = "auto";
 
 static int try_rule(char *w, char *name, struct rule **rp)
 {
 
 static int try_rule(char *w, char *name, struct rule **rp)
 {
@@ -436,7 +445,8 @@ void policyline(char *line, char *type)
                else if (! try_rule(w, rule_type, &pr->rule) &&
                         ! try_rule(w, pol_metadata, &pr->rule) &&
                         ! try_rule(w, pol_act, &pr->rule) &&
                else if (! try_rule(w, rule_type, &pr->rule) &&
                         ! try_rule(w, pol_metadata, &pr->rule) &&
                         ! try_rule(w, pol_act, &pr->rule) &&
-                        ! try_rule(w, pol_domain, &pr->rule))
+                        ! try_rule(w, pol_domain, &pr->rule) &&
+                        ! try_rule(w, pol_auto, &pr->rule))
                        fprintf(stderr, Name ": policy rule %s unrecognised and ignored\n",
                                w);
        }
                        fprintf(stderr, Name ": policy rule %s unrecognised and ignored\n",
                                w);
        }
@@ -444,6 +454,32 @@ void policyline(char *line, char *type)
        config_rules = pr;
 }
 
        config_rules = pr;
 }
 
+void policy_add(char *type, ...)
+{
+       va_list ap;
+       struct pol_rule *pr;
+       char *name, *val;
+
+       pr = malloc(sizeof(*pr));
+       pr->type = type;
+       pr->rule = NULL;
+
+       va_start(ap, type);
+       while ((name = va_arg(ap, char*)) != NULL) {
+               struct rule *r;
+
+               val = va_arg(ap, char*);
+               r = malloc(sizeof(*r));
+               r->next = pr->rule;
+               r->name = name;
+               r->value = strdup(val);
+               r->dups = NULL;
+               pr->rule = r;
+       }
+       pr->next = config_rules;
+       config_rules = pr;
+}
+
 void policy_free(void)
 {
        while (config_rules) {
 void policy_free(void)
 {
        while (config_rules) {
@@ -580,9 +616,9 @@ int domain_test(struct domainlist *dom, struct dev_policy *pol,
        pol = pol_find(pol, pol_domain);
        pol_for_each(p, pol, metadata) {
                found_any = 1;
        pol = pol_find(pol, pol_domain);
        pol_for_each(p, pol, metadata) {
                found_any = 1;
-               while (dom && strcmp(dom->dom, pol->value) < 0)
+               while (dom && strcmp(dom->dom, p->value) < 0)
                        dom = dom->next;
                        dom = dom->next;
-               if (!dom || strcmp(dom->dom, pol->value) != 0)
+               if (!dom || strcmp(dom->dom, p->value) != 0)
                        return 0;
        }
        return found_any;
                        return 0;
        }
        return found_any;