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