Add alias_prefix to get multipath names based on storage type
authorMalahal Naineni <malahal@us.ibm.com>
Wed, 23 Jun 2010 02:27:33 +0000 (19:27 -0700)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Fri, 16 Jul 2010 07:07:22 +0000 (09:07 +0200)
The current multipath tools use "mpath" prefix for all LUNs when
user_friendly_names is set. It would be nice if the names are generated
based on the storage subsystem. For example, all EMC LUNs would be named
emc_a, emc_b, elm_c etc., and all IBM's SVC LUNs would be named svc_a,
svc_b, svc_c. This patch attempts to do that using only multipath.conf.
Patches can be added to the internal hardware table, if needed.

Signed-off-by: Malahal Naineni (malahal@us.ibm.com)
libmultipath/alias.c
libmultipath/alias.h
libmultipath/config.c
libmultipath/config.h
libmultipath/defaults.h
libmultipath/dict.c
libmultipath/propsel.c
libmultipath/structs.h

index 95506b4..d4b94ee 100644 (file)
@@ -180,34 +180,35 @@ fail:
 }
 
 static int
-format_devname(char *name, int id, int len)
+format_devname(char *name, int id, int len, char *prefix)
 {
        int pos;
+       int prefix_len = strlen(prefix);
 
        memset(name,0, len);
-       strcpy(name,"mpath");
-       for (pos = len - 1; pos >= 5; pos--) {
+       strcpy(name, prefix);
+       for (pos = len - 1; pos >= prefix_len; pos--) {
                name[pos] = 'a' + id % 26;
                if (id < 26)
                        break;
                id /= 26;
                id--;
        }
-       memmove(name + 5, name + pos, len - pos);
-       name[5 + len - pos] = '\0';
-       return (5 + len - pos);
+       memmove(name + prefix_len, name + pos, len - pos);
+       name[prefix_len + len - pos] = '\0';
+       return (prefix_len + len - pos);
 }
 
 static int
-scan_devname(char *alias)
+scan_devname(char *alias, char *prefix)
 {
        char *c;
        int i, n = 0;
 
-       if (strncmp(alias, "mpath", 5))
+       if (!prefix || strncmp(alias, prefix, strlen(prefix)))
                return -1;
 
-       c = alias + 5;
+       c = alias + strlen(prefix);
        while (*c != '\0' && *c != ' ' && *c != '\t') {
                i = *c - 'a';
                n = ( n * 26 ) + i;
@@ -221,7 +222,7 @@ scan_devname(char *alias)
 }
 
 static int
-lookup_binding(FILE *f, char *map_wwid, char **map_alias)
+lookup_binding(FILE *f, char *map_wwid, char **map_alias, char *prefix)
 {
        char buf[LINE_MAX];
        unsigned int line_nr = 0;
@@ -240,7 +241,7 @@ lookup_binding(FILE *f, char *map_wwid, char **map_alias)
                alias = strtok(buf, " \t");
                if (!alias) /* blank line */
                        continue;
-               curr_id = scan_devname(alias);
+               curr_id = scan_devname(alias, prefix);
                if (curr_id >= id)
                        id = curr_id + 1;
                wwid = strtok(NULL, "");
@@ -284,7 +285,7 @@ rlookup_binding(FILE *f, char **map_wwid, char *map_alias)
                alias = strtok(buf, " \t");
                if (!alias) /* blank line */
                        continue;
-               curr_id = scan_devname(alias);
+               curr_id = scan_devname(alias, NULL); /* TBD: Why this call? */
                if (curr_id >= id)
                        id = curr_id + 1;
                wwid = strtok(NULL, " \t");
@@ -309,7 +310,7 @@ rlookup_binding(FILE *f, char **map_wwid, char *map_alias)
 }
 
 static char *
-allocate_binding(int fd, char *wwid, int id)
+allocate_binding(int fd, char *wwid, int id, char *prefix)
 {
        char buf[LINE_MAX];
        off_t offset;
@@ -321,7 +322,7 @@ allocate_binding(int fd, char *wwid, int id)
                return NULL;
        }
 
-       i = format_devname(buf, id, LINE_MAX);
+       i = format_devname(buf, id, LINE_MAX, prefix);
        c = buf + i;
        snprintf(c,LINE_MAX - i, " %s\n", wwid);
        buf[LINE_MAX - 1] = '\0';
@@ -352,7 +353,7 @@ allocate_binding(int fd, char *wwid, int id)
 }
 
 char *
-get_user_friendly_alias(char *wwid, char *file)
+get_user_friendly_alias(char *wwid, char *file, char *prefix)
 {
        char *alias;
        int fd, scan_fd, id;
@@ -385,7 +386,7 @@ get_user_friendly_alias(char *wwid, char *file)
                return NULL;
        }
 
-       id = lookup_binding(f, wwid, &alias);
+       id = lookup_binding(f, wwid, &alias, prefix);
        if (id < 0) {
                fclose(f);
                close(scan_fd);
@@ -394,7 +395,7 @@ get_user_friendly_alias(char *wwid, char *file)
        }
 
        if (!alias && can_write)
-               alias = allocate_binding(fd, wwid, id);
+               alias = allocate_binding(fd, wwid, id, prefix);
 
        fclose(f);
        close(scan_fd);
index fe1191b..832959b 100644 (file)
@@ -8,5 +8,5 @@
 "# alias wwid\n" \
 "#\n"
 
-char *get_user_friendly_alias(char *wwid, char *file);
+char *get_user_friendly_alias(char *wwid, char *file, char *prefix);
 char *get_user_friendly_wwid(char *alias, char *file);
index a4178be..0083cfb 100644 (file)
@@ -158,6 +158,9 @@ free_hwe (struct hwentry * hwe)
        if (hwe->prio_args)
                FREE(hwe->prio_args);
 
+       if (hwe->alias_prefix)
+               FREE(hwe->alias_prefix);
+
        if (hwe->bl_product)
                FREE(hwe->bl_product);
 
@@ -282,6 +285,7 @@ merge_hwe (struct hwentry * hwe1, struct hwentry * hwe2)
        merge_str(checker_name);
        merge_str(prio_name);
        merge_str(prio_args);
+       merge_str(alias_prefix);
        merge_str(bl_product);
        merge_num(pgpolicy);
        merge_num(pgfailback);
@@ -333,6 +337,9 @@ store_hwe (vector hwtable, struct hwentry * dhwe)
        if (dhwe->prio_args && !(hwe->prio_args = set_param_str(dhwe->prio_args)))
                goto out;
 
+       if (dhwe->alias_prefix && !(hwe->alias_prefix = set_param_str(dhwe->alias_prefix)))
+               goto out;
+
        hwe->pgpolicy = dhwe->pgpolicy;
        hwe->pgfailback = dhwe->pgfailback;
        hwe->rr_weight = dhwe->rr_weight;
@@ -409,6 +416,9 @@ free_config (struct config * conf)
        if (conf->prio_name)
                FREE(conf->prio_name);
 
+       if (conf->alias_prefix)
+               FREE(conf->alias_prefix);
+
        if (conf->prio_args)
                FREE(conf->prio_args);
 
index 471eed0..18bfff9 100644 (file)
@@ -25,6 +25,7 @@ struct hwentry {
        char * checker_name;
        char * prio_name;
        char * prio_args;
+       char * alias_prefix;
 
        int pgpolicy;
        int pgfailback;
@@ -99,6 +100,7 @@ struct config {
        char * prio_name;
        char * prio_args;
        char * checker_name;
+       char * alias_prefix;
 
        vector keywords;
        vector mptable;
index 5a38d25..77526dd 100644 (file)
@@ -2,6 +2,7 @@
 #define DEFAULT_UDEVDIR                "/dev"
 #define DEFAULT_MULTIPATHDIR   "/" LIB_STRING "/multipath"
 #define DEFAULT_SELECTOR       "round-robin 0"
+#define DEFAULT_ALIAS_PREFIX   "mpath"
 #define DEFAULT_FEATURES       "0"
 #define DEFAULT_HWHANDLER      "0"
 #define DEFAULT_MINIO          1000
index 02aa238..62f0f21 100644 (file)
@@ -147,6 +147,17 @@ def_prio_handler(vector strvec)
        return 0;
 }
 
+static int
+def_alias_prefix_handler(vector strvec)
+{
+       conf->alias_prefix = set_value(strvec);
+
+       if (!conf->alias_prefix)
+               return 1;
+
+       return 0;
+}
+
 static int
 def_prio_args_handler(vector strvec)
 {
@@ -830,6 +841,22 @@ hw_prio_handler(vector strvec)
        return 0;
 }
 
+static int
+hw_alias_prefix_handler(vector strvec)
+{
+       struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
+
+       if (!hwe)
+               return 1;
+
+       hwe->alias_prefix = set_value(strvec);
+
+       if (!hwe->alias_prefix)
+               return 1;
+
+       return 0;
+}
+
 static int
 hw_prio_args_handler(vector strvec)
 {
@@ -1579,6 +1606,19 @@ snprint_hw_prio (char * buff, int len, void * data)
        return snprintf(buff, len, "%s", hwe->prio_name);
 }
 
+static int
+snprint_hw_alias_prefix (char * buff, int len, void * data)
+{
+       struct hwentry * hwe = (struct hwentry *)data;
+
+       if (!hwe->alias_prefix || (strlen(hwe->alias_prefix) == 0))
+               return 0;
+       if (conf->alias_prefix && !strcmp(hwe->alias_prefix, conf->alias_prefix))
+               return 0;
+
+       return snprintf(buff, len, "%s", hwe->alias_prefix);
+}
+
 static int
 snprint_hw_prio_args (char * buff, int len, void * data)
 {
@@ -2075,6 +2115,16 @@ snprint_def_user_friendly_names (char * buff, int len, void * data)
        return snprintf(buff, len, "yes");
 }
 
+static int
+snprint_def_alias_prefix (char * buff, int len, void * data)
+{
+       if (!conf->alias_prefix)
+               return 0;
+       if (!strcmp(conf->alias_prefix, DEFAULT_ALIAS_PREFIX))
+               return 0;
+       return snprintf(buff, len, conf->alias_prefix);
+}
+
 static int
 snprint_ble_simple (char * buff, int len, void * data)
 {
@@ -2117,6 +2167,7 @@ init_keywords(void)
        install_keyword("features", &def_features_handler, &snprint_def_features);
        install_keyword("path_checker", &def_path_checker_handler, &snprint_def_path_checker);
        install_keyword("checker", &def_path_checker_handler, &snprint_def_path_checker);
+       install_keyword("alias_prefix", &def_alias_prefix_handler, &snprint_def_alias_prefix);
        install_keyword("failback", &default_failback_handler, &snprint_def_failback);
        install_keyword("rr_min_io", &def_minio_handler, &snprint_def_rr_min_io);
        install_keyword("max_fds", &max_fds_handler, &snprint_max_fds);
@@ -2176,6 +2227,7 @@ init_keywords(void)
        install_keyword("path_selector", &hw_selector_handler, &snprint_hw_selector);
        install_keyword("path_checker", &hw_path_checker_handler, &snprint_hw_path_checker);
        install_keyword("checker", &hw_path_checker_handler, &snprint_hw_path_checker);
+       install_keyword("alias_prefix", &hw_alias_prefix_handler, &snprint_hw_alias_prefix);
        install_keyword("features", &hw_features_handler, &snprint_hw_features);
        install_keyword("hardware_handler", &hw_handler_handler, &snprint_hw_hardware_handler);
        install_keyword("prio", &hw_prio_handler, &snprint_hw_prio);
index 2187558..ee4109e 100644 (file)
@@ -215,6 +215,26 @@ select_selector (struct multipath * mp)
        return 0;
 }
 
+static void
+select_alias_prefix (struct multipath * mp)
+{
+       if (mp->hwe && mp->hwe->alias_prefix) {
+               mp->alias_prefix = mp->hwe->alias_prefix;
+               condlog(3, "%s: alias_prefix = %s (controller setting)",
+                       mp->wwid, mp->alias_prefix);
+               return;
+       }
+       if (conf->alias_prefix) {
+               mp->alias_prefix = conf->alias_prefix;
+               condlog(3, "%s: alias_prefix = %s (config file default)",
+                       mp->wwid, mp->alias_prefix);
+               return;
+       }
+       mp->alias_prefix = set_default(DEFAULT_ALIAS_PREFIX);
+       condlog(3, "%s: alias_prefix = %s (internal default)",
+               mp->wwid, mp->alias_prefix);
+}
+
 extern int
 select_alias (struct multipath * mp)
 {
@@ -222,9 +242,11 @@ select_alias (struct multipath * mp)
                mp->alias = mp->mpe->alias;
        else {
                mp->alias = NULL;
-               if (conf->user_friendly_names)
+               if (conf->user_friendly_names) {
+                       select_alias_prefix(mp);
                        mp->alias = get_user_friendly_alias(mp->wwid,
-                                       conf->bindings_file);
+                                       conf->bindings_file, mp->alias_prefix);
+               }
                if (mp->alias == NULL){
                        char *alias;
                        if ((alias = MALLOC(WWID_SIZE)) != NULL){
index c559838..fc6413b 100644 (file)
@@ -186,6 +186,7 @@ struct multipath {
 
        /* configlet pointers */
        char * alias;
+       char * alias_prefix;
        char * selector;
        char * features;
        char * hwhandler;