zdev: add --deconfigure-all function for chzdev

Introduce --deconfigure-all feature, which will remove all available
settings from the mentioned device. A typical device can have 10
different site-specific settings, active settings, persistent
settings and sometimes auto-configured settings configured in it.
--deconfigure-all can be used to remove all of them with a single
command.

usage: 	chzdev -D <device-id>
	chzdev --deconfigure-all <device-id>

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Vineeth Vijayan
2022-09-29 23:35:01 +02:00
committed by Jan Höppner
parent 34146c3f92
commit fa3dd0ec20
5 changed files with 138 additions and 26 deletions

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);
}