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

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