Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:15-SP4
s390-tools.15658
s390-tools-sles15sp1-09-zdev-Implement-internal...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File s390-tools-sles15sp1-09-zdev-Implement-internal-device-attributes.patch of Package s390-tools.15658
Subject: zdev: Implement internal device attributes From: Peter Oberparleiter <oberpar@linux.ibm.com> Summary: zdev: Add support for handling I/O configuration data Description: LPARs that are running in IBM Dynamic Partition Manager (DPM) mode can access a firmware-generated I/O configuration data file that contains s390-specific information about available I/O devices such as qeth device numbers and parameters, and FCP device IDs. This data file is intended to remove the need for users to manually enter the corresponding device data during installation. Linux kernels with the corresponding support make the I/O configuration data available at the following location: /sys/firmware/sclp_sd/config/data This patch set adds support for handling this data file using the chzdev and lszdev tools: - I/O configuration data can be applied using chzdev's --import option - Initial RAM-Disk scripts automatically apply the I/O configuration data to the system configuration - lszdev can be used to display the applied auto-configuration data - chzdev can be used to manually override the auto-configuration data Upstream-ID: c0392efa39e48cb12fdf3524b2f9e683e46f0f14 Problem-ID: LS1604 Upstream-Description: zdev: Implement internal device attributes This change adds base infrastructure for implementing internal device attributes. In the context of the zdev tools, an internal device attribute is a new type of device attribute with the following characteristics: - Can be set and removed like normal device attributes - Affects zdev-internal handling only - Does not correspond to an actual device attribute, that is it has no representation in SysFS - Can not be set in the active configuration - Name starts with "zdev:" to prevent conflicts with actual device attributes Values for internal device attributes are stored in udev rules alongside the normal persistent configuration of a device. They are encoded as udev environment variables. Note that they have no further effect on udev processing. Signed-off-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com> Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com> --- zdev/include/attrib.h | 2 zdev/include/internal.h | 20 +++++++++ zdev/include/misc.h | 1 zdev/include/udev.h | 7 +++ zdev/src/Makefile | 4 - zdev/src/device.c | 15 +++++++ zdev/src/internal.c | 25 ++++++++++++ zdev/src/misc.c | 15 +++++++ zdev/src/udev.c | 32 +++++++++++++++ zdev/src/udev_ccw.c | 16 +++++++ zdev/src/udev_ccwgroup.c | 11 +++++ zdev/src/udev_zfcp_lun.c | 80 ++++++++++++++++++++++++++++++++++++--- 12 files changed, 220 insertions(+), 8 deletions(-) --- a/zdev/include/attrib.h +++ b/zdev/include/attrib.h @@ -189,6 +189,7 @@ struct value_map { * in the persistent configuration * @nounload: (Device type attributes only) This attribute can be set while * the corresponding kernel module remains loaded. + * @internal: This attribute only affects internal handling * @order: A number indicating the order in which to apply attribute * @order_cmp: A function determining if a setting for this attribute should * be applied before (-1) or after (1) another setting, or @@ -216,6 +217,7 @@ struct attrib { unsigned int activerem :1; unsigned int defunset :1; unsigned int nounload :1; + unsigned int internal :1; /* Optional */ int order; --- /dev/null +++ b/zdev/include/internal.h @@ -0,0 +1,20 @@ +/* + * zdev - Modify and display the persistent configuration of devices + * + * Copyright IBM Corp. 2017 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef INTERNAL_H +#define INTERNAL_H + +#include <stdbool.h> + +#define INTERNAL_ATTR_PREFIX "zdev:" + +const char *internal_get_name(const char *name); +bool internal_by_name(const char *name); + +#endif /* INTERNAL_H */ --- a/zdev/include/misc.h +++ b/zdev/include/misc.h @@ -183,6 +183,7 @@ bool str_to_config(const char *, config_ char *quote_str(const char *, int); char *unquote_str(const char *); char *shrink_str(const char *); +char *misc_strrstr(const char *haystack, const char *needle); struct util_list *strlist_new(void); void strlist_free(struct util_list *); --- a/zdev/include/udev.h +++ b/zdev/include/udev.h @@ -13,6 +13,9 @@ #include "lib/util_list.h" #include "exit_code.h" +struct attrib; +struct setting_list; + extern int udev_need_settle; extern int udev_no_settle; @@ -46,4 +49,8 @@ exit_code_t udev_remove_rule(const char void udev_settle(void); +void udev_add_internal_from_entry(struct setting_list *list, + struct udev_entry_node *entry, + struct attrib **attribs); + #endif /* UDEV_H */ --- a/zdev/src/Makefile +++ b/zdev/src/Makefile @@ -8,7 +8,7 @@ ALL_CPPFLAGS += -I ../include -std=gnu99 chzdev_objects += attrib.o chzdev.o device.o devnode.o devtype.o exit_code.o \ export.o hash.o inuse.o misc.o namespace.o opts.o path.o \ root.o select.o setting.o subtype.o table.o table_attribs.o \ - table_types.o net.o firmware.o + table_types.o net.o firmware.o internal.o # Devtype Helpers chzdev_objects += blkinfo.o ccw.o ccwgroup.o findmnt.o modprobe.o module.o \ @@ -38,7 +38,7 @@ chzdev_objects += generic_ccw.o lszdev_objects += attrib.o lszdev.o device.o devnode.o devtype.o exit_code.o \ export.o hash.o inuse.o misc.o namespace.o opts.o path.o \ root.o select.o setting.o subtype.o table.o table_types.o \ - net.o + net.o internal.o # Devtype Helpers lszdev_objects += blkinfo.o ccw.o ccwgroup.o findmnt.o modprobe.o module.o \ --- a/zdev/src/device.c +++ b/zdev/src/device.c @@ -16,6 +16,7 @@ #include "attrib.h" #include "device.h" #include "devtype.h" +#include "internal.h" #include "misc.h" #include "namespace.h" #include "setting.h" @@ -221,6 +222,9 @@ static exit_code_t apply_setting(struct goto err_activeonly_forceable; if (!force && SCOPE_AUTOCONF(config) && a->activeonly) goto err_activeonly_forceable; + /* Check for internal. */ + if (config == config_active && a->internal) + goto err_int_noactive; /* Check for multiple values. */ if (!force && !a->multi && strlist_find(processed, key)) goto err_multi_forceable; @@ -230,6 +234,9 @@ static exit_code_t apply_setting(struct goto err_unknown; if (!force) goto err_unknown_forceable; + /* Check for internal. */ + if (config == config_active && internal_by_name(key)) + goto err_int_noactive; } strlist_add(processed, "%s", key); @@ -294,6 +301,11 @@ err_activeonly_forceable: delayed_forceable("Attribute '%s' should only be changed in the active " "config\n", a->name); return EXIT_INVALID_SETTING; + +err_int_noactive: + delayed_err("Internal attribute '%s' cannot be set in the active config\n", + key); + return EXIT_INVALID_SETTING; } /* Apply device settings from strlist to device. */ @@ -542,6 +554,9 @@ exit_code_t device_write_active_settings s = p->ptr; if (!s->modified || s->removed) continue; + if ((s->attrib && s->attrib->internal) || + internal_by_name(s->name)) + continue; path = subtype_get_active_attrib_path(st, dev, s->name); if (!path) { --- /dev/null +++ b/zdev/src/internal.c @@ -0,0 +1,25 @@ +/* + * zdev - Modify and display the persistent configuration of devices + * + * Copyright IBM Corp. 2017 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include <stdbool.h> + +#include "internal.h" +#include "misc.h" + +/* Return identifier of internal attribute with specified @name. */ +const char *internal_get_name(const char *name) +{ + return name + sizeof(INTERNAL_ATTR_PREFIX) - 1; +} + +/* Check if attribute is internal by name. */ +bool internal_by_name(const char *name) +{ + return starts_with(name, INTERNAL_ATTR_PREFIX); +} --- a/zdev/src/misc.c +++ b/zdev/src/misc.c @@ -1717,3 +1717,18 @@ void debug_init(int argc, char *argv[]) fprintf(stderr, "%s\"%s\"", i > 0 ? ", " : "", argv[i]); fprintf(stderr, "\n"); } + +/* Return the last occurrence of @needle in @haystack, or %NULL if @needle + * was not found. */ +char *misc_strrstr(const char *haystack, const char *needle) +{ + char *result, *next; + + result = strstr(haystack, needle); + if (result) { + while ((next = strstr(result + 1, needle))) + result = next; + } + + return result; +} --- a/zdev/src/udev.c +++ b/zdev/src/udev.c @@ -409,3 +409,35 @@ void udev_settle(void) return; misc_system(err_ignore, "%s settle", PATH_UDEVADM); } + +/* Extract internal attribute settings from @entry and add to @list. + * Associate corresponding attribute if found in @attribs. */ +void udev_add_internal_from_entry(struct setting_list *list, + struct udev_entry_node *entry, + struct attrib **attribs) +{ + char *copy, *name, *end, *u; + struct attrib *a; + + /* ENV{zdev_var}="1" */ + copy = misc_strdup(entry->key); + + /* Find attribute name start. */ + name = strchr(copy, '{'); + end = strrchr(copy, '}'); + if (!name || !end) + goto out; + *end = 0; + name++; + + /* zdev_ => zdev: */ + u = strchr(name, '_'); + if (u) + *u = ':'; + + a = attrib_find(attribs, name); + setting_list_apply_actual(list, a, name, entry->value); + +out: + free(copy); +} --- a/zdev/src/udev_ccw.c +++ b/zdev/src/udev_ccw.c @@ -18,6 +18,7 @@ #include "attrib.h" #include "ccw.h" #include "device.h" +#include "internal.h" #include "misc.h" #include "path.h" #include "setting.h" @@ -49,6 +50,12 @@ static void add_setting_from_entry(struc char *copy, *name, *end; struct attrib *a; + /* ENV{zdev_var}="1" */ + if (starts_with(entry->key, "ENV{zdev_") && + strcmp(entry->op, "=") == 0) { + udev_add_internal_from_entry(list, entry, attribs); + return; + } /* ATTR{[ccw/0.0.37bf]online}=1 */ if (strncmp(entry->key, "ATTR{[ccw/", 10) != 0 || strcmp(entry->op, "=") != 0) @@ -190,7 +197,14 @@ exit_code_t udev_ccw_write_device(struct s = p->ptr; if (s->removed) continue; - fprintf(fd, "ATTR{[ccw/%s]%s}=\"%s\"\n", id, s->name, s->value); + if ((s->attrib && s->attrib->internal) || + internal_by_name(s->name)) { + fprintf(fd, "ENV{zdev_%s}=\"%s\"\n", + internal_get_name(s->name), s->value); + } else { + fprintf(fd, "ATTR{[ccw/%s]%s}=\"%s\"\n", id, s->name, + s->value); + } } /* Write udev rule epilog. */ --- a/zdev/src/udev_ccwgroup.c +++ b/zdev/src/udev_ccwgroup.c @@ -18,6 +18,7 @@ #include "attrib.h" #include "ccwgroup.h" #include "device.h" +#include "internal.h" #include "misc.h" #include "path.h" #include "setting.h" @@ -68,6 +69,12 @@ static void add_setting_from_entry(struc char *copy, *name, *end; struct attrib *a; + /* ENV{zdev_var}="1" */ + if (starts_with(entry->key, "ENV{zdev_") && + strcmp(entry->op, "=") == 0) { + udev_add_internal_from_entry(list, entry, attribs); + return; + } /* ATTR{[ccwgroup/0.0.f5f0]online}=1 */ if (strncmp(entry->key, "ATTR{[ccwgroup/", 10) != 0 || strcmp(entry->op, "=") != 0) @@ -282,6 +289,10 @@ exit_code_t udev_ccwgroup_write_device(s fprintf(fd, "ATTR{[ccwgroup/%s]%s}=\"%s\"\n", ccw_id, s->name, str->str); } + } else if ((s->attrib && s->attrib->internal) || + internal_by_name(s->name)) { + fprintf(fd, "ENV{zdev_%s}=\"%s\"\n", + internal_get_name(s->name), s->value); } else { fprintf(fd, "ATTR{[ccwgroup/%s]%s}=\"%s\"\n", ccw_id, s->name, s->value); --- a/zdev/src/udev_zfcp_lun.c +++ b/zdev/src/udev_zfcp_lun.c @@ -18,6 +18,7 @@ #include "attrib.h" #include "device.h" +#include "internal.h" #include "misc.h" #include "path.h" #include "scsi.h" @@ -128,7 +129,7 @@ static bool zfcp_lun_devid_from_entry(st struct udev_entry_node *entry) { struct zfcp_lun_devid id; - char *copy = NULL, *s; + char *copy = NULL, *s, *e, *u; int i; bool rc = false; @@ -182,6 +183,28 @@ static bool zfcp_lun_devid_from_entry(st goto out; } + /*ENV{zdev_var__0_0_1941_0x500507630510c1ae_0x402340d400000000}="1"*/ + if (starts_with(entry->key, "ENV{zdev_")) { + copy = misc_strdup(entry->key); + + /* Find ID start (last __) and end (last }). */ + s = misc_strrstr(copy, "__"); + e = strrchr(copy, '}'); + if (!s || !e) + goto out; + *e = 0; + s += 2; + /* Convert variable name to ID format. */ + for (i = 0, u = s; (u = strchr(u, '_')); i++, u++) { + if (i < 2) + *u = '.'; + else + *u = ':'; + } + rc = zfcp_lun_parse_devid(&id, s, err_ignore) == EXIT_OK ? + true : false; + } + out: free(copy); if (rc) @@ -211,11 +234,46 @@ static struct zfcp_lun_node *zfcp_lun_no return node; } +static void add_internal_setting_from_entry(struct udev_entry_node *entry, + struct zfcp_lun_node *node) +{ + char *copy, *name, *end, *u; + struct attrib *a; + + /*ENV{zdev_var__0_0_1941_0x500507630510c1ae_0x402340d400000000}="1"*/ + copy = misc_strdup(entry->key); + + /* Find attribute name start and end. */ + name = strchr(copy, '{'); + end = misc_strrstr(copy, "__"); + if (!name || !end) + goto out; + *end = 0; + name++; + + /* zdev_ => zdev: */ + u = strchr(name, '_'); + if (u) + *u = ':'; + + a = attrib_find(zfcp_lun_subtype.dev_attribs, name); + setting_list_apply_actual(node->fc_settings, a, name, entry->value); + +out: + free(copy); +} + static void add_fc_setting_from_entry(struct udev_entry_node *entry, struct zfcp_lun_node *node) { char *copy, *s, *e; + /*ENV{zdev_var__0_0_1941_0x500507630510c1ae_0x402340d400000000}="1"*/ + if (starts_with(entry->key, "ENV{zdev_") && + strcmp(entry->op, "=") == 0) { + add_internal_setting_from_entry(entry, node); + return; + } /*ATTR{[ccw/0.0.1941]0x500507630510c1ae/0x402340d400000000/failed}="0"*/ if (!starts_with(entry->key, "ATTR{[ccw/")) return; @@ -490,7 +548,7 @@ static struct zfcp_lun_node *state_to_zf s->value); setting_list_add(node->scsi_settings, n); } else { - n = setting_new(NULL, s->name, s->value); + n = setting_new(s->attrib, s->name, s->value); setting_list_add(node->fc_settings, n); } } @@ -580,9 +638,21 @@ static exit_code_t write_luns_rule(const node->id.lun); util_list_iterate(&node->fc_settings->list, s) { - fprintf(fd, "ATTR{[ccw/%s]0x%016" PRIx64 "/0x%016" - PRIx64 "/%s}=\"%s\"\n", hba_id, node->id.wwpn, - node->id.lun, s->name, s->value); + if ((s->attrib && s->attrib->internal) || + internal_by_name(s->name)) { + fprintf(fd, "ENV{zdev_%s__%x_%x_%04x_0x%016" + PRIx64 "_0x%016" PRIx64 "}=\"%s\"\n", + internal_get_name(s->name), + node->id.fcp_dev.cssid, + node->id.fcp_dev.ssid, + node->id.fcp_dev.devno, node->id.wwpn, + node->id.lun, s->value); + } else { + fprintf(fd, "ATTR{[ccw/%s]0x%016" PRIx64 + "/0x%016" PRIx64 "/%s}=\"%s\"\n", + hba_id, node->id.wwpn, node->id.lun, + s->name, s->value); + } } last_node = node; }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor