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

@@ -45,6 +45,7 @@ struct device_state {
* @node: Node for adding this device to a list
* @active: Device state in the active configuration
* @persistent: Device state in the persistent configuration
* @autoconf: Auto-configured device state
* @errors: A strlist of error and warning messages issued for the device
* @processed: Device has been processed
*/
@@ -59,6 +60,7 @@ struct device {
struct device_state active;
struct device_state persistent;
struct device_state autoconf;
unsigned int processed:1;
};
@@ -97,4 +99,6 @@ void device_list_print(struct device_list *, int);
struct setting_list *device_get_setting_list(struct device *dev,
config_t config);
config_t device_get_config(struct device *dev);
#endif /* DEVICE_H */

View File

@@ -19,9 +19,14 @@
#include "exit_code.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define SCOPE_ACTIVE(x) (((x) == config_active) || ((x) == config_all))
#define SCOPE_PERSISTENT(x) (((x) == config_persistent) || \
((x) == config_all))
#define SCOPE_ACTIVE(x) ((x) & config_active ? 1 : 0)
#define SCOPE_PERSISTENT(x) ((x) & config_persistent ? 1 : 0)
#define SCOPE_AUTOCONF(x) ((x) & config_autoconf ? 1 : 0)
#define SCOPE_ALL(x) ((x) == (config_active | config_persistent |\
config_autoconf))
#define SCOPE_SINGLE(x) ((x) == config_active || \
(x) == config_persistent || \
(x) == config_autoconf)
#define DELAY_INDENT 4
@@ -34,12 +39,15 @@
#define EVEN(x) (((x) & 1) == 0)
/* Enumeration of configuration sets. */
typedef enum {
config_active,
config_persistent,
config_all,
} config_t;
/* Enumeration of configuration sets. Multiple configuration sets can be
* combined using bit-wise or. */
enum {
config_active = 1,
config_persistent = 2,
config_autoconf = 4,
config_all = 7,
};
typedef int config_t;
typedef enum {
err_ignore,
@@ -167,7 +175,7 @@ exit_code_t misc_write_text_file(const char *, const char *, err_t);
exit_code_t misc_write_text_file_retry(const char *, const char *, err_t);
exit_code_t misc_mktemp(char **, int *);
char *misc_readlink(const char *path);
config_t get_config(int, int);
config_t get_config(int act, int pers, int ac);
bool is_zvm(void);
bool is_terminal(void);
const char *config_to_str(config_t);

View File

@@ -24,6 +24,7 @@
#define PATH_CCW_BUS "/sys/bus/ccw"
#define PATH_CCWGROUP_BUS "/sys/bus/ccwgroup"
#define PATH_UDEV_RULES "/etc/udev/rules.d"
#define PATH_UDEV_RULES_VOLATILE "/run/udev/rules.d"
#define PATH_PROC "/proc"
#define PATH_UDEVADM "udevadm"
@@ -55,8 +56,8 @@ char *path_get_ccw_device(const char *, const char *);
char *path_get_ccw_devices(const char *);
char *path_get_ccwgroup_device(const char *, const char *);
char *path_get_ccwgroup_devices(const char *);
char *path_get_udev_rule(const char *, const char *);
char *path_get_udev_rules(void);
char *path_get_udev_rule(const char *type, const char *id, bool vol);
char *path_get_udev_rules(bool vol);
char *path_get_proc(const char *);
char *path_get_sys_bus_dev(const char *, const char *);
char *path_get_sys_bus_drv(const char *, const char *);

View File

@@ -94,7 +94,8 @@ void setting_list_map_values(struct setting_list *);
void setting_list_mark_default_derived(struct setting_list *);
int setting_list_count_set(struct setting_list *);
void setting_list_remove_derived(struct setting_list *);
char *setting_get_changes(struct setting_list *, struct setting_list *);
char *setting_get_changes(struct setting_list *act, struct setting_list *pers,
struct setting_list *ac);
bool setting_match_value(struct setting *, const char *);
#endif /* SETTING_H */

View File

@@ -67,17 +67,22 @@ typedef exit_code_t (*subtype_cb_t)(struct subtype *st, const char *id,
*
* @exists_active: Check if device exists in active configuration
* @exists_persistent: Check if device exists in persistent configuration
* @exists_autoconf: Check if device exists in autoconf configuration
*
* @add_active_ids: Add IDs of all devices existing in active configuration to
* specified strlist
* @add_persistent_ids: Add IDs of all devices existing in persistent
* configuration to specified strlist
* @add_autoconf_ids: Add IDs of all devices existing in autoconf
* configuration to specified strlist
*
* @read_active: Read device configuration from active configuration
* @read_persistent: Read device configuration from persistent configuration
* @read_autoconf: Read device configuration from autoconf configuration
*
* @configure_active: Apply configuration to active configuration
* @configure_persistent: Apply configuration to persistent configuration
* @configure_autoconf: Apply configuration to autoconf configuration
*
* @check_pre_write: Optional: Determine if the given configuration is valid
* for the specified device. If not, emit warning messages
@@ -150,24 +155,33 @@ struct subtype {
bool (*exists_active)(struct subtype *, const char *);
bool (*exists_persistent)(struct subtype *, const char *);
bool (*exists_autoconf)(struct subtype *, const char *);
void (*add_active_ids)(struct subtype *, struct util_list *);
void (*add_persistent_ids)(struct subtype *,
struct util_list *);
void (*add_autoconf_ids)(struct subtype *,
struct util_list *);
exit_code_t (*read_active)(struct subtype *, struct device *,
read_scope_t);
exit_code_t (*read_persistent)(struct subtype *, struct device *,
read_scope_t);
exit_code_t (*read_autoconf)(struct subtype *, struct device *,
read_scope_t);
exit_code_t (*configure_active)(struct subtype *, struct device *);
exit_code_t (*configure_persistent)(struct subtype *,
struct device *);
exit_code_t (*configure_autoconf)(struct subtype *,
struct device *);
exit_code_t (*deconfigure_active)(struct subtype *,
struct device *);
exit_code_t (*deconfigure_persistent)(struct subtype *,
struct device *);
exit_code_t (*deconfigure_autoconf)(struct subtype *,
struct device *);
exit_code_t (*check_pre_configure)(struct subtype *,
struct device *, int, config_t);
@@ -217,23 +231,31 @@ void subtype_exit(struct subtype *);
bool subtype_device_exists_active(struct subtype *, const char *);
bool subtype_device_exists_persistent(struct subtype *, const char *);
bool subtype_device_exists_autoconf(struct subtype *st, const char *id);
void subtype_add_active_ids(struct subtype *, struct util_list *);
void subtype_add_persistent_ids(struct subtype *, struct util_list *);
void subtype_add_autoconf_ids(struct subtype *st, struct util_list *ids);
exit_code_t subtype_device_read_active(struct subtype *, struct device *,
read_scope_t);
exit_code_t subtype_device_read_persistent(struct subtype *, struct device *,
read_scope_t);
exit_code_t subtype_device_read_autoconf(struct subtype *st, struct device *dev,
read_scope_t scope);
exit_code_t subtype_device_configure_active(struct subtype *, struct device *);
exit_code_t subtype_device_configure_persistent(struct subtype *,
struct device *);
exit_code_t subtype_device_configure_autoconf(struct subtype *st,
struct device *dev);
exit_code_t subtype_device_deconfigure_active(struct subtype *,
struct device *);
exit_code_t subtype_device_deconfigure_persistent(struct subtype *st,
struct device *);
exit_code_t subtype_device_deconfigure_autoconf(struct subtype *st,
struct device *dev);
exit_code_t subtype_check_pre_configure(struct subtype *, struct device *, int,
config_t);

View File

@@ -40,8 +40,9 @@ exit_code_t udev_read_file(const char *, struct udev_file **);
void udev_free_file(struct udev_file *);
void udev_file_print(struct udev_file *);
void udev_get_device_ids(const char *, struct util_list *);
exit_code_t udev_remove_rule(const char *, const char *);
void udev_get_device_ids(const char *type, struct util_list *list,
bool autoconf);
exit_code_t udev_remove_rule(const char *type, const char *id, bool autoconf);
void udev_settle(void);

View File

@@ -15,9 +15,9 @@
struct device;
bool udev_ccw_exists(const char *, const char *);
exit_code_t udev_ccw_read_device(struct device *);
exit_code_t udev_ccw_write_device(struct device *);
exit_code_t udev_ccw_write_cio_ignore(const char *);
bool udev_ccw_exists(const char *type, const char *id, bool autoconf);
exit_code_t udev_ccw_read_device(struct device *dev, bool autoconf);
exit_code_t udev_ccw_write_device(struct device *dev, bool autoconf);
exit_code_t udev_ccw_write_cio_ignore(const char *id_list, bool autoconf);
#endif /* UDEV_CCW_H */

View File

@@ -16,10 +16,12 @@
struct device;
struct util_list;
bool udev_ccwgroup_exists(const char *, const char *);
exit_code_t udev_ccwgroup_read_device(struct device *);
exit_code_t udev_ccwgroup_write_device(struct device *);
void udev_ccwgroup_add_device_ids(const char *, struct util_list *);
exit_code_t udev_ccwgroup_remove_rule(const char *, const char *);
bool udev_ccwgroup_exists(const char *type, const char *id, bool autoconf);
exit_code_t udev_ccwgroup_read_device(struct device *dev, bool autoconf);
exit_code_t udev_ccwgroup_write_device(struct device *dev, bool autoconf);
void udev_ccwgroup_add_device_ids(const char *type, struct util_list *list,
bool autoconf);
exit_code_t udev_ccwgroup_remove_rule(const char *type, const char *id,
bool autoconf);
#endif /* UDEV_CCWGROUP_H */

View File

@@ -15,10 +15,10 @@
struct device;
void udev_zfcp_lun_add_device_ids(struct util_list *);
bool udev_zfcp_lun_exists(const char *);
exit_code_t udev_zfcp_lun_read_device(struct device *);
exit_code_t udev_zfcp_lun_write_device(struct device *);
exit_code_t udev_zfcp_lun_remove_rule(const char *);
void udev_zfcp_lun_add_device_ids(struct util_list *list, bool autoconf);
bool udev_zfcp_lun_exists(const char *id, bool autoconf);
exit_code_t udev_zfcp_lun_read_device(struct device *dev, bool autoconf);
exit_code_t udev_zfcp_lun_write_device(struct device *dev, bool autoconf);
exit_code_t udev_zfcp_lun_remove_rule(const char *id, bool autoconf);
#endif /* UDEV_ZFCP_LUN_H */

View File

@@ -428,8 +428,8 @@ using the \-\-import action like in the following example
.B Note:
By default all configuration data that is read is also applied. To reduce the
scope of imported configuration data, you can select specific devices, a device
type, or define whether only data for the active or persistent configuration
should be imported.
type, or define whether only data for the active, persistent or
auto-configuration should be imported.
.PP
.
.OD list-attributes "l" ""
@@ -472,6 +472,18 @@ on reboot, or when a device becomes unavailable, or when a device driver is
unloaded.
.PP
.
.OD auto-conf "" ""
Apply changes to the auto-configuration only.
This option is used internally to apply machine-provided I/O configuration data
to a Linux system.
.B Note:
There is typically no need for users to specify this option directly.
In particular, user-initiated changes to this configuration will be lost
the next time that machine-provided data is obtained (i.e. during boot).
.PP
.
.OD base "" "PATH" | "KEY" = "VALUE"
Change file system paths used to access files.

View File

@@ -69,12 +69,13 @@ With no further options specified, the output format defaults to list format.
.
.
.SS "Configurations"
There are two sources for configuration information: the active configuration
of the currently running system, and the persistent configuration stored in
configuration files.
There are three sources for configuration information: the active configuration
of the currently running system, the persistent configuration stored in
configuration files, and the auto-configuration that is provided by some
machine types to automatically enable I/O devices.
.PP
By default lszdev displays information from both the active and the persistent
configuration.
configuration, and, if available, from the auto-configuration.
.PP
.
.
@@ -319,6 +320,19 @@ Restricts output to information obtained from the active configuration, that
is information from the running system.
.PP
.
.OD auto-conf "" ""
List information from the auto-configuration only.
Restricts output to information obtained from the auto-configuration.
The auto-configuration is the collection of configuration data obtained
automatically on some machine models during boot.
.B Note:
This data is refreshed during each boot. Also configuration directives in
the auto-configuration only take effect if there is no directive for the
same device in the persistent configuration.
.PP
.
.OD base "" "PATH" | "KEY" = "VALUE"
Change file system paths used to access files.

View File

@@ -892,12 +892,13 @@ static exit_code_t collect_group_cb(struct subtype *st, const char *id,
}
/* Set bits for all persistently configured CCW devices. */
static char ***id_bitmap_collect(void)
static char ***id_bitmap_collect(bool autoconf)
{
char ***id_bitmap;
int i, j;
struct devtype *dt;
struct subtype *st;
config_t config = autoconf ? config_autoconf : config_persistent;
id_bitmap = id_bitmap_new();
@@ -906,14 +907,14 @@ static char ***id_bitmap_collect(void)
for (j = 0; (st = dt->subtypes[j]); j++) {
/* Collect CCW device IDs. */
if (st->namespace == &ccw_namespace) {
subtype_for_each_id(st, config_persistent,
subtype_for_each_id(st, config,
collect_cb, id_bitmap);
}
/* Collect CCWGROUP device IDs. Since there may be
* multiple namespaces, we need to make use of this
* hack. */
if (ccwgroup_compatible_namespace(st->namespace)) {
subtype_for_each_id(st, config_persistent,
subtype_for_each_id(st, config,
collect_group_cb,
id_bitmap);
}
@@ -952,7 +953,7 @@ static void range_add(struct util_list *list, struct ccw_devid *from,
free(f_str);
}
static struct util_list *cio_ignore_get_ranges(void)
static struct util_list *cio_ignore_get_ranges(bool autoconf)
{
char ***id_bitmap;
unsigned int cssid, ssid, devno;
@@ -962,7 +963,7 @@ static struct util_list *cio_ignore_get_ranges(void)
ranges = strlist_new();
id_bitmap = id_bitmap_collect();
id_bitmap = id_bitmap_collect(autoconf);
for (cssid = 0; cssid < CSSID_MAX; cssid++) {
if (!id_bitmap[cssid])
continue;
@@ -1003,24 +1004,34 @@ static struct util_list *cio_ignore_get_ranges(void)
}
/* Persistently configure cio_ignore. */
exit_code_t ccw_blacklist_persist(void)
static exit_code_t _ccw_blacklist_persist(bool autoconf)
{
struct util_list *ranges;
char *id_list;
exit_code_t rc;
/* Get string to write to /proc/cio_ignore. */
ranges = cio_ignore_get_ranges();
ranges = cio_ignore_get_ranges(autoconf);
id_list = strlist_flatten(ranges, ",");
strlist_free(ranges);
/* Write udev rule to automatically write cio_ignore. */
rc = udev_ccw_write_cio_ignore(id_list);
rc = udev_ccw_write_cio_ignore(id_list, autoconf);
free(id_list);
return rc;
}
exit_code_t ccw_blacklist_persist(void)
{
exit_code_t rc1, rc2;
rc1 = _ccw_blacklist_persist(false);
rc2 = _ccw_blacklist_persist(true);
return rc1 ? rc1 : rc2;
}
/*
* CCW device ID namespace.
*/
@@ -1368,7 +1379,13 @@ static bool ccw_st_exists_active(struct subtype *st, const char *id)
/* Check if a configuration exists for a CCW device with the specified @id. */
static bool ccw_st_exists_persistent(struct subtype *st, const char *id)
{
return udev_ccw_exists(st->name, id);
return udev_ccw_exists(st->name, id, false);
}
/* Check if a configuration exists for a CCW device with the specified @id. */
static bool ccw_st_exists_autoconf(struct subtype *st, const char *id)
{
return udev_ccw_exists(st->name, id, true);
}
static bool get_ids_cb(const char *file, void *data)
@@ -1404,7 +1421,14 @@ static void ccw_st_add_active_ids(struct subtype *st, struct util_list *ids)
* to strlist @ids. */
static void ccw_st_add_persistent_ids(struct subtype *st, struct util_list *ids)
{
udev_get_device_ids(st->name, ids);
udev_get_device_ids(st->name, ids, false);
}
/* Add the IDs of all CCW devices for which a autoconf configuration exists
* to strlist @ids. */
static void ccw_st_add_autoconf_ids(struct subtype *st, struct util_list *ids)
{
udev_get_device_ids(st->name, ids, true);
}
/* Read the configuration of the CCW device with the specified @id from the
@@ -1440,7 +1464,16 @@ static exit_code_t ccw_st_read_persistent(struct subtype *st,
struct device *dev,
read_scope_t scope)
{
return udev_ccw_read_device(dev);
return udev_ccw_read_device(dev, false);
}
/* Read the configuration of the CCW device with the specified @id from the
* autoconf configuration and add the resulting data to @dev. */
static exit_code_t ccw_st_read_autoconf(struct subtype *st,
struct device *dev,
read_scope_t scope)
{
return udev_ccw_read_device(dev, true);
}
static int get_online(struct setting_list *list)
@@ -1505,7 +1538,14 @@ static exit_code_t ccw_st_configure_active(struct subtype *st,
static exit_code_t ccw_st_configure_persistent(struct subtype *st,
struct device *dev)
{
return udev_ccw_write_device(dev);
return udev_ccw_write_device(dev, false);
}
/* Create a autoconf configuration for the specified device @dev. */
static exit_code_t ccw_st_configure_autoconf(struct subtype *st,
struct device *dev)
{
return udev_ccw_write_device(dev, true);
}
@@ -1552,7 +1592,22 @@ static exit_code_t ccw_st_deconfigure_active(struct subtype *st,
static exit_code_t ccw_st_deconfigure_persistent(struct subtype *st,
struct device *dev)
{
return udev_remove_rule(st->name, dev->id);
return udev_remove_rule(st->name, dev->id, false);
}
/**
* ccw_st_deconfigure_autoconf - Deconfigure device in autoconf
* configuration set
* @st: Subtype of target device
* @dev: Target device
*
* Deconfigure device @dev in the autoconf configuration set. Return %EXIT_OK
* on success, an error code otherwise.
*/
static exit_code_t ccw_st_deconfigure_autoconf(struct subtype *st,
struct device *dev)
{
return udev_remove_rule(st->name, dev->id, true);
}
/* Perform basic sanity checks. */
@@ -1589,6 +1644,8 @@ static void ccw_st_online_set(struct subtype *st, struct device *dev,
setting_list_apply(dev->active.settings, a, name, value);
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);
}
/* Determine the online state of the specified CCW device (0=offline, 1=online,
@@ -1596,14 +1653,16 @@ static void ccw_st_online_set(struct subtype *st, struct device *dev,
static int ccw_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 CCW device was specified */
@@ -1622,6 +1681,11 @@ static bool ccw_st_online_specified(struct subtype *st, struct device *dev,
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;
}
@@ -1769,18 +1833,23 @@ struct subtype ccw_subtype = {
.exists_active = &ccw_st_exists_active,
.exists_persistent = &ccw_st_exists_persistent,
.exists_autoconf = &ccw_st_exists_autoconf,
.add_active_ids = &ccw_st_add_active_ids,
.add_persistent_ids = &ccw_st_add_persistent_ids,
.add_autoconf_ids = &ccw_st_add_autoconf_ids,
.read_active = &ccw_st_read_active,
.read_persistent = &ccw_st_read_persistent,
.read_autoconf = &ccw_st_read_autoconf,
.configure_active = &ccw_st_configure_active,
.configure_persistent = &ccw_st_configure_persistent,
.configure_autoconf = &ccw_st_configure_autoconf,
.deconfigure_active = &ccw_st_deconfigure_active,
.deconfigure_persistent = &ccw_st_deconfigure_persistent,
.deconfigure_autoconf = &ccw_st_deconfigure_autoconf,
.check_pre_configure = &ccw_st_check_pre_configure,

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,

View File

@@ -86,6 +86,7 @@ struct options {
config_t config;
unsigned int active:1;
unsigned int persistent:1;
unsigned int auto_conf:1;
struct util_list *remove; /* List of struct strlist_node */
unsigned int remove_all:1;
unsigned int force:1;
@@ -138,6 +139,7 @@ enum {
OPT_VERBOSE = 'V',
OPT_QUIET = 'q',
OPT_NO_SETTLE = (OPT_ANONYMOUS_BASE+__COUNTER__),
OPT_AUTO_CONF = (OPT_ANONYMOUS_BASE+__COUNTER__),
};
static struct opts_conflict conflict_list[] = {
@@ -172,11 +174,13 @@ static struct opts_conflict conflict_list[] = {
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, OPT_PERSISTENT, 0),
OPT_REMOVE_ALL, OPT_ACTIVE, 0),
OPTS_CONFLICT(OPT_ONLINE,
OPT_OFFLINE),
OPTS_CONFLICT(OPT_QUIET,
OPT_VERBOSE),
OPTS_CONFLICT(OPT_AUTO_CONF,
OPT_TYPE, OPT_LIST_ATTRIBS, OPT_LIST_TYPES),
OPTS_CONFLICT(0, 0),
};
@@ -210,6 +214,7 @@ static const struct option opt_list[] = {
/* Options. */
{ "active", no_argument, NULL, OPT_ACTIVE },
{ "persistent", no_argument, NULL, OPT_PERSISTENT },
{ "auto-conf", no_argument, NULL, OPT_AUTO_CONF },
{ "remove", required_argument, NULL, OPT_REMOVE },
{ "remove-all", no_argument, NULL, OPT_REMOVE_ALL },
{ "force", no_argument, NULL, OPT_FORCE },
@@ -883,6 +888,11 @@ static exit_code_t parse_options(struct options *opts, int argc, char *argv[])
opts->persistent = 1;
break;
case OPT_AUTO_CONF:
/* --auto-conf */
opts->auto_conf = 1;
break;
case OPT_REMOVE:
/* --remove ATTRIB */
strlist_add(opts->remove, "%s", optarg);
@@ -977,7 +987,13 @@ static exit_code_t parse_options(struct options *opts, int argc, char *argv[])
goto out;
/* Determine configuration set. */
opts->config = get_config(opts->active, opts->persistent);
if (!opts->active && !opts->persistent && !opts->auto_conf) {
/* Default configuration targets are active + persistent */
opts->config = config_active | config_persistent;
} else {
opts->config = get_config(opts->active, opts->persistent,
opts->auto_conf);
}
/* Handle positional parameters. */
rc = parse_positional(opts, argc, argv, optind);
@@ -1049,13 +1065,15 @@ static void remove_all_settings(struct setting_list *settings, int active)
/* Perform --remove-all operation for specified config on device. */
static exit_code_t device_remove_all(struct device *dev, config_t config)
{
int active, persistent;
int active, persistent, autoconf;
active = SCOPE_ACTIVE(config) ?
count_removable(dev->active.settings, 1) : 0;
persistent = SCOPE_PERSISTENT(config) ?
count_removable(dev->persistent.settings, 0) : 0;
if (active == 0 && persistent == 0) {
autoconf = SCOPE_AUTOCONF(config) ?
count_removable(dev->autoconf.settings, 0) : 0;
if (active == 0 && persistent == 0 && autoconf == 0) {
delayed_err("No removable settings found\n");
return EXIT_SETTING_NOT_FOUND;
}
@@ -1063,6 +1081,8 @@ static exit_code_t device_remove_all(struct device *dev, config_t config)
remove_all_settings(dev->active.settings, 1);
if (persistent)
remove_all_settings(dev->persistent.settings, 0);
if (autoconf)
remove_all_settings(dev->autoconf.settings, 0);
return EXIT_OK;
}
@@ -1132,6 +1152,13 @@ static exit_code_t device_remove_settings(struct device *dev,
goto out;
}
if (SCOPE_AUTOCONF(config)) {
rc = remove_settings(dev->autoconf.settings, names, found,
notfound, 0);
if (rc)
goto out;
}
if (!util_list_is_empty(notfound)) {
flat = strlist_flatten(notfound, " ");
delayed_err("Setting not found: %s\n", flat);
@@ -1199,7 +1226,8 @@ static void print_dev_config_info(struct device *dev, config_t config)
changes = setting_get_changes(
SCOPE_ACTIVE(config) ? dev->active.settings : NULL,
SCOPE_PERSISTENT(config) ? dev->persistent.settings : NULL);
SCOPE_PERSISTENT(config) ? dev->persistent.settings : NULL,
SCOPE_AUTOCONF(config) ? dev->autoconf.settings : NULL);
if (changes)
info(" Changes: %s\n", changes);
free(changes);
@@ -1257,6 +1285,12 @@ static exit_code_t cfg_mod_existence(struct device *dev, config_t config)
dev->persistent.modified = 1;
}
/* Create autoconf config if necessary. */
if (SCOPE_AUTOCONF(config) && !dev->autoconf.exists) {
dev->autoconf.exists = 1;
dev->autoconf.modified = 1;
}
return EXIT_OK;
}
@@ -1296,11 +1330,14 @@ online:
/* Make sure there's an online attribute. */
ensure_online(dev, config_active);
ensure_online(dev, config_persistent);
ensure_online(dev, config_autoconf);
mand:
/* Ensure default values for mandatory attributes. */
setting_list_apply_defaults(dev->persistent.settings,
dev->subtype->dev_attribs, true);
setting_list_apply_defaults(dev->autoconf.settings,
dev->subtype->dev_attribs, true);
return EXIT_OK;
}
@@ -1336,7 +1373,8 @@ static exit_code_t cfg_write(struct device *dev, int prereq, config_t config,
if (!device_needs_writing(dev, config) && !force)
goto out;
if (check_active && config == config_persistent &&
if (check_active && !SCOPE_ACTIVE(config) &&
(SCOPE_PERSISTENT(config) || SCOPE_AUTOCONF(config)) &&
(!dev->active.exists && !dev->active.definable)) {
rc = handle_nonexistent(dev);
if (rc)
@@ -1377,7 +1415,7 @@ static exit_code_t cfg_configure(struct subtype *st, const char *id,
if (proc_ptr)
*proc_ptr = 0;
/* Read current device data. Note that we read data from both
/* Read current device data. Note that we read data from all
* configurations to enable QETH autodetection and subtype
* detection (e.g. dasd -> dasd_fba).*/
dev = NULL;
@@ -1398,23 +1436,17 @@ static exit_code_t cfg_configure(struct subtype *st, const char *id,
/* Exit here if we're only trying and device cannot be configured. */
if (try && !(dev->active.exists || dev->active.definable ||
dev->persistent.exists)) {
dev->persistent.exists || dev->autoconf.exists)) {
return EXIT_DEVICE_NOT_FOUND;
}
if (config == config_persistent) {
/* Abort if a modification action is triggered for a
* non-existing persistent device. */
if (!dev->persistent.exists &&
(!util_list_is_empty(opts->remove) || opts->remove_all))
return EXIT_DEVICE_NOT_FOUND;
/* Create device if needed by action. */
if (opts->enable || !util_list_is_empty(opts->settings)) {
rc = cfg_mod_existence(dev, config);
if (rc)
return rc;
}
/* Apply changes to device existence. */
rc = cfg_mod_existence(dev, config);
if (rc)
return rc;
/* Apply changes to device settings. */
rc = cfg_mod_settings(dev, opts, prereq);
if (rc)
@@ -1426,10 +1458,12 @@ static exit_code_t cfg_configure(struct subtype *st, const char *id,
/* Apply persistent configuration to active configuration. */
static exit_code_t cfg_apply(struct subtype *st, const char *id, int prereq,
struct device **dev_ptr, int *proc_ptr)
struct device **dev_ptr, int *proc_ptr,
bool autoconf)
{
exit_code_t rc;
struct device *dev;
struct device_state *state;
/* Reset processed flag. */
if (proc_ptr)
@@ -1452,8 +1486,9 @@ static exit_code_t cfg_apply(struct subtype *st, const char *id, int prereq,
*proc_ptr = 1;
dev->processed = 1;
state = autoconf ? &dev->autoconf : &dev->persistent;
/* Exit here if there is no persistent configuration. */
if (!dev->persistent.exists)
if (!state->exists)
return EXIT_NO_DATA;
/* Apply changes to device existence. */
@@ -1462,8 +1497,7 @@ static exit_code_t cfg_apply(struct subtype *st, const char *id, int prereq,
return rc;
/* Copy persistent settings to active configuration. */
rc = device_apply_settings(dev, config_active,
&dev->persistent.settings->list);
rc = device_apply_settings(dev, config_active, &state->settings->list);
if (rc)
return rc;
@@ -1477,7 +1511,8 @@ static exit_code_t cfg_import(struct subtype *st, const char *id,
struct device **dev_ptr, int *proc_ptr)
{
exit_code_t rc;
struct setting_list *active = NULL, *persistent = NULL;
struct setting_list *active = NULL, *persistent = NULL,
*autoconf = NULL;
struct device *dev;
/* Reset processed flag. */
@@ -1495,6 +1530,7 @@ static exit_code_t cfg_import(struct subtype *st, const char *id,
return EXIT_OK;
active = setting_list_copy(dev->active.settings);
persistent = setting_list_copy(dev->persistent.settings);
autoconf = setting_list_copy(dev->autoconf.settings);
} else if (!prereq) {
/* Should not happen. */
return EXIT_OK;
@@ -1524,14 +1560,20 @@ static exit_code_t cfg_import(struct subtype *st, const char *id,
&persistent->list);
if (rc)
goto out;
rc = device_apply_settings(dev, config_autoconf,
&autoconf->list);
if (rc)
goto out;
}
ensure_online(dev, config_active);
ensure_online(dev, config_persistent);
ensure_online(dev, config_autoconf);
/* Write resulting device data. */
rc = cfg_write(dev, prereq, config, 0);
out:
setting_list_free(autoconf);
setting_list_free(persistent);
setting_list_free(active);
@@ -1609,11 +1651,13 @@ static exit_code_t print_config_result(struct selected_dev_node *sel,
if (opts->deconfigure) {
op = "deconfigure";
verb = "deconfigured";
if (dev)
if (dev) {
already = !dev->active.modified &&
!dev->persistent.modified;
else if (rc == EXIT_DEVICE_NOT_FOUND &&
config == config_persistent) {
!dev->persistent.modified &&
!dev->autoconf.modified;
} else if (rc == EXIT_DEVICE_NOT_FOUND &&
(!SCOPE_ACTIVE(config) && (SCOPE_PERSISTENT(config) ||
SCOPE_AUTOCONF(config)))) {
rc = EXIT_OK;
already = 1;
}
@@ -1685,9 +1729,10 @@ static exit_code_t cfg_prereqs(struct subtype *st, const char *id,
prereqs = selected_dev_list_new();
subtype_add_prereqs(st, id, prereqs);
util_list_iterate(prereqs, sel) {
if (opts->apply)
rc = cfg_apply(sel->st, sel->id, 1, &dev, &proc);
else if (opts->import) {
if (opts->apply) {
rc = cfg_apply(sel->st, sel->id, 1, &dev, &proc,
opts->auto_conf);
} else if (opts->import) {
rc = cfg_import(sel->st, sel->id, config, 1, &dev,
&proc);
} else {
@@ -1760,9 +1805,11 @@ static exit_code_t configure_devices(struct options *opts, int specified,
struct namespace *ns;
const char *param;
struct device *dev;
config_t config = opts->config;
/* Determine list of selected devices. */
if (opts->config == config_persistent ||
if ((!SCOPE_ACTIVE(config) &&
(SCOPE_PERSISTENT(config) || SCOPE_AUTOCONF(config))) ||
(opts->select->subtype && opts->select->subtype->support_definable))
existing = 0;
else
@@ -1808,9 +1855,10 @@ static exit_code_t configure_devices(struct options *opts, int specified,
goto next;
/* Configure actual target device. */
if (opts->apply)
rc = cfg_apply(sel->st, sel->id, 0, &dev, &proc);
else {
if (opts->apply) {
rc = cfg_apply(sel->st, sel->id, 0, &dev, &proc,
opts->auto_conf);
} else {
rc = cfg_configure(sel->st, sel->id, opts, 0,
0, &dev, &proc);
}
@@ -1906,7 +1954,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->persistent.exists || dev->autoconf.exists)) {
/* Attempt to deconfigure this device will fail. */
return EXIT_DEVICE_NOT_FOUND;
}
@@ -1916,7 +1964,8 @@ 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) && dev->persistent.exists) ||
(SCOPE_AUTOCONF(config) && dev->autoconf.exists)))
return EXIT_DEVICE_NOT_FOUND;
}
@@ -1940,7 +1989,12 @@ static exit_code_t deconfigure_one_device(struct subtype *st, const char *id,
dev->persistent.deconfigured = 1;
dev->persistent.modified = 1;
}
if (!dev->active.modified && !dev->persistent.modified)
if (SCOPE_AUTOCONF(config) && dev->autoconf.exists) {
dev->autoconf.deconfigured = 1;
dev->autoconf.modified = 1;
}
if (!dev->active.modified && !dev->persistent.modified &&
!dev->autoconf.modified)
return EXIT_OK;
/* Pre-write check. */
@@ -2084,7 +2138,8 @@ static void print_type_config_info(struct devtype *dt, const char *title,
changes = setting_get_changes(
SCOPE_ACTIVE(config) ? dt->active_settings : NULL,
SCOPE_PERSISTENT(config) ? dt->persistent_settings : NULL);
SCOPE_PERSISTENT(config) ? dt->persistent_settings : NULL,
NULL);
if (changes)
info(" %s: %s\n", title, changes);
free(changes);
@@ -2498,6 +2553,8 @@ static void action_note(const char *msg, config_t config)
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_autoconf)
info("%s the auto-configuration only\n", msg);
}
/* Export configuration of selected devices and/or device type to file. */
@@ -2619,7 +2676,7 @@ static exit_code_t import_device(struct device *dev, struct options *opts)
struct subtype *st = dev->subtype;
exit_code_t rc;
config_t config;
int proc = 0, active, persistent;
int proc = 0, active, persistent, autoconf;
if (SCOPE_ACTIVE(opts->config))
active = (dev->active.exists || dev->active.definable);
@@ -2629,7 +2686,16 @@ static exit_code_t import_device(struct device *dev, struct options *opts)
persistent = dev->persistent.exists;
else
persistent = 0;
config = get_config(active, persistent);
if (SCOPE_AUTOCONF(opts->config))
autoconf = dev->autoconf.exists;
else
autoconf = 0;
if (!active && !persistent && !autoconf) {
/* Nothing to import */
return EXIT_OK;
}
config = get_config(active, persistent, autoconf);
/* First check for prerequisite devices that need to be configured. */
rc = cfg_prereqs(st, dev->id, opts, config, 0);
@@ -2656,17 +2722,9 @@ static bool import_device_selected(struct device *dev, struct options *opts)
if (!select_opts_dev_specified(select))
return false;
/* --active */
if (opts->config == config_active) {
if (!dev->active.exists && !dev->active.definable)
return false;
}
/* --persistent */
if (opts->config == config_persistent) {
if (!dev->persistent.exists)
return false;
}
/* Target configuration */
if ((device_get_config(dev) & opts->config) == 0)
return false;
/* Devtype */
if (select->devtype && dt != select->devtype)

View File

@@ -55,5 +55,6 @@ OPTIONS
--dry-run Display changes without applying
--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
-V, --verbose Print additional run-time information
-q, --quiet Print only minimal run-time information

View File

@@ -316,34 +316,34 @@ static struct attrib dasd_attr_safe_offline = {
* DASD subtype methods.
*/
static bool _check_use_diag(struct setting_list *list)
{
struct setting *u;
u = setting_list_find(list, dasd_attr_use_diag.name);
if (u && u->modified) {
if (u->value && atoi(u->value) == 1) {
delayed_warn("Cannot set 'use_diag=1' on non-z/VM system\n");
return false;
}
}
return true;
}
/* Check if use_diag setting can be correctly applied. */
static exit_code_t check_use_diag(struct device *dev, config_t config)
{
struct setting *u;
int zvm = is_zvm();
if (is_zvm())
return EXIT_OK;
if (SCOPE_ACTIVE(config)) {
u = setting_list_find(dev->active.settings,
dasd_attr_use_diag.name);
if (u && u->modified) {
if (u->value && atoi(u->value) == 1 && !zvm) {
delayed_warn("Cannot set 'use_diag=1' on "
"non-z/VM system\n");
return EXIT_INVALID_CONFIG;
}
}
}
if (SCOPE_PERSISTENT(config)) {
u = setting_list_find(dev->persistent.settings,
dasd_attr_use_diag.name);
if (u && u->modified) {
if (u->value && atoi(u->value) == 1 && !zvm) {
delayed_warn("Cannot set 'use_diag=1' on "
"non-z/VM system\n");
return EXIT_INVALID_CONFIG;
}
}
}
if (SCOPE_ACTIVE(config) && !_check_use_diag(dev->active.settings))
return EXIT_INVALID_CONFIG;
if (SCOPE_PERSISTENT(config) &&
!_check_use_diag(dev->persistent.settings))
return EXIT_INVALID_CONFIG;
if (SCOPE_AUTOCONF(config) &&
!_check_use_diag(dev->autoconf.settings))
return EXIT_INVALID_CONFIG;
return EXIT_OK;
}
@@ -376,6 +376,8 @@ static void dasd_st_add_modules(struct subtype *st, struct device *dev,
dasd_attr_use_diag.name, &changed, &aset);
setting_list_get_bool_state(dev->persistent.settings,
dasd_attr_use_diag.name, &changed, &pset);
setting_list_get_bool_state(dev->autoconf.settings,
dasd_attr_use_diag.name, &changed, &pset);
if (aset || pset)
strlist_add_unique(modules, DASD_DIAG_MOD_NAME);

View File

@@ -40,6 +40,7 @@ struct device *device_new(struct subtype *st, const char *id)
dev->active.settings = setting_list_new();
dev->persistent.settings = setting_list_new();
dev->autoconf.settings = setting_list_new();
return dev;
}
@@ -53,6 +54,7 @@ void device_free(struct device *dev)
free(dev->devid);
setting_list_free(dev->active.settings);
setting_list_free(dev->persistent.settings);
setting_list_free(dev->autoconf.settings);
free(dev);
}
@@ -83,6 +85,15 @@ void device_print(struct device *dev, int level)
setting_list_print(dev->persistent.settings, level + 8);
else
printf("%*s<none>\n", level + 8, "");
printf("%*sautoconf:\n", level + 4, "");
printf("%*sexists=%d mod=%d deconf=%d\n",
level + 8, "", dev->autoconf.exists, dev->autoconf.modified,
dev->autoconf.deconfigured);
if (dev->autoconf.settings)
setting_list_print(dev->autoconf.settings, level + 8);
else
printf("%*s<none>\n", level + 8, "");
}
static const void *device_hash_get_id(void *dev_ptr)
@@ -182,6 +193,10 @@ bool device_needs_writing(struct device *dev, config_t config)
(dev->persistent.modified || dev->persistent.deconfigured ||
setting_list_modified(dev->persistent.settings)))
return true;
if (SCOPE_AUTOCONF(config) &&
(dev->autoconf.modified || dev->autoconf.deconfigured ||
setting_list_modified(dev->autoconf.settings)))
return true;
return false;
}
@@ -204,6 +219,8 @@ static exit_code_t apply_setting(struct device *dev, config_t config,
/* Check for activeonly. */
if (!force && SCOPE_PERSISTENT(config) && a->activeonly)
goto err_activeonly_forceable;
if (!force && SCOPE_AUTOCONF(config) && a->activeonly)
goto err_activeonly_forceable;
/* Check for multiple values. */
if (!force && !a->multi && strlist_find(processed, key))
goto err_multi_forceable;
@@ -231,8 +248,15 @@ static exit_code_t apply_setting(struct device *dev, config_t config,
a, key, value);
}
/* Apply to autoconf config. */
if (SCOPE_AUTOCONF(config)) {
setting_list_apply_specified(dev->autoconf.settings,
a, key, value);
}
/* Additional warning when trying to persist read-only setting. */
if (config == config_persistent) {
if (!SCOPE_ACTIVE(config) && (SCOPE_PERSISTENT(config) ||
SCOPE_AUTOCONF(config))) {
s = setting_list_find(dev->active.settings, key);
if (s && s->readonly)
warn_readonly = true;
@@ -341,6 +365,8 @@ void device_reset(struct device *dev, config_t config)
reset_device_state(&dev->active);
if (SCOPE_PERSISTENT(config))
reset_device_state(&dev->persistent);
if (SCOPE_AUTOCONF(config))
reset_device_state(&dev->autoconf);
dev->processed = 0;
}
@@ -567,6 +593,12 @@ exit_code_t device_check_settings(struct device *dev, config_t config,
err))
return EXIT_INVALID_CONFIG;
}
if (SCOPE_AUTOCONF(config)) {
if (!setting_list_check_conflict(dev->autoconf.settings,
config_autoconf,
err))
return EXIT_INVALID_CONFIG;
}
return EXIT_OK;
}
@@ -578,8 +610,27 @@ struct setting_list *device_get_setting_list(struct device *dev,
if (config == config_active)
settings = dev->active.settings;
else
else if (config == config_persistent)
settings = dev->persistent.settings;
else if (config == config_autoconf)
settings = dev->autoconf.settings;
return settings;
}
/* Return configuration set in which device exists. */
config_t device_get_config(struct device *dev)
{
config_t config = 0;
if (dev->active.exists || dev->active.definable)
config |= config_active;
if (dev->persistent.exists)
config |= config_persistent;
if (dev->autoconf.exists)
config |= config_autoconf;
return config;
}

View File

@@ -83,7 +83,7 @@ static bool is_exportable(struct setting *s, config_t config)
return true;
}
}
if (SCOPE_PERSISTENT(config)) {
if (SCOPE_PERSISTENT(config) || SCOPE_AUTOCONF(config)) {
if (setting_is_set(s))
return true;
}
@@ -148,10 +148,9 @@ static int count_exportable(struct device *dev, config_t config)
struct setting *s;
int count;
if (config == config_active)
list = dev->active.settings;
else
list = dev->persistent.settings;
list = device_get_setting_list(dev, config);
if (!list)
return 0;
count = 0;
util_list_iterate(&list->list, s) {
@@ -169,12 +168,26 @@ exit_code_t export_write_device(FILE *fd, struct device *dev, config_t config,
exit_code_t rc;
struct setting_list *settings;
if (config == config_all) {
rc = export_write_device(fd, dev, config_active, first_ptr);
if (rc)
return rc;
return export_write_device(fd, dev, config_persistent,
first_ptr);
if (!SCOPE_SINGLE(config)) {
if (SCOPE_ACTIVE(config)) {
rc = export_write_device(fd, dev, config_active,
first_ptr);
if (rc)
return rc;
}
if (SCOPE_PERSISTENT(config)) {
rc = export_write_device(fd, dev, config_persistent,
first_ptr);
if (rc)
return rc;
}
if (SCOPE_AUTOCONF(config)) {
rc = export_write_device(fd, dev, config_autoconf,
first_ptr);
if (rc)
return rc;
}
return EXIT_OK;
}
if (config == config_active) {
@@ -185,10 +198,14 @@ exit_code_t export_write_device(FILE *fd, struct device *dev, config_t config,
!dev->subtype->support_definable)
return EXIT_OK;
settings = dev->active.settings;
} else {
} else if (config == config_persistent) {
if (!dev->persistent.exists)
return EXIT_OK;
settings = dev->persistent.settings;
} else {
if (!dev->autoconf.exists)
return EXIT_OK;
settings = dev->autoconf.settings;
}
write_header(fd, config, dev->subtype->name, dev->id, first_ptr);
@@ -204,12 +221,21 @@ exit_code_t export_write_devtype(FILE *fd, struct devtype *dt, config_t config,
exit_code_t rc;
struct setting_list *settings;
if (config == config_all) {
rc = export_write_devtype(fd, dt, config_active, first_ptr);
if (rc)
return rc;
return export_write_devtype(fd, dt, config_persistent,
first_ptr);
if (!SCOPE_SINGLE(config)) {
if (SCOPE_ACTIVE(config)) {
rc = export_write_devtype(fd, dt, config_active,
first_ptr);
if (rc)
return rc;
}
if (SCOPE_PERSISTENT(config)) {
rc = export_write_devtype(fd, dt, config_persistent,
first_ptr);
if (rc)
return rc;
}
/* Scope autoconf not supported for devtype */
return EXIT_OK;
}
if (config == config_active)
@@ -379,6 +405,10 @@ static exit_code_t handle_header(const char *filename, int lineno,
setting_list_clear(dev->persistent.settings);
dev->persistent.exists = 1;
}
if (SCOPE_AUTOCONF(hdr->config)) {
setting_list_clear(dev->autoconf.settings);
dev->autoconf.exists = 1;
}
}
out:
@@ -397,13 +427,26 @@ static exit_code_t handle_setting(const char *filename, int lineno,
struct attrib **attribs, *a;
struct setting_list *list;
if (config == config_all) {
rc = handle_setting(filename, lineno, key, value, dt, dev,
config_active);
if (rc)
return rc;
return handle_setting(filename, lineno, key, value, dt, dev,
config_persistent);
if (!SCOPE_SINGLE(config)) {
if (SCOPE_ACTIVE(config)) {
rc = handle_setting(filename, lineno, key, value, dt,
dev, config_active);
if (rc)
return rc;
}
if (SCOPE_PERSISTENT(config)) {
rc = handle_setting(filename, lineno, key, value, dt,
dev, config_persistent);
if (rc)
return rc;
}
if (SCOPE_AUTOCONF(config)) {
rc = handle_setting(filename, lineno, key, value, dt,
dev, config_autoconf);
if (rc)
return rc;
}
return EXIT_OK;
}
if (dt) {
@@ -452,7 +495,8 @@ static bool empty_device(struct device *dev)
if (dev->subtype->support_definable)
return false;
if (util_list_is_empty(&dev->active.settings->list) &&
util_list_is_empty(&dev->persistent.settings->list))
util_list_is_empty(&dev->persistent.settings->list) &&
util_list_is_empty(&dev->autoconf.settings->list))
return true;
return false;
}

View File

@@ -360,6 +360,8 @@ static void add_setting(const char *filename, struct device *dev,
_add_setting(filename, dev, config_active, key, value);
if (SCOPE_PERSISTENT(config))
_add_setting(filename, dev, config_persistent, key, value);
if (SCOPE_AUTOCONF(config))
_add_setting(filename, dev, config_autoconf, key, value);
}
/* Parse a single device setting in firmware format and apply it to the
@@ -477,6 +479,10 @@ static struct device *add_device(struct fw_file *f, struct subtype *st,
setting_list_clear(dev->persistent.settings);
dev->persistent.exists = 1;
}
if (SCOPE_AUTOCONF(config)) {
setting_list_clear(dev->autoconf.settings);
dev->autoconf.exists = 1;
}
return dev;
}

View File

@@ -59,6 +59,7 @@ struct options {
config_t config;
unsigned int active:1;
unsigned int persistent:1;
unsigned int auto_conf:1;
struct util_list *columns; /* List of struct strlist_node */
unsigned int no_headings:1;
struct util_list *base; /* List of struct strlist_node */
@@ -98,6 +99,7 @@ enum {
OPT_VERBOSE = 'V',
OPT_QUIET = 'q',
OPT_PAIRS = 'P',
OPT_AUTO_CONF = (OPT_ANONYMOUS_BASE+__COUNTER__),
};
static struct opts_conflict conflict_list[] = {
@@ -150,6 +152,7 @@ static const struct option opt_list[] = {
/* Options. */
{ "active", no_argument, NULL, OPT_ACTIVE },
{ "persistent", no_argument, NULL, OPT_PERSISTENT },
{ "auto-conf", no_argument, NULL, OPT_AUTO_CONF },
{ "columns", required_argument, NULL, OPT_COLUMNS },
{ "no-headings", no_argument, NULL, OPT_NO_HEADINGS },
{ "base", required_argument, NULL, OPT_BASE },
@@ -623,6 +626,11 @@ static exit_code_t parse_options(struct options *opts, int argc, char *argv[])
opts->persistent = 1;
break;
case OPT_AUTO_CONF:
/* --auto-conf */
opts->auto_conf = 1;
break;
case OPT_COLUMNS:
/* --columns COLUMN */
strlist_add_multi(opts->columns, optarg, ",", 0);
@@ -685,7 +693,15 @@ static exit_code_t parse_options(struct options *opts, int argc, char *argv[])
goto out;
/* Determine configuration set. */
opts->config = get_config(opts->active, opts->persistent);
if (!opts->active && !opts->persistent && !opts->auto_conf) {
/* Default display targets are active + persistent - note that
* autoconf data is still shown when available to make users
* aware of this type of data. */
opts->config = config_active | config_persistent;
} else {
opts->config = get_config(opts->active, opts->persistent,
opts->auto_conf);
}
/* Handle positional parameters. */
rc = parse_positional(opts, argc, argv, optind);
@@ -725,6 +741,7 @@ enum dev_table_id {
dev_netdevs,
dev_exists,
dev_pers,
dev_auto,
dev_online,
dev_failed,
dev_modules,
@@ -744,6 +761,8 @@ static struct column *dev_table = COLUMN_ARRAY(
"Device exists in the active configuration"),
COLUMN("PERS", align_left, dev_pers, 1,
"Device is configured persistently"),
COLUMN("AUTO", align_left, dev_auto, 0,
"Auto-configuration exists for device"),
COLUMN("FAILED", align_left, dev_failed, 0,
"Device is in error"),
COLUMN("NAMES", align_left, dev_names, 1,
@@ -762,21 +781,34 @@ static struct column *dev_table = COLUMN_ARRAY(
"Path to specific attribute in active configuration")
);
static char *merge_str(const char *act, const char *pers)
static char *merge_str(const char *act, const char *pers, const char *ac,
config_t config)
{
char *str;
size_t len;
if (act && pers) {
if (strcmp(act, pers) == 0)
str = misc_strdup(act);
else
str = misc_asprintf("%s/%s", act, pers);
} else if (act)
str = misc_strdup(act);
else if (pers)
str = misc_strdup(pers);
else
str = misc_strdup("-");
act = act ? act : "-";
pers = pers ? pers : "-";
ac = ac ? ac : "-";
if (strcmp(act, pers) == 0 && strcmp(act, ac) == 0)
return misc_strdup(act);
len = strlen(act) + strlen(pers) + strlen(ac) + /* 3 * / + NUL */ 4;
str = misc_malloc(len);
if (SCOPE_ACTIVE(config))
strcat(str, act);
if (SCOPE_PERSISTENT(config)) {
if (*str)
strcat(str, "/");
strcat(str, pers);
}
if (SCOPE_AUTOCONF(config)) {
if (*str)
strcat(str, "/");
strcat(str, ac);
}
return str;
}
@@ -821,10 +853,9 @@ static char *get_attr(struct device *dev, const char *name, config_t config)
struct setting_list *list;
struct setting *s;
if (config == config_active)
list = dev->active.settings;
else
list = dev->persistent.settings;
list = device_get_setting_list(dev, config);
if (!list)
return NULL;
s = setting_list_find(list, name);
if (!s) {
if (config == config_active) {
@@ -841,7 +872,7 @@ static char *get_attr(struct device *dev, const char *name, config_t config)
static char *dev_table_get_attr(struct device *dev, const char *attr,
config_t config)
{
char *act = NULL, *pers = NULL, *str;
char *act = NULL, *pers = NULL, *ac = NULL, *str;
const char *name;
name = strchr(attr, ':');
@@ -853,10 +884,13 @@ static char *dev_table_get_attr(struct device *dev, const char *attr,
act = get_attr(dev, name, config_active);
if (SCOPE_PERSISTENT(config))
pers = get_attr(dev, name, config_persistent);
if (SCOPE_AUTOCONF(config))
ac = get_attr(dev, name, config_autoconf);
str = merge_str(act, pers);
str = merge_str(act, pers, ac, config);
free(act);
free(pers);
free(ac);
return str;
}
@@ -904,7 +938,11 @@ static char *dev_table_get_value(void *item, int id, const char *heading,
return misc_strdup(YESNO(dev->active.exists ||
dev->active.definable));
case dev_pers:
if (!dev->persistent.exists && dev->autoconf.exists)
return misc_strdup("auto");
return misc_strdup(YESNO(dev->persistent.exists));
case dev_auto:
return misc_strdup(YESNO(dev->autoconf.exists));
case dev_online:
return dev_table_get_online(dev, config_active);
case dev_failed:
@@ -942,6 +980,7 @@ static read_scope_t get_scope(struct options *opts)
case dev_netdevs:
case dev_exists:
case dev_pers:
case dev_auto:
case dev_online:
case dev_modules:
continue;
@@ -960,14 +999,21 @@ static struct util_list *dev_table_build(struct options *opts,
struct util_list *selected, *devices = NULL;
struct selected_dev_node *sel;
struct device *dev;
int active, persistent;
int active, persistent, autoconf;
read_scope_t scope;
exit_code_t rc;
config_t config = opts->config;
scope = get_scope(opts);
selected = selected_dev_list_new();
/* Read auto-config data when no configuration set was specified to
* make user aware of auto-config data. */
if (!opts->active && !opts->persistent && !opts->auto_conf)
config |= config_autoconf;
rc = select_devices(opts->select, selected, 1, 0, opts->pairs,
opts->config, scope, err_print);
config, scope, err_print);
if (rc)
goto out;
devices = ptrlist_new();
@@ -987,7 +1033,8 @@ static struct util_list *dev_table_build(struct options *opts,
/* Only process existing devices. */
active = dev->active.exists || dev->active.definable;
persistent = dev->persistent.exists;
if (!active && !persistent)
autoconf = dev->autoconf.exists;
if (!active && !persistent && !autoconf)
continue;
ptrlist_add(devices, dev);
@@ -1025,9 +1072,11 @@ static exit_code_t do_list_devices(struct options *opts)
if (!items)
return EXIT_EMPTY_SELECTION;
/* Adjust columns visible depending on --active and --persistent. */
/* Adjust columns visible depending on selected config set. */
table_set_default(dev_table, dev_online, SCOPE_ACTIVE(opts->config));
table_set_default(dev_table, dev_pers, SCOPE_PERSISTENT(opts->config));
table_set_default(dev_table, dev_auto, SCOPE_AUTOCONF(opts->config) &&
!SCOPE_PERSISTENT(opts->config));
table_set_default(dev_table, dev_names, SCOPE_ACTIVE(opts->config));
/* Display table. */
@@ -1057,17 +1106,20 @@ enum settings_table_id {
settings_readonly,
settings_active,
settings_persistent,
settings_autoconf,
};
static struct column *settings_table = COLUMN_ARRAY(
COLUMN("ATTRIBUTE", align_left, settings_attribute, 1, ""),
COLUMN("READONLY", align_left, settings_readonly, 1, ""),
COLUMN("ACTIVE", align_left, settings_active, 1, ""),
COLUMN("PERSISTENT", align_left, settings_persistent, 1, "")
COLUMN("PERSISTENT", align_left, settings_persistent, 1, ""),
COLUMN("AUTOCONF", align_left, settings_autoconf, 0, "")
);
static struct util_list *settings_table_build(struct setting_list *active,
struct setting_list *persistent,
struct setting_list *autoconf,
bool readonly)
{
struct util_list *names, *items;
@@ -1088,6 +1140,10 @@ static struct util_list *settings_table_build(struct setting_list *active,
util_list_iterate(&persistent->list, s)
strlist_add(names, s->name);
}
if (autoconf && !readonly) {
util_list_iterate(&autoconf->list, s)
strlist_add(names, s->name);
}
strlist_sort_unique(names, str_cmp);
/* Convert strlist to ptrlist. */
@@ -1102,6 +1158,7 @@ static struct util_list *settings_table_build(struct setting_list *active,
struct settings_table_data {
struct setting_list *active;
struct setting_list *persistent;
struct setting_list *autoconf;
int pairs;
bool readonly;
};
@@ -1124,12 +1181,17 @@ static char *settings_table_get_value(void *item, int id, const char *heading,
case settings_persistent:
list = stdata->persistent;
break;
case settings_autoconf:
list = stdata->autoconf;
break;
default:
break;
}
if (list) {
s = setting_list_find(list, name);
if (s && !(id == settings_persistent && s->derived)) {
if (s &&
!((id == settings_persistent || id == settings_autoconf) &&
s->derived)) {
if (stdata->pairs)
return misc_strdup(s->value);
else
@@ -1145,6 +1207,7 @@ static char *settings_table_get_value(void *item, int id, const char *heading,
static void settings_table_print(struct setting_list *active,
struct setting_list *persistent,
struct setting_list *autoconf,
struct options *opts, int ind, bool readonly,
bool neednl)
{
@@ -1154,7 +1217,7 @@ static void settings_table_print(struct setting_list *active,
items = settings_table_build(
SCOPE_ACTIVE(opts->config) ? active : NULL,
SCOPE_PERSISTENT(opts->config) ? persistent : NULL,
readonly);
autoconf, readonly);
if (util_list_is_empty(items)) {
if (!opts->pairs && !readonly)
indent(ind, "%sNo settings found\n",
@@ -1170,8 +1233,12 @@ static void settings_table_print(struct setting_list *active,
SCOPE_ACTIVE(opts->config));
table_set_default(settings_table, settings_persistent,
SCOPE_PERSISTENT(opts->config) && !readonly ? 1 : 0);
table_set_default(settings_table, settings_autoconf,
(SCOPE_AUTOCONF(opts->config) || autoconf) &&
!readonly ? 1 : 0);
data.active = active;
data.persistent = persistent;
data.autoconf = autoconf;
data.pairs = opts->pairs;
table_print(settings_table, settings_table_get_value, &data, items,
NULL, 1, opts->pairs, ind, 0);
@@ -1253,7 +1320,7 @@ static exit_code_t do_info_type(struct options *opts)
}
} else {
settings_table_print(dt->active_settings,
dt->persistent_settings, opts,
dt->persistent_settings, NULL, opts,
INFO_INDENT, false, false);
}
@@ -1280,7 +1347,7 @@ static void do_info_one_device(struct device *dev, struct options *opts)
{
struct subtype *st = dev->subtype;
char *names, *bdevs, *cdevs, *ndevs, *modules, *online, *path, *key;
const char *id, *type, *exists, *persist, *prefix;
const char *id, *type, *exists, *persist, *ac, *prefix;
struct util_list *resources, *errors;
struct strlist_node *s;
bool first;
@@ -1299,6 +1366,7 @@ static void do_info_one_device(struct device *dev, struct options *opts)
errors = subtype_get_errors(dev->subtype, dev->id);
exists = YESNO(dev->active.exists || dev->active.definable);
persist = YESNO(dev->persistent.exists);
ac = YESNO(dev->autoconf.exists);
/* Print information. */
if (opts->pairs) {
@@ -1316,6 +1384,8 @@ static void do_info_one_device(struct device *dev, struct options *opts)
print_pair("ONLINE", online);
print_pair("EXISTS", exists);
print_pair("PERSISTENT", persist);
if (SCOPE_AUTOCONF(opts->config) || dev->autoconf.exists)
print_pair("AUTOCONF", ac);
if (errors) {
util_list_iterate(errors, s)
print_pair("ERROR", s->str);
@@ -1341,6 +1411,8 @@ static void do_info_one_device(struct device *dev, struct options *opts)
print_info("Online", online);
print_info("Exists", exists);
print_info("Persistent", persist);
if (SCOPE_AUTOCONF(opts->config) || dev->autoconf.exists)
print_info("Auto-configured", ac);
if (errors) {
first = true;
util_list_iterate(errors, s) {
@@ -1382,11 +1454,17 @@ static void do_info_one_device(struct device *dev, struct options *opts)
settings_table_print(dev->active.exists ? dev->active.settings : NULL,
dev->persistent.exists ? dev->persistent.settings :
NULL, opts, INFO_INDENT, false, !opts->pairs);
NULL,
dev->autoconf.exists ? dev->autoconf.settings :
NULL,
opts, INFO_INDENT, false, !opts->pairs);
settings_table_print(dev->active.exists ? dev->active.settings : NULL,
dev->persistent.exists ? dev->persistent.settings :
NULL, opts, INFO_INDENT, true, !opts->pairs);
NULL,
dev->autoconf.exists ? dev->autoconf.settings :
NULL,
opts, INFO_INDENT, true, !opts->pairs);
strlist_free(errors);
free(online);
@@ -1404,9 +1482,10 @@ static exit_code_t do_info_devices(struct options *opts)
struct util_list *selected;
struct selected_dev_node *sel;
struct device *dev;
int found, active, persistent;
int found, active, persistent, autoconf;
exit_code_t rc, drc = EXIT_OK;
read_scope_t scope;
config_t config = opts->config;
if (opts->info > 1)
scope = scope_all;
@@ -1415,7 +1494,13 @@ static exit_code_t do_info_devices(struct options *opts)
/* Get list of selected devices. */
selected = selected_dev_list_new();
select_devices(opts->select, selected, 1, 0, opts->pairs, opts->config,
/* Read auto-config data when no configuration set was specified to
* make user aware of auto-config data. */
if (!opts->active && !opts->persistent && !opts->auto_conf)
config |= config_autoconf;
select_devices(opts->select, selected, 1, 0, opts->pairs, config,
scope, err_print);
/* Process selected devices. */
@@ -1434,9 +1519,8 @@ static exit_code_t do_info_devices(struct options *opts)
/* Only process existing devices. */
active = dev->active.exists || dev->active.definable;
persistent = dev->persistent.exists;
if ((opts->config == config_active && !active) ||
(opts->config == config_persistent && !persistent) ||
(opts->config == config_all && !active && !persistent))
autoconf = dev->autoconf.exists;
if (!active && !persistent && !autoconf)
continue;
if (found > 0)
printf("\n");

View File

@@ -41,5 +41,6 @@ OPTIONS
-n, --no-headings Do not print column headings
--base PATH Use PATH as base for accessing files
--pairs Produce output in KEY="VALUE" format
--auto-conf Only show auto-configuration data
-V, --verbose Print additional run-time information
-q, --quiet Print only minimal run-time information

View File

@@ -1107,14 +1107,18 @@ char *misc_readlink(const char *path)
}
/* Determine configuration set. */
config_t get_config(int active, int persistent)
config_t get_config(int active, int persistent, int autoconf)
{
if ((!active && !persistent) || (active && persistent))
return config_all;
else if (active)
return config_active;
else
return config_persistent;
config_t config = 0;
if (active)
config |= config_active;
if (persistent)
config |= config_persistent;
if (autoconf)
config |= config_autoconf;
return config;
}
/* Determine if program is running under z/VM. */
@@ -1248,11 +1252,12 @@ const char *config_to_str(config_t config)
return "active";
case config_persistent:
return "persistent";
case config_autoconf:
return "autoconf";
case config_all:
return "all";
}
/* Should not happen. */
return "";
return "multiple";
}
/* Convert textual config representation to config_t. */
@@ -1262,6 +1267,8 @@ bool str_to_config(const char *str, config_t *config_ptr)
*config_ptr = config_active;
else if (strcasecmp(str, "persistent") == 0)
*config_ptr = config_persistent;
else if (strcasecmp(str, "autoconf") == 0)
*config_ptr = config_autoconf;
else if (strcasecmp(str, "all") == 0)
*config_ptr = config_all;
else

View File

@@ -297,21 +297,25 @@ char *path_get_ccwgroup_devices(const char *drv)
}
/* Return path to udev rule. */
char *path_get_udev_rule(const char *type, const char *id)
char *path_get_udev_rule(const char *type, const char *id, bool vol)
{
const char *path = vol ? PATH_UDEV_RULES_VOLATILE : PATH_UDEV_RULES;
if (id) {
return path_get("%s/%s-%s-%s%s", PATH_UDEV_RULES,
return path_get("%s/%s-%s-%s%s", path,
UDEV_PREFIX, type, id, UDEV_SUFFIX);
}
return path_get("%s/%s-%s%s", PATH_UDEV_RULES,
return path_get("%s/%s-%s%s", path,
UDEV_PREFIX, type, UDEV_SUFFIX);
}
/* Return path to directory containing all udev rules. */
char *path_get_udev_rules(void)
char *path_get_udev_rules(bool vol)
{
return path_get("%s", PATH_UDEV_RULES);
const char *path = vol ? PATH_UDEV_RULES_VOLATILE : PATH_UDEV_RULES;
return path_get("%s", path);
}
/* Return path to the specified file in the proc file system. */

View File

@@ -1207,7 +1207,7 @@ static exit_code_t check_layer2(struct device *dev, config_t config)
{
struct setting *l;
int layer2_detected, layer2_active = -1, layer2_persistent = -1,
layer2_modified = 0;
layer2_autoconf = -1, layer2_modified = 0;
exit_code_t rc = EXIT_OK;
layer2_detected = detect_layer2(dev);
@@ -1231,13 +1231,25 @@ static exit_code_t check_layer2(struct device *dev, config_t config)
if (rc)
goto out;
}
l = setting_list_find(dev->autoconf.settings, qeth_attr_layer2.name);
if (l) {
layer2_autoconf = atoi(l->value);
layer2_modified |= l->modified;
} else if (SCOPE_AUTOCONF(config)) {
rc = generate_layer2("autoconf", dev->autoconf.settings,
&layer2_autoconf, &layer2_modified);
if (rc)
goto out;
}
/* Check correct layer2 setting. */
if (layer2_detected != -1) {
if ((SCOPE_ACTIVE(config) && layer2_active != -1 &&
layer2_active != layer2_detected) ||
(SCOPE_PERSISTENT(config) && layer2_persistent != -1 &&
layer2_persistent != layer2_detected)) {
layer2_persistent != layer2_detected) ||
(SCOPE_AUTOCONF(config) && layer2_autoconf != -1 &&
layer2_autoconf != layer2_detected)) {
rc = layer2_mismatch(layer2_detected, layer2_modified);
if (rc)
goto out;
@@ -1256,14 +1268,25 @@ static exit_code_t check_layer2(struct device *dev, config_t config)
if (rc)
goto out;
}
if (SCOPE_AUTOCONF(config)) {
rc = check_ineffective_settings(dev->autoconf.settings,
layer2_autoconf);
if (rc)
goto out;
}
/* check for conflicting layer2 attribute groups */
if (SCOPE_ACTIVE(config)) {
rc = check_conflicting_settings(dev->active.settings);
if (rc)
goto out;
}
if (SCOPE_PERSISTENT(config))
if (SCOPE_PERSISTENT(config)) {
rc = check_conflicting_settings(dev->persistent.settings);
if (rc)
goto out;
}
if (SCOPE_AUTOCONF(config))
rc = check_conflicting_settings(dev->autoconf.settings);
out:
return rc;
@@ -1277,7 +1300,8 @@ static exit_code_t qeth_st_check_pre_configure(struct subtype *st,
/* No need to check if device is deconfigured. */
if ((SCOPE_ACTIVE(config) && dev->active.deconfigured) ||
(SCOPE_PERSISTENT(config) && dev->persistent.deconfigured))
(SCOPE_PERSISTENT(config) && dev->persistent.deconfigured) ||
(SCOPE_AUTOCONF(config) && dev->autoconf.deconfigured))
return EXIT_OK;
rc = check_layer2(dev, config);

View File

@@ -248,12 +248,13 @@ static void unblacklist_devices(struct select_opts *select)
bool select_match_state(struct device *dev, struct select_opts *select)
{
struct subtype *st = dev->subtype;
int exists, configured, online;
int exists, configured, autoconf, online;
struct util_list *errors;
exists = dev->active.exists || dev->active.definable;
configured = dev->persistent.exists;
if (select->all && !(exists || configured))
autoconf = dev->autoconf.exists;
if (select->all && !(exists || configured || autoconf))
return false;
if (select->existing && !exists)
return false;
@@ -862,7 +863,8 @@ static exit_code_t select_nocreate(struct select_opts *select,
select->offline || select->online ||
SCOPE_ACTIVE(config),
select->configured || select->all ||
SCOPE_PERSISTENT(config));
SCOPE_PERSISTENT(config),
select->all || SCOPE_AUTOCONF(config));
longrun_total = 0;
if (quiet)
@@ -870,7 +872,7 @@ static exit_code_t select_nocreate(struct select_opts *select,
/* Count devices. */
verb("Scanning for devices in %s configuration%s:\n",
config_to_str(id_config), id_config == config_all ? "s" : "");
config_to_str(id_config), !SCOPE_SINGLE(id_config) ? "s" : "");
for (i = 0; (dt = devtypes[i]); i++) {
if (select->devtype && dt != select->devtype)
continue;
@@ -1128,6 +1130,13 @@ static exit_code_t by_attr_cb(struct subtype *st, const char *id,
/* Check for attribute value in persistent configuration. */
s = setting_list_find(dev->persistent.settings, cb_data->key);
if (s) {
match = setting_match_value(s, cb_data->value);
if (match)
goto out;
}
/* Check for attribute value in autoconf configuration. */
s = setting_list_find(dev->autoconf.settings, cb_data->key);
if (s)
match = setting_match_value(s, cb_data->value);

View File

@@ -646,7 +646,8 @@ static void add_changes(struct util_list *list, struct setting *s)
/* Return a newly allocated string containing the setting changes found
* in PERS and ACT or NULL if no change was found. */
char *setting_get_changes(struct setting_list *act, struct setting_list *pers)
char *setting_get_changes(struct setting_list *act, struct setting_list *pers,
struct setting_list *ac)
{
struct util_list *out;
struct util_list *processed;
@@ -668,6 +669,17 @@ char *setting_get_changes(struct setting_list *act, struct setting_list *pers)
strlist_add(processed, s->name);
}
}
if (ac) {
util_list_iterate(&ac->list, s) {
if (s->removed)
strlist_add(out, "-%s", s->name);
else if (s->modified)
add_changes(out, s);
else
continue;
strlist_add(processed, s->name);
}
}
if (act) {
util_list_iterate(&act->list, s) {
if (!s->modified && !s->removed)

View File

@@ -195,6 +195,13 @@ bool subtype_device_exists_persistent(struct subtype *st, const char *id)
return super->exists_persistent(st, id);
}
bool subtype_device_exists_autoconf(struct subtype *st, const char *id)
{
struct subtype *super = super_get(st, exists_autoconf, 1);
return super->exists_autoconf(st, id);
}
void subtype_add_active_ids(struct subtype *st, struct util_list *ids)
{
struct subtype *super = super_get(st, add_active_ids, 1);
@@ -209,6 +216,13 @@ void subtype_add_persistent_ids(struct subtype *st, struct util_list *ids)
super->add_persistent_ids(st, ids);
}
void subtype_add_autoconf_ids(struct subtype *st, struct util_list *ids)
{
struct subtype *super = super_get(st, add_autoconf_ids, 1);
super->add_autoconf_ids(st, ids);
}
exit_code_t subtype_device_read_active(struct subtype *st, struct device *dev,
read_scope_t scope)
{
@@ -226,6 +240,15 @@ exit_code_t subtype_device_read_persistent(struct subtype *st,
return super->read_persistent(st, dev, scope);
}
exit_code_t subtype_device_read_autoconf(struct subtype *st,
struct device *dev,
read_scope_t scope)
{
struct subtype *super = super_get(st, read_autoconf, 1);
return super->read_autoconf(st, dev, scope);
}
exit_code_t subtype_device_configure_active(struct subtype *st,
struct device *dev)
{
@@ -242,6 +265,14 @@ exit_code_t subtype_device_configure_persistent(struct subtype *st,
return super->configure_persistent(st, dev);
}
exit_code_t subtype_device_configure_autoconf(struct subtype *st,
struct device *dev)
{
struct subtype *super = super_get(st, configure_autoconf, 1);
return super->configure_autoconf(st, dev);
}
exit_code_t subtype_device_deconfigure_active(struct subtype *st,
struct device *dev)
{
@@ -258,6 +289,14 @@ exit_code_t subtype_device_deconfigure_persistent(struct subtype *st,
return super->deconfigure_persistent(st, dev);
}
exit_code_t subtype_device_deconfigure_autoconf(struct subtype *st,
struct device *dev)
{
struct subtype *super = super_get(st, deconfigure_autoconf, 1);
return super->deconfigure_autoconf(st, dev);
}
exit_code_t subtype_check_pre_configure(struct subtype *st, struct device *dev,
int prereq, config_t config)
{
@@ -299,7 +338,7 @@ void subtype_online_set(struct subtype *st, struct device *dev, int online,
int subtype_online_get(struct subtype *st, struct device *dev, config_t config)
{
struct subtype *super = super_get(st, online_get, 0);
int act_online = 1, pers_online = 1;
int act_online = 1, pers_online = 1, auto_online = 1;
if (super)
return super->online_get(st, dev, config);
@@ -310,8 +349,10 @@ int subtype_online_get(struct subtype *st, struct device *dev, config_t config)
act_online = dev->active.exists;
if (SCOPE_PERSISTENT(config))
pers_online = dev->persistent.exists;
if (SCOPE_AUTOCONF(config))
auto_online = dev->autoconf.exists;
return MIN(act_online, pers_online);
return MIN(MIN(act_online, pers_online), auto_online);
}
bool subtype_online_specified(struct subtype *st, struct device *dev,
@@ -495,6 +536,10 @@ bool subtype_device_exists(struct subtype *st, const char *id, config_t config)
if (!subtype_device_exists_persistent(st, id))
return false;
}
if (SCOPE_AUTOCONF(config)) {
if (!subtype_device_exists_autoconf(st, id))
return false;
}
return true;
}
@@ -512,6 +557,8 @@ static struct util_list *get_ids(struct subtype *st, config_t config)
}
if (SCOPE_PERSISTENT(config))
subtype_add_persistent_ids(st, ids);
if (SCOPE_AUTOCONF(config))
subtype_add_autoconf_ids(st, ids);
/* Provide a sorted view. */
strlist_sort_unique(ids, st->namespace->qsort_cmp);
@@ -683,6 +730,19 @@ static exit_code_t read_device(struct subtype *st, const char *id,
goto out;
}
if (SCOPE_AUTOCONF(config)) {
if (subtype_device_exists_autoconf(st, id))
rc = subtype_device_read_autoconf(st, dev, scope);
else if (defined) {
/* Need to copy detected settings to autoconf
* config. */
setting_list_merge(dev->autoconf.settings,
dev->active.settings, false, false);
}
if (rc)
goto out;
}
if (add)
device_list_add(st->devices, dev);
@@ -756,6 +816,25 @@ exit_code_t subtype_write_device(struct subtype *st, struct device *dev,
if (!rc)
namespace_set_modified(dev->subtype->namespace);
}
if (SCOPE_AUTOCONF(config)) {
if (dev->autoconf.deconfigured) {
/* Deconfigure device. */
if (dev->autoconf.exists) {
rc = subtype_device_deconfigure_autoconf(st,
dev);
if (rc)
return rc;
}
} else if (dev->autoconf.exists) {
/* Configure device. */
rc = subtype_device_configure_autoconf(st, dev);
if (rc)
return rc;
}
if (!rc)
namespace_set_modified(dev->subtype->namespace);
}
return EXIT_OK;
}

View File

@@ -360,7 +360,8 @@ static bool get_ids_cb(const char *filename, void *data)
/* Add the IDs for all devices of the specified subtype name for which a
* udev rule exists to strlist LIST. */
void udev_get_device_ids(const char *type, struct util_list *list)
void udev_get_device_ids(const char *type, struct util_list *list,
bool autoconf)
{
char *path, *prefix;
struct util_list *files;
@@ -369,7 +370,7 @@ void udev_get_device_ids(const char *type, struct util_list *list)
prefix = misc_asprintf("%s-%s-", UDEV_PREFIX, type);
plen = strlen(prefix);
path = path_get_udev_rules();
path = path_get_udev_rules(autoconf);
files = strlist_new();
if (!misc_read_dir(path, files, get_ids_cb, prefix))
goto out;
@@ -388,12 +389,12 @@ out:
}
/* Remove UDEV rule for device. */
exit_code_t udev_remove_rule(const char *type, const char *id)
exit_code_t udev_remove_rule(const char *type, const char *id, bool autoconf)
{
char *path;
exit_code_t rc = EXIT_OK;
path = path_get_udev_rule(type, id);
path = path_get_udev_rule(type, id, autoconf);
if (util_path_is_reg_file(path))
rc = remove_file(path);
free(path);

View File

@@ -25,7 +25,7 @@
#include "udev_ccw.h"
/* Check if a udev rule for the specified ccw device exists. */
bool udev_ccw_exists(const char *type, const char *id)
bool udev_ccw_exists(const char *type, const char *id, bool autoconf)
{
char *path, *normid;
bool rc;
@@ -34,7 +34,7 @@ bool udev_ccw_exists(const char *type, const char *id)
if (!normid)
return false;
path = path_get_udev_rule(type, normid);
path = path_get_udev_rule(type, normid, autoconf);
rc = util_path_is_reg_file(path);
free(path);
free(normid);
@@ -88,15 +88,16 @@ static void udev_file_get_settings(struct udev_file *file,
}
/* Read the persistent configuration of a CCW device from a udev rule. */
exit_code_t udev_ccw_read_device(struct device *dev)
exit_code_t udev_ccw_read_device(struct device *dev, bool autoconf)
{
struct subtype *st = dev->subtype;
struct device_state *state = &dev->persistent;
struct device_state *state = autoconf ? &dev->autoconf :
&dev->persistent;
struct udev_file *file = NULL;
exit_code_t rc;
char *path;
path = path_get_udev_rule(st->name, dev->id);
path = path_get_udev_rule(st->name, dev->id, autoconf);
rc = udev_read_file(path, &file);
if (rc)
goto out;
@@ -128,12 +129,13 @@ static char *get_label_id(const char *prefix, const char *type,
}
/* Write the persistent configuration of a CCW device to a udev rule. */
exit_code_t udev_ccw_write_device(struct device *dev)
exit_code_t udev_ccw_write_device(struct device *dev, bool autoconf)
{
struct subtype *st = dev->subtype;
struct ccw_subtype_data *data = st->data;
const char *type = st->name, *drv = data->ccwdrv, *id = dev->id;
struct device_state *state = &dev->persistent;
struct device_state *state = autoconf ? &dev->autoconf :
&dev->persistent;
char *path, *cfg_label = NULL, *end_label = NULL;
struct util_list *list;
struct ptrlist_node *p;
@@ -142,7 +144,7 @@ exit_code_t udev_ccw_write_device(struct device *dev)
FILE *fd;
if (!state->exists)
return udev_remove_rule(type, id);
return udev_remove_rule(type, id, autoconf);
cfg_label = get_label_id("cfg", type, id);
end_label = get_label_id("end", type, id);
@@ -150,7 +152,7 @@ exit_code_t udev_ccw_write_device(struct device *dev)
/* Apply attributes in correct order. */
list = setting_list_get_sorted(state->settings);
path = path_get_udev_rule(type, id);
path = path_get_udev_rule(type, id, autoconf);
debug("Writing %s udev rule file %s\n", type, path);
if (!util_path_exists(path)) {
rc = path_create(path);
@@ -234,14 +236,18 @@ out:
}
/* Write a udev rule to free devices from the cio-ignore blacklist. */
exit_code_t udev_ccw_write_cio_ignore(const char *id_list)
exit_code_t udev_ccw_write_cio_ignore(const char *id_list, bool autoconf)
{
char *path, *curr = NULL;
char *path, *prefix, *curr = NULL;
FILE *fd;
exit_code_t rc = EXIT_OK;
/* Ensure that autoconf version of cio-ignore is not masked
* by normal one. */
prefix = autoconf ? "cio-ignore-autoconf" : "cio-ignore";
/* Create file. */
path = path_get_udev_rule("cio-ignore", NULL);
path = path_get_udev_rule(prefix, NULL, autoconf);
if (!*id_list) {
/* Empty id_list string - remove file. */

View File

@@ -25,34 +25,34 @@
#include "udev_ccwgroup.h"
static char *get_rule_path_by_devid(const char *type,
struct ccwgroup_devid *devid)
struct ccwgroup_devid *devid, bool autoconf)
{
char *ccw_id, *path;
ccw_id = ccw_devid_to_str(&devid->devid[0]);
path = path_get_udev_rule(type, ccw_id);
path = path_get_udev_rule(type, ccw_id, autoconf);
free(ccw_id);
return path;
}
static char *get_rule_path(const char *type, const char *id)
static char *get_rule_path(const char *type, const char *id, bool autoconf)
{
struct ccwgroup_devid devid;
if (ccwgroup_parse_devid(&devid, id, err_ignore) != EXIT_OK)
return NULL;
return get_rule_path_by_devid(type, &devid);
return get_rule_path_by_devid(type, &devid, autoconf);
}
/* Check if a udev rule for the specified CCWGROUP device exists. */
bool udev_ccwgroup_exists(const char *type, const char *id)
bool udev_ccwgroup_exists(const char *type, const char *id, bool autoconf)
{
char *path;
bool rc;
path = get_rule_path(type, id);
path = get_rule_path(type, id, autoconf);
if (!path)
return false;
rc = util_path_is_reg_file(path);
@@ -143,15 +143,16 @@ static void expand_id(struct device *dev, struct udev_file *file)
}
/* Read the persistent configuration of a CCWGROUP device from a udev rule. */
exit_code_t udev_ccwgroup_read_device(struct device *dev)
exit_code_t udev_ccwgroup_read_device(struct device *dev, bool autoconf)
{
struct subtype *st = dev->subtype;
struct device_state *state = &dev->persistent;
struct device_state *state = autoconf ? &dev->autoconf :
&dev->persistent;
struct udev_file *file = NULL;
exit_code_t rc;
char *path;
path = get_rule_path_by_devid(st->name, dev->devid);
path = get_rule_path_by_devid(st->name, dev->devid, autoconf);
rc = udev_read_file(path, &file);
if (rc)
goto out;
@@ -184,9 +185,11 @@ static char *get_label_id(const char *prefix, const char *type,
}
/* Write the persistent configuration of a CCWGROUP device to a udev rule. */
exit_code_t udev_ccwgroup_write_device(struct device *dev)
exit_code_t udev_ccwgroup_write_device(struct device *dev, bool autoconf)
{
struct subtype *st = dev->subtype;
struct device_state *state = autoconf ? &dev->autoconf :
&dev->persistent;
struct ccwgroup_subtype_data *data = st->data;
const char *type = st->name, *drv = data->ccwgroupdrv, *id = dev->id;
struct ccwgroup_devid devid;
@@ -200,21 +203,21 @@ exit_code_t udev_ccwgroup_write_device(struct device *dev)
FILE *fd;
unsigned int i;
if (!dev->persistent.exists)
return udev_ccwgroup_remove_rule(type, id);
if (!state->exists)
return udev_ccwgroup_remove_rule(type, id, autoconf);
if (ccwgroup_parse_devid(&devid, id, err_ignore) != EXIT_OK)
return EXIT_INVALID_ID;
ccw_id = ccw_devid_to_str(&devid.devid[0]);
path = get_rule_path(type, ccw_id);
path = get_rule_path(type, ccw_id, autoconf);
group_label = get_label_id("group", type, ccw_id);
cfg_label = get_label_id("cfg", type, ccw_id);
end_label = get_label_id("end", type, ccw_id);
/* Apply attributes in correct order. */
list = setting_list_get_sorted(dev->persistent.settings);
list = setting_list_get_sorted(state->settings);
debug("Writing %s udev rule file %s\n", type, path);
if (!util_path_exists(path)) {
@@ -357,12 +360,13 @@ static exit_code_t get_ids_cb(const char *path, const char *filename,
/* Add the IDs for all devices of the specified subtype name for which a
* udev rule exists to strlist LIST. */
void udev_ccwgroup_add_device_ids(const char *type, struct util_list *list)
void udev_ccwgroup_add_device_ids(const char *type, struct util_list *list,
bool autoconf)
{
struct get_ids_cb_data cb_data;
char *path;
path = path_get_udev_rules();
path = path_get_udev_rules(autoconf);
cb_data.prefix = misc_asprintf("%s-%s-", UDEV_PREFIX, type);
cb_data.ids = list;
@@ -374,7 +378,8 @@ void udev_ccwgroup_add_device_ids(const char *type, struct util_list *list)
}
/* Remove UDEV rule for CCWGROUP device. */
exit_code_t udev_ccwgroup_remove_rule(const char *type, const char *id)
exit_code_t udev_ccwgroup_remove_rule(const char *type, const char *id,
bool autoconf)
{
char *partial_id, *path;
exit_code_t rc = EXIT_OK;
@@ -383,7 +388,7 @@ exit_code_t udev_ccwgroup_remove_rule(const char *type, const char *id)
if (!partial_id)
return EXIT_INVALID_ID;
path = path_get_udev_rule(type, partial_id);
path = path_get_udev_rule(type, partial_id, autoconf);
if (util_path_is_reg_file(path))
rc = remove_file(path);
free(path);

View File

@@ -369,14 +369,14 @@ static exit_code_t lun_cb(const char *path, const char *name, void *data)
/* Add the IDs for all zfcp lun devices for which a configuration exists to
* LIST. */
void udev_zfcp_lun_add_device_ids(struct util_list *list)
void udev_zfcp_lun_add_device_ids(struct util_list *list, bool autoconf)
{
struct lun_cb_data cb_data;
char *path;
cb_data.prefix = misc_asprintf("%s-%s-", UDEV_PREFIX, ZFCP_LUN_NAME);
cb_data.list = list;
path = path_get_udev_rules();
path = path_get_udev_rules(autoconf);
if (util_path_is_dir(path))
path_for_each(path, lun_cb, &cb_data);
@@ -387,7 +387,7 @@ void udev_zfcp_lun_add_device_ids(struct util_list *list)
/* Return path to zfcp lun udev rule file containing configuration data for
* all LUNs of a zfcp device. */
static char *get_zfcp_lun_path(const char *id)
static char *get_zfcp_lun_path(const char *id, bool autoconf)
{
char *copy, *e, *path;
@@ -395,7 +395,7 @@ static char *get_zfcp_lun_path(const char *id)
e = strchr(copy, ':');
if (e)
*e = 0;
path = path_get_udev_rule(ZFCP_LUN_NAME, copy);
path = path_get_udev_rule(ZFCP_LUN_NAME, copy, autoconf);
free(copy);
return path;
@@ -403,9 +403,9 @@ static char *get_zfcp_lun_path(const char *id)
/* Return path to zfcp lun udev rule file containing configuration data for
* a single LUN. */
static char *get_single_zfcp_lun_path(const char *id)
static char *get_single_zfcp_lun_path(const char *id, bool autoconf)
{
return path_get_udev_rule(ZFCP_LUN_NAME, id);
return path_get_udev_rule(ZFCP_LUN_NAME, id, autoconf);
}
/* Apply the settings found in NODE to STATE. */
@@ -437,20 +437,21 @@ static void zfcp_lun_node_to_state(struct zfcp_lun_node *node,
}
/* Read the persistent configuration of a zfcp lun from a udev rule. */
exit_code_t udev_zfcp_lun_read_device(struct device *dev)
exit_code_t udev_zfcp_lun_read_device(struct device *dev, bool autoconf)
{
struct subtype *st = dev->subtype;
struct device_state *state = &dev->persistent;
struct device_state *state = autoconf ? &dev->autoconf :
&dev->persistent;
struct util_list *luns;
struct zfcp_lun_node *node;
exit_code_t rc = EXIT_OK;
char *path;
/* Check for single lun file first then try multi lun file. */
path = get_single_zfcp_lun_path(dev->id);
path = get_single_zfcp_lun_path(dev->id, autoconf);
if (!util_path_exists(path)) {
free(path);
path = get_zfcp_lun_path(dev->id);
path = get_zfcp_lun_path(dev->id, autoconf);
}
/* Get previous rule data. */
@@ -616,7 +617,7 @@ out:
* applies the corresponding parameters. If @single is set, update a single
* lun rule file, otherwise update a multi lun rule file. */
static exit_code_t update_lun_rule(const char *id, struct device_state *state,
bool single)
bool single, bool autoconf)
{
struct zfcp_lun_devid devid;
struct util_list *luns;
@@ -628,7 +629,8 @@ static exit_code_t update_lun_rule(const char *id, struct device_state *state,
rc = zfcp_lun_parse_devid(&devid, id, err_delayed_print);
if (rc)
return rc;
path = single ? get_single_zfcp_lun_path(id) : get_zfcp_lun_path(id);
path = single ? get_single_zfcp_lun_path(id, autoconf) :
get_zfcp_lun_path(id, autoconf);
/* Get previous rule data. */
luns = zfcp_lun_node_list_new();
@@ -664,26 +666,28 @@ static exit_code_t update_lun_rule(const char *id, struct device_state *state,
/* Write a udev-rule to configure the specified zfcp lun and associated
* device state. */
exit_code_t udev_zfcp_lun_write_device(struct device *dev)
exit_code_t udev_zfcp_lun_write_device(struct device *dev, bool autoconf)
{
exit_code_t rc;
struct device_state *state = autoconf ? &dev->autoconf :
&dev->persistent;
rc = update_lun_rule(dev->id, &dev->persistent, true);
rc = update_lun_rule(dev->id, state, true, autoconf);
/* We only want single lun rule files so remove any remaining
* references in multi lun rule files. */
update_lun_rule(dev->id, NULL, false);
update_lun_rule(dev->id, NULL, false, autoconf);
return rc;
}
/* Remove the UDEV rule used to configure the zfcp lun with the specified ID. */
exit_code_t udev_zfcp_lun_remove_rule(const char *id)
exit_code_t udev_zfcp_lun_remove_rule(const char *id, bool autoconf)
{
exit_code_t rc, rc2;
rc = update_lun_rule(id, NULL, true);
rc2 = update_lun_rule(id, NULL, false);
rc = update_lun_rule(id, NULL, true, autoconf);
rc2 = update_lun_rule(id, NULL, false, autoconf);
if (rc)
return rc;
@@ -692,7 +696,7 @@ exit_code_t udev_zfcp_lun_remove_rule(const char *id)
}
/* Determine if a udev rule exists for configuring the specified zfcp lun. */
bool udev_zfcp_lun_exists(const char *id)
bool udev_zfcp_lun_exists(const char *id, bool autoconf)
{
struct zfcp_lun_devid devid;
char *path, *rule = NULL, *pattern = NULL;
@@ -702,7 +706,7 @@ bool udev_zfcp_lun_exists(const char *id)
return false;
/* Check for single lun rule file first. */
path = get_single_zfcp_lun_path(id);
path = get_single_zfcp_lun_path(id, autoconf);
if (util_path_exists(path)) {
rc = true;
goto out;
@@ -710,7 +714,7 @@ bool udev_zfcp_lun_exists(const char *id)
free(path);
/* Check multi lun rule file next. */
path = get_zfcp_lun_path(id);
path = get_zfcp_lun_path(id, autoconf);
rule = misc_read_text_file(path, 1, err_ignore);
if (!rule)
goto out;

View File

@@ -467,7 +467,14 @@ static exit_code_t zfcp_lun_st_read_persistent(struct subtype *st,
struct device *dev,
read_scope_t scope)
{
return udev_zfcp_lun_read_device(dev);
return udev_zfcp_lun_read_device(dev, false);
}
static exit_code_t zfcp_lun_st_read_autoconf(struct subtype *st,
struct device *dev,
read_scope_t scope)
{
return udev_zfcp_lun_read_device(dev, true);
}
static exit_code_t zfcp_lun_add(struct device *dev)
@@ -564,7 +571,13 @@ static exit_code_t zfcp_lun_st_configure_active(struct subtype *st,
static exit_code_t zfcp_lun_st_configure_persistent(struct subtype *st,
struct device *dev)
{
return udev_zfcp_lun_write_device(dev);
return udev_zfcp_lun_write_device(dev, false);
}
static exit_code_t zfcp_lun_st_configure_autoconf(struct subtype *st,
struct device *dev)
{
return udev_zfcp_lun_write_device(dev, true);
}
static exit_code_t zfcp_lun_st_deconfigure_active(struct subtype *st,
@@ -578,7 +591,13 @@ static exit_code_t zfcp_lun_st_deconfigure_active(struct subtype *st,
static exit_code_t zfcp_lun_st_deconfigure_persistent(struct subtype *st,
struct device *dev)
{
return udev_zfcp_lun_remove_rule(dev->id);
return udev_zfcp_lun_remove_rule(dev->id, false);
}
static exit_code_t zfcp_lun_st_deconfigure_autoconf(struct subtype *st,
struct device *dev)
{
return udev_zfcp_lun_remove_rule(dev->id, true);
}
static exit_code_t check_npiv(struct subtype *st, struct device *dev,
@@ -606,7 +625,8 @@ static exit_code_t check_npiv(struct subtype *st, struct device *dev,
if (!allow_lun_scan)
goto out;
if (!(dev->active.deconfigured || dev->persistent.deconfigured)) {
if (!(dev->active.deconfigured || dev->persistent.deconfigured ||
dev->autoconf.deconfigured)) {
delayed_info("Note: Auto LUN scan enabled - manual LUN "
"configuration is redundant for %s %s\n",
zfcp_host_subtype.devname, fcp_dev_id);
@@ -643,7 +663,8 @@ static exit_code_t zfcp_lun_st_check_post_configure(struct subtype *st,
/* Don't show note when an attribute was modified. */
if (setting_list_modified(dev->active.settings) ||
setting_list_modified(dev->persistent.settings))
setting_list_modified(dev->persistent.settings) ||
setting_list_modified(dev->autoconf.settings))
return EXIT_OK;
/* Check for NPIV but don't route exit code to caller - we only
@@ -795,7 +816,12 @@ static bool zfcp_lun_st_exists_active(struct subtype *st, const char *id)
static bool zfcp_lun_st_exists_persistent(struct subtype *st, const char *id)
{
return udev_zfcp_lun_exists(id);
return udev_zfcp_lun_exists(id, false);
}
static bool zfcp_lun_st_exists_autoconf(struct subtype *st, const char *id)
{
return udev_zfcp_lun_exists(id, true);
}
static exit_code_t zfcp_lun_st_is_definable(struct subtype *st, const char *id,
@@ -889,7 +915,13 @@ static void zfcp_lun_st_add_active_ids(struct subtype *st,
static void zfcp_lun_st_add_persistent_ids(struct subtype *st,
struct util_list *ids)
{
udev_zfcp_lun_add_device_ids(ids);
udev_zfcp_lun_add_device_ids(ids, false);
}
static void zfcp_lun_st_add_autoconf_ids(struct subtype *st,
struct util_list *ids)
{
udev_zfcp_lun_add_device_ids(ids, true);
}
static exit_code_t add_sg_cb(const char *path, const char *filename, void *data)
@@ -1072,18 +1104,23 @@ struct subtype zfcp_lun_subtype = {
.exists_active = &zfcp_lun_st_exists_active,
.exists_persistent = &zfcp_lun_st_exists_persistent,
.exists_autoconf = &zfcp_lun_st_exists_autoconf,
.add_active_ids = &zfcp_lun_st_add_active_ids,
.add_persistent_ids = &zfcp_lun_st_add_persistent_ids,
.add_autoconf_ids = &zfcp_lun_st_add_autoconf_ids,
.read_active = &zfcp_lun_st_read_active,
.read_persistent = &zfcp_lun_st_read_persistent,
.read_autoconf = &zfcp_lun_st_read_autoconf,
.configure_active = &zfcp_lun_st_configure_active,
.configure_persistent = &zfcp_lun_st_configure_persistent,
.configure_autoconf = &zfcp_lun_st_configure_autoconf,
.deconfigure_active = &zfcp_lun_st_deconfigure_active,
.deconfigure_persistent = &zfcp_lun_st_deconfigure_persistent,
.deconfigure_autoconf = &zfcp_lun_st_deconfigure_autoconf,
.check_pre_configure = &zfcp_lun_st_check_pre_configure,
.check_post_configure = &zfcp_lun_st_check_post_configure,