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