2 * Copyright (c) 2004, 2005 Christophe Varoqui
3 * Copyright (c) 2005 Benjamin Marzinski, Redhat
4 * Copyright (c) 2005 Edward Goggin, EMC
23 #include "blacklist.h"
26 #include "devmapper.h"
27 #include "mpath_cmd.h"
31 hwe_strmatch (const struct hwentry *hwe1, const struct hwentry *hwe2)
33 if ((hwe2->vendor && !hwe1->vendor) ||
34 (hwe1->vendor && (!hwe2->vendor ||
35 strcmp(hwe1->vendor, hwe2->vendor))))
38 if ((hwe2->product && !hwe1->product) ||
39 (hwe1->product && (!hwe2->product ||
40 strcmp(hwe1->product, hwe2->product))))
43 if ((hwe2->revision && !hwe1->revision) ||
44 (hwe1->revision && (!hwe2->revision ||
45 strcmp(hwe1->revision, hwe2->revision))))
51 static struct hwentry *
52 find_hwe_strmatch (const struct _vector *hwtable, const struct hwentry *hwe)
55 struct hwentry *tmp, *ret = NULL;
57 vector_foreach_slot (hwtable, tmp, i) {
58 if (hwe_strmatch(tmp, hwe))
67 hwe_regmatch (const struct hwentry *hwe1, const char *vendor,
68 const char *product, const char *revision)
70 regex_t vre, pre, rre;
74 regcomp(&vre, hwe1->vendor, REG_EXTENDED|REG_NOSUB))
78 regcomp(&pre, hwe1->product, REG_EXTENDED|REG_NOSUB))
82 regcomp(&rre, hwe1->revision, REG_EXTENDED|REG_NOSUB))
85 if ((vendor || product || revision) &&
86 (!hwe1->vendor || !vendor ||
87 !regexec(&vre, vendor, 0, NULL, 0)) &&
88 (!hwe1->product || !product ||
89 !regexec(&pre, product, 0, NULL, 0)) &&
90 (!hwe1->revision || !revision ||
91 !regexec(&rre, revision, 0, NULL, 0)))
106 static void _log_match(const char *fn, const struct hwentry *h,
107 const char *vendor, const char *product,
108 const char *revision)
110 condlog(4, "%s: found match /%s:%s:%s/ for '%s:%s:%s'", fn,
111 h->vendor, h->product, h->revision,
112 vendor, product, revision);
114 #define log_match(h, v, p, r) _log_match(__func__, (h), (v), (p), (r))
117 find_hwe (const struct _vector *hwtable,
118 const char * vendor, const char * product, const char * revision,
125 * Search backwards here, and add forward.
126 * User modified entries are attached at the end of
127 * the list, so we have to check them first before
128 * continuing to the generic entries
130 vector_reset(result);
131 vector_foreach_slot_backwards (hwtable, tmp, i) {
132 if (hwe_regmatch(tmp, vendor, product, revision))
134 if (vector_alloc_slot(result) != NULL) {
135 vector_set_slot(result, tmp);
138 log_match(tmp, vendor, product, revision);
140 condlog(n > 1 ? 3 : 4, "%s: found %d hwtable matches for %s:%s:%s",
141 __func__, n, vendor, product, revision);
145 struct mpentry *find_mpe(vector mptable, char *wwid)
148 struct mpentry * mpe;
153 vector_foreach_slot (mptable, mpe, i)
154 if (mpe->wwid && !strcmp(mpe->wwid, wwid))
160 char *get_mpe_wwid(vector mptable, char *alias)
163 struct mpentry * mpe;
168 vector_foreach_slot (mptable, mpe, i)
169 if (mpe->alias && strcmp(mpe->alias, alias) == 0)
176 free_hwe (struct hwentry * hwe)
193 if (hwe->uid_attribute)
194 FREE(hwe->uid_attribute);
200 FREE(hwe->hwhandler);
205 if (hwe->checker_name)
206 FREE(hwe->checker_name);
209 FREE(hwe->prio_name);
212 FREE(hwe->prio_args);
214 if (hwe->alias_prefix)
215 FREE(hwe->alias_prefix);
218 FREE(hwe->bl_product);
224 free_hwtable (vector hwtable)
227 struct hwentry * hwe;
232 vector_foreach_slot (hwtable, hwe, i)
235 vector_free(hwtable);
239 free_mpe (struct mpentry * mpe)
253 if (mpe->uid_attribute)
254 FREE(mpe->uid_attribute);
260 FREE(mpe->prio_name);
263 FREE(mpe->prio_args);
269 free_mptable (vector mptable)
272 struct mpentry * mpe;
277 vector_foreach_slot (mptable, mpe, i)
280 vector_free(mptable);
286 struct mpentry * mpe = (struct mpentry *)
287 MALLOC(sizeof(struct mpentry));
295 struct hwentry * hwe = (struct hwentry *)
296 MALLOC(sizeof(struct hwentry));
302 set_param_str(const char * str)
315 dst = (char *)MALLOC(len + 1);
324 #define merge_str(s) \
325 if (!dst->s && src->s) { \
326 if (!(dst->s = set_param_str(src->s))) \
330 #define merge_num(s) \
331 if (!dst->s && src->s) \
336 merge_hwe (struct hwentry * dst, struct hwentry * src)
338 char id[SCSI_VENDOR_SIZE+PATH_PRODUCT_SIZE];
343 merge_str(uid_attribute);
345 merge_str(hwhandler);
347 merge_str(checker_name);
348 merge_str(prio_name);
349 merge_str(prio_args);
350 merge_str(alias_prefix);
351 merge_str(bl_product);
353 merge_num(pgfailback);
354 merge_num(rr_weight);
355 merge_num(no_path_retry);
358 merge_num(flush_on_last_del);
359 merge_num(fast_io_fail);
361 merge_num(user_friendly_names);
362 merge_num(retain_hwhandler);
363 merge_num(detect_prio);
364 merge_num(detect_checker);
365 merge_num(deferred_remove);
366 merge_num(delay_watch_checks);
367 merge_num(delay_wait_checks);
368 merge_num(skip_kpartx);
369 merge_num(max_sectors_kb);
370 merge_num(ghost_delay);
371 merge_num(all_tg_pt);
373 snprintf(id, sizeof(id), "%s/%s", dst->vendor, dst->product);
374 reconcile_features_with_options(id, &dst->features,
376 &dst->retain_hwhandler);
381 merge_mpe(struct mpentry *dst, struct mpentry *src)
387 merge_str(uid_attribute);
391 merge_str(prio_name);
392 merge_str(prio_args);
394 if (dst->prkey_source == PRKEY_SOURCE_NONE &&
395 src->prkey_source != PRKEY_SOURCE_NONE) {
396 dst->prkey_source = src->prkey_source;
397 memcpy(&dst->reservation_key, &src->reservation_key,
398 sizeof(dst->reservation_key));
402 merge_num(pgfailback);
403 merge_num(rr_weight);
404 merge_num(no_path_retry);
407 merge_num(flush_on_last_del);
408 merge_num(attribute_flags);
409 merge_num(user_friendly_names);
410 merge_num(deferred_remove);
411 merge_num(delay_watch_checks);
412 merge_num(delay_wait_checks);
413 merge_num(marginal_path_err_sample_time);
414 merge_num(marginal_path_err_rate_threshold);
415 merge_num(marginal_path_err_recheck_gap_time);
416 merge_num(marginal_path_double_failed_time);
417 merge_num(skip_kpartx);
418 merge_num(max_sectors_kb);
419 merge_num(ghost_delay);
427 void merge_mptable(vector mptable)
429 struct mpentry *mp1, *mp2;
432 vector_foreach_slot(mptable, mp1, i) {
434 vector_foreach_slot_after(mptable, mp2, j) {
435 if (strcmp(mp1->wwid, mp2->wwid))
437 condlog(1, "%s: duplicate multipath config section for %s",
438 __func__, mp1->wwid);
441 vector_del_slot(mptable, i);
449 store_hwe (vector hwtable, struct hwentry * dhwe)
451 struct hwentry * hwe;
453 if (find_hwe_strmatch(hwtable, dhwe))
456 if (!(hwe = alloc_hwe()))
459 if (!dhwe->vendor || !(hwe->vendor = set_param_str(dhwe->vendor)))
462 if (!dhwe->product || !(hwe->product = set_param_str(dhwe->product)))
465 if (dhwe->revision && !(hwe->revision = set_param_str(dhwe->revision)))
468 if (dhwe->uid_attribute && !(hwe->uid_attribute = set_param_str(dhwe->uid_attribute)))
471 if (dhwe->getuid && !(hwe->getuid = set_param_str(dhwe->getuid)))
474 if (dhwe->features && !(hwe->features = set_param_str(dhwe->features)))
477 if (dhwe->hwhandler && !(hwe->hwhandler = set_param_str(dhwe->hwhandler)))
480 if (dhwe->selector && !(hwe->selector = set_param_str(dhwe->selector)))
483 if (dhwe->checker_name && !(hwe->checker_name = set_param_str(dhwe->checker_name)))
486 if (dhwe->prio_name && !(hwe->prio_name = set_param_str(dhwe->prio_name)))
489 if (dhwe->prio_args && !(hwe->prio_args = set_param_str(dhwe->prio_args)))
492 if (dhwe->alias_prefix && !(hwe->alias_prefix = set_param_str(dhwe->alias_prefix)))
495 hwe->pgpolicy = dhwe->pgpolicy;
496 hwe->pgfailback = dhwe->pgfailback;
497 hwe->rr_weight = dhwe->rr_weight;
498 hwe->no_path_retry = dhwe->no_path_retry;
499 hwe->minio = dhwe->minio;
500 hwe->minio_rq = dhwe->minio_rq;
501 hwe->flush_on_last_del = dhwe->flush_on_last_del;
502 hwe->fast_io_fail = dhwe->fast_io_fail;
503 hwe->dev_loss = dhwe->dev_loss;
504 hwe->user_friendly_names = dhwe->user_friendly_names;
505 hwe->retain_hwhandler = dhwe->retain_hwhandler;
506 hwe->detect_prio = dhwe->detect_prio;
507 hwe->detect_checker = dhwe->detect_checker;
508 hwe->ghost_delay = dhwe->ghost_delay;
510 if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product)))
513 if (!vector_alloc_slot(hwtable))
516 vector_set_slot(hwtable, hwe);
524 factorize_hwtable (vector hw, int n, const char *table_desc)
526 struct hwentry *hwe1, *hwe2;
530 vector_foreach_slot(hw, hwe1, i) {
531 /* drop invalid device configs */
532 if (i >= n && (!hwe1->vendor || !hwe1->product)) {
533 condlog(0, "device config in %s missing vendor or product parameter",
535 vector_del_slot(hw, i--);
539 j = n > i + 1 ? n : i + 1;
540 vector_foreach_slot_after(hw, hwe2, j) {
541 if (hwe_strmatch(hwe2, hwe1) == 0) {
542 condlog(i >= n ? 1 : 3,
543 "%s: duplicate device section for %s:%s:%s in %s",
544 __func__, hwe1->vendor, hwe1->product,
545 hwe1->revision, table_desc);
546 vector_del_slot(hw, i);
547 merge_hwe(hwe2, hwe1);
552 * Play safe here; we have modified
553 * the original vector so the outer
554 * vector_foreach_slot() might
567 return (struct config *)MALLOC(sizeof(struct config));
571 free_config (struct config * conf)
576 if (conf->multipath_dir)
577 FREE(conf->multipath_dir);
580 FREE(conf->selector);
582 if (conf->uid_attribute)
583 FREE(conf->uid_attribute);
586 FREE(conf->uid_attrs);
592 FREE(conf->features);
595 FREE(conf->hwhandler);
597 if (conf->bindings_file)
598 FREE(conf->bindings_file);
600 if (conf->wwids_file)
601 FREE(conf->wwids_file);
603 if (conf->prkeys_file)
604 FREE(conf->prkeys_file);
607 FREE(conf->prio_name);
609 if (conf->alias_prefix)
610 FREE(conf->alias_prefix);
611 if (conf->partition_delim)
612 FREE(conf->partition_delim);
615 FREE(conf->prio_args);
617 if (conf->checker_name)
618 FREE(conf->checker_name);
620 if (conf->config_dir)
621 FREE(conf->config_dir);
623 free_blacklist(conf->blist_devnode);
624 free_blacklist(conf->blist_wwid);
625 free_blacklist(conf->blist_property);
626 free_blacklist(conf->blist_protocol);
627 free_blacklist_device(conf->blist_device);
629 free_blacklist(conf->elist_devnode);
630 free_blacklist(conf->elist_wwid);
631 free_blacklist(conf->elist_property);
632 free_blacklist(conf->elist_protocol);
633 free_blacklist_device(conf->elist_device);
635 free_mptable(conf->mptable);
636 free_hwtable(conf->hwtable);
637 free_hwe(conf->overrides);
638 free_keywords(conf->keywords);
642 /* if multipath fails to process the config directory, it should continue,
643 * with just a warning message */
645 process_config_dir(struct config *conf, vector keywords, char *dir)
647 struct dirent **namelist;
648 struct scandir_result sr;
651 int old_hwtable_size;
654 condlog(1, "config_dir '%s' must be a fully qualified path",
658 n = scandir(dir, &namelist, NULL, alphasort);
661 condlog(3, "No configuration dir '%s'", dir);
663 condlog(0, "couldn't open configuration dir '%s': %s",
664 dir, strerror(errno));
670 pthread_cleanup_push_cast(free_scandir_result, &sr);
671 for (i = 0; i < n; i++) {
672 if (!strstr(namelist[i]->d_name, ".conf"))
674 old_hwtable_size = VECTOR_SIZE(conf->hwtable);
675 snprintf(path, LINE_MAX, "%s/%s", dir, namelist[i]->d_name);
676 path[LINE_MAX-1] = '\0';
677 process_file(conf, path);
678 factorize_hwtable(conf->hwtable, old_hwtable_size,
679 namelist[i]->d_name);
681 pthread_cleanup_pop(1);
685 load_config (char * file)
687 struct config *conf = alloc_config();
695 conf->verbosity = DEFAULT_VERBOSITY;
697 get_sys_max_fds(&conf->max_fds);
698 conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
699 conf->wwids_file = set_default(DEFAULT_WWIDS_FILE);
700 conf->prkeys_file = set_default(DEFAULT_PRKEYS_FILE);
701 conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
702 conf->attribute_flags = 0;
703 conf->reassign_maps = DEFAULT_REASSIGN_MAPS;
704 conf->checkint = DEFAULT_CHECKINT;
705 conf->max_checkint = 0;
706 conf->force_sync = DEFAULT_FORCE_SYNC;
707 conf->partition_delim = (default_partition_delim != NULL ?
708 strdup(default_partition_delim) : NULL);
709 conf->processed_main_config = 0;
710 conf->find_multipaths = DEFAULT_FIND_MULTIPATHS;
711 conf->uxsock_timeout = DEFAULT_REPLY_TIMEOUT;
712 conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES;
713 conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY;
714 conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT;
715 conf->disable_changed_wwids = DEFAULT_DISABLE_CHANGED_WWIDS;
716 conf->remove_retries = 0;
717 conf->ghost_delay = DEFAULT_GHOST_DELAY;
718 conf->all_tg_pt = DEFAULT_ALL_TG_PT;
721 * preload default hwtable
723 conf->hwtable = vector_alloc();
726 if (setup_default_hwtable(conf->hwtable))
729 #ifdef CHECK_BUILTIN_HWTABLE
730 factorize_hwtable(conf->hwtable, 0, "builtin");
733 * read the config file
735 conf->keywords = vector_alloc();
736 init_keywords(conf->keywords);
737 if (filepresent(file)) {
738 int builtin_hwtable_size;
740 builtin_hwtable_size = VECTOR_SIZE(conf->hwtable);
741 if (process_file(conf, file)) {
742 condlog(0, "error parsing config file");
745 factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
748 conf->processed_main_config = 1;
749 if (conf->config_dir == NULL)
750 conf->config_dir = set_default(DEFAULT_CONFIG_DIR);
751 if (conf->config_dir && conf->config_dir[0] != '\0')
752 process_config_dir(conf, conf->keywords, conf->config_dir);
755 * fill the voids left in the config file
757 if (conf->max_checkint == 0)
758 conf->max_checkint = MAX_CHECKINT(conf->checkint);
759 if (conf->blist_devnode == NULL) {
760 conf->blist_devnode = vector_alloc();
762 if (!conf->blist_devnode)
765 if (conf->blist_wwid == NULL) {
766 conf->blist_wwid = vector_alloc();
768 if (!conf->blist_wwid)
771 if (conf->blist_device == NULL) {
772 conf->blist_device = vector_alloc();
774 if (!conf->blist_device)
777 if (conf->blist_property == NULL) {
778 conf->blist_property = vector_alloc();
780 if (!conf->blist_property)
783 if (conf->blist_protocol == NULL) {
784 conf->blist_protocol = vector_alloc();
786 if (!conf->blist_protocol)
790 if (conf->elist_devnode == NULL) {
791 conf->elist_devnode = vector_alloc();
793 if (!conf->elist_devnode)
796 if (conf->elist_wwid == NULL) {
797 conf->elist_wwid = vector_alloc();
799 if (!conf->elist_wwid)
803 if (conf->elist_device == NULL) {
804 conf->elist_device = vector_alloc();
806 if (!conf->elist_device)
810 if (conf->elist_property == NULL) {
811 conf->elist_property = vector_alloc();
813 if (!conf->elist_property)
816 if (conf->elist_protocol == NULL) {
817 conf->elist_protocol = vector_alloc();
819 if (!conf->elist_protocol)
823 if (setup_default_blist(conf))
826 if (conf->mptable == NULL) {
827 conf->mptable = vector_alloc();
832 merge_mptable(conf->mptable);
833 merge_blacklist(conf->blist_devnode);
834 merge_blacklist(conf->blist_property);
835 merge_blacklist(conf->blist_wwid);
836 merge_blacklist_device(conf->blist_device);
837 merge_blacklist(conf->elist_devnode);
838 merge_blacklist(conf->elist_property);
839 merge_blacklist(conf->elist_wwid);
840 merge_blacklist_device(conf->elist_device);
842 if (conf->bindings_file == NULL)
843 conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
845 if (!conf->multipath_dir || !conf->bindings_file ||
846 !conf->wwids_file || !conf->prkeys_file)