char DefaultAltConfFile[] = CONFFILE2;
enum linetype { Devices, Array, Mailaddr, Mailfrom, Program, CreateDev,
- Homehost, AutoMode, LTEnd };
+ Homehost, AutoMode, Policy, PartPolicy, LTEnd };
char *keywords[] = {
[Devices] = "devices",
[Array] = "array",
[CreateDev]= "create",
[Homehost] = "homehost",
[AutoMode] = "auto",
+ [Policy] = "policy",
+ [PartPolicy]="part-policy",
[LTEnd] = NULL
};
char *name;
} *cdevlist = NULL;
-mddev_dev_t load_partitions(void)
+struct mddev_dev *load_partitions(void)
{
FILE *f = fopen("/proc/partitions", "r");
char buf[1024];
- mddev_dev_t rv = NULL;
+ struct mddev_dev *rv = NULL;
if (f == NULL) {
fprintf(stderr, Name ": cannot open /proc/partitions\n");
return NULL;
while (fgets(buf, 1024, f)) {
int major, minor;
char *name, *mp;
- mddev_dev_t d;
+ struct mddev_dev *d;
buf[1023] = '\0';
if (buf[0] != ' ')
d->devname = strdup(name);
d->next = rv;
d->used = 0;
- d->content = NULL;
rv = d;
}
fclose(f);
return rv;
}
-mddev_dev_t load_containers(void)
+struct mddev_dev *load_containers(void)
{
struct mdstat_ent *mdstat = mdstat_read(1, 0);
struct mdstat_ent *ent;
- mddev_dev_t d;
- mddev_dev_t rv = NULL;
+ struct mddev_dev *d;
+ struct mddev_dev *rv = NULL;
if (!mdstat)
return NULL;
}
d->next = rv;
d->used = 0;
- d->content = NULL;
rv = d;
}
free_mdstat(mdstat);
}
}
-mddev_ident_t mddevlist = NULL;
-mddev_ident_t *mddevlp = &mddevlist;
+struct mddev_ident *mddevlist = NULL;
+struct mddev_ident **mddevlp = &mddevlist;
static int is_number(char *w)
{
{
char *w;
- struct mddev_ident_s mis;
- mddev_ident_t mi;
+ struct mddev_ident mis;
+ struct mddev_ident *mi;
mis.uuid_set = 0;
mis.super_minor = UnSet;
w);
else {
char *endptr;
- mis.super_minor= strtol(w+12, &endptr, 10);
- if (w[12]==0 || endptr[0]!=0 || mis.super_minor < 0) {
+ int minor = strtol(w+12, &endptr, 10);
+
+ if (w[12]==0 || endptr[0]!=0 || minor < 0)
fprintf(stderr, Name ": invalid super-minor number: %s\n",
w);
- mis.super_minor = UnSet;
- }
+ else
+ mis.super_minor = minor;
}
} else if (strncasecmp(w, "name=", 5)==0) {
if (mis.name[0])
}
}
-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;
case AutoMode:
autoline(line);
break;
+ case Policy:
+ policyline(line, rule_policy);
+ break;
+ case PartPolicy:
+ policyline(line, rule_part);
+ break;
default:
fprintf(stderr, Name ": Unknown keyword %s\n", line);
}
return &createinfo;
}
-mddev_ident_t conf_get_ident(char *dev)
+struct mddev_ident *conf_get_ident(char *dev)
{
- mddev_ident_t rv;
+ struct mddev_ident *rv;
load_conffile();
rv = mddevlist;
while (dev && rv && (rv->devname == NULL
return rv;
}
-static void append_dlist(mddev_dev_t *dlp, mddev_dev_t list)
+static void append_dlist(struct mddev_dev **dlp, struct mddev_dev *list)
{
while (*dlp)
dlp = &(*dlp)->next;
*dlp = list;
}
-mddev_dev_t conf_get_devs()
+struct mddev_dev *conf_get_devs()
{
glob_t globbuf;
struct conf_dev *cd;
int flags = 0;
- static mddev_dev_t dlist = NULL;
+ static struct mddev_dev *dlist = NULL;
unsigned int i;
while (dlist) {
- mddev_dev_t t = dlist;
+ struct mddev_dev *t = dlist;
dlist = dlist->next;
free(t->devname);
free(t);
}
if (flags & GLOB_APPEND) {
for (i=0; i<globbuf.gl_pathc; i++) {
- mddev_dev_t t = malloc(sizeof(*t));
+ struct mddev_dev *t = malloc(sizeof(*t));
t->devname = strdup(globbuf.gl_pathv[i]);
t->next = dlist;
t->used = 0;
- t->content = NULL;
dlist = t;
/* printf("one dev is %s\n", t->devname);*/
}
return 0;
}
-int conf_test_metadata(const char *version)
+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.
- * Word 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.
+ /* 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)
+
+ pol = pol_find(pol, pol_auto);
+ pol_for_each(p, pol, version) {
+ if (strcmp(p->value, "yes") == 0)
return 1;
- if (strcasecmp(w, "no") == 0)
- return 0;
- 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;
}
* matches devname
*/
-
while (devices && *devices) {
char patn[1024];
char *p = devices;
* It can be taken either by a match on devname, name, or
* even super-minor.
*/
- mddev_ident_t dev;
+ struct mddev_ident *dev;
load_conffile();
for (dev = mddevlist; dev; dev = dev->next) {
return 1;
}
-struct mddev_ident_s *conf_match(struct mdinfo *info, struct supertype *st)
+struct mddev_ident *conf_match(struct mdinfo *info, struct supertype *st)
{
- struct mddev_ident_s *array_list, *match;
+ struct mddev_ident *array_list, *match;
int verbose = 0;
char *devname = NULL;
array_list = conf_get_ident(NULL);