X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=policy.c;h=b4f39434268e896a38c45eff2203680040bdc0cc;hb=62ff3c40c1b42f85b902b8010ee69d9382cfc407;hp=38b0072b5d111ab6f76168185c575efc0a5d4d8c;hpb=20b60dcd6cea6cb517cea31056241607a2964e5d;p=thirdparty%2Fmdadm.git diff --git a/policy.c b/policy.c index 38b0072b..b4f39434 100644 --- a/policy.c +++ b/policy.c @@ -43,7 +43,7 @@ static void pol_new(struct dev_policy **pol, char *name, const char *val, const char *metadata) { - struct dev_policy *n = malloc(sizeof(*n)); + struct dev_policy *n = xmalloc(sizeof(*n)); const char *real_metadata = NULL; int i; @@ -67,7 +67,7 @@ static void pol_new(struct dev_policy **pol, char *name, const char *val, if (!real_metadata) { static const char *prev = NULL; if (prev != metadata) { - fprintf(stderr, Name ": metadata=%s unrecognised - ignoring rule\n", + pr_err("metadata=%s unrecognised - ignoring rule\n", metadata); prev = metadata; } @@ -195,7 +195,9 @@ static char *disk_path(struct mdinfo *disk) int prefix_len; DIR *by_path; char symlink[PATH_MAX] = "/dev/disk/by-path/"; + char nm[PATH_MAX]; struct dirent *ent; + int rv; by_path = opendir(symlink); if (!by_path) @@ -215,10 +217,20 @@ static char *disk_path(struct mdinfo *disk) if (stb.st_rdev != makedev(disk->disk.major, disk->disk.minor)) continue; closedir(by_path); - return strdup(ent->d_name); + return xstrdup(ent->d_name); } closedir(by_path); - return NULL; + /* A NULL path isn't really acceptable - use the devname.. */ + sprintf(symlink, "/sys/dev/block/%d:%d", disk->disk.major, disk->disk.minor); + rv = readlink(symlink, nm, sizeof(nm)-1); + if (rv > 0) { + char *dname; + nm[rv] = 0; + dname = strrchr(nm, '/'); + if (dname) + return xstrdup(dname + 1); + } + return xstrdup("unknown"); } char type_part[] = "part"; @@ -245,13 +257,13 @@ static int pol_match(struct rule *rule, char *path, char *type) if (rule->name == rule_path) { if (pathok == 0) pathok = -1; - if (fnmatch(rule->value, path, 0) == 0) + if (path && fnmatch(rule->value, path, 0) == 0) pathok = 1; } if (rule->name == rule_type) { if (typeok == 0) typeok = -1; - if (strcmp(rule->value, type) == 0) + if (type && strcmp(rule->value, type) == 0) typeok = 1; } rule = rule->next; @@ -270,7 +282,8 @@ static void pol_merge(struct dev_policy **pol, struct rule *rule) for (r = rule; r ; r = r->next) if (r->name == pol_act || - r->name == pol_domain) + r->name == pol_domain || + r->name == pol_auto) pol_new(pol, r->name, r->value, metadata); } @@ -280,7 +293,10 @@ static int path_has_part(char *path, char **part) * if it does, place a pointer to "-pathNN" * in 'part'. */ - int l = strlen(path); + int l; + if (!path) + return 0; + l = strlen(path); while (l > 1 && isdigit(path[l-1])) l--; if (l < 5 || strncmp(path+l-5, "-part", 5) != 0) @@ -343,9 +359,6 @@ struct dev_policy *path_policy(char *path, char *type) struct dev_policy *pol = NULL; int i; - if (!type) - return NULL; - rules = config_rules; while (rules) { @@ -366,7 +379,7 @@ struct dev_policy *path_policy(char *path, char *type) /* Now add any metadata-specific internal knowledge * about this path */ - for (i=0; superlist[i]; i++) + for (i=0; path && superlist[i]; i++) if (superlist[i]->get_disk_controller_domain) { const char *d = superlist[i]->get_disk_controller_domain(path); @@ -388,7 +401,6 @@ void pol_add(struct dev_policy **pol, pol_dedup(*pol); } - /* * disk_policy() gathers policy information for the * disk described in the given mdinfo (disk.{major,minor}). @@ -399,12 +411,8 @@ struct dev_policy *disk_policy(struct mdinfo *disk) char *type = disk_type(disk); struct dev_policy *pol = NULL; - if (!type) - return NULL; if (config_rules_has_path) path = disk_path(disk); - if (!path) - return NULL; pol = path_policy(path, type); @@ -412,7 +420,7 @@ struct dev_policy *disk_policy(struct mdinfo *disk) return pol; } -struct dev_policy *devnum_policy(int dev) +struct dev_policy *devid_policy(int dev) { struct mdinfo disk; disk.disk.major = major(dev); @@ -442,10 +450,10 @@ static int try_rule(char *w, char *name, struct rule **rp) if (strncmp(w, name, len) != 0 || w[len] != '=') return 0; - r = malloc(sizeof(*r)); + r = xmalloc(sizeof(*r)); r->next = *rp; r->name = name; - r->value = strdup(w+len+1); + r->value = xstrdup(w+len+1); r->dups = NULL; *rp = r; return 1; @@ -459,7 +467,7 @@ void policyline(char *line, char *type) if (config_rules_end == NULL) config_rules_end = &config_rules; - pr = malloc(sizeof(*pr)); + pr = xmalloc(sizeof(*pr)); pr->type = type; pr->rule = NULL; for (w = dl_next(line); w != line ; w = dl_next(w)) { @@ -470,7 +478,7 @@ void policyline(char *line, char *type) ! try_rule(w, pol_act, &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", + pr_err("policy rule %s unrecognised and ignored\n", w); } pr->next = config_rules; @@ -483,7 +491,7 @@ void policy_add(char *type, ...) struct pol_rule *pr; char *name, *val; - pr = malloc(sizeof(*pr)); + pr = xmalloc(sizeof(*pr)); pr->type = type; pr->rule = NULL; @@ -492,15 +500,16 @@ void policy_add(char *type, ...) struct rule *r; val = va_arg(ap, char*); - r = malloc(sizeof(*r)); + r = xmalloc(sizeof(*r)); r->next = pr->rule; r->name = name; - r->value = strdup(val); + r->value = xstrdup(val); r->dups = NULL; pr->rule = r; } pr->next = config_rules; config_rules = pr; + va_end(ap); } void policy_free(void) @@ -582,7 +591,6 @@ int disk_action_allows(struct mdinfo *disk, const char *metadata, enum policy_ac return rv; } - /* Domain policy: * Any device can have a list of domains asserted by different policy * statements. @@ -608,7 +616,7 @@ static struct domainlist **domain_merge_one(struct domainlist **domp, dom = *domp; } if (dom == NULL || strcmp(dom->dom, domain) != 0) { - dom = malloc(sizeof(*dom)); + dom = xmalloc(sizeof(*dom)); dom->next = *domp; dom->dom = domain; *domp = dom; @@ -648,9 +656,12 @@ int domain_test(struct domainlist *dom, struct dev_policy *pol, /* Check that all domains in pol (for metadata) are also in * dom. Both lists are sorted. * If pol has no domains, we don't really know about this device - * so we reject the match. + * so we allow caller to choose: + * -1: has no domains + * 0: has domains, not all match + * 1: has domains, all match */ - int found_any = 0; + int found_any = -1; struct dev_policy *p; pol = pol_find(pol, pol_domain); @@ -664,9 +675,9 @@ int domain_test(struct domainlist *dom, struct dev_policy *pol, return found_any; } -void domainlist_add_dev(struct domainlist **dom, int devnum, const char *metadata) +void domainlist_add_dev(struct domainlist **dom, int devid, const char *metadata) { - struct dev_policy *pol = devnum_policy(devnum); + struct dev_policy *pol = devid_policy(devid); domain_merge(dom, pol, metadata); dev_policy_free(pol); } @@ -675,6 +686,8 @@ struct domainlist *domain_from_array(struct mdinfo *mdi, const char *metadata) { struct domainlist *domlist = NULL; + if (!mdi) + return NULL; for (mdi = mdi->devs ; mdi ; mdi = mdi->next) domainlist_add_dev(&domlist, makedev(mdi->disk.major, mdi->disk.minor), @@ -688,7 +701,6 @@ void domain_add(struct domainlist **domp, char *domain) domain_merge_one(domp, domain); } - void domain_free(struct domainlist *dl) { while (dl) { @@ -716,7 +728,7 @@ void policy_save_path(char *id_path, struct map_ent *array) FILE *f = NULL; if (mkdir(FAILED_SLOTS_DIR, S_IRWXU) < 0 && errno != EEXIST) { - fprintf(stderr, Name ": can't create file to save path " + pr_err("can't create file to save path " "to old disk: %s\n", strerror(errno)); return; } @@ -724,7 +736,7 @@ void policy_save_path(char *id_path, struct map_ent *array) snprintf(path, PATH_MAX, FAILED_SLOTS_DIR "/%s", id_path); f = fopen(path, "w"); if (!f) { - fprintf(stderr, Name ": can't create file to" + pr_err("can't create file to" " save path to old disk: %s\n", strerror(errno)); return; @@ -734,8 +746,8 @@ void policy_save_path(char *id_path, struct map_ent *array) array->metadata, array->uuid[0], array->uuid[1], array->uuid[2], array->uuid[3]) <= 0) - fprintf(stderr, Name ": Failed to write to " - " cookie\n"); + pr_err("Failed to write to " + " cookie\n"); fclose(f); } @@ -752,8 +764,10 @@ int policy_check_path(struct mdinfo *disk, struct map_ent *array) snprintf(path, PATH_MAX, FAILED_SLOTS_DIR "/%s", id_path); f = fopen(path, "r"); - if (!f) + if (!f) { + free(id_path); return 0; + } rv = fscanf(f, " %s %x:%x:%x:%x\n", array->metadata, @@ -762,6 +776,7 @@ int policy_check_path(struct mdinfo *disk, struct map_ent *array) array->uuid+2, array->uuid+3); fclose(f); + free(id_path); return rv == 5; } @@ -773,24 +788,24 @@ char udev_template_start[] = /* find rule named rule_type and return its value */ char *find_rule(struct rule *rule, char *rule_type) { - while (rule) { - if (rule->name == rule_type) - return rule->value; + while (rule) { + if (rule->name == rule_type) + return rule->value; - rule = rule->next; - } - return NULL; + rule = rule->next; + } + return NULL; } #define UDEV_RULE_FORMAT \ -"ACTION==\"add\", SUBSYSTEM=\"block\", " \ +"ACTION==\"add\", SUBSYSTEM==\"block\", " \ "ENV{DEVTYPE}==\"%s\", ENV{ID_PATH}==\"%s\", " \ -"RUN+=\"/sbin/mdadm --incremental $env{DEVNAME}\", " +"RUN+=\"/sbin/mdadm --incremental $env{DEVNAME}\"\n" #define UDEV_RULE_FORMAT_NOTYPE \ -"ACTION==\"add\", SUBSYSTEM=\"block\", " \ +"ACTION==\"add\", SUBSYSTEM==\"block\", " \ "ENV{ID_PATH}==\"%s\", " \ -"RUN+=\"/sbin/mdadm --incremental $env{DEVNAME}\", " +"RUN+=\"/sbin/mdadm --incremental $env{DEVNAME}\"\n" /* Write rule in the rule file. Use format from UDEV_RULE_FORMAT */ int write_rule(struct rule *rule, int fd, int force_part) @@ -816,44 +831,44 @@ int write_rule(struct rule *rule, int fd, int force_part) */ int generate_entries(int fd) { - struct pol_rule *loop, *dup; - char *loop_value, *dup_value; - int duplicate; - - for (loop = config_rules; loop; loop = loop->next) { - if (loop->type != rule_policy && loop->type != rule_part) - continue; - duplicate = 0; - - /* only policies with paths and with actions supporting - * bare disks are considered */ - loop_value = find_rule(loop->rule, pol_act); - if (!loop_value || map_act(loop_value) < act_spare_same_slot) - continue; - loop_value = find_rule(loop->rule, rule_path); - if (!loop_value) - continue; - for (dup = config_rules; dup != loop; dup = dup->next) { - if (dup->type != rule_policy && loop->type != rule_part) - continue; - dup_value = find_rule(dup->rule, pol_act); - if (!dup_value || map_act(dup_value) < act_spare_same_slot) - continue; - dup_value = find_rule(dup->rule, rule_path); - if (!dup_value) - continue; - if (strcmp(loop_value, dup_value) == 0) { - duplicate = 1; - break; - } - } - - /* not a dup or first occurrence */ - if (!duplicate) - if (!write_rule(loop->rule, fd, loop->type == rule_part) ) - return 0; - } - return 1; + struct pol_rule *loop, *dup; + char *loop_value, *dup_value; + int duplicate; + + for (loop = config_rules; loop; loop = loop->next) { + if (loop->type != rule_policy && loop->type != rule_part) + continue; + duplicate = 0; + + /* only policies with paths and with actions supporting + * bare disks are considered */ + loop_value = find_rule(loop->rule, pol_act); + if (!loop_value || map_act(loop_value) < act_spare_same_slot) + continue; + loop_value = find_rule(loop->rule, rule_path); + if (!loop_value) + continue; + for (dup = config_rules; dup != loop; dup = dup->next) { + if (dup->type != rule_policy && loop->type != rule_part) + continue; + dup_value = find_rule(dup->rule, pol_act); + if (!dup_value || map_act(dup_value) < act_spare_same_slot) + continue; + dup_value = find_rule(dup->rule, rule_path); + if (!dup_value) + continue; + if (strcmp(loop_value, dup_value) == 0) { + duplicate = 1; + break; + } + } + + /* not a dup or first occurrence */ + if (!duplicate) + if (!write_rule(loop->rule, fd, loop->type == rule_part) ) + return 0; + } + return 1; } /* Write_rules routine creates dynamic udev rules used to handle @@ -861,39 +876,40 @@ int generate_entries(int fd) */ int Write_rules(char *rule_name) { - int fd; - char udev_rule_file[PATH_MAX]; - - if (rule_name) { - strcpy(udev_rule_file, rule_name); - strcat(udev_rule_file, ".temp"); - fd = creat(udev_rule_file, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (fd == -1) - return 1; - } else - fd = 1; - - /* write static invocation */ - if (write(fd, udev_template_start, - sizeof(udev_template_start) - 1) - != (int)sizeof(udev_template_start)-1) - goto abort; - - /* iterate, if none created or error occurred, remove file */ - if (generate_entries(fd) < 0) - goto abort; - - fsync(fd); - if (rule_name) { - close(fd); - rename(udev_rule_file, rule_name); - } - return 0; + int fd; + char udev_rule_file[PATH_MAX]; + + if (rule_name) { + strncpy(udev_rule_file, rule_name, sizeof(udev_rule_file) - 6); + udev_rule_file[sizeof(udev_rule_file) - 6] = '\0'; + strcat(udev_rule_file, ".temp"); + fd = creat(udev_rule_file, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd == -1) + return 1; + } else + fd = 1; + + /* write static invocation */ + if (write(fd, udev_template_start, + sizeof(udev_template_start) - 1) + != (int)sizeof(udev_template_start)-1) + goto abort; + + /* iterate, if none created or error occurred, remove file */ + if (generate_entries(fd) < 0) + goto abort; + + fsync(fd); + if (rule_name) { + close(fd); + rename(udev_rule_file, rule_name); + } + return 0; abort: - if (rule_name) { - close(fd); - unlink(udev_rule_file); - } - return 1; + if (rule_name) { + close(fd); + unlink(udev_rule_file); + } + return 1; }