]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Add domain policy support.
authorNeilBrown <neilb@suse.de>
Mon, 23 Aug 2010 05:36:08 +0000 (15:36 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 6 Sep 2010 01:26:27 +0000 (11:26 +1000)
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>
mdadm.h
policy.c

diff --git a/mdadm.h b/mdadm.h
index ce57f9e8bd32897d4d2bc6d064c7a006e588c7fe..1fe257459bac3f7cb4b84a54bad921384f52b824 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -805,6 +805,20 @@ extern int policy_action_allows(struct dev_policy *plist, const char *metadata,
                                enum policy_action want);
 extern int disk_action_allows(struct mdinfo *disk, const char *metadata,
                              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
 struct stat64;
 #endif
index 8b37ead60bc69b2ece0c00478d37c5a4c43be173..0e343b989748ee77a7913a985bc7a449508dc06a 100644 (file)
--- a/policy.c
+++ b/policy.c
@@ -504,3 +504,92 @@ int disk_action_allows(struct mdinfo *disk, const char *metadata, enum policy_ac
        dev_policy_free(pol);
        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);
+       }
+}