]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Policy is aware of metadata disk's controller domains.
authorMarcin Labun <marcin.labun@intel.com>
Mon, 22 Nov 2010 09:58:07 +0000 (20:58 +1100)
committerNeilBrown <neilb@suse.de>
Mon, 22 Nov 2010 09:58:07 +0000 (20:58 +1100)
Platform (metadata) domain let the metadata handlers differentiate
disk domains based on controllers that the disk belongs to.
Platform domain is sub-domain inside user specified domain
in mdadm.conf configuration files inheriting all parameters from it.
The metadata domain name is used disk domain matching functions.
The disk with the same metadata domain name belong to the same metadata
domain.

New metadata handler is added that retrieves platform domain string based
on disk path:
const char *(*get_disk_controller_domain)(const char *path);

Signed-off-by: Marcin Labun <marcin.labun@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
mdadm.h
policy.c
super-intel.c

diff --git a/mdadm.h b/mdadm.h
index 25d2bca3192d33d7bfd42a6bb2a0a839caa344f8..22e3d2cf791a3d42980ade0a6dd8fce2afb42a75 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -682,6 +682,21 @@ extern struct superswitch {
         */
        struct mdinfo *(*activate_spare)(struct active_array *a,
                                         struct metadata_update **updates);
+       /*
+        * Return statically allocated string that represents metadata specific
+        * controller domain of the disk. The domain is used in disk domain
+        * matching functions. Disks belong to the same domain if the they have
+        * the same domain from mdadm.conf and belong the same metadata domain.
+        * Returning NULL or not providing this handler means that metadata
+        * does not distinguish the differences between disks that belong to
+        * different controllers. They are in the domain specified by
+        * configuration file (mdadm.conf).
+        * In case when the metadata has the notion of domains based on disk
+        * it shall return NULL for disks that do not belong to the controller
+        * the supported domains. Such disks will form another domain and won't
+        * be mixed with supported ones.
+        */
+       const char *(*get_disk_controller_domain)(const char *path);
 
        int swapuuid; /* true if uuid is bigending rather than hostendian */
        int external;
@@ -768,7 +783,7 @@ struct dev_policy {
                         * name and metadata can be compared by address equality.
                         */
        const char *metadata;
-       char *value;
+       const char *value;
 };
 
 extern char pol_act[], pol_domain[], pol_metadata[], pol_auto[];
@@ -834,7 +849,7 @@ extern int disk_action_allows(struct mdinfo *disk, const char *metadata,
 
 struct domainlist {
        struct domainlist *next;
-       char *dom;
+       const char *dom;
 };
 
 extern int domain_test(struct domainlist *dom, struct dev_policy *pol,
index ad5850bd8244a8a1eae9a07595d3ad826355f7b0..ba976db1a7c0fc8374916b2a37a9641672592505 100644 (file)
--- a/policy.c
+++ b/policy.c
@@ -40,7 +40,8 @@
  * particularly from a set of policy rules in mdadm.conf
  */
 
-static void pol_new(struct dev_policy **pol, char *name, char *val, char *metadata)
+static void pol_new(struct dev_policy **pol, char *name, const char *val,
+                   const char *metadata)
 {
        struct dev_policy *n = malloc(sizeof(*n));
        const char *real_metadata = NULL;
@@ -64,7 +65,7 @@ static void pol_new(struct dev_policy **pol, char *name, char *val, char *metada
                                real_metadata = super1.name;
                }
                if (!real_metadata) {
-                       static char *prev = NULL;
+                       static const char *prev = NULL;
                        if (prev != metadata) {
                                fprintf(stderr, Name ": metadata=%s unrecognised - ignoring rule\n",
                                        metadata);
@@ -340,6 +341,7 @@ struct dev_policy *path_policy(char *path, char *type)
 {
        struct pol_rule *rules;
        struct dev_policy *pol = NULL;
+       int i;
 
        if (!type)
                return NULL;
@@ -360,6 +362,18 @@ struct dev_policy *path_policy(char *path, char *type)
                        }
                rules = rules->next;
        }
+
+       /* Now add any metadata-specific internal knowledge
+        * about this path
+        */
+       for (i=0; superlist[i]; i++)
+               if (superlist[i]->get_disk_controller_domain) {
+                       const char *d =
+                               superlist[i]->get_disk_controller_domain(path);
+                       if (d)
+                               pol_new(&pol, pol_domain, d, superlist[i]->name);
+               }
+
        pol_sort(&pol);
        pol_dedup(pol);
        return pol;
@@ -521,7 +535,7 @@ void dev_policy_free(struct dev_policy *p)
        }
 }
 
-static enum policy_action map_act(char *act)
+static enum policy_action map_act(const char *act)
 {
        if (strcmp(act, "include") == 0)
                return act_include;
@@ -581,7 +595,8 @@ int disk_action_allows(struct mdinfo *disk, const char *metadata, enum policy_ac
  * As dev policies are already sorted, this is fairly easy to manage.
  */
 
-static struct domainlist **domain_merge_one(struct domainlist **domp, char *domain)
+static struct domainlist **domain_merge_one(struct domainlist **domp,
+                                           const char *domain)
 {
        /* merge a domain name into a sorted list and return the
         * location of the insertion or match
@@ -601,6 +616,20 @@ static struct domainlist **domain_merge_one(struct domainlist **domp, char *doma
        return domp;
 }
 
+#if (DEBUG)
+void dump_policy(struct dev_policy *policy)
+{
+       while (policy) {
+               dprintf("policy: %p name: %s value: %s metadata: %s\n",
+                       policy,
+                       policy->name,
+                       policy->value,
+                       policy->metadata);
+               policy = policy->next;
+       }
+}
+#endif
+
 void domain_merge(struct domainlist **domp, struct dev_policy *pollist,
                         const char *metadata)
 {
index 805ee9975c9d8db65cb11d321736841b3c9ea398..7087af23af41e5aab5e7f1f61f71ccd9158487bd 100644 (file)
@@ -5635,6 +5635,41 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind
 }
 #endif /* MDASSEMBLE */
 
+static char disk_by_path[] = "/dev/disk/by-path/";
+
+static const char *imsm_get_disk_controller_domain(const char *path)
+{
+       struct sys_dev *list, *hba = NULL;
+       char disk_path[PATH_MAX];
+       int ahci = 0;
+       char *dpath = NULL;
+
+       list = find_driver_devices("pci", "ahci");
+       for (hba = list; hba; hba = hba->next)
+               if (devpath_to_vendor(hba->path) == 0x8086)
+                       break;
+
+       if (hba) {
+               struct stat st;
+
+               strncpy(disk_path, disk_by_path, PATH_MAX - 1);
+               strncat(disk_path, path, PATH_MAX - strlen(disk_path) - 1);
+               if (stat(disk_path, &st) == 0) {
+                       dpath = devt_to_devpath(st.st_rdev);
+                       if (dpath)
+                               ahci = path_attached_to_hba(dpath, hba->path);
+               }
+       }
+       dprintf("path: %s(%s) hba: %s attached: %d\n",
+               path, dpath, (hba) ? hba->path : "NULL", ahci);
+       free_sys_dev(&list);
+       if (ahci)
+               return "ahci";
+       else
+               return NULL;
+}
+
+
 struct superswitch super_imsm = {
 #ifndef        MDASSEMBLE
        .examine_super  = examine_super_imsm,
@@ -5670,6 +5705,7 @@ struct superswitch super_imsm = {
        .match_metadata_desc = match_metadata_desc_imsm,
        .container_content = container_content_imsm,
        .default_layout = imsm_level_to_layout,
+       .get_disk_controller_domain = imsm_get_disk_controller_domain,
 
        .external       = 1,
        .name = "imsm",