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