diff --git a/zdev/include/root.h b/zdev/include/root.h index d15d3934..b13039be 100644 --- a/zdev/include/root.h +++ b/zdev/include/root.h @@ -12,6 +12,6 @@ #include "exit_code.h" -exit_code_t initrd_check(bool all_pers); +exit_code_t initrd_check(bool all_pers, int site_validate); #endif /* ROOT_H */ diff --git a/zdev/man/chzdev.8 b/zdev/man/chzdev.8 index da78ac81..2db9ac17 100644 --- a/zdev/man/chzdev.8 +++ b/zdev/man/chzdev.8 @@ -428,6 +428,10 @@ Removes configuration files and settings associated with the selected device. .PP . +.OD disable-all "D" "" +Disable device in all configurations. +.PP +. .OD enable "e" "" Enable device. diff --git a/zdev/src/chzdev.c b/zdev/src/chzdev.c index aaec52bd..1605a939 100644 --- a/zdev/src/chzdev.c +++ b/zdev/src/chzdev.c @@ -80,6 +80,7 @@ struct options { /* Actions */ unsigned int enable:1; unsigned int deconfigure:1; + unsigned int deconfigure_all:1; unsigned int list_attribs:1; unsigned int list_types:1; unsigned int help_attribs:1; @@ -127,6 +128,7 @@ enum { OPT_TYPE = 't', OPT_ENABLE = 'e', OPT_DECONFIGURE = 'd', + OPT_DECONFIGURE_ALL = 'D', OPT_LIST_ATTRIBS = 'l', OPT_HELP_ATTRIBS = 'H', OPT_LIST_TYPES = 'L', @@ -154,36 +156,42 @@ enum { static struct opts_conflict conflict_list[] = { OPTS_CONFLICT(OPT_ENABLE, OPT_DECONFIGURE, OPT_LIST_ATTRIBS, OPT_LIST_TYPES, - OPT_EXPORT, OPT_IMPORT, OPT_APPLY, OPT_TYPE, 0), + OPT_EXPORT, OPT_IMPORT, OPT_APPLY, OPT_TYPE, + OPT_DECONFIGURE_ALL, 0), OPTS_CONFLICT(OPT_DECONFIGURE, OPT_LIST_ATTRIBS, OPT_HELP_ATTRIBS, OPT_LIST_TYPES, OPT_EXPORT, OPT_IMPORT, OPT_APPLY, OPT_REMOVE, - OPT_REMOVE_ALL, OPT_TYPE, 0), + OPT_REMOVE_ALL, OPT_TYPE, + OPT_DECONFIGURE_ALL, 0), OPTS_CONFLICT(OPT_LIST_ATTRIBS, OPT_DECONFIGURE, OPT_HELP_ATTRIBS, OPT_LIST_TYPES, OPT_EXPORT, OPT_IMPORT, OPT_APPLY, OPT_REMOVE, OPT_REMOVE_ALL, OPT_CONFIGURED, OPT_EXISTING, OPT_ONLINE, OPT_OFFLINE, OPT_BY_PATH, OPT_BY_NODE, OPT_BY_INTERFACE, - OPT_BY_ATTRIB, OPT_ACTIVE, OPT_PERSISTENT, OPT_FAILED, 0), + OPT_BY_ATTRIB, OPT_ACTIVE, OPT_PERSISTENT, OPT_FAILED, + OPT_DECONFIGURE_ALL, 0), OPTS_CONFLICT(OPT_LIST_TYPES, OPT_DECONFIGURE, OPT_LIST_ATTRIBS, OPT_HELP_ATTRIBS, OPT_EXPORT, OPT_IMPORT, OPT_APPLY, OPT_REMOVE, OPT_REMOVE_ALL, OPT_CONFIGURED, OPT_EXISTING, OPT_ONLINE, OPT_OFFLINE, OPT_BY_PATH, OPT_BY_NODE, OPT_BY_INTERFACE, - OPT_BY_ATTRIB, OPT_ACTIVE, OPT_PERSISTENT, OPT_FAILED, 0), + OPT_BY_ATTRIB, OPT_ACTIVE, OPT_PERSISTENT, OPT_FAILED, + OPT_DECONFIGURE_ALL, 0), OPTS_CONFLICT(OPT_EXPORT, OPT_DECONFIGURE, OPT_LIST_ATTRIBS, OPT_HELP_ATTRIBS, OPT_LIST_TYPES, OPT_IMPORT, OPT_APPLY, OPT_REMOVE, - OPT_REMOVE_ALL, 0), + OPT_REMOVE_ALL, OPT_DECONFIGURE_ALL, 0), OPTS_CONFLICT(OPT_IMPORT, OPT_DECONFIGURE, OPT_LIST_ATTRIBS, OPT_HELP_ATTRIBS, OPT_LIST_TYPES, OPT_EXPORT, OPT_APPLY, OPT_REMOVE, OPT_REMOVE_ALL, OPT_CONFIGURED, OPT_EXISTING, OPT_BY_PATH, - OPT_BY_ATTRIB, OPT_BY_NODE, OPT_BY_INTERFACE, 0), + OPT_BY_ATTRIB, OPT_BY_NODE, OPT_BY_INTERFACE, + OPT_DECONFIGURE_ALL, 0), OPTS_CONFLICT(OPT_APPLY, OPT_DECONFIGURE, OPT_LIST_ATTRIBS, OPT_HELP_ATTRIBS, OPT_LIST_TYPES, OPT_EXPORT, OPT_IMPORT, OPT_REMOVE, - OPT_REMOVE_ALL, OPT_ACTIVE, 0), + OPT_REMOVE_ALL, OPT_ACTIVE, + OPT_DECONFIGURE_ALL, 0), OPTS_CONFLICT(OPT_ONLINE, OPT_OFFLINE), OPTS_CONFLICT(OPT_SITE, @@ -213,6 +221,7 @@ static const struct option opt_list[] = { /* Actions. */ { "enable", no_argument, NULL, OPT_ENABLE }, { "disable", no_argument, NULL, OPT_DECONFIGURE }, + { "disable-all", no_argument, NULL, OPT_DECONFIGURE_ALL }, { "list-attributes", no_argument, NULL, OPT_LIST_ATTRIBS }, { "help-attribute", no_argument, NULL, OPT_HELP_ATTRIBS }, { "list-types", no_argument, NULL, OPT_LIST_TYPES }, @@ -241,7 +250,7 @@ static const struct option opt_list[] = { }; /* Command line abbreviations. */ -static const char opt_str[] = ":edlHLapr:RfyhvVqts:"; +static const char opt_str[] = ":edlHLapr:RfyhvVqts:D"; /* Count of persistently modified devices. */ static int pers_mod_devs; @@ -852,6 +861,12 @@ static exit_code_t parse_options(struct options *opts, int argc, char *argv[]) opts->deconfigure = 1; break; + case OPT_DECONFIGURE_ALL: + /* --disable all the settings*/ + opts->deconfigure = 1; + opts->deconfigure_all = 1; + break; + case OPT_LIST_ATTRIBS: /* --list-attributes */ opts->list_attribs = 1; @@ -1023,7 +1038,9 @@ static exit_code_t parse_options(struct options *opts, int argc, char *argv[]) goto out; /* Determine configuration set. */ - if (!opts->active && !opts->persistent && !opts->auto_conf) { + if (opts->deconfigure_all) { + opts->config = config_all; + } else if (!opts->active && !opts->persistent && !opts->auto_conf) { /* Default configuration targets are active + persistent */ opts->config = config_active | config_persistent; } else { @@ -1970,6 +1987,18 @@ static exit_code_t check_in_use(struct device *dev) return EXIT_OK; } +static bool is_site_modified(struct device *dev) +{ + int i; + + for (i = 0; i < NUM_USER_SITES; i++) { + if (dev->site_specific[i].modified) + return true; + } + + return false; +} + /* Deconfigure specified device. */ static exit_code_t deconfigure_one_device(struct subtype *st, const char *id, struct options *opts, int try, @@ -1979,6 +2008,7 @@ static exit_code_t deconfigure_one_device(struct subtype *st, const char *id, exit_code_t rc; struct device *dev; config_t config, read_config; + int i, site_available = 0; /* Reset processed flag. */ if (proc_ptr) @@ -2011,7 +2041,7 @@ static exit_code_t deconfigure_one_device(struct subtype *st, const char *id, dev->processed = 1; if (try && !(dev->active.exists || dev->active.definable || - dev->persistent.exists || dev->autoconf.exists)) { + is_dev_pers(dev) || dev->autoconf.exists)) { /* Attempt to deconfigure this device will fail. */ return EXIT_DEVICE_NOT_FOUND; } @@ -2021,7 +2051,7 @@ static exit_code_t deconfigure_one_device(struct subtype *st, const char *id, * dev. */ if (SCOPE_ACTIVE(config) && !(dev->active.exists || dev->active.definable)) { - if (!((SCOPE_PERSISTENT(config) && dev->persistent.exists) || + if (!((SCOPE_PERSISTENT(config) && is_dev_pers(dev)) || (SCOPE_AUTOCONF(config) && dev->autoconf.exists))) return EXIT_DEVICE_NOT_FOUND; } @@ -2042,16 +2072,48 @@ static exit_code_t deconfigure_one_device(struct subtype *st, const char *id, } else if (subtype_online_get(st, dev, config_active) == 1) dev->active.modified = 1; } - if (SCOPE_PERSISTENT(config) && dev->persistent.exists) { - dev->persistent.deconfigured = 1; - dev->persistent.modified = 1; + if (SCOPE_PERSISTENT(config)) { + if (dev->persistent.exists) { + dev->persistent.deconfigured = 1; + dev->persistent.modified = 1; + } else if (is_dev_pers(dev) && global_site_id != SITE_FALLBACK) { + dev->persistent.deconfigured = 1; + dev->persistent.modified = 1; + } } if (SCOPE_AUTOCONF(config) && dev->autoconf.exists) { dev->autoconf.deconfigured = 1; dev->autoconf.modified = 1; } + + /* In case of deconfigure_all command, make sure that site specific + * settings are also removed. + */ + if (opts->deconfigure_all) { + for (i = 0; i < NUM_USER_SITES; i++) { + if (dev->site_specific[i].exists) { + site_available++; + /* To remove site-specific settings, simply + * make the deconfigured = 1 + */ + dev->site_specific[i].deconfigured = 1; + dev->site_specific[i].modified = 1; + } + } + } + + if (site_available) { + /* set persistent.exists = 1 to let the + * drivers know that we need to modify the + * udev-rule + */ + dev->persistent.exists = 1; + dev->persistent.modified = 1; + dev->persistent.deconfigured = 1; + } + if (!dev->active.modified && !dev->persistent.modified && - !dev->autoconf.modified) + !dev->autoconf.modified && !is_site_modified(dev)) return EXIT_OK; /* Pre-write check. */ @@ -3099,7 +3161,7 @@ int main(int argc, char *argv[]) !dryrun) { /* If the root device/device type or early devices have been * modified, additional work might be necessary. */ - rc = initrd_check(ZDEV_ALWAYS_UPDATE_INITRD); + rc = initrd_check(ZDEV_ALWAYS_UPDATE_INITRD, opts.deconfigure_all); if (rc && !drc) drc = rc; } diff --git a/zdev/src/chzdev_usage.txt b/zdev/src/chzdev_usage.txt index ba1d6d22..7e81ea73 100644 --- a/zdev/src/chzdev_usage.txt +++ b/zdev/src/chzdev_usage.txt @@ -33,7 +33,8 @@ SETTINGS ACTIONS -e, --enable Enable device - -d, --disable Disable device + -d, --disable Disable specified setting of the device + -D, --disable-all Disable all the settings of the device -l, --list-attributes List attributes -L, --list-types List supported device types -H, --help-attribute Show detailed help on specified attribute diff --git a/zdev/src/root.c b/zdev/src/root.c index 385b7787..6957bd1b 100644 --- a/zdev/src/root.c +++ b/zdev/src/root.c @@ -83,23 +83,58 @@ static bool is_zdev_early_0(struct selected_dev_node *sel) { struct setting *s; struct device *dev; + int i; dev = device_list_find(sel->st->devices, sel->id, NULL); if (!dev) return false; - s = setting_list_find(dev->persistent.settings, - internal_attr_early.name); - if (!s) + + for (i = 0; i < NUM_SITES; i++) { + s = setting_list_find(dev->site_specific[i].settings, + internal_attr_early.name); + if (!s) + return false; + if (s->specified && strcmp(s->value, "0") == 0) + return true; + } + + return false; +} + +/* When site-specific settings has zdev:early configured, it is not + * detected with the --by-attr functionality of select_devices. Instead + * we will have to iterate through each configuration and check if there + * is a zdev:early set in the device. This is usually applicable only in + * the case of deconfigure-all command, because, for all other commands + * we copy the settings-in-action to the persistent settings and do the + * processing there. + */ +static bool is_zdev_early_site(struct selected_dev_node *sel) +{ + struct setting *s; + struct device *dev; + int i; + + if (global_site_id != SITE_FALLBACK) return false; - if (s->specified && strcmp(s->value, "0") == 0) - return true; + + dev = device_list_find(sel->st->devices, sel->id, NULL); + if (!dev) + return false; + + for (i = 0; i < NUM_SITES; i++) { + s = setting_list_find(dev->site_specific[i].settings, + internal_attr_early.name); + if (s) + return true; + } return false; } /* Determine if initial RAM-disk needs updating. If so, run the corresponding * scripts if available. */ -exit_code_t initrd_check(bool all_pers) +exit_code_t initrd_check(bool all_pers, int site_validate) { struct util_list *selected, *params, *mod = strlist_new(); struct selected_dev_node *sel; @@ -142,7 +177,12 @@ exit_code_t initrd_check(bool all_pers) } /* Finally add devices with zdev:early=1. */ select = select_opts_new(); - strlist_add(&select->by_attr, "%s=1", INTERNAL_ATTR_EARLY); + /* If we need information from multiple site, we cannot use the by-attr + * functionality of select_devices function. Instead we have to iterate + * through individual devices and site settings to find the key. + */ + if (!site_validate) + strlist_add(&select->by_attr, "%s=1", INTERNAL_ATTR_EARLY); select_devices(select, selected, 1, 0, 0, config_active | config_persistent, scope_mandatory, err_ignore); @@ -162,7 +202,12 @@ check_mod: /* Check devices. */ dev = device_list_find(sel->st->devices, sel->id, NULL); if (dev && dev->persistent.exists && - (device_needs_writing(dev, config_persistent) || force)) { + (device_needs_writing(dev, config_persistent) || force) && + !site_validate) { + strlist_add(mod, "%s %s", dev->subtype->devname, + dev->id); + } else if (site_validate && is_zdev_early_site(sel) && + device_needs_writing(dev, config_persistent)) { strlist_add(mod, "%s %s", dev->subtype->devname, dev->id); }