zdev: Add support for handling auto-configuration data

Auto-configuration is the name of a new configuration target that is
supported by chzdev and lszdev besides the existing active and
persistent configuration targets. Directives created in this new
configuration are stored as udev rules in the /run/udev/rules.d
directory.

Auto-configuration directives are only in effect if there are no
directives for the same device in the user-provided persistent
configuration. This allows users to override auto-configuration
directives if necessary.

Due to the volatile nature of the /run directory, auto-configuration
directives are cleared on reboot. Therefore mechanisms that generate
auto-configuration directives must recreate them on every boot.

The lszdev tool displays auto-configuration data both in list view
as well as in detail view. Users can specify the new option --auto-conf
to only show data from this configuration target.

Mechanisms that generate automated configuration directives can use
chzdev together with the --auto-conf option to create the corresponding
udev rules.

Note: This change does not include a mechanism that generates
      auto-configuration directives.

Signed-off-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Peter Oberparleiter
2017-09-01 11:05:55 +02:00
committed by Jan Höppner
parent a86fb8b091
commit fe68ec513d
32 changed files with 911 additions and 286 deletions

View File

@@ -426,6 +426,8 @@ static void ccwgroup_st_online_set(struct subtype *st, struct device *dev,
}
if (SCOPE_PERSISTENT(config))
setting_list_apply(dev->persistent.settings, a, name, value);
if (SCOPE_AUTOCONF(config))
setting_list_apply(dev->autoconf.settings, a, name, value);
}
static int get_online(struct setting_list *list)
@@ -446,18 +448,20 @@ static int get_online(struct setting_list *list)
}
/* Return -1 if online state is not configured, 0 for offline and 1 for online.
* If multiple configurations are specified, return the minimum of both. */
* If multiple configurations are specified, return the minimum of all. */
static int ccwgroup_st_online_get(struct subtype *st, struct device *dev,
config_t config)
{
int act_online = 1, pers_online = 1;
int act_online = 1, pers_online = 1, auto_online = 1;
if (SCOPE_ACTIVE(config))
act_online = get_online(dev->active.settings);
if (SCOPE_PERSISTENT(config))
pers_online = get_online(dev->persistent.settings);
if (SCOPE_AUTOCONF(config))
auto_online = get_online(dev->autoconf.settings);
return MIN(act_online, pers_online);
return MIN(MIN(act_online, pers_online), auto_online);
}
/* Determine if the online state of the specified device was modified. */
@@ -476,6 +480,11 @@ static bool ccwgroup_st_online_specified(struct subtype *st,
if (s && s->specified)
return true;
}
if (SCOPE_AUTOCONF(config) && dev->autoconf.settings) {
s = setting_list_find(dev->autoconf.settings, "online");
if (s && s->specified)
return true;
}
return false;
}
@@ -682,7 +691,18 @@ static exit_code_t ccwgroup_st_read_persistent(struct subtype *st,
expand_id(data->ccwgroupdrv, dev);
return udev_ccwgroup_read_device(dev);
return udev_ccwgroup_read_device(dev, false);
}
static exit_code_t ccwgroup_st_read_autoconf(struct subtype *st,
struct device *dev,
read_scope_t scope)
{
struct ccwgroup_subtype_data *data = st->data;
expand_id(data->ccwgroupdrv, dev);
return udev_ccwgroup_read_device(dev, true);
}
static exit_code_t ccwgroup_st_configure_active(struct subtype *st,
@@ -693,8 +713,9 @@ static exit_code_t ccwgroup_st_configure_active(struct subtype *st,
return device_write_active_settings(dev);
}
static exit_code_t ccwgroup_st_configure_persistent(struct subtype *st,
struct device *dev)
static exit_code_t _ccwgroup_st_configure_persistent(struct subtype *st,
struct device *dev,
bool autoconf)
{
struct ccwgroup_subtype_data *data = st->data;
struct ccwgroup_devid *devid = dev->devid;
@@ -703,9 +724,22 @@ static exit_code_t ccwgroup_st_configure_persistent(struct subtype *st,
delayed_err("Incomplete device ID specified\n");
return EXIT_INCOMPLETE_ID;
}
return udev_ccwgroup_write_device(dev);
return udev_ccwgroup_write_device(dev, autoconf);
}
static exit_code_t ccwgroup_st_configure_persistent(struct subtype *st,
struct device *dev)
{
return _ccwgroup_st_configure_persistent(st, dev, false);
}
static exit_code_t ccwgroup_st_configure_autoconf(struct subtype *st,
struct device *dev)
{
return _ccwgroup_st_configure_persistent(st, dev, true);
}
static char *ccwgroup_st_get_active_attrib_path(struct subtype *,
struct device *, const char *);
@@ -733,7 +767,13 @@ static exit_code_t ccwgroup_st_deconfigure_active(struct subtype *st,
static exit_code_t ccwgroup_st_deconfigure_persistent(struct subtype *st,
struct device *dev)
{
return udev_ccwgroup_remove_rule(st->name, dev->id);
return udev_ccwgroup_remove_rule(st->name, dev->id, false);
}
static exit_code_t ccwgroup_st_deconfigure_autoconf(struct subtype *st,
struct device *dev)
{
return udev_ccwgroup_remove_rule(st->name, dev->id, true);
}
/* Check if a CCWGROUP device with the specified ID exists. */
@@ -774,7 +814,12 @@ static bool ccwgroup_st_exists_active(struct subtype *st, const char *id)
static bool ccwgroup_st_exists_persistent(struct subtype *st, const char *id)
{
return udev_ccwgroup_exists(st->name, id);
return udev_ccwgroup_exists(st->name, id, false);
}
static bool ccwgroup_st_exists_autoconf(struct subtype *st, const char *id)
{
return udev_ccwgroup_exists(st->name, id, true);
}
int ccwgroup_qsort_cmp(const void *a_ptr, const void *b_ptr)
@@ -796,7 +841,13 @@ static void ccwgroup_st_add_active_ids(struct subtype *st,
static void ccwgroup_st_add_persistent_ids(struct subtype *st,
struct util_list *ids)
{
udev_ccwgroup_add_device_ids(st->name, ids);
udev_ccwgroup_add_device_ids(st->name, ids, false);
}
static void ccwgroup_st_add_autoconf_ids(struct subtype *st,
struct util_list *ids)
{
udev_ccwgroup_add_device_ids(st->name, ids, true);
}
/* Check if CCW device ID @b is part of CCW group device ID @a. */
@@ -1185,18 +1236,23 @@ struct subtype ccwgroup_subtype = {
.exists_active = &ccwgroup_st_exists_active,
.exists_persistent = &ccwgroup_st_exists_persistent,
.exists_autoconf = &ccwgroup_st_exists_autoconf,
.add_active_ids = &ccwgroup_st_add_active_ids,
.add_persistent_ids = &ccwgroup_st_add_persistent_ids,
.add_autoconf_ids = &ccwgroup_st_add_autoconf_ids,
.read_active = &ccwgroup_st_read_active,
.read_persistent = &ccwgroup_st_read_persistent,
.read_autoconf = &ccwgroup_st_read_autoconf,
.configure_active = &ccwgroup_st_configure_active,
.configure_persistent = &ccwgroup_st_configure_persistent,
.configure_autoconf = &ccwgroup_st_configure_autoconf,
.deconfigure_active = &ccwgroup_st_deconfigure_active,
.deconfigure_persistent = &ccwgroup_st_deconfigure_persistent,
.deconfigure_autoconf = &ccwgroup_st_deconfigure_autoconf,
.online_set = &ccwgroup_st_online_set,
.online_get = &ccwgroup_st_online_get,