2 * mdadm - manage Linux "md" devices aka RAID arrays.
4 * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Email: <neilb@suse.de>
31 * Policy module for mdadm.
32 * A policy statement about a device lists a set of values for each
33 * of a set of names. Each value can have a metadata type as context.
36 * action - the actions that can be taken on hot-plug
37 * domain - the domain(s) that the device is part of
39 * Policy information is extracted from various sources, but
40 * particularly from a set of policy rules in mdadm.conf
43 static void pol_new(struct dev_policy **pol, char *name, const char *val,
46 struct dev_policy *n = xmalloc(sizeof(*n));
47 const char *real_metadata = NULL;
53 /* We need to normalise the metadata name */
55 for (i = 0; superlist[i] ; i++)
56 if (strcmp(metadata, superlist[i]->name) == 0) {
57 real_metadata = superlist[i]->name;
61 if (strcmp(metadata, "1") == 0 ||
62 strcmp(metadata, "1.0") == 0 ||
63 strcmp(metadata, "1.1") == 0 ||
64 strcmp(metadata, "1.2") == 0)
65 real_metadata = super1.name;
68 static const char *prev = NULL;
69 if (prev != metadata) {
70 pr_err("metadata=%s unrecognised - ignoring rule\n",
74 real_metadata = "unknown";
78 n->metadata = real_metadata;
83 static int pol_lesseq(struct dev_policy *a, struct dev_policy *b)
87 if (a->name < b->name)
89 if (a->name > b->name)
92 cmp = strcmp(a->value, b->value);
98 return (a->metadata <= b->metadata);
101 static void pol_sort(struct dev_policy **pol)
103 /* sort policy list in *pol by name/metadata/value
107 struct dev_policy *pl[2];
112 struct dev_policy **plp[2], *p[2];
114 struct dev_policy nul = { NULL, NULL, NULL, NULL };
115 struct dev_policy *prev = &nul;
118 /* p[] are the two lists that we are merging.
119 * plp[] are the ends of the two lists we create
121 * 'curr' is which of plp[] that we are currently
123 * 'next' is which if p[] we will take the next
125 * 'prev' is that last value, which was placed in
133 /* take least of p[0] and p[1]
134 * if it is larger than prev, add to
135 * plp[curr], else swap curr then add
137 while (p[0] || p[1]) {
138 if (p[next] == NULL ||
139 (p[1-next] != NULL &&
140 !(pol_lesseq(prev, p[1-next])
141 ^pol_lesseq(prev, p[next])
142 ^pol_lesseq(p[next], p[1-next])))
146 if (!pol_lesseq(prev, p[next]))
149 *plp[curr] = prev = p[next];
150 plp[curr] = &p[next]->next;
151 p[next] = p[next]->next;
155 } while (pl[0] && pl[1]);
162 static void pol_dedup(struct dev_policy *pol)
164 /* This is a sorted list - remove duplicates. */
165 while (pol && pol->next) {
166 if (pol_lesseq(pol->next, pol)) {
167 struct dev_policy *tmp = pol->next;
168 pol->next = tmp->next;
176 * pol_find finds the first entry in the policy
177 * list to match name.
178 * If it returns non-NULL there is at least one
179 * value, but how many can only be found by
180 * iterating through the list.
182 struct dev_policy *pol_find(struct dev_policy *pol, char *name)
184 while (pol && pol->name < name)
187 if (!pol || pol->name != name)
192 static char *disk_path(struct mdinfo *disk)
197 char symlink[PATH_MAX] = "/dev/disk/by-path/";
202 by_path = opendir(symlink);
204 prefix_len = strlen(symlink);
205 while ((ent = readdir(by_path)) != NULL) {
206 if (ent->d_type != DT_LNK)
208 strncpy(symlink + prefix_len,
210 sizeof(symlink) - prefix_len);
211 if (stat(symlink, &stb) < 0)
213 if ((stb.st_mode & S_IFMT) != S_IFBLK)
215 if (stb.st_rdev != makedev(disk->disk.major, disk->disk.minor))
218 return xstrdup(ent->d_name);
222 /* A NULL path isn't really acceptable - use the devname.. */
223 sprintf(symlink, "/sys/dev/block/%d:%d", disk->disk.major, disk->disk.minor);
224 rv = readlink(symlink, nm, sizeof(nm)-1);
228 dname = strrchr(nm, '/');
230 return xstrdup(dname + 1);
232 return xstrdup("unknown");
235 char type_part[] = "part";
236 char type_disk[] = "disk";
237 static char *disk_type(struct mdinfo *disk)
241 sprintf(buf, "/sys/dev/block/%d:%d/partition",
242 disk->disk.major, disk->disk.minor);
243 if (stat(buf, &stb) == 0)
249 static int pol_match(struct rule *rule, char *path, char *type)
251 /* check if this rule matches on path and type */
252 int pathok = 0; /* 0 == no path, 1 == match, -1 == no match yet */
256 if (rule->name == rule_path) {
259 if (path && fnmatch(rule->value, path, 0) == 0)
262 if (rule->name == rule_type) {
265 if (type && strcmp(rule->value, type) == 0)
270 return pathok >= 0 && typeok >= 0;
273 static void pol_merge(struct dev_policy **pol, struct rule *rule)
275 /* copy any name assignments from rule into pol */
277 char *metadata = NULL;
278 for (r = rule; r ; r = r->next)
279 if (r->name == pol_metadata)
282 for (r = rule; r ; r = r->next)
283 if (r->name == pol_act ||
284 r->name == pol_domain ||
286 pol_new(pol, r->name, r->value, metadata);
289 static int path_has_part(char *path, char **part)
291 /* check if path ends with "-partNN" and
292 * if it does, place a pointer to "-pathNN"
299 while (l > 1 && isdigit(path[l-1]))
301 if (l < 5 || strncmp(path+l-5, "-part", 5) != 0)
307 static void pol_merge_part(struct dev_policy **pol, struct rule *rule, char *part)
309 /* copy any name assignments from rule into pol, appending
310 * -part to any domain. The string with -part appended is
311 * stored with the rule so it has a lifetime to match
315 char *metadata = NULL;
316 for (r = rule; r ; r = r->next)
317 if (r->name == pol_metadata)
320 for (r = rule; r ; r = r->next) {
321 if (r->name == pol_act)
322 pol_new(pol, r->name, r->value, metadata);
323 else if (r->name == pol_domain) {
328 len = strlen(r->value);
329 for (dom = dl_next(r->dups); dom != r->dups;
331 if (strcmp(dom+len+1, part)== 0)
333 if (dom == r->dups) {
334 char *newdom = dl_strndup(
335 r->value, len + 1 + strlen(part));
336 strcat(strcat(newdom, "-"), part);
337 dl_add(r->dups, newdom);
340 pol_new(pol, r->name, dom, metadata);
345 static struct pol_rule *config_rules = NULL;
346 static struct pol_rule **config_rules_end = NULL;
347 static int config_rules_has_path = 0;
350 * most policy comes from a set policy rules that are
351 * read from the config file.
352 * path_policy() gathers policy information for the
353 * disk described in the given a 'path' and a 'type'.
355 struct dev_policy *path_policy(char *path, char *type)
357 struct pol_rule *rules;
358 struct dev_policy *pol = NULL;
361 rules = config_rules;
365 if (rules->type == rule_policy)
366 if (pol_match(rules->rule, path, type))
367 pol_merge(&pol, rules->rule);
368 if (rules->type == rule_part && strcmp(type, type_part) == 0)
369 if (path_has_part(path, &part)) {
371 if (pol_match(rules->rule, path, type_disk))
372 pol_merge_part(&pol, rules->rule, part+1);
378 /* Now add any metadata-specific internal knowledge
381 for (i=0; path && superlist[i]; i++)
382 if (superlist[i]->get_disk_controller_domain) {
384 superlist[i]->get_disk_controller_domain(path);
386 pol_new(&pol, pol_domain, d, superlist[i]->name);
394 void pol_add(struct dev_policy **pol,
395 char *name, char *val,
398 pol_new(pol, name, val, metadata);
404 * disk_policy() gathers policy information for the
405 * disk described in the given mdinfo (disk.{major,minor}).
407 struct dev_policy *disk_policy(struct mdinfo *disk)
410 char *type = disk_type(disk);
411 struct dev_policy *pol = NULL;
413 if (config_rules_has_path)
414 path = disk_path(disk);
416 pol = path_policy(path, type);
422 struct dev_policy *devid_policy(int dev)
425 disk.disk.major = major(dev);
426 disk.disk.minor = minor(dev);
427 return disk_policy(&disk);
431 * process policy rules read from config file.
434 char rule_path[] = "path";
435 char rule_type[] = "type";
437 char rule_policy[] = "policy";
438 char rule_part[] = "part-policy";
440 char pol_metadata[] = "metadata";
441 char pol_act[] = "action";
442 char pol_domain[] = "domain";
443 char pol_auto[] = "auto";
445 static int try_rule(char *w, char *name, struct rule **rp)
448 int len = strlen(name);
449 if (strncmp(w, name, len) != 0 ||
452 r = xmalloc(sizeof(*r));
455 r->value = xstrdup(w+len+1);
461 void policyline(char *line, char *type)
466 if (config_rules_end == NULL)
467 config_rules_end = &config_rules;
469 pr = xmalloc(sizeof(*pr));
472 for (w = dl_next(line); w != line ; w = dl_next(w)) {
473 if (try_rule(w, rule_path, &pr->rule))
474 config_rules_has_path = 1;
475 else if (! try_rule(w, rule_type, &pr->rule) &&
476 ! try_rule(w, pol_metadata, &pr->rule) &&
477 ! try_rule(w, pol_act, &pr->rule) &&
478 ! try_rule(w, pol_domain, &pr->rule) &&
479 ! try_rule(w, pol_auto, &pr->rule))
480 pr_err("policy rule %s unrecognised and ignored\n",
483 pr->next = config_rules;
487 void policy_add(char *type, ...)
493 pr = xmalloc(sizeof(*pr));
498 while ((name = va_arg(ap, char*)) != NULL) {
501 val = va_arg(ap, char*);
502 r = xmalloc(sizeof(*r));
505 r->value = xstrdup(val);
509 pr->next = config_rules;
514 void policy_free(void)
516 while (config_rules) {
517 struct pol_rule *pr = config_rules;
520 config_rules = config_rules->next;
522 for (r = pr->rule; r; ) {
523 struct rule *next = r->next;
532 config_rules_end = NULL;
533 config_rules_has_path = 0;
536 void dev_policy_free(struct dev_policy *p)
538 struct dev_policy *t;
546 static enum policy_action map_act(const char *act)
548 if (strcmp(act, "include") == 0)
550 if (strcmp(act, "re-add") == 0)
552 if (strcmp(act, "spare") == 0)
554 if (strcmp(act, "spare-same-slot") == 0)
555 return act_spare_same_slot;
556 if (strcmp(act, "force-spare") == 0)
557 return act_force_spare;
561 static enum policy_action policy_action(struct dev_policy *plist, const char *metadata)
563 enum policy_action rv = act_default;
564 struct dev_policy *p;
566 plist = pol_find(plist, pol_act);
567 pol_for_each(p, plist, metadata) {
568 enum policy_action a = map_act(p->value);
575 int policy_action_allows(struct dev_policy *plist, const char *metadata, enum policy_action want)
577 enum policy_action act = policy_action(plist, metadata);
581 return (act >= want);
584 int disk_action_allows(struct mdinfo *disk, const char *metadata, enum policy_action want)
586 struct dev_policy *pol = disk_policy(disk);
587 int rv = policy_action_allows(pol, metadata, want);
589 dev_policy_free(pol);
594 * Any device can have a list of domains asserted by different policy
596 * An array also has a list of domains comprising all the domains of
597 * all the devices in an array.
598 * Where an array has a spare-group, that becomes an addition domain for
599 * every device in the array and thus for the array.
601 * We keep the list of domains in a sorted linked list
602 * As dev policies are already sorted, this is fairly easy to manage.
605 static struct domainlist **domain_merge_one(struct domainlist **domp,
608 /* merge a domain name into a sorted list and return the
609 * location of the insertion or match
611 struct domainlist *dom = *domp;
613 while (dom && strcmp(dom->dom, domain) < 0) {
617 if (dom == NULL || strcmp(dom->dom, domain) != 0) {
618 dom = xmalloc(sizeof(*dom));
627 void dump_policy(struct dev_policy *policy)
630 dprintf("policy: %p name: %s value: %s metadata: %s\n",
635 policy = policy->next;
640 void domain_merge(struct domainlist **domp, struct dev_policy *pollist,
641 const char *metadata)
643 /* Add to 'domp' all the domains in pol that apply to 'metadata'
644 * which are not already in domp
646 struct dev_policy *pol;
647 pollist = pol_find(pollist, pol_domain);
648 pol_for_each(pol, pollist, metadata)
649 domain_merge_one(domp, pol->value);
652 int domain_test(struct domainlist *dom, struct dev_policy *pol,
653 const char *metadata)
655 /* Check that all domains in pol (for metadata) are also in
656 * dom. Both lists are sorted.
657 * If pol has no domains, we don't really know about this device
658 * so we allow caller to choose:
660 * 0: has domains, not all match
661 * 1: has domains, all match
664 struct dev_policy *p;
666 pol = pol_find(pol, pol_domain);
667 pol_for_each(p, pol, metadata) {
669 while (dom && strcmp(dom->dom, p->value) < 0)
671 if (!dom || strcmp(dom->dom, p->value) != 0)
677 void domainlist_add_dev(struct domainlist **dom, int devid, const char *metadata)
679 struct dev_policy *pol = devid_policy(devid);
680 domain_merge(dom, pol, metadata);
681 dev_policy_free(pol);
684 struct domainlist *domain_from_array(struct mdinfo *mdi, const char *metadata)
686 struct domainlist *domlist = NULL;
690 for (mdi = mdi->devs ; mdi ; mdi = mdi->next)
691 domainlist_add_dev(&domlist, makedev(mdi->disk.major,
698 void domain_add(struct domainlist **domp, char *domain)
700 domain_merge_one(domp, domain);
703 void domain_free(struct domainlist *dl)
706 struct domainlist *head = dl;
714 * Some policy decisions are guided by knowledge of which
715 * array previously owned the device at a given physical location (path).
716 * When removing a device from an array we might record the array against
717 * the path, and when finding a new device, we might look for which
718 * array previously used that path.
720 * The 'array' is described by a map_ent, and the path by a the disk in an
721 * mdinfo, or a string.
724 void policy_save_path(char *id_path, struct map_ent *array)
729 if (mkdir(FAILED_SLOTS_DIR, S_IRWXU) < 0 && errno != EEXIST) {
730 pr_err("can't create file to save path to old disk: %s\n", strerror(errno));
734 snprintf(path, PATH_MAX, FAILED_SLOTS_DIR "/%s", id_path);
735 f = fopen(path, "w");
737 pr_err("can't create file to save path to old disk: %s\n",
742 if (fprintf(f, "%s %08x:%08x:%08x:%08x\n",
744 array->uuid[0], array->uuid[1],
745 array->uuid[2], array->uuid[3]) <= 0)
746 pr_err("Failed to write to <id_path> cookie\n");
751 int policy_check_path(struct mdinfo *disk, struct map_ent *array)
755 char *id_path = disk_path(disk);
761 snprintf(path, PATH_MAX, FAILED_SLOTS_DIR "/%s", id_path);
762 f = fopen(path, "r");
768 rv = fscanf(f, " %s %x:%x:%x:%x\n",
779 /* invocation of udev rule file */
780 char udev_template_start[] =
781 "# do not edit this file, it is automatically generated by mdadm\n"
784 /* find rule named rule_type and return its value */
785 char *find_rule(struct rule *rule, char *rule_type)
788 if (rule->name == rule_type)
796 #define UDEV_RULE_FORMAT \
797 "ACTION==\"add\", SUBSYSTEM==\"block\", " \
798 "ENV{DEVTYPE}==\"%s\", ENV{ID_PATH}==\"%s\", " \
799 "RUN+=\"" BINDIR "/mdadm --incremental $env{DEVNAME}\"\n"
801 #define UDEV_RULE_FORMAT_NOTYPE \
802 "ACTION==\"add\", SUBSYSTEM==\"block\", " \
803 "ENV{ID_PATH}==\"%s\", " \
804 "RUN+=\"" BINDIR "/mdadm --incremental $env{DEVNAME}\"\n"
806 /* Write rule in the rule file. Use format from UDEV_RULE_FORMAT */
807 int write_rule(struct rule *rule, int fd, int force_part)
810 char *pth = find_rule(rule, rule_path);
811 char *typ = find_rule(rule, rule_type);
818 snprintf(line, sizeof(line) - 1, UDEV_RULE_FORMAT, typ, pth);
820 snprintf(line, sizeof(line) - 1, UDEV_RULE_FORMAT_NOTYPE, pth);
821 return write(fd, line, strlen(line)) == (int)strlen(line);
824 /* Generate single entry in udev rule basing on POLICY line found in config
825 * file. Take only those with paths, only first occurrence if paths are equal
826 * and if actions supports handling of spares (>=act_spare_same_slot)
828 int generate_entries(int fd)
830 struct pol_rule *loop, *dup;
831 char *loop_value, *dup_value;
834 for (loop = config_rules; loop; loop = loop->next) {
835 if (loop->type != rule_policy && loop->type != rule_part)
839 /* only policies with paths and with actions supporting
840 * bare disks are considered */
841 loop_value = find_rule(loop->rule, pol_act);
842 if (!loop_value || map_act(loop_value) < act_spare_same_slot)
844 loop_value = find_rule(loop->rule, rule_path);
847 for (dup = config_rules; dup != loop; dup = dup->next) {
848 if (dup->type != rule_policy && loop->type != rule_part)
850 dup_value = find_rule(dup->rule, pol_act);
851 if (!dup_value || map_act(dup_value) < act_spare_same_slot)
853 dup_value = find_rule(dup->rule, rule_path);
856 if (strcmp(loop_value, dup_value) == 0) {
862 /* not a dup or first occurrence */
864 if (!write_rule(loop->rule, fd, loop->type == rule_part) )
870 /* Write_rules routine creates dynamic udev rules used to handle
871 * hot-plug events for bare devices (and making them spares)
873 int Write_rules(char *rule_name)
876 char udev_rule_file[PATH_MAX];
879 strncpy(udev_rule_file, rule_name, sizeof(udev_rule_file) - 6);
880 udev_rule_file[sizeof(udev_rule_file) - 6] = '\0';
881 strcat(udev_rule_file, ".temp");
882 fd = creat(udev_rule_file,
883 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
889 /* write static invocation */
890 if (write(fd, udev_template_start,
891 sizeof(udev_template_start) - 1)
892 != (int)sizeof(udev_template_start)-1)
895 /* iterate, if none created or error occurred, remove file */
896 if (generate_entries(fd) < 0)
902 rename(udev_rule_file, rule_name);
908 unlink(udev_rule_file);