Convert 'auto' config line to policy statements
This commit is contained in:
parent
61018da020
commit
4e8d9f0a16
|
@ -230,6 +230,7 @@ int Assemble(struct supertype *st, char *mddev,
|
|||
int dfd;
|
||||
struct stat stb;
|
||||
struct supertype *tst = dup_super(st);
|
||||
struct dev_policy *pol = NULL;
|
||||
|
||||
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 &&
|
||||
!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 "
|
||||
|
@ -403,6 +404,7 @@ int Assemble(struct supertype *st, char *mddev,
|
|||
devname);
|
||||
if (st)
|
||||
st->ss->free_super(st);
|
||||
dev_policy_free(pol);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -424,6 +426,7 @@ int Assemble(struct supertype *st, char *mddev,
|
|||
content = NULL;
|
||||
if (auto_assem)
|
||||
goto loop;
|
||||
dev_policy_free(pol);
|
||||
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);
|
||||
dev_policy_free(pol);
|
||||
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);
|
||||
dev_policy_free(pol);
|
||||
return 1;
|
||||
}
|
||||
|
||||
tmpdev->used = 1;
|
||||
|
||||
loop:
|
||||
dev_policy_free(pol);
|
||||
pol = NULL;
|
||||
if (tmpdev->content)
|
||||
goto next_member;
|
||||
if (tst)
|
||||
|
|
|
@ -246,7 +246,7 @@ int Incremental(char *devname, int verbose, int runstop,
|
|||
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
|
||||
|
|
176
config.c
176
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;
|
||||
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;
|
||||
}
|
||||
/* 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;
|
||||
|
@ -900,64 +989,30 @@ int conf_test_dev(char *devname)
|
|||
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();
|
||||
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)
|
||||
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;
|
||||
pol = pol_find(pol, pol_auto);
|
||||
pol_for_each(p, pol, version) {
|
||||
if (strcmp(p->value, "yes") == 0)
|
||||
return 1;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -967,7 +1022,6 @@ int match_oneof(char *devices, char *devname)
|
|||
* matches devname
|
||||
*/
|
||||
|
||||
|
||||
while (devices && *devices) {
|
||||
char patn[1024];
|
||||
char *p = devices;
|
||||
|
|
6
mdadm.h
6
mdadm.h
|
@ -757,7 +757,7 @@ struct dev_policy {
|
|||
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
|
||||
|
@ -790,10 +790,12 @@ extern char rule_path[], rule_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 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);
|
||||
|
@ -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 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);
|
||||
|
|
42
policy.c
42
policy.c
|
@ -389,6 +389,14 @@ struct dev_policy *disk_policy(struct mdinfo *disk)
|
|||
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.
|
||||
*/
|
||||
|
@ -402,6 +410,7 @@ char rule_part[] = "part-policy";
|
|||
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)
|
||||
{
|
||||
|
@ -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) &&
|
||||
! 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);
|
||||
}
|
||||
|
@ -444,6 +454,32 @@ void policyline(char *line, char *type)
|
|||
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) {
|
||||
|
@ -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;
|
||||
while (dom && strcmp(dom->dom, pol->value) < 0)
|
||||
while (dom && strcmp(dom->dom, p->value) < 0)
|
||||
dom = dom->next;
|
||||
if (!dom || strcmp(dom->dom, pol->value) != 0)
|
||||
if (!dom || strcmp(dom->dom, p->value) != 0)
|
||||
return 0;
|
||||
}
|
||||
return found_any;
|
||||
|
|
Loading…
Reference in New Issue