You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
616 lines
18 KiB
616 lines
18 KiB
--- |
|
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 |
|
@@ -452,6 +452,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
|
|
|