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);
372 merge_num(vpd_vendor_id);
373 merge_num(san_path_err_threshold);
374 merge_num(san_path_err_forget_rate);
375 merge_num(san_path_err_recovery_time);
376 merge_num(marginal_path_err_sample_time);
377 merge_num(marginal_path_err_rate_threshold);
378 merge_num(marginal_path_err_recheck_gap_time);
379 merge_num(marginal_path_double_failed_time);
381 snprintf(id, sizeof(id), "%s/%s", dst->vendor, dst->product);
382 reconcile_features_with_options(id, &dst->features,
384 &dst->retain_hwhandler);
389 merge_mpe(struct mpentry *dst, struct mpentry *src)
395 merge_str(uid_attribute);
399 merge_str(prio_name);
400 merge_str(prio_args);
402 if (dst->prkey_source == PRKEY_SOURCE_NONE &&
403 src->prkey_source != PRKEY_SOURCE_NONE) {
404 dst->prkey_source = src->prkey_source;
405 dst->sa_flags = src->sa_flags;
406 memcpy(&dst->reservation_key, &src->reservation_key,
407 sizeof(dst->reservation_key));
411 merge_num(pgfailback);
412 merge_num(rr_weight);
413 merge_num(no_path_retry);
416 merge_num(flush_on_last_del);
417 merge_num(attribute_flags);
418 merge_num(user_friendly_names);
419 merge_num(deferred_remove);
420 merge_num(delay_watch_checks);
421 merge_num(delay_wait_checks);
422 merge_num(san_path_err_threshold);
423 merge_num(san_path_err_forget_rate);
424 merge_num(san_path_err_recovery_time);
425 merge_num(marginal_path_err_sample_time);
426 merge_num(marginal_path_err_rate_threshold);
427 merge_num(marginal_path_err_recheck_gap_time);
428 merge_num(marginal_path_double_failed_time);
429 merge_num(skip_kpartx);
430 merge_num(max_sectors_kb);
431 merge_num(ghost_delay);
439 void merge_mptable(vector mptable)
441 struct mpentry *mp1, *mp2;
444 vector_foreach_slot(mptable, mp1, i) {
446 vector_foreach_slot_after(mptable, mp2, j) {
447 if (strcmp(mp1->wwid, mp2->wwid))
449 condlog(1, "%s: duplicate multipath config section for %s",
450 __func__, mp1->wwid);
453 vector_del_slot(mptable, i);
461 store_hwe (vector hwtable, struct hwentry * dhwe)
463 struct hwentry * hwe;
465 if (find_hwe_strmatch(hwtable, dhwe))
468 if (!(hwe = alloc_hwe()))
471 if (!dhwe->vendor || !(hwe->vendor = set_param_str(dhwe->vendor)))
474 if (!dhwe->product || !(hwe->product = set_param_str(dhwe->product)))
477 if (dhwe->revision && !(hwe->revision = set_param_str(dhwe->revision)))
480 if (dhwe->uid_attribute && !(hwe->uid_attribute = set_param_str(dhwe->uid_attribute)))
483 if (dhwe->getuid && !(hwe->getuid = set_param_str(dhwe->getuid)))
486 if (dhwe->features && !(hwe->features = set_param_str(dhwe->features)))
489 if (dhwe->hwhandler && !(hwe->hwhandler = set_param_str(dhwe->hwhandler)))
492 if (dhwe->selector && !(hwe->selector = set_param_str(dhwe->selector)))
495 if (dhwe->checker_name && !(hwe->checker_name = set_param_str(dhwe->checker_name)))
498 if (dhwe->prio_name && !(hwe->prio_name = set_param_str(dhwe->prio_name)))
501 if (dhwe->prio_args && !(hwe->prio_args = set_param_str(dhwe->prio_args)))
504 if (dhwe->alias_prefix && !(hwe->alias_prefix = set_param_str(dhwe->alias_prefix)))
507 hwe->pgpolicy = dhwe->pgpolicy;
508 hwe->pgfailback = dhwe->pgfailback;
509 hwe->rr_weight = dhwe->rr_weight;
510 hwe->no_path_retry = dhwe->no_path_retry;
511 hwe->minio = dhwe->minio;
512 hwe->minio_rq = dhwe->minio_rq;
513 hwe->flush_on_last_del = dhwe->flush_on_last_del;
514 hwe->fast_io_fail = dhwe->fast_io_fail;
515 hwe->dev_loss = dhwe->dev_loss;
516 hwe->user_friendly_names = dhwe->user_friendly_names;
517 hwe->retain_hwhandler = dhwe->retain_hwhandler;
518 hwe->detect_prio = dhwe->detect_prio;
519 hwe->detect_checker = dhwe->detect_checker;
520 hwe->ghost_delay = dhwe->ghost_delay;
521 hwe->vpd_vendor_id = dhwe->vpd_vendor_id;
523 if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product)))
526 if (!vector_alloc_slot(hwtable))
529 vector_set_slot(hwtable, hwe);
537 factorize_hwtable (vector hw, int n, const char *table_desc)
539 struct hwentry *hwe1, *hwe2;
543 vector_foreach_slot(hw, hwe1, i) {
544 /* drop invalid device configs */
545 if (i >= n && (!hwe1->vendor || !hwe1->product)) {
546 condlog(0, "device config in %s missing vendor or product parameter",
548 vector_del_slot(hw, i--);
552 j = n > i + 1 ? n : i + 1;
553 vector_foreach_slot_after(hw, hwe2, j) {
554 if (hwe_strmatch(hwe2, hwe1) == 0) {
555 condlog(i >= n ? 1 : 3,
556 "%s: duplicate device section for %s:%s:%s in %s",
557 __func__, hwe1->vendor, hwe1->product,
558 hwe1->revision, table_desc);
559 vector_del_slot(hw, i);
560 merge_hwe(hwe2, hwe1);
565 * Play safe here; we have modified
566 * the original vector so the outer
567 * vector_foreach_slot() might
580 return (struct config *)MALLOC(sizeof(struct config));
584 free_config (struct config * conf)
589 if (conf->multipath_dir)
590 FREE(conf->multipath_dir);
593 FREE(conf->selector);
595 if (conf->uid_attribute)
596 FREE(conf->uid_attribute);
598 vector_reset(&conf->uid_attrs);
604 FREE(conf->features);
607 FREE(conf->hwhandler);
609 if (conf->bindings_file)
610 FREE(conf->bindings_file);
612 if (conf->wwids_file)
613 FREE(conf->wwids_file);
615 if (conf->prkeys_file)
616 FREE(conf->prkeys_file);
619 FREE(conf->prio_name);
621 if (conf->alias_prefix)
622 FREE(conf->alias_prefix);
623 if (conf->partition_delim)
624 FREE(conf->partition_delim);
627 FREE(conf->prio_args);
629 if (conf->checker_name)
630 FREE(conf->checker_name);
632 if (conf->config_dir)
633 FREE(conf->config_dir);
635 free_blacklist(conf->blist_devnode);
636 free_blacklist(conf->blist_wwid);
637 free_blacklist(conf->blist_property);
638 free_blacklist(conf->blist_protocol);
639 free_blacklist_device(conf->blist_device);
641 free_blacklist(conf->elist_devnode);
642 free_blacklist(conf->elist_wwid);
643 free_blacklist(conf->elist_property);
644 free_blacklist(conf->elist_protocol);
645 free_blacklist_device(conf->elist_device);
647 free_mptable(conf->mptable);
648 free_hwtable(conf->hwtable);
649 free_hwe(conf->overrides);
650 free_keywords(conf->keywords);
654 /* if multipath fails to process the config directory, it should continue,
655 * with just a warning message */
657 process_config_dir(struct config *conf, char *dir)
659 struct dirent **namelist;
660 struct scandir_result sr;
663 int old_hwtable_size;
666 condlog(1, "config_dir '%s' must be a fully qualified path",
670 n = scandir(dir, &namelist, NULL, alphasort);
673 condlog(3, "No configuration dir '%s'", dir);
675 condlog(0, "couldn't open configuration dir '%s': %s",
676 dir, strerror(errno));
682 pthread_cleanup_push_cast(free_scandir_result, &sr);
683 for (i = 0; i < n; i++) {
684 char *ext = strrchr(namelist[i]->d_name, '.');
686 if (!ext || strcmp(ext, ".conf"))
689 old_hwtable_size = VECTOR_SIZE(conf->hwtable);
690 snprintf(path, LINE_MAX, "%s/%s", dir, namelist[i]->d_name);
691 path[LINE_MAX-1] = '\0';
692 process_file(conf, path);
693 factorize_hwtable(conf->hwtable, old_hwtable_size,
694 namelist[i]->d_name);
696 pthread_cleanup_pop(1);
699 static void set_max_checkint_from_watchdog(struct config *conf)
702 char *envp = getenv("WATCHDOG_USEC");
703 unsigned long checkint;
705 if (envp && sscanf(envp, "%lu", &checkint) == 1) {
706 /* Value is in microseconds */
708 if (checkint < 1 || checkint > UINT_MAX) {
709 condlog(1, "invalid value for WatchdogSec: \"%s\"", envp);
712 if (conf->max_checkint == 0 || conf->max_checkint > checkint)
713 conf->max_checkint = checkint;
714 condlog(3, "enabling watchdog, interval %ld", checkint);
715 conf->use_watchdog = true;
721 load_config (char * file)
723 struct config *conf = alloc_config();
731 conf->verbosity = DEFAULT_VERBOSITY;
733 get_sys_max_fds(&conf->max_fds);
734 conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
735 conf->wwids_file = set_default(DEFAULT_WWIDS_FILE);
736 conf->prkeys_file = set_default(DEFAULT_PRKEYS_FILE);
737 conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
738 conf->attribute_flags = 0;
739 conf->reassign_maps = DEFAULT_REASSIGN_MAPS;
740 conf->checkint = CHECKINT_UNDEF;
741 conf->use_watchdog = false;
742 conf->max_checkint = 0;
743 conf->force_sync = DEFAULT_FORCE_SYNC;
744 conf->partition_delim = (default_partition_delim != NULL ?
745 strdup(default_partition_delim) : NULL);
746 conf->processed_main_config = 0;
747 conf->find_multipaths = DEFAULT_FIND_MULTIPATHS;
748 conf->uxsock_timeout = DEFAULT_REPLY_TIMEOUT;
749 conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES;
750 conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY;
751 conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT;
752 conf->remove_retries = 0;
753 conf->ghost_delay = DEFAULT_GHOST_DELAY;
754 conf->all_tg_pt = DEFAULT_ALL_TG_PT;
756 * preload default hwtable
758 conf->hwtable = vector_alloc();
761 if (setup_default_hwtable(conf->hwtable))
764 #ifdef CHECK_BUILTIN_HWTABLE
765 factorize_hwtable(conf->hwtable, 0, "builtin");
768 * read the config file
770 conf->keywords = vector_alloc();
771 init_keywords(conf->keywords);
772 if (filepresent(file)) {
773 int builtin_hwtable_size;
775 builtin_hwtable_size = VECTOR_SIZE(conf->hwtable);
776 if (process_file(conf, file)) {
777 condlog(0, "error parsing config file");
780 factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
783 conf->processed_main_config = 1;
784 if (conf->config_dir == NULL)
785 conf->config_dir = set_default(DEFAULT_CONFIG_DIR);
786 if (conf->config_dir && conf->config_dir[0] != '\0')
787 process_config_dir(conf, conf->config_dir);
790 * fill the voids left in the config file
792 set_max_checkint_from_watchdog(conf);
793 if (conf->max_checkint == 0) {
794 if (conf->checkint == CHECKINT_UNDEF)
795 conf->checkint = DEFAULT_CHECKINT;
796 conf->max_checkint = (conf->checkint < UINT_MAX / 4 ?
797 conf->checkint * 4 : UINT_MAX);
798 } else if (conf->checkint == CHECKINT_UNDEF)
799 conf->checkint = (conf->max_checkint >= 4 ?
800 conf->max_checkint / 4 : 1);
801 else if (conf->checkint > conf->max_checkint)
802 conf->checkint = conf->max_checkint;
803 condlog(3, "polling interval: %d, max: %d",
804 conf->checkint, conf->max_checkint);
806 if (conf->blist_devnode == NULL) {
807 conf->blist_devnode = vector_alloc();
809 if (!conf->blist_devnode)
812 if (conf->blist_wwid == NULL) {
813 conf->blist_wwid = vector_alloc();
815 if (!conf->blist_wwid)
818 if (conf->blist_device == NULL) {
819 conf->blist_device = vector_alloc();
821 if (!conf->blist_device)
824 if (conf->blist_property == NULL) {
825 conf->blist_property = vector_alloc();
827 if (!conf->blist_property)
830 if (conf->blist_protocol == NULL) {
831 conf->blist_protocol = vector_alloc();
833 if (!conf->blist_protocol)
837 if (conf->elist_devnode == NULL) {
838 conf->elist_devnode = vector_alloc();
840 if (!conf->elist_devnode)
843 if (conf->elist_wwid == NULL) {
844 conf->elist_wwid = vector_alloc();
846 if (!conf->elist_wwid)
850 if (conf->elist_device == NULL) {
851 conf->elist_device = vector_alloc();
853 if (!conf->elist_device)
857 if (conf->elist_property == NULL) {
858 conf->elist_property = vector_alloc();
860 if (!conf->elist_property)
863 if (conf->elist_protocol == NULL) {
864 conf->elist_protocol = vector_alloc();
866 if (!conf->elist_protocol)
870 if (setup_default_blist(conf))
873 if (conf->mptable == NULL) {
874 conf->mptable = vector_alloc();
879 merge_mptable(conf->mptable);
880 merge_blacklist(conf->blist_devnode);
881 merge_blacklist(conf->blist_property);
882 merge_blacklist(conf->blist_wwid);
883 merge_blacklist_device(conf->blist_device);
884 merge_blacklist(conf->elist_devnode);
885 merge_blacklist(conf->elist_property);
886 merge_blacklist(conf->elist_wwid);
887 merge_blacklist_device(conf->elist_device);
889 if (conf->bindings_file == NULL)
890 conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
892 if (!conf->multipath_dir || !conf->bindings_file ||
893 !conf->wwids_file || !conf->prkeys_file)
902 char *get_uid_attribute_by_attrs(struct config *conf,
903 const char *path_dev)
905 vector uid_attrs = &conf->uid_attrs;
909 vector_foreach_slot(uid_attrs, att, j) {
910 col = strrchr(att, ':');
913 if (!strncmp(path_dev, att, col - att))
919 int parse_uid_attrs(char *uid_attrs, struct config *conf)
921 vector attrs = &conf->uid_attrs;
922 char *uid_attr_record, *tmp;
928 count = get_word(uid_attrs, &uid_attr_record);
929 while (uid_attr_record) {
930 tmp = strchr(uid_attr_record, ':');
932 condlog(2, "invalid record in uid_attrs: %s",
934 free(uid_attr_record);
936 } else if (!vector_alloc_slot(attrs)) {
937 free(uid_attr_record);
940 vector_set_slot(attrs, uid_attr_record);
944 count = get_word(uid_attrs, &uid_attr_record);