diff --git a/zdev/include/device.h b/zdev/include/device.h index fe0895f5..e5ec9435 100644 --- a/zdev/include/device.h +++ b/zdev/include/device.h @@ -19,6 +19,20 @@ struct subtype; struct setting_list; +/** + * Currently zdev supports 10 sites. Which means, zdev support 10 different + * set of attributes which are specific to each site. When the user does + * not provide any site information, the common set will be used which is + * not specific to any site. So, total we have 11 persistent attribute sets + * Where, + * 0- 9: Site specific attributes + * 10: Common attributes which do not belong to any sites + */ + +#define NUM_SITES 11 +#define NUM_USER_SITES (NUM_SITES - 1) +#define SITE_FALLBACK NUM_USER_SITES + /** * struct device_state - Represent the state of a device in a configuration * @settings: List of attribute settings diff --git a/zdev/include/devtype.h b/zdev/include/devtype.h index 70112c3a..c5f27305 100644 --- a/zdev/include/devtype.h +++ b/zdev/include/devtype.h @@ -38,6 +38,7 @@ extern struct devtype *devtypes[]; * devtypes with empty title will not be shown with --list-types. * @devname: Short name for devices of this device type * @modules: (Optional) Array of kernel modules required for this devtype + * @site_support: Support for site-specific configuration for the device-type * @subtypes: Array of subtypes * @type_attribs: Array of device type attributes (may point to empty array) * @unknown_type_attribs: Allow specification of unknown device type attributes @@ -59,6 +60,7 @@ struct devtype { const char title[DEVTYPE_TITLE_LEN + 1]; const char *devname; const char **modules; + unsigned int site_support:1; struct subtype **subtypes; struct attrib **type_attribs; diff --git a/zdev/include/misc.h b/zdev/include/misc.h index 2e4e7da3..61b300e7 100644 --- a/zdev/include/misc.h +++ b/zdev/include/misc.h @@ -103,6 +103,8 @@ extern int delayed_warnings; extern unsigned long longrun_total; extern unsigned long longrun_current; +extern int global_site_id; + void misc_exit(void); void indent(unsigned int, const char *, ...); void error(const char *, ...); @@ -239,6 +241,7 @@ void longrun_stop(void); char *skip_comp(char *); void byte_swap(uint8_t *, unsigned int *, unsigned); bool valid_hex(const char *); +bool is_valid_site(const char *); void debug_init(int, char **); #endif /* MISC_H */ diff --git a/zdev/src/chzdev.c b/zdev/src/chzdev.c index a37b41a8..aaec52bd 100644 --- a/zdev/src/chzdev.c +++ b/zdev/src/chzdev.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "lib/util_path.h" #include "lib/zt_common.h" @@ -44,6 +45,12 @@ #include "udev.h" #include "zfcp_lun.h" +/* current site-id in action. By default, operations are always on fallback + * site; We need the current site-id as global variable to avoid excessive + * diff of simple function parameter modifications to pass this value. + */ +int global_site_id = SITE_FALLBACK; + /* Main program action. */ typedef enum { ACT_CONFIGURE, @@ -97,6 +104,7 @@ struct options { unsigned int verbose:1; unsigned int quiet:1; unsigned int no_settle:1; + unsigned int site_id; }; /* Makefile converts chzdev_usage.txt into C file which we include here. */ @@ -140,6 +148,7 @@ enum { OPT_QUIET = 'q', OPT_NO_SETTLE = (OPT_ANONYMOUS_BASE+__COUNTER__), OPT_AUTO_CONF = (OPT_ANONYMOUS_BASE+__COUNTER__), + OPT_SITE = 's', }; static struct opts_conflict conflict_list[] = { @@ -177,6 +186,8 @@ static struct opts_conflict conflict_list[] = { OPT_REMOVE_ALL, OPT_ACTIVE, 0), OPTS_CONFLICT(OPT_ONLINE, OPT_OFFLINE), + OPTS_CONFLICT(OPT_SITE, + OPT_TYPE, OPT_EXPORT, OPT_IMPORT, 0), OPTS_CONFLICT(OPT_QUIET, OPT_VERBOSE), OPTS_CONFLICT(OPT_AUTO_CONF, @@ -225,11 +236,12 @@ static const struct option opt_list[] = { { "verbose", no_argument, NULL, OPT_VERBOSE }, { "quiet", no_argument, NULL, OPT_QUIET }, { "no-settle", no_argument, NULL, OPT_NO_SETTLE }, + { "site", required_argument, NULL, OPT_SITE }, { NULL, no_argument, NULL, 0 }, }; /* Command line abbreviations. */ -static const char opt_str[] = ":edlHLapr:RfyhvVqt"; +static const char opt_str[] = ":edlHLapr:RfyhvVqts:"; /* Count of persistently modified devices. */ static int pers_mod_devs; @@ -246,6 +258,8 @@ static void init_options(struct options *opts) opts->settings = strlist_new(); opts->remove = strlist_new(); opts->base = strlist_new(); + /* Default operations are on fallback site*/ + opts->site_id = SITE_FALLBACK; } /* Release memory used in options data structure. */ @@ -955,6 +969,28 @@ static exit_code_t parse_options(struct options *opts, int argc, char *argv[]) opts->no_settle = 1; break; + case OPT_SITE: + /* --site */ + /* 1. User can specify only site-ids from 0 to 9 + * 2. only one --site parameter is accepted + */ + + if (!is_valid_site(optarg)) { + syntax("Unsupported site ID\n"); + return EXIT_USAGE_ERROR; + } + + if (opts->site_id != SITE_FALLBACK) { + syntax("Cannot specify '--site' multiple " + "times\n"); + return EXIT_USAGE_ERROR; + } + + opts->site_id = atoi(optarg); + global_site_id = opts->site_id; + opts->persistent = 1; + break; + case ':': /* Missing option argument. */ syntax("Option '%s' requires an argument\n", @@ -1794,6 +1830,24 @@ static void unblacklist_ranges(struct selected_dev_node *sel, *param_ptr = param; } +/* Currently the site-specific configurations are supported only + * for some device types. Make sure that user get an error message when + * try to configure other device-types with site parameter. + */ +static exit_code_t is_site_supported(struct util_list *selected) +{ + struct selected_dev_node *sel; + + util_list_iterate(selected, sel) { + if (sel->dt && !sel->dt->site_support) { + error("Site specific configuration is not supported" + " for %s devices\n", sel->dt->devname); + return EXIT_USAGE_ERROR; + } + } + return EXIT_OK; +} + /* Handle device configuration. */ static exit_code_t configure_devices(struct options *opts, int specified, int *found_ptr) @@ -1827,6 +1881,9 @@ static exit_code_t configure_devices(struct options *opts, int specified, error("No device was selected!\n"); rc = EXIT_EMPTY_SELECTION; goto out; + } else if (opts->site_id != SITE_FALLBACK) { + if (is_site_supported(selected)) + goto out; } /* Work on selected devices. */ @@ -2036,6 +2093,9 @@ static exit_code_t deconfigure_devices(struct options *opts) error("No device was selected!\n"); rc = EXIT_EMPTY_SELECTION; goto out; + } else if (opts->site_id != SITE_FALLBACK) { + if (is_site_supported(selected)) + goto out; } /* Work on selected devices. */ @@ -2558,8 +2618,13 @@ static void action_note(const char *msg, config_t config) { if (config == config_active) info("%s the active configuration only\n", msg); - else if (config == config_persistent) - info("%s the persistent configuration only\n", msg); + else if (config == config_persistent) { + if (global_site_id == SITE_FALLBACK) + info("%s the persistent configuration only\n", msg); + else + info("%s the site %d configuration only\n", msg, + global_site_id); + } else if (config == config_autoconf) info("%s the auto-configuration only\n", msg); } diff --git a/zdev/src/chzdev_usage.txt b/zdev/src/chzdev_usage.txt index b7bc04c4..ba1d6d22 100644 --- a/zdev/src/chzdev_usage.txt +++ b/zdev/src/chzdev_usage.txt @@ -56,5 +56,6 @@ OPTIONS --base PATH Use PATH as base for accessing files --no-settle Do not wait for udev to settle --auto-conf Apply changes to auto-configuration only + -s, --site ID Apply changes to the specified site only -V, --verbose Print additional run-time information -q, --quiet Print only minimal run-time information diff --git a/zdev/src/dasd.c b/zdev/src/dasd.c index 63b49e34..daec916d 100644 --- a/zdev/src/dasd.c +++ b/zdev/src/dasd.c @@ -688,6 +688,7 @@ struct devtype dasd_devtype = { "(DASDs)", .devname = "DASD", .modules = STRING_ARRAY(DASD_MOD_NAME), + .site_support = 1, .subtypes = SUBTYPE_ARRAY( &dasd_subtype_eckd, diff --git a/zdev/src/lszdev.c b/zdev/src/lszdev.c index 0e19408a..d932c583 100644 --- a/zdev/src/lszdev.c +++ b/zdev/src/lszdev.c @@ -32,6 +32,12 @@ #include "table.h" #include "table_types.h" +/* current site-id in action. By default, operations are always on fallback + * site; We need the current site-id as global variable to avoid excessive + * diff of simple function parameter modifications to pass this value. + */ +int global_site_id = SITE_FALLBACK; + /* Main program action. */ typedef enum { ACT_LIST, @@ -66,6 +72,7 @@ struct options { unsigned int pairs:1; unsigned int verbose:1; unsigned int quiet:1; + unsigned int site_id; }; /* Makefile converts lszdev_usage.txt into C file which we include here. */ @@ -100,6 +107,7 @@ enum { OPT_QUIET = 'q', OPT_PAIRS = 'P', OPT_AUTO_CONF = (OPT_ANONYMOUS_BASE+__COUNTER__), + OPT_SITE = 's', }; static struct opts_conflict conflict_list[] = { @@ -120,6 +128,8 @@ static struct opts_conflict conflict_list[] = { OPT_CONFIGURED, OPT_EXISTING, OPT_ONLINE, OPT_OFFLINE, OPT_BY_PATH, OPT_BY_NODE, OPT_BY_INTERFACE, OPT_FAILED, 0), + OPTS_CONFLICT(OPT_SITE, + OPT_TYPE), OPTS_CONFLICT(OPT_ONLINE, OPT_OFFLINE), OPTS_CONFLICT(OPT_QUIET, @@ -159,11 +169,12 @@ static const struct option opt_list[] = { { "pairs", no_argument, NULL, OPT_PAIRS }, { "verbose", no_argument, NULL, OPT_VERBOSE }, { "quiet", no_argument, NULL, OPT_QUIET }, + { "site", required_argument, NULL, OPT_SITE }, { NULL, no_argument, NULL, 0 }, }; /* Command line abbreviations. */ -static const char opt_str[] = ":tilLhvapPc:nVq"; +static const char opt_str[] = ":tilLhvapPc:nVqs:"; /* Initialize options data structure. */ static void init_options(struct options *opts) @@ -172,6 +183,8 @@ static void init_options(struct options *opts) opts->select = select_opts_new(); opts->columns = strlist_new(); opts->base = strlist_new(); + /* Default operations are on fallback site*/ + opts->site_id = SITE_FALLBACK; } /* Release memory used in options data structure. */ @@ -661,6 +674,27 @@ static exit_code_t parse_options(struct options *opts, int argc, char *argv[]) opts->quiet = 1; break; + case OPT_SITE: + /* --site */ + /* User can specify only site-ids from 0 to 9 */ + if (!is_valid_site(optarg)) { + syntax("Unsupported site ID\n"); + return EXIT_USAGE_ERROR; + } + + if (opts->site_id != SITE_FALLBACK) { + syntax("Cannot specify '--site' multiple " + "times\n"); + return EXIT_USAGE_ERROR; + } + + /* site information is a persistent configuration. + * set opts->persistent here. + */ + opts->site_id = atoi(optarg); + opts->persistent = 1; + break; + case ':': /* Missing option argument. */ syntax("Option '%s' requires an argument\n", @@ -718,7 +752,8 @@ static exit_code_t parse_options(struct options *opts, int argc, char *argv[]) opts->select->all = 1; else if (opts->config == config_active) opts->select->existing = 1; - else if (opts->config == config_persistent) + else if (opts->config == config_persistent || + opts->site_id != SITE_FALLBACK) opts->select->configured = 1; } break; @@ -1558,6 +1593,7 @@ int main(int argc, char *argv[]) /* Set globals. */ verbose = opts.verbose; quiet = opts.quiet; + global_site_id = opts.site_id; path_set_base(opts.base); if (opts.pairs) set_stdout_data(); diff --git a/zdev/src/lszdev_usage.txt b/zdev/src/lszdev_usage.txt index a1553674..f4aa394d 100644 --- a/zdev/src/lszdev_usage.txt +++ b/zdev/src/lszdev_usage.txt @@ -42,5 +42,6 @@ OPTIONS --base PATH Use PATH as base for accessing files --pairs Produce output in KEY="VALUE" format --auto-conf Only show auto-configuration data + -s, --site ID Only show data configured for the specified site -V, --verbose Print additional run-time information -q, --quiet Print only minimal run-time information diff --git a/zdev/src/misc.c b/zdev/src/misc.c index 369d5b6d..4f14e8f5 100644 --- a/zdev/src/misc.c +++ b/zdev/src/misc.c @@ -1695,3 +1695,20 @@ char *misc_strrstr(const char *haystack, const char *needle) return result; } + +/* Check if the site mentioned is valid */ +bool is_valid_site(const char *str) +{ + char *ptr = NULL; + long site_id; + + site_id = strtol(str, &ptr, 10); + + if (*ptr) + return false; + + if (site_id < 0 || site_id >= NUM_USER_SITES) + return false; + + return true; +}