policy.c (mdadm-4.1) | : | policy.c (mdadm-4.2) | ||
---|---|---|---|---|
skipping to change at line 192 | skipping to change at line 192 | |||
struct dev_policy *pol_find(struct dev_policy *pol, char *name) | struct dev_policy *pol_find(struct dev_policy *pol, char *name) | |||
{ | { | |||
while (pol && pol->name < name) | while (pol && pol->name < name) | |||
pol = pol->next; | pol = pol->next; | |||
if (!pol || pol->name != name) | if (!pol || pol->name != name) | |||
return NULL; | return NULL; | |||
return pol; | return pol; | |||
} | } | |||
static char *disk_path(struct mdinfo *disk) | static char **disk_paths(struct mdinfo *disk) | |||
{ | { | |||
struct stat stb; | struct stat stb; | |||
int prefix_len; | int prefix_len; | |||
DIR *by_path; | DIR *by_path; | |||
char symlink[PATH_MAX] = "/dev/disk/by-path/"; | char symlink[PATH_MAX] = "/dev/disk/by-path/"; | |||
char nm[PATH_MAX]; | char **paths; | |||
int cnt = 0; | ||||
struct dirent *ent; | struct dirent *ent; | |||
int rv; | ||||
paths = xmalloc(sizeof(*paths) * (cnt+1)); | ||||
by_path = opendir(symlink); | by_path = opendir(symlink); | |||
if (by_path) { | if (by_path) { | |||
prefix_len = strlen(symlink); | prefix_len = strlen(symlink); | |||
while ((ent = readdir(by_path)) != NULL) { | while ((ent = readdir(by_path)) != NULL) { | |||
if (ent->d_type != DT_LNK) | if (ent->d_type != DT_LNK) | |||
continue; | continue; | |||
strncpy(symlink + prefix_len, | strncpy(symlink + prefix_len, | |||
ent->d_name, | ent->d_name, | |||
sizeof(symlink) - prefix_len); | sizeof(symlink) - prefix_len); | |||
if (stat(symlink, &stb) < 0) | if (stat(symlink, &stb) < 0) | |||
continue; | continue; | |||
if ((stb.st_mode & S_IFMT) != S_IFBLK) | if ((stb.st_mode & S_IFMT) != S_IFBLK) | |||
continue; | continue; | |||
if (stb.st_rdev != makedev(disk->disk.major, disk->disk.m inor)) | if (stb.st_rdev != makedev(disk->disk.major, disk->disk.m inor)) | |||
continue; | continue; | |||
closedir(by_path); | paths[cnt++] = xstrdup(ent->d_name); | |||
return xstrdup(ent->d_name); | paths = xrealloc(paths, sizeof(*paths) * (cnt+1)); | |||
} | } | |||
closedir(by_path); | closedir(by_path); | |||
} | } | |||
/* A NULL path isn't really acceptable - use the devname.. */ | paths[cnt] = NULL; | |||
sprintf(symlink, "/sys/dev/block/%d:%d", disk->disk.major, disk->disk.min | return paths; | |||
or); | ||||
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"; | char type_part[] = "part"; | |||
char type_disk[] = "disk"; | char type_disk[] = "disk"; | |||
static char *disk_type(struct mdinfo *disk) | static char *disk_type(struct mdinfo *disk) | |||
{ | { | |||
char buf[30+20+20]; | char buf[30+20+20]; | |||
struct stat stb; | struct stat stb; | |||
sprintf(buf, "/sys/dev/block/%d:%d/partition", | sprintf(buf, "/sys/dev/block/%d:%d/partition", | |||
disk->disk.major, disk->disk.minor); | disk->disk.major, disk->disk.minor); | |||
if (stat(buf, &stb) == 0) | if (stat(buf, &stb) == 0) | |||
return type_part; | return type_part; | |||
else | else | |||
return type_disk; | return type_disk; | |||
} | } | |||
static int pol_match(struct rule *rule, char *path, char *type) | static int path_has_part(char *path, char **part) | |||
{ | ||||
/* check if path ends with "-partNN" and | ||||
* if it does, place a pointer to "-pathNN" | ||||
* in 'part'. | ||||
*/ | ||||
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) | ||||
return 0; | ||||
*part = path+l-5; | ||||
return 1; | ||||
} | ||||
static int pol_match(struct rule *rule, char **paths, char *type, char **part) | ||||
{ | { | |||
/* check if this rule matches on path and type */ | /* Check if this rule matches on any path and type. | |||
* If 'part' is not NULL, then 'path' must end in -partN, which | ||||
* we ignore for matching, and return in *part on success. | ||||
*/ | ||||
int pathok = 0; /* 0 == no path, 1 == match, -1 == no match yet */ | int pathok = 0; /* 0 == no path, 1 == match, -1 == no match yet */ | |||
int typeok = 0; | int typeok = 0; | |||
while (rule) { | for (; rule; rule = rule->next) { | |||
if (rule->name == rule_path) { | if (rule->name == rule_path) { | |||
char *p = NULL; | ||||
int i; | ||||
if (pathok == 0) | if (pathok == 0) | |||
pathok = -1; | pathok = -1; | |||
if (path && fnmatch(rule->value, path, 0) == 0) | if (!paths) | |||
pathok = 1; | continue; | |||
for (i = 0; paths[i]; i++) { | ||||
if (part) { | ||||
if (!path_has_part(paths[i], &p)) | ||||
continue; | ||||
*p = '\0'; | ||||
*part = p+1; | ||||
} | ||||
if (fnmatch(rule->value, paths[i], 0) == 0) | ||||
pathok = 1; | ||||
if (part) | ||||
*p = '-'; | ||||
} | ||||
} | } | |||
if (rule->name == rule_type) { | if (rule->name == rule_type) { | |||
if (typeok == 0) | if (typeok == 0) | |||
typeok = -1; | typeok = -1; | |||
if (type && strcmp(rule->value, type) == 0) | if (type && strcmp(rule->value, type) == 0) | |||
typeok = 1; | typeok = 1; | |||
} | } | |||
rule = rule->next; | ||||
} | } | |||
return pathok >= 0 && typeok >= 0; | return pathok >= 0 && typeok >= 0; | |||
} | } | |||
static void pol_merge(struct dev_policy **pol, struct rule *rule) | static void pol_merge(struct dev_policy **pol, struct rule *rule) | |||
{ | { | |||
/* copy any name assignments from rule into pol */ | /* copy any name assignments from rule into pol */ | |||
struct rule *r; | struct rule *r; | |||
char *metadata = NULL; | char *metadata = NULL; | |||
for (r = rule; r ; r = r->next) | for (r = rule; r ; r = r->next) | |||
if (r->name == pol_metadata) | if (r->name == pol_metadata) | |||
metadata = r->value; | metadata = r->value; | |||
for (r = rule; r ; r = r->next) | for (r = rule; r ; r = r->next) | |||
if (r->name == pol_act || | if (r->name == pol_act || | |||
r->name == pol_domain || | r->name == pol_domain || | |||
r->name == pol_auto) | r->name == pol_auto) | |||
pol_new(pol, r->name, r->value, metadata); | pol_new(pol, r->name, r->value, metadata); | |||
} | } | |||
static int path_has_part(char *path, char **part) | ||||
{ | ||||
/* check if path ends with "-partNN" and | ||||
* if it does, place a pointer to "-pathNN" | ||||
* in 'part'. | ||||
*/ | ||||
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) | ||||
return 0; | ||||
*part = path+l-4; | ||||
return 1; | ||||
} | ||||
static void pol_merge_part(struct dev_policy **pol, struct rule *rule, char *par t) | static void pol_merge_part(struct dev_policy **pol, struct rule *rule, char *par t) | |||
{ | { | |||
/* copy any name assignments from rule into pol, appending | /* copy any name assignments from rule into pol, appending | |||
* -part to any domain. The string with -part appended is | * -part to any domain. The string with -part appended is | |||
* stored with the rule so it has a lifetime to match | * stored with the rule so it has a lifetime to match | |||
* the rule. | * the rule. | |||
*/ | */ | |||
struct rule *r; | struct rule *r; | |||
char *metadata = NULL; | char *metadata = NULL; | |||
for (r = rule; r ; r = r->next) | for (r = rule; r ; r = r->next) | |||
skipping to change at line 355 | skipping to change at line 364 | |||
static struct pol_rule *config_rules = NULL; | static struct pol_rule *config_rules = NULL; | |||
static struct pol_rule **config_rules_end = NULL; | static struct pol_rule **config_rules_end = NULL; | |||
static int config_rules_has_path = 0; | static int config_rules_has_path = 0; | |||
/* | /* | |||
* most policy comes from a set policy rules that are | * most policy comes from a set policy rules that are | |||
* read from the config file. | * read from the config file. | |||
* path_policy() gathers policy information for the | * path_policy() gathers policy information for the | |||
* disk described in the given a 'path' and a 'type'. | * disk described in the given a 'path' and a 'type'. | |||
*/ | */ | |||
struct dev_policy *path_policy(char *path, char *type) | struct dev_policy *path_policy(char **paths, char *type) | |||
{ | { | |||
struct pol_rule *rules; | struct pol_rule *rules; | |||
struct dev_policy *pol = NULL; | struct dev_policy *pol = NULL; | |||
int i; | int i; | |||
rules = config_rules; | rules = config_rules; | |||
while (rules) { | while (rules) { | |||
char *part; | char *part = NULL; | |||
if (rules->type == rule_policy) | if (rules->type == rule_policy) | |||
if (pol_match(rules->rule, path, type)) | if (pol_match(rules->rule, paths, type, NULL)) | |||
pol_merge(&pol, rules->rule); | pol_merge(&pol, rules->rule); | |||
if (rules->type == rule_part && strcmp(type, type_part) == 0) | if (rules->type == rule_part && strcmp(type, type_part) == 0) | |||
if (path_has_part(path, &part)) { | if (pol_match(rules->rule, paths, type_disk, &part)) | |||
*part = 0; | pol_merge_part(&pol, rules->rule, part); | |||
if (pol_match(rules->rule, path, type_disk)) | ||||
pol_merge_part(&pol, rules->rule, part+1) | ||||
; | ||||
*part = '-'; | ||||
} | ||||
rules = rules->next; | rules = rules->next; | |||
} | } | |||
/* Now add any metadata-specific internal knowledge | /* Now add any metadata-specific internal knowledge | |||
* about this path | * about this path | |||
*/ | */ | |||
for (i=0; path && superlist[i]; i++) | for (i=0; paths && paths[0] && superlist[i]; i++) | |||
if (superlist[i]->get_disk_controller_domain) { | if (superlist[i]->get_disk_controller_domain) { | |||
const char *d = | const char *d = | |||
superlist[i]->get_disk_controller_domain(path); | superlist[i]->get_disk_controller_domain( | |||
paths[0]); | ||||
if (d) | if (d) | |||
pol_new(&pol, pol_domain, d, superlist[i]->name); | pol_new(&pol, pol_domain, d, superlist[i]->name); | |||
} | } | |||
pol_sort(&pol); | pol_sort(&pol); | |||
pol_dedup(pol); | pol_dedup(pol); | |||
return pol; | return pol; | |||
} | } | |||
void pol_add(struct dev_policy **pol, | void pol_add(struct dev_policy **pol, | |||
char *name, char *val, | char *name, char *val, | |||
char *metadata) | char *metadata) | |||
{ | { | |||
pol_new(pol, name, val, metadata); | pol_new(pol, name, val, metadata); | |||
pol_sort(pol); | pol_sort(pol); | |||
pol_dedup(*pol); | pol_dedup(*pol); | |||
} | } | |||
static void free_paths(char **paths) | ||||
{ | ||||
int i; | ||||
if (!paths) | ||||
return; | ||||
for (i = 0; paths[i]; i++) | ||||
free(paths[i]); | ||||
free(paths); | ||||
} | ||||
/* | /* | |||
* disk_policy() gathers policy information for the | * disk_policy() gathers policy information for the | |||
* disk described in the given mdinfo (disk.{major,minor}). | * disk described in the given mdinfo (disk.{major,minor}). | |||
*/ | */ | |||
struct dev_policy *disk_policy(struct mdinfo *disk) | struct dev_policy *disk_policy(struct mdinfo *disk) | |||
{ | { | |||
char *path = NULL; | char **paths = NULL; | |||
char *type = disk_type(disk); | char *type = disk_type(disk); | |||
struct dev_policy *pol = NULL; | struct dev_policy *pol = NULL; | |||
if (config_rules_has_path) | if (config_rules_has_path) | |||
path = disk_path(disk); | paths = disk_paths(disk); | |||
pol = path_policy(path, type); | pol = path_policy(paths, type); | |||
free(path); | free_paths(paths); | |||
return pol; | return pol; | |||
} | } | |||
struct dev_policy *devid_policy(int dev) | struct dev_policy *devid_policy(int dev) | |||
{ | { | |||
struct mdinfo disk; | struct mdinfo disk; | |||
disk.disk.major = major(dev); | disk.disk.major = major(dev); | |||
disk.disk.minor = minor(dev); | disk.disk.minor = minor(dev); | |||
return disk_policy(&disk); | return disk_policy(&disk); | |||
} | } | |||
skipping to change at line 746 | skipping to change at line 764 | |||
} | } | |||
snprintf(path, PATH_MAX, FAILED_SLOTS_DIR "/%s", id_path); | snprintf(path, PATH_MAX, FAILED_SLOTS_DIR "/%s", id_path); | |||
f = fopen(path, "w"); | f = fopen(path, "w"); | |||
if (!f) { | if (!f) { | |||
pr_err("can't create file to save path to old disk: %s\n", | pr_err("can't create file to save path to old disk: %s\n", | |||
strerror(errno)); | strerror(errno)); | |||
return; | return; | |||
} | } | |||
if (fprintf(f, "%s %08x:%08x:%08x:%08x\n", | if (fprintf(f, "%20s %08x:%08x:%08x:%08x\n", | |||
array->metadata, | array->metadata, | |||
array->uuid[0], array->uuid[1], | array->uuid[0], array->uuid[1], | |||
array->uuid[2], array->uuid[3]) <= 0) | array->uuid[2], array->uuid[3]) <= 0) | |||
pr_err("Failed to write to <id_path> cookie\n"); | pr_err("Failed to write to <id_path> cookie\n"); | |||
fclose(f); | fclose(f); | |||
} | } | |||
int policy_check_path(struct mdinfo *disk, struct map_ent *array) | int policy_check_path(struct mdinfo *disk, struct map_ent *array) | |||
{ | { | |||
char path[PATH_MAX]; | char path[PATH_MAX]; | |||
FILE *f = NULL; | FILE *f = NULL; | |||
char *id_path = disk_path(disk); | char **id_paths = disk_paths(disk); | |||
int rv; | int i; | |||
int rv = 0; | ||||
if (!id_path) | ||||
return 0; | ||||
snprintf(path, PATH_MAX, FAILED_SLOTS_DIR "/%s", id_path); | for (i = 0; id_paths[i]; i++) { | |||
f = fopen(path, "r"); | snprintf(path, PATH_MAX, FAILED_SLOTS_DIR "/%s", id_paths[i]); | |||
if (!f) { | f = fopen(path, "r"); | |||
free(id_path); | if (!f) | |||
return 0; | continue; | |||
rv = fscanf(f, " %20s %x:%x:%x:%x\n", | ||||
array->metadata, | ||||
array->uuid, | ||||
array->uuid+1, | ||||
array->uuid+2, | ||||
array->uuid+3); | ||||
fclose(f); | ||||
break; | ||||
} | } | |||
free_paths(id_paths); | ||||
rv = fscanf(f, " %s %x:%x:%x:%x\n", | ||||
array->metadata, | ||||
array->uuid, | ||||
array->uuid+1, | ||||
array->uuid+2, | ||||
array->uuid+3); | ||||
fclose(f); | ||||
free(id_path); | ||||
return rv == 5; | return rv == 5; | |||
} | } | |||
/* invocation of udev rule file */ | /* invocation of udev rule file */ | |||
char udev_template_start[] = | char udev_template_start[] = | |||
"# do not edit this file, it is automatically generated by mdadm\n" | "# do not edit this file, it is automatically generated by mdadm\n" | |||
"\n"; | "\n"; | |||
/* find rule named rule_type and return its value */ | /* find rule named rule_type and return its value */ | |||
char *find_rule(struct rule *rule, char *rule_type) | char *find_rule(struct rule *rule, char *rule_type) | |||
End of changes. 27 change blocks. | ||||
77 lines changed or deleted | 92 lines changed or added |