multipath: Deprecate 'getuid' configuration variable
[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->getuid)
171                 FREE(hwe->getuid);
172
173         if (hwe->uid_attribute)
174                 FREE(hwe->uid_attribute);
175
176         if (hwe->features)
177                 FREE(hwe->features);
178
179         if (hwe->hwhandler)
180                 FREE(hwe->hwhandler);
181
182         if (hwe->selector)
183                 FREE(hwe->selector);
184
185         if (hwe->checker_name)
186                 FREE(hwe->checker_name);
187
188         if (hwe->prio_name)
189                 FREE(hwe->prio_name);
190
191         if (hwe->prio_args)
192                 FREE(hwe->prio_args);
193
194         if (hwe->alias_prefix)
195                 FREE(hwe->alias_prefix);
196
197         if (hwe->bl_product)
198                 FREE(hwe->bl_product);
199
200         FREE(hwe);
201 }
202
203 void
204 free_hwtable (vector hwtable)
205 {
206         int i;
207         struct hwentry * hwe;
208
209         if (!hwtable)
210                 return;
211
212         vector_foreach_slot (hwtable, hwe, i)
213                 free_hwe(hwe);
214
215         vector_free(hwtable);
216 }
217
218 void
219 free_mpe (struct mpentry * mpe)
220 {
221         if (!mpe)
222                 return;
223
224         if (mpe->wwid)
225                 FREE(mpe->wwid);
226
227         if (mpe->selector)
228                 FREE(mpe->selector);
229
230         if (mpe->getuid)
231                 FREE(mpe->getuid);
232
233         if (mpe->uid_attribute)
234                 FREE(mpe->uid_attribute);
235
236         if (mpe->alias)
237                 FREE(mpe->alias);
238
239         if (mpe->prio_name)
240                 FREE(mpe->prio_name);
241
242         if (mpe->prio_args)
243                 FREE(mpe->prio_args);
244
245         FREE(mpe);
246 }
247
248 void
249 free_mptable (vector mptable)
250 {
251         int i;
252         struct mpentry * mpe;
253
254         if (!mptable)
255                 return;
256
257         vector_foreach_slot (mptable, mpe, i)
258                 free_mpe(mpe);
259
260         vector_free(mptable);
261 }
262
263 struct mpentry *
264 alloc_mpe (void)
265 {
266         struct mpentry * mpe = (struct mpentry *)
267                                 MALLOC(sizeof(struct mpentry));
268
269         return mpe;
270 }
271
272 struct hwentry *
273 alloc_hwe (void)
274 {
275         struct hwentry * hwe = (struct hwentry *)
276                                 MALLOC(sizeof(struct hwentry));
277
278         return hwe;
279 }
280
281 static char *
282 set_param_str(char * str)
283 {
284         char * dst;
285         int len;
286
287         if (!str)
288                 return NULL;
289
290         len = strlen(str);
291
292         if (!len)
293                 return NULL;
294
295         dst = (char *)MALLOC(len + 1);
296
297         if (!dst)
298                 return NULL;
299
300         strcpy(dst, str);
301         return dst;
302 }
303
304 #define merge_str(s) \
305         if (!dst->s && src->s) { \
306                 if (!(dst->s = set_param_str(src->s))) \
307                         return 1; \
308         }
309
310 #define merge_num(s) \
311         if (!dst->s && src->s) \
312                 dst->s = src->s
313
314
315 static int
316 merge_hwe (struct hwentry * dst, struct hwentry * src)
317 {
318         merge_str(vendor);
319         merge_str(product);
320         merge_str(revision);
321         merge_str(getuid);
322         merge_str(uid_attribute);
323         merge_str(features);
324         merge_str(hwhandler);
325         merge_str(selector);
326         merge_str(checker_name);
327         merge_str(prio_name);
328         merge_str(prio_args);
329         merge_str(alias_prefix);
330         merge_str(bl_product);
331         merge_num(pgpolicy);
332         merge_num(pgfailback);
333         merge_num(rr_weight);
334         merge_num(no_path_retry);
335         merge_num(minio);
336         merge_num(minio_rq);
337         merge_num(pg_timeout);
338         merge_num(flush_on_last_del);
339         merge_num(fast_io_fail);
340         merge_num(dev_loss);
341         merge_num(user_friendly_names);
342         merge_num(retain_hwhandler);
343         merge_num(detect_prio);
344
345         /*
346          * Make sure features is consistent with
347          * no_path_retry
348          */
349         if (dst->no_path_retry == NO_PATH_RETRY_FAIL)
350                 remove_feature(&dst->features, "queue_if_no_path");
351         else if (dst->no_path_retry != NO_PATH_RETRY_UNDEF)
352                 add_feature(&dst->features, "queue_if_no_path");
353
354         return 0;
355 }
356
357 int
358 store_hwe (vector hwtable, struct hwentry * dhwe)
359 {
360         struct hwentry * hwe;
361
362         if (find_hwe_strmatch(hwtable, dhwe))
363                 return 0;
364
365         if (!(hwe = alloc_hwe()))
366                 return 1;
367
368         if (!dhwe->vendor || !(hwe->vendor = set_param_str(dhwe->vendor)))
369                 goto out;
370
371         if (!dhwe->product || !(hwe->product = set_param_str(dhwe->product)))
372                 goto out;
373
374         if (dhwe->revision && !(hwe->revision = set_param_str(dhwe->revision)))
375                 goto out;
376
377         if (dhwe->uid_attribute && !(hwe->uid_attribute = set_param_str(dhwe->uid_attribute)))
378                 goto out;
379
380         if (dhwe->getuid && !(hwe->getuid = set_param_str(dhwe->getuid)))
381                 goto out;
382
383         if (dhwe->features && !(hwe->features = set_param_str(dhwe->features)))
384                 goto out;
385
386         if (dhwe->hwhandler && !(hwe->hwhandler = set_param_str(dhwe->hwhandler)))
387                 goto out;
388
389         if (dhwe->selector && !(hwe->selector = set_param_str(dhwe->selector)))
390                 goto out;
391
392         if (dhwe->checker_name && !(hwe->checker_name = set_param_str(dhwe->checker_name)))
393                 goto out;
394
395         if (dhwe->prio_name && !(hwe->prio_name = set_param_str(dhwe->prio_name)))
396                 goto out;
397
398         if (dhwe->prio_args && !(hwe->prio_args = set_param_str(dhwe->prio_args)))
399                 goto out;
400
401         if (dhwe->alias_prefix && !(hwe->alias_prefix = set_param_str(dhwe->alias_prefix)))
402                 goto out;
403
404         hwe->pgpolicy = dhwe->pgpolicy;
405         hwe->pgfailback = dhwe->pgfailback;
406         hwe->rr_weight = dhwe->rr_weight;
407         hwe->no_path_retry = dhwe->no_path_retry;
408         hwe->minio = dhwe->minio;
409         hwe->minio_rq = dhwe->minio_rq;
410         hwe->pg_timeout = dhwe->pg_timeout;
411         hwe->flush_on_last_del = dhwe->flush_on_last_del;
412         hwe->fast_io_fail = dhwe->fast_io_fail;
413         hwe->dev_loss = dhwe->dev_loss;
414         hwe->user_friendly_names = dhwe->user_friendly_names;
415         hwe->retain_hwhandler = dhwe->retain_hwhandler;
416         hwe->detect_prio = dhwe->detect_prio;
417
418         if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product)))
419                 goto out;
420
421         if (!vector_alloc_slot(hwtable))
422                 goto out;
423
424         vector_set_slot(hwtable, hwe);
425         return 0;
426 out:
427         free_hwe(hwe);
428         return 1;
429 }
430
431 static void
432 factorize_hwtable (vector hw, int n)
433 {
434         struct hwentry *hwe1, *hwe2;
435         int i, j;
436
437 restart:
438         vector_foreach_slot(hw, hwe1, i) {
439                 if (i == n)
440                         break;
441                 j = n;
442                 vector_foreach_slot_after(hw, hwe2, j) {
443                         if (hwe_regmatch(hwe1, hwe2))
444                                 continue;
445                         /* dup */
446                         merge_hwe(hwe2, hwe1);
447                         if (hwe_strmatch(hwe2, hwe1) == 0) {
448                                 vector_del_slot(hw, i);
449                                 free_hwe(hwe1);
450                                 n -= 1;
451                                 /*
452                                  * Play safe here; we have modified
453                                  * the original vector so the outer
454                                  * vector_foreach_slot() might
455                                  * become confused.
456                                  */
457                                 goto restart;
458                         }
459                 }
460         }
461         return;
462 }
463
464 struct config *
465 alloc_config (void)
466 {
467         return (struct config *)MALLOC(sizeof(struct config));
468 }
469
470 void
471 free_config (struct config * conf)
472 {
473         if (!conf)
474                 return;
475
476         if (conf->dev)
477                 FREE(conf->dev);
478
479         if (conf->multipath_dir)
480                 FREE(conf->multipath_dir);
481
482         if (conf->selector)
483                 FREE(conf->selector);
484
485         if (conf->uid_attribute)
486                 FREE(conf->uid_attribute);
487
488         if (conf->getuid)
489                 FREE(conf->getuid);
490
491         if (conf->features)
492                 FREE(conf->features);
493
494         if (conf->hwhandler)
495                 FREE(conf->hwhandler);
496
497         if (conf->bindings_file)
498                 FREE(conf->bindings_file);
499
500         if (conf->wwids_file)
501                 FREE(conf->wwids_file);
502         if (conf->prio_name)
503                 FREE(conf->prio_name);
504
505         if (conf->alias_prefix)
506                 FREE(conf->alias_prefix);
507
508         if (conf->prio_args)
509                 FREE(conf->prio_args);
510
511         if (conf->checker_name)
512                 FREE(conf->checker_name);
513         if (conf->reservation_key)
514                 FREE(conf->reservation_key);
515
516         free_blacklist(conf->blist_devnode);
517         free_blacklist(conf->blist_wwid);
518         free_blacklist_device(conf->blist_device);
519
520         free_blacklist(conf->elist_devnode);
521         free_blacklist(conf->elist_wwid);
522         free_blacklist_device(conf->elist_device);
523
524         free_mptable(conf->mptable);
525         free_hwtable(conf->hwtable);
526         free_keywords(conf->keywords);
527         FREE(conf);
528 }
529
530 int
531 load_config (char * file, struct udev *udev)
532 {
533         if (!conf)
534                 conf = alloc_config();
535
536         if (!conf || !udev)
537                 return 1;
538
539         /*
540          * internal defaults
541          */
542         if (!conf->verbosity)
543                 conf->verbosity = DEFAULT_VERBOSITY;
544
545         conf->udev = udev;
546         dm_drv_version(conf->version, TGT_MPATH);
547         conf->dev_type = DEV_NONE;
548         conf->minio = DEFAULT_MINIO;
549         conf->minio_rq = DEFAULT_MINIO_RQ;
550         get_sys_max_fds(&conf->max_fds);
551         conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
552         conf->wwids_file = set_default(DEFAULT_WWIDS_FILE);
553         conf->bindings_read_only = 0;
554         conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
555         conf->features = set_default(DEFAULT_FEATURES);
556         conf->flush_on_last_del = 0;
557         conf->attribute_flags = 0;
558         conf->reassign_maps = DEFAULT_REASSIGN_MAPS;
559         conf->checkint = DEFAULT_CHECKINT;
560         conf->max_checkint = MAX_CHECKINT(conf->checkint);
561         conf->fast_io_fail = DEFAULT_FAST_IO_FAIL;
562         conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER;
563         conf->detect_prio = DEFAULT_DETECT_PRIO;
564
565         /*
566          * preload default hwtable
567          */
568         if (conf->hwtable == NULL) {
569                 conf->hwtable = vector_alloc();
570
571                 if (!conf->hwtable)
572                         goto out;
573         }
574         if (setup_default_hwtable(conf->hwtable))
575                 goto out;
576
577         /*
578          * read the config file
579          */
580         set_current_keywords(&conf->keywords);
581         alloc_keywords();
582         if (filepresent(file)) {
583                 int builtin_hwtable_size;
584
585                 builtin_hwtable_size = VECTOR_SIZE(conf->hwtable);
586                 if (init_data(file, init_keywords)) {
587                         condlog(0, "error parsing config file");
588                         goto out;
589                 }
590                 if (VECTOR_SIZE(conf->hwtable) > builtin_hwtable_size) {
591                         /*
592                          * remove duplica in hwtable. config file
593                          * takes precedence over build-in hwtable
594                          */
595                         factorize_hwtable(conf->hwtable, builtin_hwtable_size);
596                 }
597
598         } else {
599                 init_keywords();
600         }
601
602         /*
603          * fill the voids left in the config file
604          */
605         if (conf->blist_devnode == NULL) {
606                 conf->blist_devnode = vector_alloc();
607
608                 if (!conf->blist_devnode)
609                         goto out;
610         }
611         if (conf->blist_wwid == NULL) {
612                 conf->blist_wwid = vector_alloc();
613
614                 if (!conf->blist_wwid)
615                         goto out;
616         }
617         if (conf->blist_device == NULL) {
618                 conf->blist_device = vector_alloc();
619
620                 if (!conf->blist_device)
621                         goto out;
622         }
623         if (setup_default_blist(conf))
624                 goto out;
625
626         if (conf->elist_devnode == NULL) {
627                 conf->elist_devnode = vector_alloc();
628
629                 if (!conf->elist_devnode)
630                         goto out;
631         }
632         if (conf->elist_wwid == NULL) {
633                 conf->elist_wwid = vector_alloc();
634
635                 if (!conf->elist_wwid)
636                         goto out;
637         }
638
639         if (conf->elist_device == NULL) {
640                 conf->elist_device = vector_alloc();
641
642                 if (!conf->elist_device)
643                         goto out;
644         }
645
646         if (conf->mptable == NULL) {
647                 conf->mptable = vector_alloc();
648                 if (!conf->mptable)
649                         goto out;
650         }
651         if (conf->bindings_file == NULL)
652                 conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
653
654         if (!conf->multipath_dir || !conf->bindings_file ||
655             !conf->wwids_file)
656                 goto out;
657
658         return 0;
659 out:
660         free_config(conf);
661         return 1;
662 }
663