zdev: provide site-specific information in lszdev

lszdev must be modified to share the site-specific configuration
information from the persistent settings. The persistent configuration
array will be read and tabularized based on the site-id input from the
user.

This patch also accommodates the site specific information in the
lszdev --info command. New information about the site-ids are integrated
with the command. For example,

DEVICE dasd-eckd 0.0.f001
  Names              : -
  Modules            : dasd_eckd_mod dasd_mod
  Online             : no
  Exists             : yes
  Persistent         : yes
  Sites              : 1,2

  ATTRIBUTE                     ACTIVE    PERSISTENT  SITE1  SITE2
  cmb_enable                    "0"       "0"         "1"    -
  eer_enabled                   "0"       -           -      -
  erplog                        "0"       -           -      -
  failfast                      "0"       -           -      -
  last_known_reservation_state  "none"    -           -      -
  online                        "0"       "1"         "1"    "1"
  raw_track_access              "0"       -           -      -
  readonly                      "0"       -           -      -
  reservation_policy            "ignore"  -           -      -
  use_diag                      "0"       -           -      -

Each available site specific configuration will be shown as column. The
"Sites" parameter in the above output indicates the available site
configurations and the SITE1 and SITE2 colums indicates the detailed
configuration for the respective sites.

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Vineeth Vijayan
2022-09-12 00:10:12 +02:00
committed by Jan Höppner
parent d66ace8121
commit 298ede17f5
3 changed files with 243 additions and 28 deletions

View File

@@ -116,5 +116,7 @@ struct setting_list *device_get_setting_list(struct device *dev,
int site_id);
config_t device_get_config(struct device *dev);
char *device_get_sites(struct device *dev);
bool is_dev_pers(struct device *dev);
#endif /* DEVICE_H */

View File

@@ -122,6 +122,24 @@ void device_print(struct device *dev, int level)
}
}
char *device_get_sites(struct device *dev)
{
struct util_list *names;
char *str;
int i;
names = strlist_new();
for (i = 0; i < NUM_USER_SITES; i++) {
if (dev->site_specific[i].exists)
strlist_add(names, "%d", i);
}
str = strlist_flatten(names, ",");
strlist_free(names);
return str;
}
static const void *device_hash_get_id(void *dev_ptr)
{
struct device *dev = dev_ptr;
@@ -688,3 +706,21 @@ config_t device_get_config(struct device *dev)
return config;
}
/* Determine if persistent configuration available for any of the sites*/
bool is_dev_pers(struct device *dev)
{
int i;
if (global_site_id != SITE_FALLBACK &&
!dev->site_specific[global_site_id].exists)
return false;
else if (dev->persistent.exists)
return true;
for (i = 0; i < NUM_SITES; i++)
if (dev->site_specific[i].exists)
return true;
return false;
}

View File

