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