]> git.ipfire.org Git - people/stevee/ipfire-3.x.git/blame - multipath-tools/patches/0112-RHBZ-1194917-add-config_dir-option.patch
multipath-tools: Update to snapshot from 2013-02-22
[people/stevee/ipfire-3.x.git] / multipath-tools / patches / 0112-RHBZ-1194917-add-config_dir-option.patch
CommitLineData
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
13Index: 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
215Index: 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);
400Index: 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,
415Index: 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 */
535Index: 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;
555Index: 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);
566Index: 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 ##
587Index: 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]*"
599Index: 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