From 315288471f44c0fc8df9b9906443b8b7da671696 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Tue, 17 Jan 2006 10:08:49 +0100 Subject: [PATCH] [multipathd] add "show config" CLI command This commands dumps a multipath.conf config file. The "defaults" section is factorized : settings in sync with the internal defaults are not printed. The "devices" section lists the internal hwtable, plus mods and adds from the actual config file. The layout is factorized : settings in sync with the "defaults" section are not printed. The "devnode_blacklist" section is ommited for now, as this requires a bit more infrastructure. The "multipaths" section is not factorized as we can not reliably guess the hardware a multipath is parented to. Multipath entries are just clones of their actual config file equivalent. --- libmultipath/dict.c | 588 ++++++++++++++++++++++++++++++++++++++++++---- libmultipath/dict.h | 2 +- libmultipath/discovery.c | 2 + libmultipath/parser.c | 87 ++++++- libmultipath/parser.h | 21 +- libmultipath/print.c | 185 ++++++++++++++- libmultipath/print.h | 5 + multipathd/cli.c | 1 + multipathd/cli.h | 2 + multipathd/cli_handlers.c | 52 +++- multipathd/cli_handlers.h | 1 + multipathd/main.c | 1 + 12 files changed, 875 insertions(+), 72 deletions(-) diff --git a/libmultipath/dict.c b/libmultipath/dict.c index 4231991..9b782de 100644 --- a/libmultipath/dict.c +++ b/libmultipath/dict.c @@ -1,6 +1,6 @@ /* * Based on Alexandre Cassen template for keepalived - * Copyright (c) 2004, 2005 Christophe Varoqui + * Copyright (c) 2004, 2005, 2006 Christophe Varoqui * Copyright (c) 2005 Benjamin Marzinski, Redhat * Copyright (c) 2005 Kiyoshi Ueda, NEC */ @@ -719,70 +719,558 @@ mp_minio_handler(vector strvec) return 0; } -vector -init_keywords(void) +/* + * config file keywords printing + */ +static int +snprint_mp_wwid (char * buff, int len, void * data) +{ + struct mpentry * mpe = (struct mpentry *)data; + + return snprintf(buff, len, "%s", mpe->wwid); +} + +static int +snprint_mp_alias (char * buff, int len, void * data) +{ + struct mpentry * mpe = (struct mpentry *)data; + + if (!mpe->alias) + return 0; + + if (conf->user_friendly_names && + (strlen(mpe->alias) == strlen("mpath")) && + !strcmp(mpe->alias, "mpath")) + return 0; + + return snprintf(buff, len, "%s", mpe->alias); +} + +static int +snprint_mp_path_grouping_policy (char * buff, int len, void * data) +{ + struct mpentry * mpe = (struct mpentry *)data; + char str[POLICY_NAME_SIZE]; + + if (!mpe->pgpolicy) + return 0; + get_pgpolicy_name(str, POLICY_NAME_SIZE, mpe->pgpolicy); + + return snprintf(buff, len, "%s", str); +} + +static int +snprint_mp_selector (char * buff, int len, void * data) +{ + struct mpentry * mpe = (struct mpentry *)data; + + if (!mpe->selector) + return 0; + + return snprintf(buff, len, "%s", mpe->selector); +} + +static int +snprint_mp_failback (char * buff, int len, void * data) +{ + struct mpentry * mpe = (struct mpentry *)data; + + if (!mpe->pgfailback) + return 0; + + switch(mpe->pgfailback) { + case FAILBACK_UNDEF: + break; + case -FAILBACK_MANUAL: + return snprintf(buff, len, "manual"); + case -FAILBACK_IMMEDIATE: + return snprintf(buff, len, "immediate"); + default: + return snprintf(buff, len, "%i", mpe->pgfailback); + } + return 0; +} + +static int +snprint_mp_rr_weight (char * buff, int len, void * data) +{ + struct mpentry * mpe = (struct mpentry *)data; + + if (!mpe->rr_weight) + return 0; + if (mpe->rr_weight == RR_WEIGHT_PRIO) + return snprintf(buff, len, "priorities"); + + return 0; +} + +static int +snprint_mp_no_path_retry (char * buff, int len, void * data) +{ + struct mpentry * mpe = (struct mpentry *)data; + + if (!mpe->no_path_retry) + return 0; + + switch(mpe->no_path_retry) { + case NO_PATH_RETRY_UNDEF: + break; + case NO_PATH_RETRY_FAIL: + return snprintf(buff, len, "fail"); + case NO_PATH_RETRY_QUEUE: + return snprintf(buff, len, "queue"); + default: + return snprintf(buff, len, "%i", + mpe->no_path_retry); + } + return 0; +} + +static int +snprint_mp_rr_min_io (char * buff, int len, void * data) +{ + struct mpentry * mpe = (struct mpentry *)data; + + if (!mpe->minio) + return 0; + + return snprintf(buff, len, "%u", mpe->minio); +} + +static int +snprint_hw_vendor (char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + if (!hwe->vendor) + return 0; + + return snprintf(buff, len, "%s", hwe->vendor); +} + +static int +snprint_hw_product (char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + if (!hwe->product) + return 0; + + return snprintf(buff, len, "%s", hwe->product); +} + +static int +snprint_hw_getuid_callout (char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + if (!hwe->getuid) + return 0; + if (strlen(hwe->getuid) == strlen(conf->default_getuid) && + !strcmp(hwe->getuid, conf->default_getuid)) + return 0; + + return snprintf(buff, len, "%s", hwe->getuid); +} + +static int +snprint_hw_prio_callout (char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + if (!hwe->getprio) + return 0; + if (strlen(hwe->getprio) == strlen(conf->default_getprio) && + !strcmp(hwe->getprio, conf->default_getprio)) + return 0; + + return snprintf(buff, len, "%s", hwe->getprio); +} + +static int +snprint_hw_features (char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + if (!hwe->features) + return 0; + if (strlen(hwe->features) == strlen(conf->features) && + !strcmp(hwe->features, conf->features)) + return 0; + + return snprintf(buff, len, "%s", hwe->features); +} + +static int +snprint_hw_hardware_handler (char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + if (!hwe->hwhandler) + return 0; + if (strlen(hwe->hwhandler) == strlen(conf->default_hwhandler) && + !strcmp(hwe->hwhandler, conf->default_hwhandler)) + return 0; + + return snprintf(buff, len, "%s", hwe->hwhandler); +} + +static int +snprint_hw_selector (char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + if (!hwe->selector) + return 0; + if (strlen(hwe->selector) == strlen(conf->selector) && + !strcmp(hwe->selector, conf->selector)) + return 0; + + return snprintf(buff, len, "%s", hwe->selector); +} + +static int +snprint_hw_path_grouping_policy (char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + char str[POLICY_NAME_SIZE]; + + if (!hwe->pgpolicy) + return 0; + if (hwe->pgpolicy == conf->default_pgpolicy) + return 0; + + get_pgpolicy_name(str, POLICY_NAME_SIZE, hwe->pgpolicy); + + return snprintf(buff, len, "%s", str); +} + +static int +snprint_hw_failback (char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + if (!hwe->pgfailback) + return 0; + if (hwe->pgfailback == conf->pgfailback) + return 0; + + switch(hwe->pgfailback) { + case FAILBACK_UNDEF: + break; + case -FAILBACK_MANUAL: + return snprintf(buff, len, "manual"); + case -FAILBACK_IMMEDIATE: + return snprintf(buff, len, "immediate"); + default: + return snprintf(buff, len, "%i", hwe->pgfailback); + } + return 0; +} + +static int +snprint_hw_rr_weight (char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + if (!hwe->rr_weight) + return 0; + if (hwe->rr_weight == conf->rr_weight) + return 0; + if (hwe->rr_weight == RR_WEIGHT_PRIO) + return snprintf(buff, len, "priorities"); + + return 0; +} + +static int +snprint_hw_no_path_retry (char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + if (!hwe->no_path_retry) + return 0; + if (hwe->no_path_retry == conf->no_path_retry) + return 0; + + switch(hwe->no_path_retry) { + case NO_PATH_RETRY_UNDEF: + break; + case NO_PATH_RETRY_FAIL: + return snprintf(buff, len, "fail"); + case NO_PATH_RETRY_QUEUE: + return snprintf(buff, len, "queue"); + default: + return snprintf(buff, len, "%i", + hwe->no_path_retry); + } + return 0; +} + +static int +snprint_hw_rr_min_io (char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + if (!hwe->minio) + return 0; + if (hwe->minio == conf->minio) + return 0; + + return snprintf(buff, len, "%u", hwe->minio); +} + +static int +snprint_hw_path_checker (char * buff, int len, void * data) +{ + char str[CHECKER_NAME_SIZE]; + struct hwentry * hwe = (struct hwentry *)data; + + if (!hwe->checker_index) + return 0; + if (hwe->checker_index == conf->default_checker_index) + return 0; + get_checker_name(str, CHECKER_NAME_SIZE, hwe->checker_index); + + return snprintf(buff, len, "%s", str); +} + +static int +snprint_def_polling_interval (char * buff, int len, void * data) +{ + if (conf->checkint == DEFAULT_CHECKINT) + return 0; + return snprintf(buff, len, "%i", conf->checkint); +} + +static int +snprint_def_udev_dir (char * buff, int len, void * data) +{ + if (!conf->udev_dir) + return 0; + if (strlen(DEFAULT_UDEVDIR) == strlen(conf->udev_dir) && + !strcmp(conf->udev_dir, DEFAULT_UDEVDIR)) + return 0; + + return snprintf(buff, len, "%s", conf->udev_dir); +} + +static int +snprint_def_selector (char * buff, int len, void * data) +{ + if (!conf->selector) + return 0; + if (strlen(conf->selector) == strlen(DEFAULT_SELECTOR) && + !strcmp(conf->selector, DEFAULT_SELECTOR)) + return 0; + + return snprintf(buff, len, "%s", conf->selector); +} + +static int +snprint_def_path_grouping_policy (char * buff, int len, void * data) +{ + char str[POLICY_NAME_SIZE]; + + if (!conf->default_pgpolicy) + return 0; + if (conf->default_pgpolicy == DEFAULT_PGPOLICY) + return 0; + + get_pgpolicy_name(str, POLICY_NAME_SIZE, conf->default_pgpolicy); + + return snprintf(buff, len, "%s", str); +} + +static int +snprint_def_getuid_callout (char * buff, int len, void * data) +{ + if (!conf->default_getuid) + return 0; + if (strlen(conf->default_getuid) == strlen(DEFAULT_GETUID) && + !strcmp(conf->default_getuid, DEFAULT_GETUID)) + return 0; + + return snprintf(buff, len, "%s", conf->default_getuid); +} + +static int +snprint_def_getprio_callout (char * buff, int len, void * data) +{ + if (!conf->default_getprio) + return 0; +#if 0 /* default is NULL */ + if (strlen(conf->default_getprio) == strlen(DEFAULT_GETPRIO) && + !strcmp(conf->default_getprio, DEFAULT_GETPRIO)) + return 0; +#endif + + return snprintf(buff, len, "%s", conf->default_getprio); +} + +static int +snprint_def_features (char * buff, int len, void * data) +{ + if (!conf->features) + return 0; + if (strlen(conf->features) == strlen(DEFAULT_FEATURES) && + !strcmp(conf->features, DEFAULT_FEATURES)) + return 0; + + return snprintf(buff, len, "%s", conf->features); +} + +static int +snprint_def_path_checker (char * buff, int len, void * data) +{ + char str[CHECKER_NAME_SIZE]; + + if (!conf->default_checker_index) + return 0; + if (conf->default_checker_index == DEFAULT_CHECKER_ID) + return 0; + get_checker_name(str, CHECKER_NAME_SIZE, conf->default_checker_index); + + return snprintf(buff, len, "%s", str); +} + +static int +snprint_def_failback (char * buff, int len, void * data) +{ + if (!conf->pgfailback) + return 0; + if (conf->pgfailback == DEFAULT_FAILBACK) + return 0; + + switch(conf->pgfailback) { + case FAILBACK_UNDEF: + break; + case -FAILBACK_MANUAL: + return snprintf(buff, len, "manual"); + case -FAILBACK_IMMEDIATE: + return snprintf(buff, len, "immediate"); + default: + return snprintf(buff, len, "%i", conf->pgfailback); + } + return 0; +} + +static int +snprint_def_rr_min_io (char * buff, int len, void * data) +{ + if (!conf->minio) + return 0; + if (conf->minio == DEFAULT_MINIO) + return 0; + + return snprintf(buff, len, "%u", conf->minio); +} + +static int +snprint_def_rr_weight (char * buff, int len, void * data) { - keywords = vector_alloc(); + if (!conf->rr_weight) + return 0; + if (conf->rr_weight == DEFAULT_RR_WEIGHT) + return 0; + if (conf->rr_weight == RR_WEIGHT_PRIO) + return snprintf(buff, len, "priorities"); + return 0; +} + +static int +snprint_def_no_path_retry (char * buff, int len, void * data) +{ + if (conf->no_path_retry == DEFAULT_NO_PATH_RETRY) + return 0; + + switch(conf->no_path_retry) { + case NO_PATH_RETRY_UNDEF: + break; + case NO_PATH_RETRY_FAIL: + return snprintf(buff, len, "fail"); + case NO_PATH_RETRY_QUEUE: + return snprintf(buff, len, "queue"); + default: + return snprintf(buff, len, "%i", + conf->no_path_retry); + } + return 0; +} + +static int +snprint_def_user_friendly_names (char * buff, int len, void * data) +{ + if (conf->user_friendly_names == DEFAULT_USER_FRIENDLY_NAMES) + return 0; + if (!conf->user_friendly_names) + return snprintf(buff, len, "no"); + + return snprintf(buff, len, "yes"); +} + +void +init_keywords(void) +{ install_keyword_root("defaults", NULL); - install_keyword("polling_interval", &polling_interval_handler); - install_keyword("udev_dir", &udev_dir_handler); - install_keyword("selector", &def_selector_handler); - install_keyword("path_grouping_policy", &def_pgpolicy_handler); - install_keyword("getuid_callout", &def_getuid_callout_handler); - install_keyword("prio_callout", &def_prio_callout_handler); - install_keyword("features", &def_features_handler); - install_keyword("path_checker", &def_path_checker_handler); - install_keyword("failback", &default_failback_handler); - install_keyword("rr_min_io", &def_minio_handler); - install_keyword("rr_weight", &def_weight_handler); - install_keyword("no_path_retry", &def_no_path_retry_handler); - install_keyword("user_friendly_names", &names_handler); + install_keyword("polling_interval", &polling_interval_handler, &snprint_def_polling_interval); + install_keyword("udev_dir", &udev_dir_handler, &snprint_def_udev_dir); + install_keyword("selector", &def_selector_handler, &snprint_def_selector); + install_keyword("path_grouping_policy", &def_pgpolicy_handler, &snprint_def_path_grouping_policy); + install_keyword("getuid_callout", &def_getuid_callout_handler, &snprint_def_getuid_callout); + install_keyword("prio_callout", &def_prio_callout_handler, &snprint_def_getprio_callout); + install_keyword("features", &def_features_handler, &snprint_def_features); + install_keyword("path_checker", &def_path_checker_handler, &snprint_def_path_checker); + install_keyword("failback", &default_failback_handler, &snprint_def_failback); + install_keyword("rr_min_io", &def_minio_handler, &snprint_def_rr_min_io); + install_keyword("rr_weight", &def_weight_handler, &snprint_def_rr_weight); + install_keyword("no_path_retry", &def_no_path_retry_handler, &snprint_def_no_path_retry); + install_keyword("user_friendly_names", &names_handler, &snprint_def_user_friendly_names); /* * deprecated synonyms */ - install_keyword("default_selector", &def_selector_handler); - install_keyword("default_path_grouping_policy", &def_pgpolicy_handler); - install_keyword("default_getuid_callout", &def_getuid_callout_handler); - install_keyword("default_prio_callout", &def_prio_callout_handler); - install_keyword("default_features", &def_features_handler); - install_keyword("default_path_checker", &def_path_checker_handler); + install_keyword("default_selector", &def_selector_handler, NULL); + install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); + install_keyword("default_getuid_callout", &def_getuid_callout_handler, NULL); + install_keyword("default_prio_callout", &def_prio_callout_handler, NULL); + install_keyword("default_features", &def_features_handler, NULL); + install_keyword("default_path_checker", &def_path_checker_handler, NULL); install_keyword_root("devnode_blacklist", &blacklist_handler); - install_keyword("devnode", &ble_handler); - install_keyword("wwid", &ble_handler); + install_keyword("devnode", &ble_handler, NULL); + install_keyword("wwid", &ble_handler, NULL); install_keyword_root("devices", &devices_handler); - install_keyword("device", &device_handler); + install_keyword("device", &device_handler, NULL); install_sublevel(); - install_keyword("vendor", &vendor_handler); - install_keyword("product", &product_handler); - install_keyword("path_grouping_policy", &hw_pgpolicy_handler); - install_keyword("getuid_callout", &hw_getuid_callout_handler); - install_keyword("path_selector", &hw_selector_handler); - install_keyword("path_checker", &hw_path_checker_handler); - install_keyword("features", &hw_features_handler); - install_keyword("hardware_handler", &hw_handler_handler); - install_keyword("prio_callout", &prio_callout_handler); - install_keyword("failback", &hw_failback_handler); - install_keyword("rr_weight", &hw_weight_handler); - install_keyword("no_path_retry", &hw_no_path_retry_handler); - install_keyword("rr_min_io", &hw_minio_handler); + install_keyword("vendor", &vendor_handler, &snprint_hw_vendor); + install_keyword("product", &product_handler, &snprint_hw_product); + install_keyword("path_grouping_policy", &hw_pgpolicy_handler, &snprint_hw_path_grouping_policy); + install_keyword("getuid_callout", &hw_getuid_callout_handler, &snprint_hw_getuid_callout); + install_keyword("path_selector", &hw_selector_handler, &snprint_hw_selector); + install_keyword("path_checker", &hw_path_checker_handler, &snprint_hw_path_checker); + install_keyword("features", &hw_features_handler, &snprint_hw_features); + install_keyword("hardware_handler", &hw_handler_handler, &snprint_hw_hardware_handler); + install_keyword("prio_callout", &prio_callout_handler, &snprint_hw_prio_callout); + install_keyword("failback", &hw_failback_handler, &snprint_hw_failback); + install_keyword("rr_weight", &hw_weight_handler, &snprint_hw_rr_weight); + install_keyword("no_path_retry", &hw_no_path_retry_handler, &snprint_hw_no_path_retry); + install_keyword("rr_min_io", &hw_minio_handler, &snprint_hw_rr_min_io); install_sublevel_end(); install_keyword_root("multipaths", &multipaths_handler); - install_keyword("multipath", &multipath_handler); + install_keyword("multipath", &multipath_handler, NULL); install_sublevel(); - install_keyword("wwid", &wwid_handler); - install_keyword("alias", &alias_handler); - install_keyword("path_grouping_policy", &mp_pgpolicy_handler); - install_keyword("path_selector", &mp_selector_handler); - install_keyword("failback", &mp_failback_handler); - install_keyword("rr_weight", &mp_weight_handler); - install_keyword("no_path_retry", &mp_no_path_retry_handler); - install_keyword("rr_min_io", &mp_minio_handler); + install_keyword("wwid", &wwid_handler, &snprint_mp_wwid); + install_keyword("alias", &alias_handler, &snprint_mp_alias); + install_keyword("path_grouping_policy", &mp_pgpolicy_handler, &snprint_mp_path_grouping_policy); + install_keyword("path_selector", &mp_selector_handler, &snprint_mp_selector); + install_keyword("failback", &mp_failback_handler, &snprint_mp_failback); + install_keyword("rr_weight", &mp_weight_handler, &snprint_mp_rr_weight); + install_keyword("no_path_retry", &mp_no_path_retry_handler, &snprint_mp_no_path_retry); + install_keyword("rr_min_io", &mp_minio_handler, &snprint_mp_rr_min_io); install_sublevel_end(); - - return keywords; } diff --git a/libmultipath/dict.h b/libmultipath/dict.h index ac35edc..5f77473 100644 --- a/libmultipath/dict.h +++ b/libmultipath/dict.h @@ -5,6 +5,6 @@ #include "vector.h" #endif -vector init_keywords(void); +void init_keywords(void); #endif /* _DICT_H */ diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index 7abda4e..ff6a12d 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -689,6 +689,8 @@ pathinfo (struct path *pp, vector hwtable, int mask) if (mask & DI_CHECKER) { if (!pp->checkfn) select_checkfn(pp); + if (!pp->checkfn) + goto out; pp->state = pp->checkfn(pp->fd, NULL, NULL); condlog(3, "state = %i", pp->state); diff --git a/libmultipath/parser.c b/libmultipath/parser.c index ebb14cd..9b0b5c2 100644 --- a/libmultipath/parser.c +++ b/libmultipath/parser.c @@ -24,9 +24,11 @@ /* local vars */ static int sublevel = 0; +vector keywords = NULL; int -keyword_alloc(vector keywords, char *string, int (*handler) (vector)) +keyword_alloc(vector keywords, char *string, int (*handler) (vector), + int (*print) (char *, int, void *)) { struct keyword *keyword; @@ -41,6 +43,7 @@ keyword_alloc(vector keywords, char *string, int (*handler) (vector)) } keyword->string = string; keyword->handler = handler; + keyword->print = print; vector_set_slot(keywords, keyword); @@ -50,7 +53,7 @@ keyword_alloc(vector keywords, char *string, int (*handler) (vector)) int install_keyword_root(char *string, int (*handler) (vector)) { - return keyword_alloc(keywords, string, handler); + return keyword_alloc(keywords, string, handler, NULL); } void @@ -66,7 +69,8 @@ install_sublevel_end(void) } int -install_keyword(char *string, int (*handler) (vector)) +install_keyword(char *string, int (*handler) (vector), + int (*print) (char *, int, void *)) { int i = 0; struct keyword *keyword; @@ -87,7 +91,7 @@ install_keyword(char *string, int (*handler) (vector)) return 1; /* add new sub keyword */ - return keyword_alloc(keyword->sub, string, handler); + return keyword_alloc(keyword->sub, string, handler, print); } void @@ -105,6 +109,73 @@ free_keywords(vector keywords) vector_free(keywords); } +struct keyword * +find_keyword(vector v, char * name) +{ + struct keyword *keyword; + int i; + int len; + + if (!name || !keywords) + return NULL; + + if (!v) + v = keywords; + + len = strlen(name); + + for (i = 0; i < VECTOR_SIZE(v); i++) { + keyword = VECTOR_SLOT(v, i); + if ((strlen(keyword->string) == len) && + !strcmp(keyword->string, name)) + return keyword; + if (keyword->sub) { + keyword = find_keyword(keyword->sub, name); + if (keyword) + return keyword; + } + } + return NULL; +} + +int +snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw, void *data) +{ + int r; + int fwd = 0; + char *f = fmt; + + if (!kw || !kw->print) + return 0; + + do { + if (fwd == len || *f == '\0') + break; + if (*f != '%') { + *(buff + fwd) = *f; + fwd++; + continue; + } + f++; + switch(*f) { + case 'k': + fwd += snprintf(buff + fwd, len - fwd, kw->string); + break; + case 'v': + r = kw->print(buff + fwd, len - fwd, data); + if (!r) { /* no output if no value */ + buff = '\0'; + return 0; + } + fwd += r; + break; + } + if (fwd > len) + fwd = len; + } while (*f++); + return fwd; +} + vector alloc_strvec(char *string) { @@ -373,10 +444,14 @@ process_stream(vector keywords) /* Data initialization */ int -init_data(char *conf_file, vector (*init_keywords) (void)) +init_data(char *conf_file, void (*init_keywords) (void)) { int r; + if (!keywords) + keywords = vector_alloc(); + if (!keywords) + return 1; stream = fopen(conf_file, "r"); if (!stream) { syslog(LOG_WARNING, "Configuration file open problem"); @@ -394,7 +469,7 @@ init_data(char *conf_file, vector (*init_keywords) (void)) /* Stream handling */ r = process_stream(keywords); fclose(stream); - free_keywords(keywords); + //free_keywords(keywords); return r; } diff --git a/libmultipath/parser.h b/libmultipath/parser.h index 7a6dd18..f0fdd94 100644 --- a/libmultipath/parser.h +++ b/libmultipath/parser.h @@ -42,24 +42,30 @@ struct keyword { char *string; int (*handler) (vector); + int (*print) (char *, int, void *); vector sub; }; +/* global var exported */ +FILE *stream; + /* Reloading helpers */ #define SET_RELOAD (reload = 1) #define UNSET_RELOAD (reload = 0) #define RELOAD_DELAY 5 -/* global var exported */ -vector keywords; -FILE *stream; +/* iterator helper */ +#define iterate_sub_keywords(k,p,i) \ + for (i = 0; i < (k)->sub->allocated && ((p) = (k)->sub->slot[i]); i++) /* Prototypes */ -extern int keyword_alloc(vector keywords, char *string, int (*handler) (vector)); +extern int keyword_alloc(vector keywords, char *string, int (*handler) (vector), + int (*print) (char *, int, void *)); extern int install_keyword_root(char *string, int (*handler) (vector)); extern void install_sublevel(void); extern void install_sublevel_end(void); -extern int install_keyword(char *string, int (*handler) (vector)); +extern int install_keyword(char *string, int (*handler) (vector), + int (*print) (char *, int, void *)); extern void dump_keywords(vector keydump, int level); extern void free_keywords(vector keywords); extern vector alloc_strvec(char *string); @@ -68,6 +74,9 @@ extern vector read_value_block(void); extern int alloc_value_block(vector strvec, void (*alloc_func) (vector)); extern void *set_value(vector strvec); extern int process_stream(vector keywords); -extern int init_data(char *conf_file, vector (*init_keywords) (void)); +extern int init_data(char *conf_file, void (*init_keywords) (void)); +extern struct keyword * find_keyword(vector v, char * name); +int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw, + void *data); #endif diff --git a/libmultipath/print.c b/libmultipath/print.c index 0cdf936..430aacb 100644 --- a/libmultipath/print.c +++ b/libmultipath/print.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "vector.h" #include "structs.h" @@ -11,9 +12,13 @@ #include "print.h" #include "dmparser.h" #include "configure.h" +#include "config.h" +#include "pgpolicies.h" #include "defaults.h" +#include "parser.h" #include "../libcheckers/path_state.h" +#include "../libcheckers/checkers.h" #define MAX(x,y) (x > y) ? x : y #define TAIL (line + len - 1 - c) @@ -647,10 +652,8 @@ snprint_multipath_topology (char * buff, int len, struct multipath * mpp, if (verbosity <= 0) return fwd; - if (verbosity == 1) { - fwd += snprint_multipath(buff + fwd, len - fwd, "%n", mpp); - return fwd; - } + if (verbosity == 1) + return snprint_multipath(buff, len, "%n", mpp); if (verbosity > 1 && mpp->action != ACT_NOTHING && @@ -663,8 +666,12 @@ snprint_multipath_topology (char * buff, int len, struct multipath * mpp, c += sprintf(c, " (%%w)"); fwd += snprint_multipath(buff + fwd, len - fwd, style, mpp); + if (fwd > len) + return len; fwd += snprint_multipath(buff + fwd, len - fwd, "[size=%S][features=%f][hwhandler=%h]", mpp); + if (fwd > len) + return len; if (!mpp->pg) return fwd; @@ -673,14 +680,182 @@ snprint_multipath_topology (char * buff, int len, struct multipath * mpp, pgp->selector = mpp->selector; /* hack */ fwd += snprint_pathgroup(buff + fwd, len - fwd, PRINT_PG_INDENT, pgp); + if (fwd > len) + return len; - vector_foreach_slot (pgp->paths, pp, i) + vector_foreach_slot (pgp->paths, pp, i) { fwd += snprint_path(buff + fwd, len - fwd, PRINT_PATH_INDENT, pp); + if (fwd > len) + return len; + } + } + return fwd; +} + +static int +snprint_hwentry (char * buff, int len, struct hwentry * hwe) +{ + int i; + int fwd = 0; + struct keyword * kw; + struct keyword * rootkw; + + rootkw = find_keyword(NULL, "device"); + + if (!rootkw) + return 0; + + fwd += snprintf(buff + fwd, len - fwd, "\tdevice {\n"); + if (fwd > len) + return len; + iterate_sub_keywords(rootkw, kw, i) { + fwd += snprint_keyword(buff + fwd, len - fwd, "\t\t%k %v\n", + kw, hwe); + if (fwd > len) + return len; + } + fwd += snprintf(buff + fwd, len - fwd, "\t}\n"); + if (fwd > len) + return len; + return fwd; +} + +extern int +snprint_hwtable (char * buff, int len, vector hwtable) +{ + int fwd = 0; + int i; + struct hwentry * hwe; + struct keyword * rootkw; + + rootkw = find_keyword(NULL, "devices"); + if (!rootkw) + return 0; + + fwd += snprintf(buff + fwd, len - fwd, "devices {\n"); + if (fwd > len) + return len; + vector_foreach_slot (hwtable, hwe, i) { + fwd += snprint_hwentry(buff + fwd, len - fwd, hwe); + if (fwd > len) + return len; + } + fwd += snprintf(buff + fwd, len - fwd, "}\n"); + if (fwd > len) + return len; + return fwd; +} + +static int +snprint_mpentry (char * buff, int len, struct mpentry * mpe) +{ + int i; + int fwd = 0; + struct keyword * kw; + struct keyword * rootkw; + + rootkw = find_keyword(NULL, "multipath"); + if (!rootkw) + return 0; + + fwd += snprintf(buff + fwd, len - fwd, "\tmultipath {\n"); + if (fwd > len) + return len; + iterate_sub_keywords(rootkw, kw, i) { + fwd += snprint_keyword(buff + fwd, len - fwd, "\t\t%k %v\n", + kw, mpe); + if (fwd > len) + return len; } + fwd += snprintf(buff + fwd, len - fwd, "\t}\n"); + if (fwd > len) + return len; return fwd; } +extern int +snprint_mptable (char * buff, int len, vector mptable) +{ + int fwd = 0; + int i; + struct mpentry * mpe; + struct keyword * rootkw; + + rootkw = find_keyword(NULL, "multipaths"); + if (!rootkw) + return 0; + + fwd += snprintf(buff + fwd, len - fwd, "multipaths {\n"); + if (fwd > len) + return len; + vector_foreach_slot (mptable, mpe, i) { + fwd += snprint_mpentry(buff + fwd, len - fwd, mpe); + if (fwd > len) + return len; + } + fwd += snprintf(buff + fwd, len - fwd, "}\n"); + if (fwd > len) + return len; + return fwd; +} + +extern int +snprint_defaults (char * buff, int len) +{ + int fwd = 0; + int i; + struct keyword *rootkw; + struct keyword *kw; + + rootkw = find_keyword(NULL, "defaults"); + if (!rootkw) + return 0; + + fwd += snprintf(buff + fwd, len - fwd, "defaults {\n"); + if (fwd > len) + return len; + + iterate_sub_keywords(rootkw, kw, i) { + fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n", + kw, NULL); + if (fwd > len) + return len; + } + fwd += snprintf(buff + fwd, len - fwd, "}\n"); + if (fwd > len) + return len; + return fwd; + +} + +extern int +snprint_blacklist (char * buff, int len) +{ + int fwd = 0; + struct keyword *rootkw; + + rootkw = find_keyword(NULL, "devnode_blacklist"); + if (!rootkw) + return 0; + + fwd += snprintf(buff + fwd, len - fwd, "devnode_blacklist {\n"); + if (fwd > len) + return len; + + fwd += snprintf(buff + fwd, len - fwd, "}\n"); + if (fwd > len) + return len; + return fwd; + +} + +extern int +snprint_config (char * buff, int len) +{ + return 0; +} + /* * stdout printing helpers */ diff --git a/libmultipath/print.h b/libmultipath/print.h index ea7f3ba..dd97cea 100644 --- a/libmultipath/print.h +++ b/libmultipath/print.h @@ -40,6 +40,9 @@ int snprint_path (char *, int, char *, struct path *); int snprint_multipath (char *, int, char *, struct multipath *); int snprint_multipath_topology (char *, int, struct multipath * mpp, int verbosity); +int snprint_defaults (char *, int); +int snprint_hwtable (char *, int, vector); +int snprint_mptable (char *, int, vector); void print_multipath_topology (struct multipath * mpp, int verbosity); void print_path (struct path * pp, char * style); @@ -47,3 +50,5 @@ void print_multipath (struct multipath * mpp, char * style); void print_pathgroup (struct pathgroup * pgp, char * style); void print_map (struct multipath * mpp); void print_all_paths (vector pathvec, int banner); +void print_hwtable (vector hwtable); + diff --git a/multipathd/cli.c b/multipathd/cli.c index c1ac93a..475819b 100644 --- a/multipathd/cli.c +++ b/multipathd/cli.c @@ -139,6 +139,7 @@ load_keys (void) r += add_key(keys, "status", STATUS, 0); r += add_key(keys, "stats", STATS, 0); r += add_key(keys, "topology", TOPOLOGY, 0); + r += add_key(keys, "config", CONFIG, 0); if (r) { free_keys(keys); diff --git a/multipathd/cli.h b/multipathd/cli.h index 9c6b1fb..ef1e3b8 100644 --- a/multipathd/cli.h +++ b/multipathd/cli.h @@ -16,6 +16,7 @@ enum { __STATUS, __STATS, __TOPOLOGY, + __CONFIG, }; #define LIST (1 << __LIST) @@ -35,6 +36,7 @@ enum { #define STATUS (1 << __STATUS) #define STATS (1 << __STATS) #define TOPOLOGY (1 << __TOPOLOGY) +#define CONFIG (1 << __CONFIG) #define INITIAL_REPLY_LEN 1000 diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c index 49f2c88..218e042 100644 --- a/multipathd/cli_handlers.c +++ b/multipathd/cli_handlers.c @@ -23,7 +23,7 @@ show_paths (char ** r, int * len, struct vectors * vecs, char * style) struct path * pp; char * c; char * reply; - int maxlen = INITIAL_REPLY_LEN; + unsigned int maxlen = INITIAL_REPLY_LEN; int again = 1; get_path_layout(vecs->pathvec); @@ -59,7 +59,7 @@ show_map_topology (char ** r, int * len, struct multipath * mpp) { char * c; char * reply; - int maxlen = INITIAL_REPLY_LEN; + unsigned int maxlen = INITIAL_REPLY_LEN; int again = 1; reply = MALLOC(maxlen); @@ -89,7 +89,7 @@ show_maps_topology (char ** r, int * len, struct vectors * vecs) struct multipath * mpp; char * c; char * reply; - int maxlen = INITIAL_REPLY_LEN; + unsigned int maxlen = INITIAL_REPLY_LEN; int again = 1; reply = MALLOC(maxlen); @@ -116,6 +116,50 @@ show_maps_topology (char ** r, int * len, struct vectors * vecs) } int +show_config (char ** r, int * len) +{ + char * c; + char * reply; + unsigned int maxlen = INITIAL_REPLY_LEN; + int again = 1; + + reply = MALLOC(maxlen); + + while (again) { + if (!reply) + return 1; + c = reply; + c += snprint_defaults(c, reply + maxlen - c); + again = ((c - reply) == maxlen); + if (again) { + reply = REALLOC(reply, maxlen *= 2); + continue; + } + c += snprint_hwtable(c, reply + maxlen - c, conf->hwtable); + again = ((c - reply) == maxlen); + if (again) { + reply = REALLOC(reply, maxlen *= 2); + continue; + } + c += snprint_mptable(c, reply + maxlen - c, conf->mptable); + again = ((c - reply) == maxlen); + if (again) + reply = REALLOC(reply, maxlen *= 2); + } + *r = reply; + *len = (int)(c - reply + 1); + return 0; +} + +int +cli_list_config (void * v, char ** reply, int * len, void * data) +{ + condlog(3, "list config (operator)"); + + return show_config(reply, len); +} + +int cli_list_paths (void * v, char ** reply, int * len, void * data) { struct vectors * vecs = (struct vectors *)data; @@ -159,7 +203,7 @@ show_maps (char ** r, int *len, struct vectors * vecs, char * style) struct multipath * mpp; char * c; char * reply; - int maxlen = INITIAL_REPLY_LEN; + unsigned int maxlen = INITIAL_REPLY_LEN; int again = 1; get_multipath_layout(vecs->mpvec); diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h index b6a04b0..8768724 100644 --- a/multipathd/cli_handlers.h +++ b/multipathd/cli_handlers.h @@ -4,6 +4,7 @@ int cli_list_maps_status (void * v, char ** reply, int * len, void * data); int cli_list_maps_stats (void * v, char ** reply, int * len, void * data); int cli_list_map_topology (void * v, char ** reply, int * len, void * data); int cli_list_maps_topology (void * v, char ** reply, int * len, void * data); +int cli_list_config (void * v, char ** reply, int * len, void * data); int cli_add_path (void * v, char ** reply, int * len, void * data); int cli_del_path (void * v, char ** reply, int * len, void * data); int cli_add_map (void * v, char ** reply, int * len, void * data); diff --git a/multipathd/main.c b/multipathd/main.c index 292d13d..e8998bf 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -993,6 +993,7 @@ uxlsnrloop (void * ap) add_handler(LIST+MAPS+STATS, cli_list_maps_stats); add_handler(LIST+MAPS+TOPOLOGY, cli_list_maps_topology); add_handler(LIST+MAP+TOPOLOGY, cli_list_map_topology); + add_handler(LIST+CONFIG, cli_list_config); add_handler(ADD+PATH, cli_add_path); add_handler(DEL+PATH, cli_del_path); add_handler(ADD+MAP, cli_add_map); -- 2.7.4