Add domain policy support.
A device can be in a number of domains. The domains of an array is the union of the domains of all devices. A device is allowed to join an array when its set of domains is a subset of the array's domains. Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
e3bb5f144b
commit
f5f12c84ac
14
mdadm.h
14
mdadm.h
|
@ -805,6 +805,20 @@ extern int policy_action_allows(struct dev_policy *plist, const char *metadata,
|
||||||
enum policy_action want);
|
enum policy_action want);
|
||||||
extern int disk_action_allows(struct mdinfo *disk, const char *metadata,
|
extern int disk_action_allows(struct mdinfo *disk, const char *metadata,
|
||||||
enum policy_action want);
|
enum policy_action want);
|
||||||
|
|
||||||
|
struct domainlist {
|
||||||
|
struct domainlist *next;
|
||||||
|
char *dom;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int domain_test(struct domainlist *dom, struct dev_policy *pol,
|
||||||
|
const char *metadata);
|
||||||
|
extern struct domainlist *domain_from_array(struct mdinfo *mdi,
|
||||||
|
const char *metadata);
|
||||||
|
extern void domain_free(struct domainlist *dl);
|
||||||
|
extern void domain_merge(struct domainlist **domp, struct dev_policy *pol,
|
||||||
|
const char *metadata);
|
||||||
|
|
||||||
#if __GNUC__ < 3
|
#if __GNUC__ < 3
|
||||||
struct stat64;
|
struct stat64;
|
||||||
#endif
|
#endif
|
||||||
|
|
89
policy.c
89
policy.c
|
@ -504,3 +504,92 @@ int disk_action_allows(struct mdinfo *disk, const char *metadata, enum policy_ac
|
||||||
dev_policy_free(pol);
|
dev_policy_free(pol);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Domain policy:
|
||||||
|
* Any device can have a list of domains asserted by different policy
|
||||||
|
* statements.
|
||||||
|
* An array also has a list of domains comprising all the domains of
|
||||||
|
* all the devices in an array.
|
||||||
|
* Where an array has a spare-group, that becomes an addition domain for
|
||||||
|
* every device in the array and thus for the array.
|
||||||
|
*
|
||||||
|
* We keep the list of domains in a sorted linked list
|
||||||
|
* As dev policies are already sorted, this is fairly easy to manage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct domainlist **domain_merge_one(struct domainlist **domp, char *domain)
|
||||||
|
{
|
||||||
|
/* merge a domain name into a sorted list and return the
|
||||||
|
* location of the insertion or match
|
||||||
|
*/
|
||||||
|
struct domainlist *dom = *domp;
|
||||||
|
|
||||||
|
while (dom && strcmp(dom->dom, domain) < 0) {
|
||||||
|
domp = &dom->next;
|
||||||
|
dom = *domp;
|
||||||
|
}
|
||||||
|
if (dom == NULL || strcmp(dom->dom, domain) != 0) {
|
||||||
|
dom = malloc(sizeof(*dom));
|
||||||
|
dom->next = *domp;
|
||||||
|
dom->dom = domain;
|
||||||
|
*domp = dom;
|
||||||
|
}
|
||||||
|
return domp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void domain_merge(struct domainlist **domp, struct dev_policy *pollist,
|
||||||
|
const char *metadata)
|
||||||
|
{
|
||||||
|
/* Add to 'domp' all the domains in pol that apply to 'metadata'
|
||||||
|
* which are not already in domp
|
||||||
|
*/
|
||||||
|
struct dev_policy *pol;
|
||||||
|
pollist = pol_find(pollist, pol_domain);
|
||||||
|
pol_for_each(pol, pollist, metadata)
|
||||||
|
domp = domain_merge_one(domp, pol->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int domain_test(struct domainlist *dom, struct dev_policy *pol,
|
||||||
|
const char *metadata)
|
||||||
|
{
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
int found_any = 0;
|
||||||
|
struct dev_policy *p;
|
||||||
|
|
||||||
|
pol = pol_find(pol, pol_domain);
|
||||||
|
pol_for_each(p, pol, metadata) {
|
||||||
|
found_any = 1;
|
||||||
|
while (dom && strcmp(dom->dom, pol->value) < 0)
|
||||||
|
dom = dom->next;
|
||||||
|
if (!dom || strcmp(dom->dom, pol->value) != 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return found_any;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct domainlist *domain_from_array(struct mdinfo *mdi, const char *metadata)
|
||||||
|
{
|
||||||
|
struct domainlist *domlist = NULL;
|
||||||
|
|
||||||
|
for (mdi = mdi->devs ; mdi ; mdi = mdi->next) {
|
||||||
|
struct dev_policy *pol = disk_policy(mdi);
|
||||||
|
|
||||||
|
domain_merge(&domlist, pol, metadata);
|
||||||
|
dev_policy_free(pol);
|
||||||
|
}
|
||||||
|
return domlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
void domain_free(struct domainlist *dl)
|
||||||
|
{
|
||||||
|
while (dl) {
|
||||||
|
struct domainlist *head = dl;
|
||||||
|
dl = dl->next;
|
||||||
|
free(head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue