085a3e12d0a0d568f7de850883c0a8da43396af8
[multipath-tools/.git] / libmultipath / config.c
1 /*
2  * Copyright (c) 2004, 2005 Christophe Varoqui
3  * Copyright (c) 2005 Benjamin Marzinski, Redhat
4  * Copyright (c) 2005 Edward Goggin, EMC
5  */
6 #include <stdio.h>
7 #include <string.h>
8 #include <libudev.h>
9 #include <dirent.h>
10 #include <limits.h>
11 #include <errno.h>
12
13 #include "checkers.h"
14 #include "memory.h"
15 #include "util.h"
16 #include "debug.h"
17 #include "parser.h"
18 #include "dict.h"
19 #include "hwtable.h"
20 #include "vector.h"
21 #include "structs.h"
22 #include "config.h"
23 #include "blacklist.h"
24 #include "defaults.h"
25 #include "prio.h"
26 #include "devmapper.h"
27 #include "mpath_cmd.h"
28 #include "propsel.h"
29
30 static int
31 hwe_strmatch (struct hwentry *hwe1, struct hwentry *hwe2)
32 {
33         if ((hwe2->vendor && !hwe1->vendor) ||
34             (hwe1->vendor && (!hwe2->vendor ||
35                               strcmp(hwe1->vendor, hwe2->vendor))))
36                 return 1;
37
38         if ((hwe2->product && !hwe1->product) ||
39             (hwe1->product && (!hwe2->product ||
40                               strcmp(hwe1->product, hwe2->product))))
41                 return 1;
42
43         if ((hwe2->revision && !hwe1->revision) ||
44             (hwe1->revision && (!hwe2->revision ||
45                               strcmp(hwe1->revision, hwe2->revision))))
46                 return 1;
47
48         return 0;
49 }
50
51 static struct hwentry *
52 find_hwe_strmatch (vector hwtable, struct hwentry *hwe)
53 {
54         int i;
55         struct hwentry *tmp, *ret = NULL;
56
57         vector_foreach_slot (hwtable, tmp, i) {
58                 if (hwe_strmatch(tmp, hwe))
59                         continue;
60                 ret = tmp;
61                 break;
62         }
63         return ret;
64 }
65
66 static int
67 hwe_regmatch (struct hwentry *hwe1, struct hwentry *hwe2)
68 {
69         regex_t vre, pre, rre;
70         int retval = 1;
71
72         if (hwe1->vendor &&
73             regcomp(&vre, hwe1->vendor, REG_EXTENDED|REG_NOSUB))
74                 goto out;
75
76         if (hwe1->product &&
77             regcomp(&pre, hwe1->product, REG_EXTENDED|REG_NOSUB))
78                 goto out_vre;
79
80         if (hwe1->revision &&
81             regcomp(&rre, hwe1->revision, REG_EXTENDED|REG_NOSUB))
82                 goto out_pre;
83
84         if ((hwe2->vendor || hwe2->product || hwe2->revision) &&
85             (!hwe1->vendor || !hwe2->vendor ||
86              !regexec(&vre, hwe2->vendor, 0, NULL, 0)) &&
87             (!hwe1->product || !hwe2->product ||
88              !regexec(&pre, hwe2->product, 0, NULL, 0)) &&
89             (!hwe1->revision || !hwe2->revision ||
90              !regexec(&rre, hwe2->revision, 0, NULL, 0)))
91                 retval = 0;
92
93         if (hwe1->revision)
94                 regfree(&rre);
95 out_pre:
96         if (hwe1->product)
97                 regfree(&pre);
98 out_vre:
99         if (hwe1->vendor)
100                 regfree(&vre);
101 out:
102         return retval;
103 }
104
105 struct hwentry *
106 find_hwe (vector hwtable, char * vendor, char * product, char * revision)
107 {
108         int i;
109         struct hwentry hwe, *tmp, *ret = NULL;
110
111         hwe.vendor = vendor;
112         hwe.product = product;
113         hwe.revision = revision;
114         /*
115          * Search backwards here.
116          * User modified entries are attached at the end of
117          * the list, so we have to check them first before
118          * continuing to the generic entries
119          */
120         vector_foreach_slot_backwards (hwtable, tmp, i) {
121                 if (hwe_regmatch(tmp, &hwe))
122                         continue;
123                 ret = tmp;
124                 break;
125         }
126         return ret;
127 }
128
129 struct mpentry *find_mpe(vector mptable, char *wwid)
130 {
131         int i;
132         struct mpentry * mpe;
133
134         if (!wwid)
135                 return NULL;
136
137         vector_foreach_slot (mptable, mpe, i)
138                 if (mpe->wwid && !strcmp(mpe->wwid, wwid))
139                         return mpe;
140
141         return NULL;
142 }
143
144 char *get_mpe_wwid(vector mptable, char *alias)
145 {
146         int i;
147         struct mpentry * mpe;
148
149         if (!alias)
150                 return NULL;
151
152         vector_foreach_slot (mptable, mpe, i)
153                 if (mpe->alias && strcmp(mpe->alias, alias) == 0)
154                         return mpe->wwid;
155
156         return NULL;
157 }
158
159 void
160 free_hwe (struct hwentry * hwe)
161 {
162         if (!hwe)
163                 return;
164
165         if (hwe->vendor)
166                 FREE(hwe->vendor);
167
168         if (hwe->product)
169                 FREE(hwe->product);
170
171         if (hwe->revision)
172                 FREE(hwe->revision);
173
174         if (hwe->getuid)
175                 FREE(hwe->getuid);
176
177         if (hwe->uid_attribute)
178                 FREE(hwe->uid_attribute);
179
180         if (hwe->features)
181                 FREE(hwe->features);
182
183         if (hwe->hwhandler)
184                 FREE(hwe->hwhandler);
185
186         if (hwe->selector)
187                 FREE(hwe->selector);
188
189         if (hwe->checker_name)
190                 FREE(hwe->checker_name);
191
192         if (hwe->prio_name)
193                 FREE(hwe->prio_name);
194
195         if (hwe->prio_args)
196                 FREE(hwe->prio_args);
197
198         if (hwe->alias_prefix)
199                 FREE(hwe->alias_prefix);
200
201         if (hwe->bl_product)
202                 FREE(hwe->bl_product);
203
204         FREE(hwe);
205 }
206
207 void
208 free_hwtable (vector hwtable)
209 {
210         int i;
211         struct hwentry * hwe;
212
213         if (!hwtable)
214                 return;
215
216         vector_foreach_slot (hwtable, hwe, i)
217                 free_hwe(hwe);
218
219         vector_free(hwtable);
220 }
221
222 void
223 free_mpe (struct mpentry * mpe)
224 {
225         if (!mpe)
226                 return;
227
228         if (mpe->wwid)
229                 FREE(mpe->wwid);
230
231         if (mpe->selector)
232                 FREE(mpe->selector);
233
234         if (mpe->getuid)
235                 FREE(mpe->getuid);
236
237         if (mpe->uid_attribute)
238                 FREE(mpe->uid_attribute);
239
240         if (mpe->alias)
241                 FREE(mpe->alias);
242
243         if (mpe->prio_name)
244                 FREE(mpe->prio_name);
245
246         if (mpe->prio_args)
247                 FREE(mpe->prio_args);
248
249         FREE(mpe);
250 }
251
252 void
253 free_mptable (vector mptable)
254 {
255         int i;
256         struct mpentry * mpe;
257
258         if (!mptable)
259                 return;
260
261         vector_foreach_slot (mptable, mpe, i)
262                 free_mpe(mpe);
263
264         vector_free(mptable);
265 }
266
267 struct mpentry *
268 alloc_mpe (void)
269 {
270         struct mpentry * mpe = (struct mpentry *)
271                                 MALLOC(sizeof(struct mpentry));
272
273         return mpe;
274 }
275
276 struct hwentry *
277 alloc_hwe (void)
278 {
279         struct hwentry * hwe = (struct hwentry *)
280                                 MALLOC(sizeof(struct hwentry));
281
282         return hwe;
283 }
284
285 static char *
286 set_param_str(char * str)
287 {
288         char * dst;
289         int len;
290
291         if (!str)
292                 return NULL;
293
294         len = strlen(str);
295
296         if (!len)
297                 return NULL;
298
299         dst = (char *)MALLOC(len + 1);
300
301         if (!dst)
302                 return NULL;
303
304         strcpy(dst, str);
305         return dst;
306 }
307
308 #define merge_str(s) \
309         if (!dst->s && src->s) { \
310                 if (!(dst->s = set_param_str(src->s))) \
311                         return 1; \
312         }
313
314 #define merge_num(s) \
315         if (!dst->s && src->s) \
316                 dst->s = src->s
317
318
319 static int
320 merge_hwe (struct hwentry * dst, struct hwentry * src)
321 {
322         char id[SCSI_VENDOR_SIZE+PATH_PRODUCT_SIZE];
323         merge_str(vendor);
324         merge_str(product);
325         merge_str(revision);
326         merge_str(getuid);
327         merge_str(uid_attribute);
328         merge_str(features);
329         merge_str(hwhandler);
330         merge_str(selector);
331         merge_str(checker_name);
332         merge_str(prio_name);
333         merge_str(prio_args);
334         merge_str(alias_prefix);
335         merge_str(bl_product);
336         merge_num(pgpolicy);
337         merge_num(pgfailback);
338         merge_num(rr_weight);
339         merge_num(no_path_retry);
340         merge_num(minio);
341         merge_num(minio_rq);
342         merge_num(flush_on_last_del);
343         merge_num(fast_io_fail);
344         merge_num(dev_loss);
345         merge_num(user_friendly_names);
346         merge_num(retain_hwhandler);
347         merge_num(detect_prio);
348         merge_num(detect_checker);
349         merge_num(deferred_remove);
350         merge_num(delay_watch_checks);
351         merge_num(delay_wait_checks);
352         merge_num(skip_kpartx);
353         merge_num(max_sectors_kb);
354         merge_num(ghost_delay);
355
356         snprintf(id, sizeof(id), "%s/%s", dst->vendor, dst->product);
357         reconcile_features_with_options(id, &dst->features,
358                                         &dst->no_path_retry,
359                                         &dst->retain_hwhandler);
360         return 0;
361 }
362
363 int
364 store_hwe (vector hwtable, struct hwentry * dhwe)
365 {
366         struct hwentry * hwe;
367
368         if (find_hwe_strmatch(hwtable, dhwe))
369                 return 0;
370
371         if (!(hwe = alloc_hwe()))
372                 return 1;
373
374         if (!dhwe->vendor || !(hwe->vendor = set_param_str(dhwe->vendor)))
375                 goto out;
376
377         if (!dhwe->product || !(hwe->product = set_param_str(dhwe->product)))
378                 goto out;
379
380         if (dhwe->revision && !(hwe->revision = set_param_str(dhwe->revision)))
381                 goto out;
382
383         if (dhwe->uid_attribute && !(hwe->uid_attribute = set_param_str(dhwe->uid_attribute)))
384                 goto out;
385
386         if (dhwe->getuid && !(hwe->getuid = set_param_str(dhwe->getuid)))
387                 goto out;
388
389         if (dhwe->features && !(hwe->features = set_param_str(dhwe->features)))
390                 goto out;
391
392         if (dhwe->hwhandler && !(hwe->hwhandler = set_param_str(dhwe->hwhandler)))
393                 goto out;
394
395         if (dhwe->selector && !(hwe->selector = set_param_str(dhwe->selector)))
396                 goto out;
397
398         if (dhwe->checker_name && !(hwe->checker_name = set_param_str(dhwe->checker_name)))
399                 goto out;
400
401         if (dhwe->prio_name && !(hwe->prio_name = set_param_str(dhwe->prio_name)))
402                 goto out;
403
404         if (dhwe->prio_args && !(hwe->prio_args = set_param_str(dhwe->prio_args)))
405                 goto out;
406
407         if (dhwe->alias_prefix && !(hwe->alias_prefix = set_param_str(dhwe->alias_prefix)))
408                 goto out;
409
410         hwe->pgpolicy = dhwe->pgpolicy;
411         hwe->pgfailback = dhwe->pgfailback;
412         hwe->rr_weight = dhwe->rr_weight;
413         hwe->no_path_retry = dhwe->no_path_retry;
414         hwe->minio = dhwe->minio;
415         hwe->minio_rq = dhwe->minio_rq;
416         hwe->flush_on_last_del = dhwe->flush_on_last_del;
417         hwe->fast_io_fail = dhwe->fast_io_fail;
418         hwe->dev_loss = dhwe->dev_loss;
419         hwe->user_friendly_names = dhwe->user_friendly_names;
420         hwe->retain_hwhandler = dhwe->retain_hwhandler;
421         hwe->detect_prio = dhwe->detect_prio;
422         hwe->detect_checker = dhwe->detect_checker;
423         hwe->ghost_delay = dhwe->ghost_delay;
424
425         if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product)))
426                 goto out;
427
428         if (!vector_alloc_slot(hwtable))
429                 goto out;
430
431         vector_set_slot(hwtable, hwe);
432         return 0;
433 out:
434         free_hwe(hwe);
435         return 1;
436 }
437
438 static void
439 factorize_hwtable (vector hw, int n)
440 {
441         struct hwentry *hwe1, *hwe2;
442         int i, j;
443
444 restart:
445         vector_foreach_slot(hw, hwe1, i) {
446                 if (i == n)
447                         break;
448                 j = n;
449                 vector_foreach_slot_after(hw, hwe2, j) {
450                         /* drop invalid device configs */
451                         if (!hwe2->vendor || !hwe2->product) {
452                                 condlog(0, "device config missing vendor or product parameter");
453                                 vector_del_slot(hw, j--);
454                                 free_hwe(hwe2);
455                                 continue;
456                         }
457                         if (hwe_regmatch(hwe1, hwe2))
458                                 continue;
459                         /* dup */
460                         merge_hwe(hwe2, hwe1);
461                         if (hwe_strmatch(hwe2, hwe1) == 0) {
462                                 vector_del_slot(hw, i);
463                                 free_hwe(hwe1);
464                                 n -= 1;
465                                 /*
466                                  * Play safe here; we have modified
467                                  * the original vector so the outer
468                                  * vector_foreach_slot() might
469                                  * become confused.
470                                  */
471                                 goto restart;
472                         }
473                 }
474         }
475         return;
476 }
477
478 struct config *
479 alloc_config (void)
480 {
481         return (struct config *)MALLOC(sizeof(struct config));
482 }
483
484 void
485 free_config (struct config * conf)
486 {
487         if (!conf)
488                 return;
489
490         if (conf->multipath_dir)
491                 FREE(conf->multipath_dir);
492
493         if (conf->selector)
494                 FREE(conf->selector);
495
496         if (conf->uid_attribute)
497                 FREE(conf->uid_attribute);
498
499         if (conf->uid_attrs)
500                 FREE(conf->uid_attrs);
501
502         if (conf->getuid)
503                 FREE(conf->getuid);
504
505         if (conf->features)
506                 FREE(conf->features);
507
508         if (conf->hwhandler)
509                 FREE(conf->hwhandler);
510
511         if (conf->bindings_file)
512                 FREE(conf->bindings_file);
513
514         if (conf->wwids_file)
515                 FREE(conf->wwids_file);
516
517         if (conf->prkeys_file)
518                 FREE(conf->prkeys_file);
519
520         if (conf->prio_name)
521                 FREE(conf->prio_name);
522
523         if (conf->alias_prefix)
524                 FREE(conf->alias_prefix);
525         if (conf->partition_delim)
526                 FREE(conf->partition_delim);
527
528         if (conf->prio_args)
529                 FREE(conf->prio_args);
530
531         if (conf->checker_name)
532                 FREE(conf->checker_name);
533
534         if (conf->config_dir)
535                 FREE(conf->config_dir);
536
537         free_blacklist(conf->blist_devnode);
538         free_blacklist(conf->blist_wwid);
539         free_blacklist(conf->blist_property);
540         free_blacklist_device(conf->blist_device);
541
542         free_blacklist(conf->elist_devnode);
543         free_blacklist(conf->elist_wwid);
544         free_blacklist(conf->elist_property);
545         free_blacklist_device(conf->elist_device);
546
547         free_mptable(conf->mptable);
548         free_hwtable(conf->hwtable);
549         free_hwe(conf->overrides);
550         free_keywords(conf->keywords);
551         FREE(conf);
552 }
553
554 /* if multipath fails to process the config directory, it should continue,
555  * with just a warning message */
556 static void
557 process_config_dir(struct config *conf, vector keywords, char *dir)
558 {
559         struct dirent **namelist;
560         int i, n;
561         char path[LINE_MAX];
562         int old_hwtable_size;
563
564         if (dir[0] != '/') {
565                 condlog(1, "config_dir '%s' must be a fully qualified path",
566                         dir);
567                 return;
568         }
569         n = scandir(dir, &namelist, NULL, alphasort);
570         if (n < 0) {
571                 if (errno == ENOENT)
572                         condlog(3, "No configuration dir '%s'", dir);
573                 else
574                         condlog(0, "couldn't open configuration dir '%s': %s",
575                                 dir, strerror(errno));
576                 return;
577         }
578         for (i = 0; i < n; i++) {
579                 if (!strstr(namelist[i]->d_name, ".conf"))
580                         continue;
581                 old_hwtable_size = VECTOR_SIZE(conf->hwtable);
582                 snprintf(path, LINE_MAX, "%s/%s", dir, namelist[i]->d_name);
583                 path[LINE_MAX-1] = '\0';
584                 process_file(conf, path);
585                 if (VECTOR_SIZE(conf->hwtable) > old_hwtable_size)
586                         factorize_hwtable(conf->hwtable, old_hwtable_size);
587
588         }
589 }
590
591 struct config *
592 load_config (char * file)
593 {
594         struct config *conf = alloc_config();
595
596         if (!conf)
597                 return NULL;
598
599         /*
600          * internal defaults
601          */
602         if (!conf->verbosity)
603                 conf->verbosity = DEFAULT_VERBOSITY;
604
605         get_sys_max_fds(&conf->max_fds);
606         conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
607         conf->wwids_file = set_default(DEFAULT_WWIDS_FILE);
608         conf->prkeys_file = set_default(DEFAULT_PRKEYS_FILE);
609         conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
610         conf->attribute_flags = 0;
611         conf->reassign_maps = DEFAULT_REASSIGN_MAPS;
612         conf->checkint = DEFAULT_CHECKINT;
613         conf->max_checkint = 0;
614         conf->force_sync = DEFAULT_FORCE_SYNC;
615         conf->partition_delim = DEFAULT_PARTITION_DELIM;
616         conf->processed_main_config = 0;
617         conf->find_multipaths = DEFAULT_FIND_MULTIPATHS;
618         conf->uxsock_timeout = DEFAULT_REPLY_TIMEOUT;
619         conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES;
620         conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY;
621         conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT;
622         conf->disable_changed_wwids = DEFAULT_DISABLE_CHANGED_WWIDS;
623         conf->remove_retries = 0;
624         conf->ghost_delay = DEFAULT_GHOST_DELAY;
625
626         /*
627          * preload default hwtable
628          */
629         if (conf->hwtable == NULL) {
630                 conf->hwtable = vector_alloc();
631
632                 if (!conf->hwtable)
633                         goto out;
634         }
635         if (setup_default_hwtable(conf->hwtable))
636                 goto out;
637
638         /*
639          * read the config file
640          */
641         conf->keywords = vector_alloc();
642         init_keywords(conf->keywords);
643         if (filepresent(file)) {
644                 int builtin_hwtable_size;
645
646                 builtin_hwtable_size = VECTOR_SIZE(conf->hwtable);
647                 if (process_file(conf, file)) {
648                         condlog(0, "error parsing config file");
649                         goto out;
650                 }
651                 if (VECTOR_SIZE(conf->hwtable) > builtin_hwtable_size) {
652                         /*
653                          * remove duplica in hwtable. config file
654                          * takes precedence over build-in hwtable
655                          */
656                         factorize_hwtable(conf->hwtable, builtin_hwtable_size);
657                 }
658
659         }
660
661         conf->processed_main_config = 1;
662         if (conf->config_dir == NULL)
663                 conf->config_dir = set_default(DEFAULT_CONFIG_DIR);
664         if (conf->config_dir && conf->config_dir[0] != '\0')
665                 process_config_dir(conf, conf->keywords, conf->config_dir);
666
667         /*
668          * fill the voids left in the config file
669          */
670         if (conf->max_checkint == 0)
671                 conf->max_checkint = MAX_CHECKINT(conf->checkint);
672         if (conf->blist_devnode == NULL) {
673                 conf->blist_devnode = vector_alloc();
674
675                 if (!conf->blist_devnode)
676                         goto out;
677         }
678         if (conf->blist_wwid == NULL) {
679                 conf->blist_wwid = vector_alloc();
680
681                 if (!conf->blist_wwid)
682                         goto out;
683         }
684         if (conf->blist_device == NULL) {
685                 conf->blist_device = vector_alloc();
686
687                 if (!conf->blist_device)
688                         goto out;
689         }
690         if (conf->blist_property == NULL) {
691                 conf->blist_property = vector_alloc();
692
693                 if (!conf->blist_property)
694                         goto out;
695         }
696
697         if (conf->elist_devnode == NULL) {
698                 conf->elist_devnode = vector_alloc();
699
700                 if (!conf->elist_devnode)
701                         goto out;
702         }
703         if (conf->elist_wwid == NULL) {
704                 conf->elist_wwid = vector_alloc();
705
706                 if (!conf->elist_wwid)
707                         goto out;
708         }
709
710         if (conf->elist_device == NULL) {
711                 conf->elist_device = vector_alloc();
712
713                 if (!conf->elist_device)
714                         goto out;
715         }
716
717         if (conf->elist_property == NULL) {
718                 conf->elist_property = vector_alloc();
719
720                 if (!conf->elist_property)
721                         goto out;
722         }
723         if (setup_default_blist(conf))
724                 goto out;
725
726         if (conf->mptable == NULL) {
727                 conf->mptable = vector_alloc();
728                 if (!conf->mptable)
729                         goto out;
730         }
731         if (conf->bindings_file == NULL)
732                 conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
733
734         if (!conf->multipath_dir || !conf->bindings_file ||
735             !conf->wwids_file || !conf->prkeys_file)
736                 goto out;
737
738         return conf;
739 out:
740         free_config(conf);
741         return NULL;
742 }