a322dfe817e5a5144def963c41a1fbb233a7c77c
[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
10 #include "checkers.h"
11 #include "memory.h"
12 #include "util.h"
13 #include "debug.h"
14 #include "parser.h"
15 #include "dict.h"
16 #include "hwtable.h"
17 #include "vector.h"
18 #include "structs.h"
19 #include "config.h"
20 #include "blacklist.h"
21 #include "defaults.h"
22 #include "prio.h"
23 #include "devmapper.h"
24
25 static int
26 hwe_strmatch (struct hwentry *hwe1, struct hwentry *hwe2)
27 {
28         if ((hwe2->vendor && !hwe1->vendor) ||
29             (hwe1->vendor && (!hwe2->vendor ||
30                               strcmp(hwe1->vendor, hwe2->vendor))))
31                 return 1;
32
33         if ((hwe2->product && !hwe1->product) ||
34             (hwe1->product && (!hwe2->product ||
35                               strcmp(hwe1->product, hwe2->product))))
36                 return 1;
37
38         if ((hwe2->revision && !hwe1->revision) ||
39             (hwe1->revision && (!hwe2->revision ||
40                               strcmp(hwe1->revision, hwe2->revision))))
41                 return 1;
42
43         return 0;
44 }
45
46 static struct hwentry *
47 find_hwe_strmatch (vector hwtable, struct hwentry *hwe)
48 {
49         int i;
50         struct hwentry *tmp, *ret = NULL;
51
52         vector_foreach_slot (hwtable, tmp, i) {
53                 if (hwe_strmatch(tmp, hwe))
54                         continue;
55                 ret = tmp;
56                 break;
57         }
58         return ret;
59 }
60
61 static int
62 hwe_regmatch (struct hwentry *hwe1, struct hwentry *hwe2)
63 {
64         regex_t vre, pre, rre;
65         int retval = 1;
66
67         if (hwe1->vendor &&
68             regcomp(&vre, hwe1->vendor, REG_EXTENDED|REG_NOSUB))
69                 goto out;
70
71         if (hwe1->product &&
72             regcomp(&pre, hwe1->product, REG_EXTENDED|REG_NOSUB))
73                 goto out_vre;
74
75         if (hwe1->revision &&
76             regcomp(&rre, hwe1->revision, REG_EXTENDED|REG_NOSUB))
77                 goto out_pre;
78
79         if ((!hwe1->vendor || !hwe2->vendor ||
80              !regexec(&vre, hwe2->vendor, 0, NULL, 0)) &&
81             (!hwe1->product || !hwe2->product ||
82              !regexec(&pre, hwe2->product, 0, NULL, 0)) &&
83             (!hwe1->revision || !hwe2->revision ||
84              !regexec(&rre, hwe2->revision, 0, NULL, 0)))
85                 retval = 0;
86
87         if (hwe1->revision)
88                 regfree(&rre);
89 out_pre:
90         if (hwe1->product)
91                 regfree(&pre);
92 out_vre:
93         if (hwe1->vendor)
94                 regfree(&vre);
95 out:
96         return retval;
97 }
98
99 struct hwentry *
100 find_hwe (vector hwtable, char * vendor, char * product, char * revision)
101 {
102         int i;
103         struct hwentry hwe, *tmp, *ret = NULL;
104
105         hwe.vendor = vendor;
106         hwe.product = product;
107         hwe.revision = revision;
108         /*
109          * Search backwards here.
110          * User modified entries are attached at the end of
111          * the list, so we have to check them first before
112          * continuing to the generic entries
113          */
114         vector_foreach_slot_backwards (hwtable, tmp, i) {
115                 if (hwe_regmatch(tmp, &hwe))
116                         continue;
117                 ret = tmp;
118                 break;
119         }
120         return ret;
121 }
122
123 extern struct mpentry *
124 find_mpe (char * wwid)
125 {
126         int i;
127         struct mpentry * mpe;
128
129         if (!wwid)
130                 return NULL;
131
132         vector_foreach_slot (conf->mptable, mpe, i)
133                 if (mpe->wwid && !strcmp(mpe->wwid, wwid))
134                         return mpe;
135
136         return NULL;
137 }
138
139 extern char *
140 get_mpe_wwid (char * alias)
141 {
142         int i;
143         struct mpentry * mpe;
144
145         if (!alias)
146                 return NULL;
147
148         vector_foreach_slot (conf->mptable, mpe, i)
149                 if (mpe->alias && strcmp(mpe->alias, alias) == 0)
150                         return mpe->wwid;
151
152         return NULL;
153 }
154
155 void
156 free_hwe (struct hwentry * hwe)
157 {
158         if (!hwe)
159                 return;
160
161         if (hwe->vendor)
162                 FREE(hwe->vendor);
163
164         if (hwe->product)
165                 FREE(hwe->product);
166
167         if (hwe->revision)
168                 FREE(hwe->revision);
169
170         if (hwe->uid_attribute)
171                 FREE(hwe->uid_attribute);
172
173         if (hwe->features)
174                 FREE(hwe->features);
175
176         if (hwe->hwhandler)
177                 FREE(hwe->hwhandler);
178
179         if (hwe->selector)
180                 FREE(hwe->selector);
181
182         if (hwe->checker_name)
183                 FREE(hwe->checker_name);
184
185         if (hwe->prio_name)
186                 FREE(hwe->prio_name);
187
188         if (hwe->prio_args)
189                 FREE(hwe->prio_args);
190
191         if (hwe->alias_prefix)
192                 FREE(hwe->alias_prefix);
193
194         if (hwe->bl_product)
195                 FREE(hwe->bl_product);
196
197         FREE(hwe);
198 }
199
200 void
201 free_hwtable (vector hwtable)
202 {
203         int i;
204         struct hwentry * hwe;
205
206         if (!hwtable)
207                 return;
208
209         vector_foreach_slot (hwtable, hwe, i)
210                 free_hwe(hwe);
211
212         vector_free(hwtable);
213 }
214
215 void
216 free_mpe (struct mpentry * mpe)
217 {
218         if (!mpe)
219                 return;
220
221         if (mpe->wwid)
222                 FREE(mpe->wwid);
223
224         if (mpe->selector)
225                 FREE(mpe->selector);
226
227         if (mpe->uid_attribute)
228                 FREE(mpe->uid_attribute);
229
230         if (mpe->alias)
231                 FREE(mpe->alias);
232
233         if (mpe->prio_name)
234                 FREE(mpe->prio_name);
235
236         if (mpe->prio_args)
237                 FREE(mpe->prio_args);
238
239         FREE(mpe);
240 }
241
242 void
243 free_mptable (vector mptable)
244 {
245         int i;
246         struct mpentry * mpe;
247
248         if (!mptable)
249                 return;
250
251         vector_foreach_slot (mptable, mpe, i)
252                 free_mpe(mpe);
253
254         vector_free(mptable);
255 }
256
257 struct mpentry *
258 alloc_mpe (void)
259 {
260         struct mpentry * mpe = (struct mpentry *)
261                                 MALLOC(sizeof(struct mpentry));
262
263         return mpe;
264 }
265
266 struct hwentry *
267 alloc_hwe (void)
268 {
269         struct hwentry * hwe = (struct hwentry *)
270                                 MALLOC(sizeof(struct hwentry));
271
272         return hwe;
273 }
274
275 static char *
276 set_param_str(char * str)
277 {
278         char * dst;
279         int len;
280
281         if (!str)
282                 return NULL;
283
284         len = strlen(str);
285
286         if (!len)
287                 return NULL;
288
289         dst = (char *)MALLOC(len + 1);
290
291         if (!dst)
292                 return NULL;
293
294         strcpy(dst, str);
295         return dst;
296 }
297
298 #define merge_str(s) \
299         if (!dst->s && src->s) { \
300                 if (!(dst->s = set_param_str(src->s))) \
301                         return 1; \
302         }
303
304 #define merge_num(s) \
305         if (!dst->s && src->s) \
306                 dst->s = src->s
307
308
309 static int
310 merge_hwe (struct hwentry * dst, struct hwentry * src)
311 {
312         merge_str(vendor);
313         merge_str(product);
314         merge_str(revision);
315         merge_str(uid_attribute);
316         merge_str(features);
317         merge_str(hwhandler);
318         merge_str(selector);
319         merge_str(checker_name);
320         merge_str(prio_name);
321         merge_str(prio_args);
322         merge_str(alias_prefix);
323         merge_str(bl_product);
324         merge_num(pgpolicy);
325         merge_num(pgfailback);
326         merge_num(rr_weight);
327         merge_num(no_path_retry);
328         merge_num(minio);
329         merge_num(minio_rq);
330         merge_num(pg_timeout);
331         merge_num(flush_on_last_del);
332         merge_num(fast_io_fail);
333         merge_num(dev_loss);
334         merge_num(user_friendly_names);
335         merge_num(retain_hwhandler);
336         merge_num(detect_prio);
337
338         /*
339          * Make sure features is consistent with
340          * no_path_retry
341          */
342         if (dst->no_path_retry == NO_PATH_RETRY_FAIL)
343                 remove_feature(&dst->features, "queue_if_no_path");
344         else if (dst->no_path_retry != NO_PATH_RETRY_UNDEF)
345                 add_feature(&dst->features, "queue_if_no_path");
346
347         return 0;
348 }
349
350 int
351 store_hwe (vector hwtable, struct hwentry * dhwe)
352 {
353         struct hwentry * hwe;
354
355         if (find_hwe_strmatch(hwtable, dhwe))
356                 return 0;
357
358         if (!(hwe = alloc_hwe()))
359                 return 1;
360
361         if (!dhwe->vendor || !(hwe->vendor = set_param_str(dhwe->vendor)))
362                 goto out;
363
364         if (!dhwe->product || !(hwe->product = set_param_str(dhwe->product)))
365                 goto out;
366
367         if (dhwe->revision && !(hwe->revision = set_param_str(dhwe->revision)))
368                 goto out;
369
370         if (dhwe->uid_attribute && !(hwe->uid_attribute = set_param_str(dhwe->uid_attribute)))
371                 goto out;
372
373         if (dhwe->features && !(hwe->features = set_param_str(dhwe->features)))
374                 goto out;
375
376         if (dhwe->hwhandler && !(hwe->hwhandler = set_param_str(dhwe->hwhandler)))
377                 goto out;
378
379         if (dhwe->selector && !(hwe->selector = set_param_str(dhwe->selector)))
380                 goto out;
381
382         if (dhwe->checker_name && !(hwe->checker_name = set_param_str(dhwe->checker_name)))
383                 goto out;
384
385         if (dhwe->prio_name && !(hwe->prio_name = set_param_str(dhwe->prio_name)))
386                 goto out;
387
388         if (dhwe->prio_args && !(hwe->prio_args = set_param_str(dhwe->prio_args)))
389                 goto out;
390
391         if (dhwe->alias_prefix && !(hwe->alias_prefix = set_param_str(dhwe->alias_prefix)))
392                 goto out;
393
394         hwe->pgpolicy = dhwe->pgpolicy;
395         hwe->pgfailback = dhwe->pgfailback;
396         hwe->rr_weight = dhwe->rr_weight;
397         hwe->no_path_retry = dhwe->no_path_retry;
398         hwe->minio = dhwe->minio;
399         hwe->minio_rq = dhwe->minio_rq;
400         hwe->pg_timeout = dhwe->pg_timeout;
401         hwe->flush_on_last_del = dhwe->flush_on_last_del;
402         hwe->fast_io_fail = dhwe->fast_io_fail;
403         hwe->dev_loss = dhwe->dev_loss;
404         hwe->user_friendly_names = dhwe->user_friendly_names;
405         hwe->retain_hwhandler = dhwe->retain_hwhandler;
406         hwe->detect_prio = dhwe->detect_prio;
407
408         if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product)))
409                 goto out;
410
411         if (!vector_alloc_slot(hwtable))
412                 goto out;
413
414         vector_set_slot(hwtable, hwe);
415         return 0;
416 out:
417         free_hwe(hwe);
418         return 1;
419 }
420
421 static void
422 factorize_hwtable (vector hw, int n)
423 {
424         struct hwentry *hwe1, *hwe2;
425         int i, j;
426
427 restart:
428         vector_foreach_slot(hw, hwe1, i) {
429                 if (i == n)
430                         break;
431                 j = n;
432                 vector_foreach_slot_after(hw, hwe2, j) {
433                         if (hwe_regmatch(hwe1, hwe2))
434                                 continue;
435                         /* dup */
436                         merge_hwe(hwe2, hwe1);
437                         if (hwe_strmatch(hwe2, hwe1) == 0) {
438                                 vector_del_slot(hw, i);
439                                 free_hwe(hwe1);
440                                 n -= 1;
441                                 /*
442                                  * Play safe here; we have modified
443                                  * the original vector so the outer
444                                  * vector_foreach_slot() might
445                                  * become confused.
446                                  */
447                                 goto restart;
448                         }
449                 }
450         }
451         return;
452 }
453
454 struct config *
455 alloc_config (void)
456 {
457         return (struct config *)MALLOC(sizeof(struct config));
458 }
459
460 void
461 free_config (struct config * conf)
462 {
463         if (!conf)
464                 return;
465
466         if (conf->dev)
467                 FREE(conf->dev);
468
469         if (conf->multipath_dir)
470                 FREE(conf->multipath_dir);
471
472         if (conf->selector)
473                 FREE(conf->selector);
474
475         if (conf->uid_attribute)
476                 FREE(conf->uid_attribute);
477
478         if (conf->features)
479                 FREE(conf->features);
480
481         if (conf->hwhandler)
482                 FREE(conf->hwhandler);
483
484         if (conf->bindings_file)
485                 FREE(conf->bindings_file);
486
487         if (conf->wwids_file)
488                 FREE(conf->wwids_file);
489         if (conf->prio_name)
490                 FREE(conf->prio_name);
491
492         if (conf->alias_prefix)
493                 FREE(conf->alias_prefix);
494
495         if (conf->prio_args)
496                 FREE(conf->prio_args);
497
498         if (conf->checker_name)
499                 FREE(conf->checker_name);
500         if (conf->reservation_key)
501                 FREE(conf->reservation_key);
502
503         free_blacklist(conf->blist_devnode);
504         free_blacklist(conf->blist_wwid);
505         free_blacklist_device(conf->blist_device);
506
507         free_blacklist(conf->elist_devnode);
508         free_blacklist(conf->elist_wwid);
509         free_blacklist_device(conf->elist_device);
510
511         free_mptable(conf->mptable);
512         free_hwtable(conf->hwtable);
513         free_keywords(conf->keywords);
514         FREE(conf);
515 }
516
517 int
518 load_config (char * file, struct udev *udev)
519 {
520         if (!conf)
521                 conf = alloc_config();
522
523         if (!conf || !udev)
524                 return 1;
525
526         /*
527          * internal defaults
528          */
529         if (!conf->verbosity)
530                 conf->verbosity = DEFAULT_VERBOSITY;
531
532         conf->udev = udev;
533         dm_drv_version(conf->version, TGT_MPATH);
534         conf->dev_type = DEV_NONE;
535         conf->minio = DEFAULT_MINIO;
536         conf->minio_rq = DEFAULT_MINIO_RQ;
537         get_sys_max_fds(&conf->max_fds);
538         conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
539         conf->wwids_file = set_default(DEFAULT_WWIDS_FILE);
540         conf->bindings_read_only = 0;
541         conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
542         conf->features = set_default(DEFAULT_FEATURES);
543         conf->flush_on_last_del = 0;
544         conf->attribute_flags = 0;
545         conf->reassign_maps = DEFAULT_REASSIGN_MAPS;
546         conf->checkint = DEFAULT_CHECKINT;
547         conf->max_checkint = MAX_CHECKINT(conf->checkint);
548         conf->fast_io_fail = DEFAULT_FAST_IO_FAIL;
549         conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER;
550         conf->detect_prio = DEFAULT_DETECT_PRIO;
551
552         /*
553          * preload default hwtable
554          */
555         if (conf->hwtable == NULL) {
556                 conf->hwtable = vector_alloc();
557
558                 if (!conf->hwtable)
559                         goto out;
560         }
561         if (setup_default_hwtable(conf->hwtable))
562                 goto out;
563
564         /*
565          * read the config file
566          */
567         set_current_keywords(&conf->keywords);
568         alloc_keywords();
569         if (filepresent(file)) {
570                 int builtin_hwtable_size;
571
572                 builtin_hwtable_size = VECTOR_SIZE(conf->hwtable);
573                 if (init_data(file, init_keywords)) {
574                         condlog(0, "error parsing config file");
575                         goto out;
576                 }
577                 if (VECTOR_SIZE(conf->hwtable) > builtin_hwtable_size) {
578                         /*
579                          * remove duplica in hwtable. config file
580                          * takes precedence over build-in hwtable
581                          */
582                         factorize_hwtable(conf->hwtable, builtin_hwtable_size);
583                 }
584
585         } else {
586                 init_keywords();
587         }
588
589         /*
590          * fill the voids left in the config file
591          */
592         if (conf->blist_devnode == NULL) {
593                 conf->blist_devnode = vector_alloc();
594
595                 if (!conf->blist_devnode)
596                         goto out;
597         }
598         if (conf->blist_wwid == NULL) {
599                 conf->blist_wwid = vector_alloc();
600
601                 if (!conf->blist_wwid)
602                         goto out;
603         }
604         if (conf->blist_device == NULL) {
605                 conf->blist_device = vector_alloc();
606
607                 if (!conf->blist_device)
608                         goto out;
609         }
610         if (setup_default_blist(conf))
611                 goto out;
612
613         if (conf->elist_devnode == NULL) {
614                 conf->elist_devnode = vector_alloc();
615
616                 if (!conf->elist_devnode)
617                         goto out;
618         }
619         if (conf->elist_wwid == NULL) {
620                 conf->elist_wwid = vector_alloc();
621
622                 if (!conf->elist_wwid)
623                         goto out;
624         }
625
626         if (conf->elist_device == NULL) {
627                 conf->elist_device = vector_alloc();
628
629                 if (!conf->elist_device)
630                         goto out;
631         }
632
633         if (conf->mptable == NULL) {
634                 conf->mptable = vector_alloc();
635                 if (!conf->mptable)
636                         goto out;
637         }
638         if (conf->bindings_file == NULL)
639                 conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
640
641         if (!conf->multipath_dir || !conf->bindings_file ||
642             !conf->wwids_file)
643                 goto out;
644
645         return 0;
646 out:
647         free_config(conf);
648         return 1;
649 }
650