fine-grained hwentry config override
authorChristophe Varoqui <christophe.varoqui@free.fr>
Tue, 20 May 2008 13:35:10 +0000 (15:35 +0200)
committerChristophe Varoqui <christophe.varoqui@free.fr>
Wed, 21 May 2008 20:01:19 +0000 (22:01 +0200)
== Before:
adding

device {
 vendor EMC
 product FOO
 checker tur
}

resets all hwentry vars not specified in the block to internal
defaults ... losing the precious bits in the internal default
hwtable.

== After:
adding the same block retains all info present in the
default hwtable and override only the bits specified in the conf
file.

libmultipath/config.c
libmultipath/dict.c

index 86c9a4b..a109cd9 100644 (file)
 #include "defaults.h"
 #include "prio.h"
 
-static struct hwentry *
-find_hwe_strmatch (vector hwtable, char * vendor, char * product, char * revision)
+static int
+hwe_strmatch (struct hwentry *hwe1, struct hwentry *hwe2)
 {
-       int i;
-       struct hwentry *hwe, *ret = NULL;
+       if (hwe1->vendor && hwe2->vendor && strcmp(hwe1->vendor, hwe2->vendor))
+               return 1;
 
-       vector_foreach_slot (hwtable, hwe, i) {
-               if (hwe->vendor && vendor && strcmp(hwe->vendor, vendor))
-                       continue;
+       if (hwe1->product && hwe2->product && strcmp(hwe1->product, hwe2->product))
+               return 1;
 
-               if (hwe->product && product && strcmp(hwe->product, product))
-                       continue;
+       if (hwe1->revision && hwe2->revision && strcmp(hwe1->revision, hwe2->revision))
+               return 1;
 
-               if (hwe->revision && revision && strcmp(hwe->revision, revision))
-                       continue;
+       return 0;
+}
+
+static struct hwentry *
+find_hwe_strmatch (vector hwtable, struct hwentry *hwe)
+{
+       int i;
+       struct hwentry *tmp, *ret = NULL;
 
-               ret = hwe;
+       vector_foreach_slot (hwtable, tmp, i) {
+               if (hwe_strmatch(tmp, hwe))
+                       continue;
+               ret = tmp;
                break;
        }
        return ret;
@@ -239,12 +247,47 @@ set_param_str(char * str)
        return dst;
 }
 
+#define merge_str(s) \
+       if (hwe2->s) { \
+               if (hwe1->s) \
+                       free(hwe1->s); \
+               if (!(hwe1->s = set_param_str(hwe2->s))) \
+                       return 1; \
+       }
+
+#define merge_num(s) \
+       if (hwe2->s) \
+               hwe1->s = hwe2->s
+
+
+static int
+merge_hwe (struct hwentry * hwe1, struct hwentry * hwe2)
+{
+       merge_str(vendor);
+       merge_str(product);
+       merge_str(revision);
+       merge_str(getuid);
+       merge_str(features);
+       merge_str(hwhandler);
+       merge_str(selector);
+       merge_str(checker_name);
+       merge_str(prio_name);
+       merge_str(bl_product);
+       merge_num(pgpolicy);
+       merge_num(pgfailback);
+       merge_num(rr_weight);
+       merge_num(no_path_retry);
+       merge_num(minio);
+
+       return 0;
+}
+
 int
 store_hwe (vector hwtable, struct hwentry * dhwe)
 {
        struct hwentry * hwe;
 
-       if (find_hwe_strmatch(hwtable, dhwe->vendor, dhwe->product, dhwe->revision))
+       if (find_hwe_strmatch(hwtable, dhwe))
                return 0;
        
        if (!(hwe = alloc_hwe()))
@@ -296,6 +339,27 @@ out:
        return 1;
 }
 
+static int
+factorize_hwtable (vector hw)
+{
+       struct hwentry *hwe1, *hwe2;
+       int i, j;
+
+       vector_foreach_slot(hw, hwe1, i) {
+               j = i+1;
+               vector_foreach_slot_after(hw, hwe2, j) {
+                       if (hwe_strmatch(hwe1, hwe2))
+                               continue;
+                       /* dup */
+                       merge_hwe(hwe1, hwe2);
+                       free_hwe(hwe2);
+                       vector_del_slot(hw, j);
+                       j--;
+               }
+       }
+       return 0;
+}
+
 struct config *
 alloc_config (void)
 {
@@ -365,6 +429,18 @@ load_config (char * file)
        conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
 
        /*
+        * preload default hwtable
+        */
+       if (conf->hwtable == NULL) {
+               conf->hwtable = vector_alloc();
+
+               if (!conf->hwtable)
+                       goto out;
+       }
+       if (setup_default_hwtable(conf->hwtable))
+               goto out;
+
+       /*
         * read the config file
         */
        if (filepresent(file)) {
@@ -376,17 +452,14 @@ load_config (char * file)
        }
 
        /*
-        * fill the voids left in the config file
+        * remove duplica in hwtable. config file takes precedence
+        * over build-in hwtable
         */
-       if (conf->hwtable == NULL) {
-               conf->hwtable = vector_alloc();
-
-               if (!conf->hwtable)
-                       goto out;
-       }
-       if (setup_default_hwtable(conf->hwtable))
-               goto out;
+       factorize_hwtable(conf->hwtable);
 
+       /*
+        * fill the voids left in the config file
+        */
        if (conf->blist_devnode == NULL) {
                conf->blist_devnode = vector_alloc();
 
index f851890..f5bca30 100644 (file)
@@ -418,7 +418,8 @@ ble_except_product_handler(vector strvec)
 static int
 devices_handler(vector strvec)
 {
-       conf->hwtable = vector_alloc();
+       if (!conf->hwtable)
+               conf->hwtable = vector_alloc();
 
        if (!conf->hwtable)
                return 1;