Blame SOURCES/0112-RHBZ-1194917-add-config_dir-option.patch

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