@@ -225,6 +225,41 @@ static action_t get_action(struct options *opts)
return ACT_LIST;
}
/* Determine the site information from the device */
static char *get_site_from_pers(struct device *dev)
{
int site, i, num = 0;
for (i = 0; i < NUM_SITES; i++) {
if (dev->site_specific[i].exists) {
site = i;
num++;
if (site == global_site_id && site != SITE_FALLBACK)
return misc_asprintf("s%d", site);
}
}
/* Incase of devices which do not have --site support, all the
* read configurations will be in the dev->persistent and not
* in dev->site_specific.
*/
if (num == 0 && dev->persistent.exists == 1 &&
global_site_id == SITE_FALLBACK)
return misc_asprintf("yes");
/* Found more site-specific information ? return s+ */
if (num > 1)
return misc_asprintf("s+");
if (num == 1)
if (site == SITE_FALLBACK)
return misc_asprintf("yes");
else
return misc_asprintf("s%d", site);
else
return misc_asprintf("no");
}
/* Check options data structure for syntax errors. */
static exit_code_t check_options(struct options *opts,
int specified[OPTS_MAX + 1], int op)
@@ -691,8 +726,8 @@ static exit_code_t parse_options(struct options *opts, int argc, char *argv[])
/* site information is a persistent configuration.
* set opts->persistent here.
*/
opts->site_id = atoi(optarg);
opts->persistent = 1;
opts->site_id = atoi(optarg);
break;
case ':':
@@ -817,34 +852,53 @@ static struct column *dev_table = COLUMN_ARRAY(
);
static char *merge_str(const char *act, const char *pers, const char *ac,
config_t config)
config_t config, char **site, int max_sites)
{
char *str;
size_t len;
int i;
struct util_list *str_list;
str_list = strlist_new();
act = act ? act : "-";
pers = pers ? pers : "-";
ac = ac ? ac : "-";
if (strcmp(act, pers) == 0 && strcmp(act, ac) == 0)
if (strcmp(act, pers) == 0 && strcmp(act, ac) == 0 &&
max_sites == 1)
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);
strlist_add(str_list, act);
if (SCOPE_PERSISTENT(config)) {
if (*str)
strcat(str, "/");
strcat(str, pers);
if (global_site_id == SITE_FALLBACK) {
strlist_add(str_list, pers);
} else {
strlist_add(str_list, site[global_site_id]);
goto out;
}
}
if (SCOPE_AUTOCONF(config)) {
if (*str)
strcat(str, "/");
strcat(str, ac);
strlist_add(str_list, ac);
}
/* Do not show site-specific information when user specifically
* asked for persistent configuration setting.
*/
if (SCOPE_PERSISTENT(config) && config != config_persistent) {
for (i = 0; i <= max_sites; i++) {
if (site[i])
strlist_add(str_list, site[i]);
else
if (str_list)
strlist_add(str_list, "-");
}
}
out:
str = strlist_flatten(str_list, "/");
strlist_free(str_list);
return str;
}
@@ -904,12 +958,27 @@ static char *get_attr(struct device *dev, const char *name, config_t config,
return misc_strdup(s->value);
}
/* When lszdev --info, make sure that the output contains only the
* valid site information. Check if the site is valid and then add
* the new SITEn column. For SITE_FALLBACK, the PERSISTENT column will
* be used.
*/
static bool is_site_show(int site_id, int current_site)
{
if (site_id == SITE_FALLBACK || site_id == current_site)
return true;
return false;
}
/* Return string for attribute with specified @name for device @dev. */
static char *dev_table_get_attr(struct device *dev, const char *attr,
config_t config)
{
char *act = NULL, *pers = NULL, *ac = NULL, *str;
const char *name;
char *site[NUM_USER_SITES];
int i;
static int max_sites;
name = strchr(attr, ':');
if (!name)
@@ -923,16 +992,27 @@ static char *dev_table_get_attr(struct device *dev, const char *attr,
*/
if (SCOPE_ACTIVE(config))
act = get_attr(dev, name, config_active, SITE_FALLBACK);
if (SCOPE_PERSISTENT(config))
if (SCOPE_PERSISTENT(config)) {
pers = get_attr(dev, name, config_persistent, SITE_FALLBACK);
for (i = 0; i < NUM_USER_SITES; i++)
site[i] = get_attr(dev, name, config, i);
}
if (SCOPE_AUTOCONF(config))
ac = get_attr(dev, name, config_autoconf, SITE_FALLBACK);
str = merge_str(act, pers, ac, config);
for (i = 0; i < NUM_USER_SITES; i++)
if (dev->site_specific[i].exists)
max_sites = (max_sites < i) ? i : max_sites;
str = merge_str(act, pers, ac, config, site, max_sites);
free(act);
free(pers);
free(ac);
if (SCOPE_PERSISTENT(config))
for (i = 0; i < NUM_USER_SITES; i++)
free(site[i]);
return str;
}
@@ -979,9 +1059,9 @@ 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)
if (!is_dev_pers(dev) && dev->autoconf.exists)
return misc_strdup("auto");
return misc_strdup(YESNO(dev->persistent.exists));
return get_site_from_pers(dev);
case dev_auto:
return misc_strdup(YESNO(dev->autoconf.exists));
case dev_online:
@@ -1073,11 +1153,17 @@ 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;
persistent = (int)is_dev_pers(dev);
autoconf = dev->autoconf.exists;
if (!active && !persistent && !autoconf)
continue;
/* with --site option, we consider only the persistent
* configurations available on the specified site-id.
* ignore active and autoconf here
*/
if (!persistent && global_site_id != SITE_FALLBACK)
continue;
ptrlist_add(devices, dev);
}
@@ -1148,6 +1234,16 @@ enum settings_table_id {
settings_active,
settings_persistent,
settings_autoconf,
settings_site0,
settings_site1,
settings_site2,
settings_site3,
settings_site4,
settings_site5,
settings_site6,
settings_site7,
settings_site8,
settings_site9,
};
static struct column *settings_table = COLUMN_ARRAY(
@@ -1155,17 +1251,29 @@ static struct column *settings_table = COLUMN_ARRAY(
COLUMN("READONLY", align_left, settings_readonly, 1, ""),
COLUMN("ACTIVE", align_left, settings_active, 1, ""),
COLUMN("PERSISTENT", align_left, settings_persistent, 1, ""),
COLUMN("AUTOCONF", align_left, settings_autoconf, 0, "")
COLUMN("AUTOCONF", align_left, settings_autoconf, 0, ""),
COLUMN("SITE0", align_left, settings_site0, 0, ""),
COLUMN("SITE1", align_left, settings_site1, 0, ""),
COLUMN("SITE2", align_left, settings_site2, 0, ""),
COLUMN("SITE3", align_left, settings_site3, 0, ""),
COLUMN("SITE4", align_left, settings_site4, 0, ""),
COLUMN("SITE5", align_left, settings_site5, 0, ""),
COLUMN("SITE6", align_left, settings_site6, 0, ""),
COLUMN("SITE7", align_left, settings_site7, 0, ""),
COLUMN("SITE8", align_left, settings_site8, 0, ""),
COLUMN("SITE9", align_left, settings_site9, 0, "")
);
static struct util_list *settings_table_build(struct setting_list *active,
struct setting_list *persistent,
struct setting_list *autoconf,
struct device *dev,
bool readonly)
{
struct util_list *names, *items;
struct setting *s;
struct strlist_node *str;
int i;
/* Get a list of all configured attributes. */
names = strlist_new();
@@ -1180,6 +1288,11 @@ static struct util_list *settings_table_build(struct setting_list *active,
if (persistent && !readonly) {
util_list_iterate(&persistent->list, s)
strlist_add(names, s->name);
if (dev) {
for (i = 0; i < NUM_SITES; i++)
util_list_iterate(&dev->site_specific[i].settings->list, s)
strlist_add(names, s->name);
}
}
if (autoconf && !readonly) {
util_list_iterate(&autoconf->list, s)
@@ -1200,6 +1313,7 @@ struct settings_table_data {
struct setting_list *active;
struct setting_list *persistent;
struct setting_list *autoconf;
struct setting_list *sites[NUM_SITES];
int pairs;
bool readonly;
};
@@ -1225,6 +1339,37 @@ static char *settings_table_get_value(void *item, int id, const char *heading,
case settings_autoconf:
list = stdata->autoconf;
break;
case settings_site0:
list = stdata->sites[0];
break;
case settings_site1:
list = stdata->sites[1];
break;
case settings_site2:
list = stdata->sites[2];
break;
case settings_site3:
list = stdata->sites[3];
break;
case settings_site4:
list = stdata->sites[4];
break;
case settings_site5:
list = stdata->sites[5];
break;
case settings_site6:
list = stdata->sites[6];
break;
case settings_site7:
list = stdata->sites[7];
break;
case settings_site8:
list = stdata->sites[8];
break;
case settings_site9:
list = stdata->sites[9];
break;
default:
break;
}
@@ -1249,16 +1394,18 @@ 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 device *dev,
struct options *opts, int ind, bool readonly,
bool neednl)
{
struct util_list *items;
struct settings_table_data data;
int i;
items = settings_table_build(
SCOPE_ACTIVE(opts->config) ? active : NULL,
SCOPE_PERSISTENT(opts->config) ? persistent : NULL,
autoconf, readonly);
autoconf, dev, readonly);
if (util_list_is_empty(items)) {
if (!opts->pairs && !readonly)
indent(ind, "%sNo settings found\n",
@@ -1273,14 +1420,28 @@ static void settings_table_print(struct setting_list *active,
table_set_default(settings_table, settings_active,
SCOPE_ACTIVE(opts->config));
table_set_default(settings_table, settings_persistent,
is_site_show(opts->site_id, SITE_FALLBACK) &&
SCOPE_PERSISTENT(opts->config) && !readonly ? 1 : 0);
table_set_default(settings_table, settings_autoconf,
(SCOPE_AUTOCONF(opts->config) || autoconf) &&
!readonly ? 1 : 0);
if (dev) {
for (i = 0; i < NUM_USER_SITES; i++)
table_set_default(settings_table, settings_site0 + i,
SCOPE_PERSISTENT(opts->config) &&
is_site_show(opts->site_id, i) &&
dev->site_specific[i].exists &&
!readonly ? 1 : 0);
for (i = 0; i < NUM_SITES; i++)
data.sites[i] = dev->site_specific[i].settings;
}
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);
@@ -1361,7 +1522,7 @@ static exit_code_t do_info_type(struct options *opts)
}
} else {
settings_table_print(dt->active_settings,
dt->persistent_settings, NULL, opts,
dt->persistent_settings, NULL, NULL, opts,
INFO_INDENT, false, false);
}
@@ -1387,7 +1548,7 @@ static void do_list_columns(struct options *opts)
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;
char *names, *bdevs, *cdevs, *ndevs, *modules, *online, *path, *key, *sites;
const char *id, *type, *exists, *persist, *ac, *prefix;
struct util_list *resources, *errors;
struct strlist_node *s;
@@ -1408,6 +1569,7 @@ static void do_info_one_device(struct device *dev, struct options *opts)
exists = YESNO(dev->active.exists || dev->active.definable);
persist = YESNO(dev->persistent.exists);
ac = YESNO(dev->autoconf.exists);
sites = device_get_sites(dev);
/* Print information. */
if (opts->pairs) {
@@ -1425,6 +1587,9 @@ 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 (*sites)
print_pair("SITES", sites);
if (SCOPE_AUTOCONF(opts->config) || dev->autoconf.exists)
print_pair("AUTOCONF", ac);
if (errors) {
@@ -1454,6 +1619,9 @@ static void do_info_one_device(struct device *dev, struct options *opts)
print_info("Persistent", persist);
if (SCOPE_AUTOCONF(opts->config) || dev->autoconf.exists)
print_info("Auto-configured", ac);
if (*sites)
print_info("Sites", sites);
if (errors) {
first = true;
util_list_iterate(errors, s) {
@@ -1494,17 +1662,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 :
is_dev_pers(dev) ? dev->persistent.settings :
NULL,
dev->autoconf.exists ? dev->autoconf.settings :
NULL,
NULL, dev,
opts, INFO_INDENT, false, !opts->pairs);
settings_table_print(dev->active.exists ? dev->active.settings : NULL,
dev->persistent.exists ? dev->persistent.settings :
is_dev_pers(dev) ? dev->persistent.settings :
NULL,
dev->autoconf.exists ? dev->autoconf.settings :
NULL,
NULL, dev,
opts, INFO_INDENT, true, !opts->pairs);
strlist_free(errors);
@@ -1515,6 +1683,7 @@ static void do_info_one_device(struct device *dev, struct options *opts)
free(cdevs);
free(bdevs);
free(names);
free(sites);
}
/* Perform --info on devices. */
@@ -1559,10 +1728,18 @@ 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;
persistent = (int)is_dev_pers(dev);
autoconf = dev->autoconf.exists;
if (!active && !persistent && !autoconf)
continue;
/* with --site option, we consider only the persistent
* configurations available on the specified site-id.
* ignore active and autoconf here
*/
if (!persistent && global_site_id != SITE_FALLBACK)
continue;
if (found > 0)
printf("\n");
do_info_one_device(dev, opts);