summaryrefslogtreecommitdiffstats
path: root/0112-RHBZ-1194917-add-config_dir-option.patch
diff options
context:
space:
mode:
Diffstat (limited to '0112-RHBZ-1194917-add-config_dir-option.patch')
-rw-r--r--0112-RHBZ-1194917-add-config_dir-option.patch616
1 files changed, 616 insertions, 0 deletions
diff --git a/0112-RHBZ-1194917-add-config_dir-option.patch b/0112-RHBZ-1194917-add-config_dir-option.patch
new file mode 100644
index 0000000..e322614
--- /dev/null
+++ b/0112-RHBZ-1194917-add-config_dir-option.patch
@@ -0,0 +1,616 @@
+---
+ libmultipath/config.c | 56 +++++++++++++++++++++++++++++++-
+ libmultipath/config.h | 2 +
+ libmultipath/defaults.h | 1
+ libmultipath/dict.c | 69 +++++++++++++++++++++++++++++++++++----
+ libmultipath/parser.c | 78 +++++++++++++++++++++++----------------------
+ libmultipath/parser.h | 3 -
+ multipath.conf.annotated | 10 +++++
+ multipath.conf.defaults | 1
+ multipath/multipath.conf.5 | 7 ++++
+ 9 files changed, 179 insertions(+), 48 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/parser.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/parser.c
++++ multipath-tools-130222/libmultipath/parser.c
+@@ -18,6 +18,7 @@
+ */
+
+ #include <syslog.h>
++#include <errno.h>
+
+ #include "parser.h"
+ #include "memory.h"
+@@ -453,14 +454,15 @@ set_value(vector strvec)
+ /* non-recursive configuration stream handler */
+ static int kw_level = 0;
+
+-int warn_on_duplicates(vector uniques, char *str)
++int warn_on_duplicates(vector uniques, char *str, char *file)
+ {
+ char *tmp;
+ int i;
+
+ vector_foreach_slot(uniques, tmp, i) {
+ if (!strcmp(str, tmp)) {
+- condlog(1, "multipath.conf line %d, duplicate keyword: %s", line_nr, str);
++ condlog(1, "%s line %d, duplicate keyword: %s",
++ file, line_nr, str);
+ return 0;
+ }
+ }
+@@ -496,65 +498,70 @@ is_sublevel_keyword(char *str)
+ }
+
+ int
+-validate_config_strvec(vector strvec)
++validate_config_strvec(vector strvec, char *file)
+ {
+ char *str;
+ int i;
+
+ str = VECTOR_SLOT(strvec, 0);
+ if (str == NULL) {
+- condlog(0, "can't parse option on line %d of config file",
+- line_nr);
++ condlog(0, "can't parse option on line %d of %s",
++ line_nr, file);
+ return -1;
+ }
+ if (*str == '}') {
+ if (VECTOR_SIZE(strvec) > 1)
+- condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 1), line_nr);
++ condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, 1), line_nr, file);
+ return 0;
+ }
+ if (*str == '{') {
+- condlog(0, "invalid keyword '%s' on line %d of config file", str, line_nr);
++ condlog(0, "invalid keyword '%s' on line %d of %s",
++ str, line_nr, file);
+ return -1;
+ }
+ if (is_sublevel_keyword(str)) {
+ str = VECTOR_SLOT(strvec, 1);
+ if (str == NULL)
+- condlog(0, "missing '{' on line %d of config file", line_nr);
++ condlog(0, "missing '{' on line %d of %s",
++ line_nr, file);
+ else if (*str != '{')
+- condlog(0, "expecting '{' on line %d of config file. found '%s'", line_nr, str);
++ condlog(0, "expecting '{' on line %d of %s. found '%s'",
++ line_nr, file, str);
+ else if (VECTOR_SIZE(strvec) > 2)
+- condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr);
++ condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, 2), line_nr, file);
+ return 0;
+ }
+ str = VECTOR_SLOT(strvec, 1);
+ if (str == NULL) {
+- condlog(0, "missing value for option '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 0), line_nr);
++ condlog(0, "missing value for option '%s' on line %d of %s",
++ (char *)VECTOR_SLOT(strvec, 0), line_nr, file);
+ return -1;
+ }
+ if (*str != '"') {
+ if (VECTOR_SIZE(strvec) > 2)
+- condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr);
++ condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, 2), line_nr, file);
+ return 0;
+ }
+ for (i = 2; i < VECTOR_SIZE(strvec); i++) {
+ str = VECTOR_SLOT(strvec, i);
+ if (str == NULL) {
+- condlog(0, "can't parse value on line %d of config file", line_nr);
++ condlog(0, "can't parse value on line %d of %s",
++ line_nr, file);
+ return -1;
+ }
+ if (*str == '"') {
+ if (VECTOR_SIZE(strvec) > i + 1)
+- condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, (i + 1)), line_nr);
++ condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, (i + 1)), line_nr, file);
+ return 0;
+ }
+ }
+- condlog(0, "missing closing quotes on line %d of config file",
+- line_nr);
++ condlog(0, "missing closing quotes on line %d of %s",
++ line_nr, file);
+ return 0;
+ }
+
+-int
+-process_stream(vector keywords)
++static int
++process_stream(vector keywords, char *file)
+ {
+ int i;
+ int r = 0;
+@@ -583,7 +590,7 @@ process_stream(vector keywords)
+ if (!strvec)
+ continue;
+
+- if (validate_config_strvec(strvec) != 0) {
++ if (validate_config_strvec(strvec, file) != 0) {
+ free_strvec(strvec);
+ continue;
+ }
+@@ -595,8 +602,8 @@ process_stream(vector keywords)
+ free_strvec(strvec);
+ break;
+ }
+- condlog(0, "unmatched '%s' at line %d of config file",
+- EOB, line_nr);
++ condlog(0, "unmatched '%s' at line %d of %s",
++ EOB, line_nr, file);
+ }
+
+ for (i = 0; i < VECTOR_SIZE(keywords); i++) {
+@@ -604,7 +611,7 @@ process_stream(vector keywords)
+
+ if (!strcmp(keyword->string, str)) {
+ if (keyword->unique &&
+- warn_on_duplicates(uniques, str)) {
++ warn_on_duplicates(uniques, str, file)) {
+ r = 1;
+ free_strvec(strvec);
+ goto out;
+@@ -614,15 +621,15 @@ process_stream(vector keywords)
+
+ if (keyword->sub) {
+ kw_level++;
+- r += process_stream(keyword->sub);
++ r += process_stream(keyword->sub, file);
+ kw_level--;
+ }
+ break;
+ }
+ }
+ if (i >= VECTOR_SIZE(keywords))
+- condlog(1, "multipath.conf +%d, invalid keyword: %s",
+- line_nr, str);
++ condlog(1, "%s line %d, invalid keyword: %s",
++ file, line_nr, str);
+
+ free_strvec(strvec);
+ }
+@@ -646,27 +653,24 @@ int alloc_keywords(void)
+
+ /* Data initialization */
+ int
+-init_data(char *conf_file, void (*init_keywords) (void))
++process_file(char *file)
+ {
+ int r;
+
+- stream = fopen(conf_file, "r");
++ if (!keywords) {
++ condlog(0, "No keywords alocated");
++ return 1;
++ }
++ stream = fopen(file, "r");
+ if (!stream) {
+- syslog(LOG_WARNING, "Configuration file open problem");
++ condlog(0, "couldn't open configuration file '%s': %s",
++ file, strerror(errno));
+ return 1;
+ }
+
+- /* Init Keywords structure */
+- (*init_keywords) ();
+-
+-/* Dump configuration *
+- vector_dump(keywords);
+- dump_keywords(keywords, 0);
+-*/
+-
+ /* Stream handling */
+ line_nr = 0;
+- r = process_stream(keywords);
++ r = process_stream(keywords, file);
+ fclose(stream);
+ //free_keywords(keywords);
+
+Index: multipath-tools-130222/libmultipath/dict.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/dict.c
++++ multipath-tools-130222/libmultipath/dict.c
+@@ -117,6 +117,8 @@ reassign_maps_handler(vector strvec)
+ static int
+ multipath_dir_handler(vector strvec)
+ {
++ if (conf->multipath_dir)
++ FREE(conf->multipath_dir);
+ conf->multipath_dir = set_value(strvec);
+
+ if (!conf->multipath_dir)
+@@ -128,6 +130,8 @@ multipath_dir_handler(vector strvec)
+ static int
+ def_selector_handler(vector strvec)
+ {
++ if (conf->selector)
++ FREE(conf->selector);
+ conf->selector = set_value(strvec);
+
+ if (!conf->selector)
+@@ -155,6 +159,8 @@ def_pgpolicy_handler(vector strvec)
+ static int
+ def_uid_attribute_handler(vector strvec)
+ {
++ if (conf->uid_attribute)
++ FREE(conf->uid_attribute);
+ conf->uid_attribute = set_value(strvec);
+
+ if (!conf->uid_attribute)
+@@ -166,6 +172,8 @@ def_uid_attribute_handler(vector strvec)
+ static int
+ def_prio_handler(vector strvec)
+ {
++ if (conf->prio_name)
++ FREE(conf->prio_name);
+ conf->prio_name = set_value(strvec);
+
+ if (!conf->prio_name)
+@@ -177,6 +185,8 @@ def_prio_handler(vector strvec)
+ static int
+ def_alias_prefix_handler(vector strvec)
+ {
++ if (conf->alias_prefix)
++ FREE(conf->alias_prefix);
+ conf->alias_prefix = set_value(strvec);
+
+ if (!conf->alias_prefix)
+@@ -188,6 +198,8 @@ def_alias_prefix_handler(vector strvec)
+ static int
+ def_prio_args_handler(vector strvec)
+ {
++ if (conf->prio_args)
++ FREE(conf->prio_args);
+ conf->prio_args = set_value(strvec);
+
+ if (!conf->prio_args)
+@@ -199,6 +211,8 @@ def_prio_args_handler(vector strvec)
+ static int
+ def_features_handler(vector strvec)
+ {
++ if (conf->features)
++ FREE(conf->features);
+ conf->features = set_value(strvec);
+
+ if (!conf->features)
+@@ -210,6 +224,8 @@ def_features_handler(vector strvec)
+ static int
+ def_path_checker_handler(vector strvec)
+ {
++ if (conf->checker_name)
++ FREE(conf->checker_name);
+ conf->checker_name = set_value(strvec);
+
+ if (!conf->checker_name)
+@@ -432,6 +448,23 @@ def_no_path_retry_handler(vector strvec)
+ return 0;
+ }
+
++
++static int
++def_config_dir_handler(vector strvec)
++{
++ /* this is only valid in the main config file */
++ if (conf->processed_main_config)
++ return 0;
++ if (conf->config_dir)
++ FREE(conf->config_dir);
++ conf->config_dir = set_value(strvec);
++
++ if (!conf->config_dir)
++ return 1;
++
++ return 0;
++}
++
+ static int
+ def_queue_without_daemon(vector strvec)
+ {
+@@ -611,6 +644,8 @@ def_names_handler(vector strvec)
+ static int
+ bindings_file_handler(vector strvec)
+ {
++ if (conf->bindings_file)
++ FREE(conf->bindings_file);
+ conf->bindings_file = set_value(strvec);
+
+ if (!conf->bindings_file)
+@@ -622,6 +657,8 @@ bindings_file_handler(vector strvec)
+ static int
+ wwids_file_handler(vector strvec)
+ {
++ if (conf->wwids_file)
++ FREE(conf->wwids_file);
+ conf->wwids_file = set_value(strvec);
+
+ if (!conf->wwids_file)
+@@ -770,9 +807,12 @@ def_ignore_new_boot_devs_handler(vector
+ static int
+ blacklist_handler(vector strvec)
+ {
+- conf->blist_devnode = vector_alloc();
+- conf->blist_wwid = vector_alloc();
+- conf->blist_device = vector_alloc();
++ if (!conf->blist_devnode)
++ conf->blist_devnode = vector_alloc();
++ if (!conf->blist_wwid)
++ conf->blist_wwid = vector_alloc();
++ if (!conf->blist_device)
++ conf->blist_device = vector_alloc();
+
+ if (!conf->blist_devnode || !conf->blist_wwid || !conf->blist_device)
+ return 1;
+@@ -783,9 +823,12 @@ blacklist_handler(vector strvec)
+ static int
+ blacklist_exceptions_handler(vector strvec)
+ {
+- conf->elist_devnode = vector_alloc();
+- conf->elist_wwid = vector_alloc();
+- conf->elist_device = vector_alloc();
++ if (!conf->elist_devnode)
++ conf->elist_devnode = vector_alloc();
++ if (!conf->elist_wwid)
++ conf->elist_wwid = vector_alloc();
++ if (!conf->elist_device)
++ conf->elist_device = vector_alloc();
+
+ if (!conf->elist_devnode || !conf->elist_wwid || !conf->elist_device)
+ return 1;
+@@ -1480,7 +1523,8 @@ hw_deferred_remove_handler(vector strvec
+ static int
+ multipaths_handler(vector strvec)
+ {
+- conf->mptable = vector_alloc();
++ if (!conf->mptable)
++ conf->mptable = vector_alloc();
+
+ if (!conf->mptable)
+ return 1;
+@@ -2945,6 +2989,16 @@ snprint_def_ignore_new_boot_devs(char *
+ return snprintf(buff, len, "no");
+ }
+
++
++static int
++snprint_def_config_dir (char * buff, int len, void * data)
++{
++ if (!conf->config_dir)
++ return 0;
++
++ return snprintf(buff, len, "\"%s\"", conf->config_dir);
++}
++
+ static int
+ snprint_ble_simple (char * buff, int len, void * data)
+ {
+@@ -3016,6 +3070,7 @@ init_keywords(void)
+ install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync);
+ install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove);
+ install_keyword("ignore_new_boot_devs", &def_ignore_new_boot_devs_handler, &snprint_def_ignore_new_boot_devs);
++ install_keyword("config_dir", &def_config_dir_handler, &snprint_def_config_dir);
+ __deprecated install_keyword("default_selector", &def_selector_handler, NULL);
+ __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
+ __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL);
+Index: multipath-tools-130222/libmultipath/parser.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/parser.h
++++ multipath-tools-130222/libmultipath/parser.h
+@@ -76,9 +76,8 @@ extern int read_line(char *buf, int size
+ extern vector read_value_block(void);
+ extern int alloc_value_block(vector strvec, void (*alloc_func) (vector));
+ extern void *set_value(vector strvec);
+-extern int process_stream(vector keywords);
+ extern int alloc_keywords(void);
+-extern int init_data(char *conf_file, void (*init_keywords) (void));
++extern int process_file(char *conf_file);
+ extern struct keyword * find_keyword(vector v, char * name);
+ void set_current_keywords (vector *k);
+ int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw,
+Index: multipath-tools-130222/libmultipath/config.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/config.c
++++ multipath-tools-130222/libmultipath/config.c
+@@ -6,6 +6,9 @@
+ #include <stdio.h>
+ #include <string.h>
+ #include <libudev.h>
++#include <dirent.h>
++#include <limits.h>
++#include <errno.h>
+
+ #include "checkers.h"
+ #include "memory.h"
+@@ -556,6 +559,7 @@ free_config (struct config * conf)
+
+ if (conf->wwids_file)
+ FREE(conf->wwids_file);
++
+ if (conf->prio_name)
+ FREE(conf->prio_name);
+
+@@ -567,6 +571,10 @@ free_config (struct config * conf)
+
+ if (conf->checker_name)
+ FREE(conf->checker_name);
++
++ if (conf->config_dir)
++ FREE(conf->config_dir);
++
+ if (conf->reservation_key)
+ FREE(conf->reservation_key);
+
+@@ -584,6 +592,43 @@ free_config (struct config * conf)
+ FREE(conf);
+ }
+
++/* if multipath fails to process the config directory, it should continue,
++ * with just a warning message */
++static void
++process_config_dir(vector keywords, char *dir)
++{
++ struct dirent **namelist;
++ int i, n;
++ char path[LINE_MAX];
++ int old_hwtable_size;
++
++ if (dir[0] != '/') {
++ condlog(1, "config_dir '%s' must be a fully qualified path",
++ dir);
++ return;
++ }
++ n = scandir(dir, &namelist, NULL, alphasort);
++ if (n < 0) {
++ if (errno == ENOENT)
++ condlog(3, "No configuration dir '%s'", dir);
++ else
++ condlog(0, "couldn't open configuration dir '%s': %s",
++ dir, strerror(errno));
++ return;
++ }
++ for (i = 0; i < n; i++) {
++ if (!strstr(namelist[i]->d_name, ".conf"))
++ continue;
++ old_hwtable_size = VECTOR_SIZE(conf->hwtable);
++ snprintf(path, LINE_MAX, "%s/%s", dir, namelist[i]->d_name);
++ path[LINE_MAX-1] = '\0';
++ process_file(path);
++ if (VECTOR_SIZE(conf->hwtable) > old_hwtable_size)
++ factorize_hwtable(conf->hwtable, old_hwtable_size);
++
++ }
++}
++
+ int
+ load_config (char * file, struct udev *udev)
+ {
+@@ -623,6 +668,7 @@ load_config (char * file, struct udev *u
+ conf->hw_strmatch = 0;
+ conf->force_sync = 0;
+ conf->ignore_new_boot_devs = 0;
++ conf->processed_main_config = 0;
+
+ /*
+ * preload default hwtable
+@@ -641,11 +687,12 @@ load_config (char * file, struct udev *u
+ */
+ set_current_keywords(&conf->keywords);
+ alloc_keywords();
++ init_keywords();
+ if (filepresent(file)) {
+ int builtin_hwtable_size;
+
+ builtin_hwtable_size = VECTOR_SIZE(conf->hwtable);
+- if (init_data(file, init_keywords)) {
++ if (process_file(file)) {
+ condlog(0, "error parsing config file");
+ goto out;
+ }
+@@ -658,7 +705,6 @@ load_config (char * file, struct udev *u
+ }
+
+ } else {
+- init_keywords();
+ condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
+ condlog(0, "A default multipath.conf file is located at");
+ condlog(0, "/usr/share/doc/device-mapper-multipath-%d.%d.%d/multipath.conf", MULTIPATH_VERSION(VERSION_CODE));
+@@ -677,6 +723,12 @@ load_config (char * file, struct udev *u
+ }
+ }
+
++ conf->processed_main_config = 1;
++ if (conf->config_dir == NULL)
++ conf->config_dir = set_default(DEFAULT_CONFIG_DIR);
++ if (conf->config_dir && conf->config_dir[0] != '\0')
++ process_config_dir(conf->keywords, conf->config_dir);
++
+ /*
+ * fill the voids left in the config file
+ */
+Index: multipath-tools-130222/libmultipath/config.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/config.h
++++ multipath-tools-130222/libmultipath/config.h
+@@ -132,6 +132,7 @@ struct config {
+ int force_sync;
+ int deferred_remove;
+ int ignore_new_boot_devs;
++ int processed_main_config;
+ unsigned int version[3];
+
+ char * dev;
+@@ -147,6 +148,7 @@ struct config {
+ char * prio_args;
+ char * checker_name;
+ char * alias_prefix;
++ char * config_dir;
+ unsigned char * reservation_key;
+
+ vector keywords;
+Index: multipath-tools-130222/libmultipath/defaults.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/defaults.h
++++ multipath-tools-130222/libmultipath/defaults.h
+@@ -31,5 +31,6 @@
+ #define DEFAULT_CONFIGFILE "/etc/multipath.conf"
+ #define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings"
+ #define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
++#define DEFAULT_CONFIG_DIR "/etc/multipath/conf.d"
+
+ char * set_default (char * str);
+Index: multipath-tools-130222/multipath.conf.annotated
+===================================================================
+--- multipath-tools-130222.orig/multipath.conf.annotated
++++ multipath-tools-130222/multipath.conf.annotated
+@@ -232,6 +232,16 @@
+ # # values : yes|no
+ # # default : no
+ # force_sync yes
++#
++# #
++# # name : config_dir
++# # scope : multipath & multipathd
++# # desc : If not set to an empty string, multipath will search
++# # this directory alphabetically for files ending in ".conf"
++# # and it will read configuration information from these
++# # files, just as if it was in /etc/multipath.conf
++# # values : "" or a fully qualified pathname
++# # default : "/etc/multipath/conf.d"
+ #}
+ #
+ ##
+Index: multipath-tools-130222/multipath.conf.defaults
+===================================================================
+--- multipath-tools-130222.orig/multipath.conf.defaults
++++ multipath-tools-130222/multipath.conf.defaults
+@@ -26,6 +26,7 @@
+ # log_checker_err always
+ # retain_attached_hw_handler no
+ # detect_prio no
++# config_dir "/etc/multipath/conf.d"
+ #}
+ #blacklist {
+ # devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
+Index: multipath-tools-130222/multipath/multipath.conf.5
+===================================================================
+--- multipath-tools-130222.orig/multipath/multipath.conf.5
++++ multipath-tools-130222/multipath/multipath.conf.5
+@@ -430,6 +430,13 @@ still in use, it will be freed when the
+ to the multipath device before the last user closes it, the deferred remove
+ will be canceled. Default is
+ .I no
++.TP
++.B config_dir
++If set to anything other than "", multipath will search this directory
++alphabetically for file ending in ".conf" and it will read configuration
++information from them, just as if it was in /etc/multipath.conf. config_dir
++must either be "" or a fully qualified directory name. Default is
++.I "/etc/multipath/conf.d"
+ .
+ .SH "blacklist section"
+ The