]>
Commit | Line | Data |
---|---|---|
289c5516 MT |
1 | --- |
2 | libmultipath/config.c | 56 +++++++++++++++++++++++++++++++- | |
3 | libmultipath/config.h | 2 + | |
4 | libmultipath/defaults.h | 1 | |
5 | libmultipath/dict.c | 69 +++++++++++++++++++++++++++++++++++---- | |
6 | libmultipath/parser.c | 78 +++++++++++++++++++++++---------------------- | |
7 | libmultipath/parser.h | 3 - | |
8 | multipath.conf.annotated | 10 +++++ | |
9 | multipath.conf.defaults | 1 | |
10 | multipath/multipath.conf.5 | 7 ++++ | |
11 | 9 files changed, 179 insertions(+), 48 deletions(-) | |
12 | ||
13 | Index: multipath-tools-130222/libmultipath/parser.c | |
14 | =================================================================== | |
15 | --- multipath-tools-130222.orig/libmultipath/parser.c | |
16 | +++ multipath-tools-130222/libmultipath/parser.c | |
17 | @@ -18,6 +18,7 @@ | |
18 | */ | |
19 | ||
20 | #include <syslog.h> | |
21 | +#include <errno.h> | |
22 | ||
23 | #include "parser.h" | |
24 | #include "memory.h" | |
25 | @@ -453,14 +454,15 @@ set_value(vector strvec) | |
26 | /* non-recursive configuration stream handler */ | |
27 | static int kw_level = 0; | |
28 | ||
29 | -int warn_on_duplicates(vector uniques, char *str) | |
30 | +int warn_on_duplicates(vector uniques, char *str, char *file) | |
31 | { | |
32 | char *tmp; | |
33 | int i; | |
34 | ||
35 | vector_foreach_slot(uniques, tmp, i) { | |
36 | if (!strcmp(str, tmp)) { | |
37 | - condlog(1, "multipath.conf line %d, duplicate keyword: %s", line_nr, str); | |
38 | + condlog(1, "%s line %d, duplicate keyword: %s", | |
39 | + file, line_nr, str); | |
40 | return 0; | |
41 | } | |
42 | } | |
43 | @@ -496,65 +498,70 @@ is_sublevel_keyword(char *str) | |
44 | } | |
45 | ||
46 | int | |
47 | -validate_config_strvec(vector strvec) | |
48 | +validate_config_strvec(vector strvec, char *file) | |
49 | { | |
50 | char *str; | |
51 | int i; | |
52 | ||
53 | str = VECTOR_SLOT(strvec, 0); | |
54 | if (str == NULL) { | |
55 | - condlog(0, "can't parse option on line %d of config file", | |
56 | - line_nr); | |
57 | + condlog(0, "can't parse option on line %d of %s", | |
58 | + line_nr, file); | |
59 | return -1; | |
60 | } | |
61 | if (*str == '}') { | |
62 | if (VECTOR_SIZE(strvec) > 1) | |
63 | - condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 1), line_nr); | |
64 | + condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, 1), line_nr, file); | |
65 | return 0; | |
66 | } | |
67 | if (*str == '{') { | |
68 | - condlog(0, "invalid keyword '%s' on line %d of config file", str, line_nr); | |
69 | + condlog(0, "invalid keyword '%s' on line %d of %s", | |
70 | + str, line_nr, file); | |
71 | return -1; | |
72 | } | |
73 | if (is_sublevel_keyword(str)) { | |
74 | str = VECTOR_SLOT(strvec, 1); | |
75 | if (str == NULL) | |
76 | - condlog(0, "missing '{' on line %d of config file", line_nr); | |
77 | + condlog(0, "missing '{' on line %d of %s", | |
78 | + line_nr, file); | |
79 | else if (*str != '{') | |
80 | - condlog(0, "expecting '{' on line %d of config file. found '%s'", line_nr, str); | |
81 | + condlog(0, "expecting '{' on line %d of %s. found '%s'", | |
82 | + line_nr, file, str); | |
83 | else if (VECTOR_SIZE(strvec) > 2) | |
84 | - condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr); | |
85 | + condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, 2), line_nr, file); | |
86 | return 0; | |
87 | } | |
88 | str = VECTOR_SLOT(strvec, 1); | |
89 | if (str == NULL) { | |
90 | - condlog(0, "missing value for option '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 0), line_nr); | |
91 | + condlog(0, "missing value for option '%s' on line %d of %s", | |
92 | + (char *)VECTOR_SLOT(strvec, 0), line_nr, file); | |
93 | return -1; | |
94 | } | |
95 | if (*str != '"') { | |
96 | if (VECTOR_SIZE(strvec) > 2) | |
97 | - condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr); | |
98 | + condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, 2), line_nr, file); | |
99 | return 0; | |
100 | } | |
101 | for (i = 2; i < VECTOR_SIZE(strvec); i++) { | |
102 | str = VECTOR_SLOT(strvec, i); | |
103 | if (str == NULL) { | |
104 | - condlog(0, "can't parse value on line %d of config file", line_nr); | |
105 | + condlog(0, "can't parse value on line %d of %s", | |
106 | + line_nr, file); | |
107 | return -1; | |
108 | } | |
109 | if (*str == '"') { | |
110 | if (VECTOR_SIZE(strvec) > i + 1) | |
111 | - condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, (i + 1)), line_nr); | |
112 | + condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, (i + 1)), line_nr, file); | |
113 | return 0; | |
114 | } | |
115 | } | |
116 | - condlog(0, "missing closing quotes on line %d of config file", | |
117 | - line_nr); | |
118 | + condlog(0, "missing closing quotes on line %d of %s", | |
119 | + line_nr, file); | |
120 | return 0; | |
121 | } | |
122 | ||
123 | -int | |
124 | -process_stream(vector keywords) | |
125 | +static int | |
126 | +process_stream(vector keywords, char *file) | |
127 | { | |
128 | int i; | |
129 | int r = 0; | |
130 | @@ -583,7 +590,7 @@ process_stream(vector keywords) | |
131 | if (!strvec) | |
132 | continue; | |
133 | ||
134 | - if (validate_config_strvec(strvec) != 0) { | |
135 | + if (validate_config_strvec(strvec, file) != 0) { | |
136 | free_strvec(strvec); | |
137 | continue; | |
138 | } | |
139 | @@ -595,8 +602,8 @@ process_stream(vector keywords) | |
140 | free_strvec(strvec); | |
141 | break; | |
142 | } | |
143 | - condlog(0, "unmatched '%s' at line %d of config file", | |
144 | - EOB, line_nr); | |
145 | + condlog(0, "unmatched '%s' at line %d of %s", | |
146 | + EOB, line_nr, file); | |
147 | } | |
148 | ||
149 | for (i = 0; i < VECTOR_SIZE(keywords); i++) { | |
150 | @@ -604,7 +611,7 @@ process_stream(vector keywords) | |
151 | ||
152 | if (!strcmp(keyword->string, str)) { | |
153 | if (keyword->unique && | |
154 | - warn_on_duplicates(uniques, str)) { | |
155 | + warn_on_duplicates(uniques, str, file)) { | |
156 | r = 1; | |
157 | free_strvec(strvec); | |
158 | goto out; | |
159 | @@ -614,15 +621,15 @@ process_stream(vector keywords) | |
160 | ||
161 | if (keyword->sub) { | |
162 | kw_level++; | |
163 | - r += process_stream(keyword->sub); | |
164 | + r += process_stream(keyword->sub, file); | |
165 | kw_level--; | |
166 | } | |
167 | break; | |
168 | } | |
169 | } | |
170 | if (i >= VECTOR_SIZE(keywords)) | |
171 | - condlog(1, "multipath.conf +%d, invalid keyword: %s", | |
172 | - line_nr, str); | |
173 | + condlog(1, "%s line %d, invalid keyword: %s", | |
174 | + file, line_nr, str); | |
175 | ||
176 | free_strvec(strvec); | |
177 | } | |
178 | @@ -646,27 +653,24 @@ int alloc_keywords(void) | |
179 | ||
180 | /* Data initialization */ | |
181 | int | |
182 | -init_data(char *conf_file, void (*init_keywords) (void)) | |
183 | +process_file(char *file) | |
184 | { | |
185 | int r; | |
186 | ||
187 | - stream = fopen(conf_file, "r"); | |
188 | + if (!keywords) { | |
189 | + condlog(0, "No keywords alocated"); | |
190 | + return 1; | |
191 | + } | |
192 | + stream = fopen(file, "r"); | |
193 | if (!stream) { | |
194 | - syslog(LOG_WARNING, "Configuration file open problem"); | |
195 | + condlog(0, "couldn't open configuration file '%s': %s", | |
196 | + file, strerror(errno)); | |
197 | return 1; | |
198 | } | |
199 | ||
200 | - /* Init Keywords structure */ | |
201 | - (*init_keywords) (); | |
202 | - | |
203 | -/* Dump configuration * | |
204 | - vector_dump(keywords); | |
205 | - dump_keywords(keywords, 0); | |
206 | -*/ | |
207 | - | |
208 | /* Stream handling */ | |
209 | line_nr = 0; | |
210 | - r = process_stream(keywords); | |
211 | + r = process_stream(keywords, file); | |
212 | fclose(stream); | |
213 | //free_keywords(keywords); | |
214 | ||
215 | Index: multipath-tools-130222/libmultipath/dict.c | |
216 | =================================================================== | |
217 | --- multipath-tools-130222.orig/libmultipath/dict.c | |
218 | +++ multipath-tools-130222/libmultipath/dict.c | |
219 | @@ -117,6 +117,8 @@ reassign_maps_handler(vector strvec) | |
220 | static int | |
221 | multipath_dir_handler(vector strvec) | |
222 | { | |
223 | + if (conf->multipath_dir) | |
224 | + FREE(conf->multipath_dir); | |
225 | conf->multipath_dir = set_value(strvec); | |
226 | ||
227 | if (!conf->multipath_dir) | |
228 | @@ -128,6 +130,8 @@ multipath_dir_handler(vector strvec) | |
229 | static int | |
230 | def_selector_handler(vector strvec) | |
231 | { | |
232 | + if (conf->selector) | |
233 | + FREE(conf->selector); | |
234 | conf->selector = set_value(strvec); | |
235 | ||
236 | if (!conf->selector) | |
237 | @@ -155,6 +159,8 @@ def_pgpolicy_handler(vector strvec) | |
238 | static int | |
239 | def_uid_attribute_handler(vector strvec) | |
240 | { | |
241 | + if (conf->uid_attribute) | |
242 | + FREE(conf->uid_attribute); | |
243 | conf->uid_attribute = set_value(strvec); | |
244 | ||
245 | if (!conf->uid_attribute) | |
246 | @@ -166,6 +172,8 @@ def_uid_attribute_handler(vector strvec) | |
247 | static int | |
248 | def_prio_handler(vector strvec) | |
249 | { | |
250 | + if (conf->prio_name) | |
251 | + FREE(conf->prio_name); | |
252 | conf->prio_name = set_value(strvec); | |
253 | ||
254 | if (!conf->prio_name) | |
255 | @@ -177,6 +185,8 @@ def_prio_handler(vector strvec) | |
256 | static int | |
257 | def_alias_prefix_handler(vector strvec) | |
258 | { | |
259 | + if (conf->alias_prefix) | |
260 | + FREE(conf->alias_prefix); | |
261 | conf->alias_prefix = set_value(strvec); | |
262 | ||
263 | if (!conf->alias_prefix) | |
264 | @@ -188,6 +198,8 @@ def_alias_prefix_handler(vector strvec) | |
265 | static int | |
266 | def_prio_args_handler(vector strvec) | |
267 | { | |
268 | + if (conf->prio_args) | |
269 | + FREE(conf->prio_args); | |
270 | conf->prio_args = set_value(strvec); | |
271 | ||
272 | if (!conf->prio_args) | |
273 | @@ -199,6 +211,8 @@ def_prio_args_handler(vector strvec) | |
274 | static int | |
275 | def_features_handler(vector strvec) | |
276 | { | |
277 | + if (conf->features) | |
278 | + FREE(conf->features); | |
279 | conf->features = set_value(strvec); | |
280 | ||
281 | if (!conf->features) | |
282 | @@ -210,6 +224,8 @@ def_features_handler(vector strvec) | |
283 | static int | |
284 | def_path_checker_handler(vector strvec) | |
285 | { | |
286 | + if (conf->checker_name) | |
287 | + FREE(conf->checker_name); | |
288 | conf->checker_name = set_value(strvec); | |
289 | ||
290 | if (!conf->checker_name) | |
291 | @@ -432,6 +448,23 @@ def_no_path_retry_handler(vector strvec) | |
292 | return 0; | |
293 | } | |
294 | ||
295 | + | |
296 | +static int | |
297 | +def_config_dir_handler(vector strvec) | |
298 | +{ | |
299 | + /* this is only valid in the main config file */ | |
300 | + if (conf->processed_main_config) | |
301 | + return 0; | |
302 | + if (conf->config_dir) | |
303 | + FREE(conf->config_dir); | |
304 | + conf->config_dir = set_value(strvec); | |
305 | + | |
306 | + if (!conf->config_dir) | |
307 | + return 1; | |
308 | + | |
309 | + return 0; | |
310 | +} | |
311 | + | |
312 | static int | |
313 | def_queue_without_daemon(vector strvec) | |
314 | { | |
315 | @@ -611,6 +644,8 @@ def_names_handler(vector strvec) | |
316 | static int | |
317 | bindings_file_handler(vector strvec) | |
318 | { | |
319 | + if (conf->bindings_file) | |
320 | + FREE(conf->bindings_file); | |
321 | conf->bindings_file = set_value(strvec); | |
322 | ||
323 | if (!conf->bindings_file) | |
324 | @@ -622,6 +657,8 @@ bindings_file_handler(vector strvec) | |
325 | static int | |
326 | wwids_file_handler(vector strvec) | |
327 | { | |
328 | + if (conf->wwids_file) | |
329 | + FREE(conf->wwids_file); | |
330 | conf->wwids_file = set_value(strvec); | |
331 | ||
332 | if (!conf->wwids_file) | |
333 | @@ -770,9 +807,12 @@ def_ignore_new_boot_devs_handler(vector | |
334 | static int | |
335 | blacklist_handler(vector strvec) | |
336 | { | |
337 | - conf->blist_devnode = vector_alloc(); | |
338 | - conf->blist_wwid = vector_alloc(); | |
339 | - conf->blist_device = vector_alloc(); | |
340 | + if (!conf->blist_devnode) | |
341 | + conf->blist_devnode = vector_alloc(); | |
342 | + if (!conf->blist_wwid) | |
343 | + conf->blist_wwid = vector_alloc(); | |
344 | + if (!conf->blist_device) | |
345 | + conf->blist_device = vector_alloc(); | |
346 | ||
347 | if (!conf->blist_devnode || !conf->blist_wwid || !conf->blist_device) | |
348 | return 1; | |
349 | @@ -783,9 +823,12 @@ blacklist_handler(vector strvec) | |
350 | static int | |
351 | blacklist_exceptions_handler(vector strvec) | |
352 | { | |
353 | - conf->elist_devnode = vector_alloc(); | |
354 | - conf->elist_wwid = vector_alloc(); | |
355 | - conf->elist_device = vector_alloc(); | |
356 | + if (!conf->elist_devnode) | |
357 | + conf->elist_devnode = vector_alloc(); | |
358 | + if (!conf->elist_wwid) | |
359 | + conf->elist_wwid = vector_alloc(); | |
360 | + if (!conf->elist_device) | |
361 | + conf->elist_device = vector_alloc(); | |
362 | ||
363 | if (!conf->elist_devnode || !conf->elist_wwid || !conf->elist_device) | |
364 | return 1; | |
365 | @@ -1480,7 +1523,8 @@ hw_deferred_remove_handler(vector strvec | |
366 | static int | |
367 | multipaths_handler(vector strvec) | |
368 | { | |
369 | - conf->mptable = vector_alloc(); | |
370 | + if (!conf->mptable) | |
371 | + conf->mptable = vector_alloc(); | |
372 | ||
373 | if (!conf->mptable) | |
374 | return 1; | |
375 | @@ -2945,6 +2989,16 @@ snprint_def_ignore_new_boot_devs(char * | |
376 | return snprintf(buff, len, "no"); | |
377 | } | |
378 | ||
379 | + | |
380 | +static int | |
381 | +snprint_def_config_dir (char * buff, int len, void * data) | |
382 | +{ | |
383 | + if (!conf->config_dir) | |
384 | + return 0; | |
385 | + | |
386 | + return snprintf(buff, len, "\"%s\"", conf->config_dir); | |
387 | +} | |
388 | + | |
389 | static int | |
390 | snprint_ble_simple (char * buff, int len, void * data) | |
391 | { | |
392 | @@ -3016,6 +3070,7 @@ init_keywords(void) | |
393 | install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync); | |
394 | install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove); | |
395 | install_keyword("ignore_new_boot_devs", &def_ignore_new_boot_devs_handler, &snprint_def_ignore_new_boot_devs); | |
396 | + install_keyword("config_dir", &def_config_dir_handler, &snprint_def_config_dir); | |
397 | __deprecated install_keyword("default_selector", &def_selector_handler, NULL); | |
398 | __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); | |
399 | __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); | |
400 | Index: multipath-tools-130222/libmultipath/parser.h | |
401 | =================================================================== | |
402 | --- multipath-tools-130222.orig/libmultipath/parser.h | |
403 | +++ multipath-tools-130222/libmultipath/parser.h | |
404 | @@ -76,9 +76,8 @@ extern int read_line(char *buf, int size | |
405 | extern vector read_value_block(void); | |
406 | extern int alloc_value_block(vector strvec, void (*alloc_func) (vector)); | |
407 | extern void *set_value(vector strvec); | |
408 | -extern int process_stream(vector keywords); | |
409 | extern int alloc_keywords(void); | |
410 | -extern int init_data(char *conf_file, void (*init_keywords) (void)); | |
411 | +extern int process_file(char *conf_file); | |
412 | extern struct keyword * find_keyword(vector v, char * name); | |
413 | void set_current_keywords (vector *k); | |
414 | int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw, | |
415 | Index: multipath-tools-130222/libmultipath/config.c | |
416 | =================================================================== | |
417 | --- multipath-tools-130222.orig/libmultipath/config.c | |
418 | +++ multipath-tools-130222/libmultipath/config.c | |
419 | @@ -6,6 +6,9 @@ | |
420 | #include <stdio.h> | |
421 | #include <string.h> | |
422 | #include <libudev.h> | |
423 | +#include <dirent.h> | |
424 | +#include <limits.h> | |
425 | +#include <errno.h> | |
426 | ||
427 | #include "checkers.h" | |
428 | #include "memory.h" | |
429 | @@ -556,6 +559,7 @@ free_config (struct config * conf) | |
430 | ||
431 | if (conf->wwids_file) | |
432 | FREE(conf->wwids_file); | |
433 | + | |
434 | if (conf->prio_name) | |
435 | FREE(conf->prio_name); | |
436 | ||
437 | @@ -567,6 +571,10 @@ free_config (struct config * conf) | |
438 | ||
439 | if (conf->checker_name) | |
440 | FREE(conf->checker_name); | |
441 | + | |
442 | + if (conf->config_dir) | |
443 | + FREE(conf->config_dir); | |
444 | + | |
445 | if (conf->reservation_key) | |
446 | FREE(conf->reservation_key); | |
447 | ||
448 | @@ -584,6 +592,43 @@ free_config (struct config * conf) | |
449 | FREE(conf); | |
450 | } | |
451 | ||
452 | +/* if multipath fails to process the config directory, it should continue, | |
453 | + * with just a warning message */ | |
454 | +static void | |
455 | +process_config_dir(vector keywords, char *dir) | |
456 | +{ | |
457 | + struct dirent **namelist; | |
458 | + int i, n; | |
459 | + char path[LINE_MAX]; | |
460 | + int old_hwtable_size; | |
461 | + | |
462 | + if (dir[0] != '/') { | |
463 | + condlog(1, "config_dir '%s' must be a fully qualified path", | |
464 | + dir); | |
465 | + return; | |
466 | + } | |
467 | + n = scandir(dir, &namelist, NULL, alphasort); | |
468 | + if (n < 0) { | |
469 | + if (errno == ENOENT) | |
470 | + condlog(3, "No configuration dir '%s'", dir); | |
471 | + else | |
472 | + condlog(0, "couldn't open configuration dir '%s': %s", | |
473 | + dir, strerror(errno)); | |
474 | + return; | |
475 | + } | |
476 | + for (i = 0; i < n; i++) { | |
477 | + if (!strstr(namelist[i]->d_name, ".conf")) | |
478 | + continue; | |
479 | + old_hwtable_size = VECTOR_SIZE(conf->hwtable); | |
480 | + snprintf(path, LINE_MAX, "%s/%s", dir, namelist[i]->d_name); | |
481 | + path[LINE_MAX-1] = '\0'; | |
482 | + process_file(path); | |
483 | + if (VECTOR_SIZE(conf->hwtable) > old_hwtable_size) | |
484 | + factorize_hwtable(conf->hwtable, old_hwtable_size); | |
485 | + | |
486 | + } | |
487 | +} | |
488 | + | |
489 | int | |
490 | load_config (char * file, struct udev *udev) | |
491 | { | |
492 | @@ -623,6 +668,7 @@ load_config (char * file, struct udev *u | |
493 | conf->hw_strmatch = 0; | |
494 | conf->force_sync = 0; | |
495 | conf->ignore_new_boot_devs = 0; | |
496 | + conf->processed_main_config = 0; | |
497 | ||
498 | /* | |
499 | * preload default hwtable | |
500 | @@ -641,11 +687,12 @@ load_config (char * file, struct udev *u | |
501 | */ | |
502 | set_current_keywords(&conf->keywords); | |
503 | alloc_keywords(); | |
504 | + init_keywords(); | |
505 | if (filepresent(file)) { | |
506 | int builtin_hwtable_size; | |
507 | ||
508 | builtin_hwtable_size = VECTOR_SIZE(conf->hwtable); | |
509 | - if (init_data(file, init_keywords)) { | |
510 | + if (process_file(file)) { | |
511 | condlog(0, "error parsing config file"); | |
512 | goto out; | |
513 | } | |
514 | @@ -658,7 +705,6 @@ load_config (char * file, struct udev *u | |
515 | } | |
516 | ||
517 | } else { | |
518 | - init_keywords(); | |
519 | condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices."); | |
520 | condlog(0, "A default multipath.conf file is located at"); | |
521 | condlog(0, "/usr/share/doc/device-mapper-multipath-%d.%d.%d/multipath.conf", MULTIPATH_VERSION(VERSION_CODE)); | |
522 | @@ -677,6 +723,12 @@ load_config (char * file, struct udev *u | |
523 | } | |
524 | } | |
525 | ||
526 | + conf->processed_main_config = 1; | |
527 | + if (conf->config_dir == NULL) | |
528 | + conf->config_dir = set_default(DEFAULT_CONFIG_DIR); | |
529 | + if (conf->config_dir && conf->config_dir[0] != '\0') | |
530 | + process_config_dir(conf->keywords, conf->config_dir); | |
531 | + | |
532 | /* | |
533 | * fill the voids left in the config file | |
534 | */ | |
535 | Index: multipath-tools-130222/libmultipath/config.h | |
536 | =================================================================== | |
537 | --- multipath-tools-130222.orig/libmultipath/config.h | |
538 | +++ multipath-tools-130222/libmultipath/config.h | |
539 | @@ -132,6 +132,7 @@ struct config { | |
540 | int force_sync; | |
541 | int deferred_remove; | |
542 | int ignore_new_boot_devs; | |
543 | + int processed_main_config; | |
544 | unsigned int version[3]; | |
545 | ||
546 | char * dev; | |
547 | @@ -147,6 +148,7 @@ struct config { | |
548 | char * prio_args; | |
549 | char * checker_name; | |
550 | char * alias_prefix; | |
551 | + char * config_dir; | |
552 | unsigned char * reservation_key; | |
553 | ||
554 | vector keywords; | |
555 | Index: multipath-tools-130222/libmultipath/defaults.h | |
556 | =================================================================== | |
557 | --- multipath-tools-130222.orig/libmultipath/defaults.h | |
558 | +++ multipath-tools-130222/libmultipath/defaults.h | |
559 | @@ -31,5 +31,6 @@ | |
560 | #define DEFAULT_CONFIGFILE "/etc/multipath.conf" | |
561 | #define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings" | |
562 | #define DEFAULT_WWIDS_FILE "/etc/multipath/wwids" | |
563 | +#define DEFAULT_CONFIG_DIR "/etc/multipath/conf.d" | |
564 | ||
565 | char * set_default (char * str); | |
566 | Index: multipath-tools-130222/multipath.conf.annotated | |
567 | =================================================================== | |
568 | --- multipath-tools-130222.orig/multipath.conf.annotated | |
569 | +++ multipath-tools-130222/multipath.conf.annotated | |
570 | @@ -232,6 +232,16 @@ | |
571 | # # values : yes|no | |
572 | # # default : no | |
573 | # force_sync yes | |
574 | +# | |
575 | +# # | |
576 | +# # name : config_dir | |
577 | +# # scope : multipath & multipathd | |
578 | +# # desc : If not set to an empty string, multipath will search | |
579 | +# # this directory alphabetically for files ending in ".conf" | |
580 | +# # and it will read configuration information from these | |
581 | +# # files, just as if it was in /etc/multipath.conf | |
582 | +# # values : "" or a fully qualified pathname | |
583 | +# # default : "/etc/multipath/conf.d" | |
584 | #} | |
585 | # | |
586 | ## | |
587 | Index: multipath-tools-130222/multipath.conf.defaults | |
588 | =================================================================== | |
589 | --- multipath-tools-130222.orig/multipath.conf.defaults | |
590 | +++ multipath-tools-130222/multipath.conf.defaults | |
591 | @@ -26,6 +26,7 @@ | |
592 | # log_checker_err always | |
593 | # retain_attached_hw_handler no | |
594 | # detect_prio no | |
595 | +# config_dir "/etc/multipath/conf.d" | |
596 | #} | |
597 | #blacklist { | |
598 | # devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*" | |
599 | Index: multipath-tools-130222/multipath/multipath.conf.5 | |
600 | =================================================================== | |
601 | --- multipath-tools-130222.orig/multipath/multipath.conf.5 | |
602 | +++ multipath-tools-130222/multipath/multipath.conf.5 | |
603 | @@ -430,6 +430,13 @@ still in use, it will be freed when the | |
604 | to the multipath device before the last user closes it, the deferred remove | |
605 | will be canceled. Default is | |
606 | .I no | |
607 | +.TP | |
608 | +.B config_dir | |
609 | +If set to anything other than "", multipath will search this directory | |
610 | +alphabetically for file ending in ".conf" and it will read configuration | |
611 | +information from them, just as if it was in /etc/multipath.conf. config_dir | |
612 | +must either be "" or a fully qualified directory name. Default is | |
613 | +.I "/etc/multipath/conf.d" | |
614 | . | |
615 | .SH "blacklist section" | |
616 | The |