SHA256
1
0
forked from pool/s390-tools

Accepting request 655900 from home:markkp:branches:Base:System

- Added the following patches for Fate#326825 (bsc#1113329)
  I/O device pre-configuration
  * s390-tools-sles15sp1-01-zdev-use-libutil-provided-path-functions.patch
  * s390-tools-sles15sp1-02-zdev-Prepare-for-firmware-configuration-file-support.patch
  * s390-tools-sles15sp1-03-zdev-Add-support-for-reading-firmware-configuration-.patch
  * s390-tools-sles15sp1-04-zdev-Implement-no-settle.patch
  * s390-tools-sles15sp1-05-zdev-Write-zfcp-lun-udev-rules-to-separate-files.patch
  * s390-tools-sles15sp1-06-zdev-Add-support-for-handling-auto-configuration-dat.patch
  * s390-tools-sles15sp1-07-zdev-Integrate-firmware-auto-configuration-with-drac.patch
  * s390-tools-sles15sp1-08-zdev-Integrate-firmware-auto-configuration-with-init.patch
  * s390-tools-sles15sp1-09-zdev-Implement-internal-device-attributes.patch
  * s390-tools-sles15sp1-10-zdev-Implement-support-for-early-device-configuratio.patch
  * s390-tools-sles15sp1-11-zdev-Do-not-call-zipl-on-initrd-update.patch
- Removed the obsolete customize-zdev-root-update-script.patch
- Replaced s390-tools-sles15-zdev-fix-qeth-BridgePort-and-VNICC-conflict-checking.patch
  with s390-tools-sles15sp1-zdev-fix-qeth-BridgePort-and-VNICC-conflict-checking.patch
  to fit the current version.

OBS-URL: https://build.opensuse.org/request/show/655900
OBS-URL: https://build.opensuse.org/package/show/Base:System/s390-tools?expand=0&rev=61
This commit is contained in:
Mark Post 2018-12-06 21:23:28 +00:00 committed by Git OBS Bridge
parent 6f83d79828
commit 5500b3a5bc
14 changed files with 6893 additions and 49 deletions

View File

@ -0,0 +1,797 @@
Subject: zdev: use libutil provided path functions
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: d542138868153a36c3de6a21c3dea56125157e26
Problem-ID: LS1604
Upstream-Description:
zdev: use libutil provided path functions
Closes: #20
Signed-off-by: Rafael Fonseca <r4f4rfs@gmail.com>
Acked-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
---
zdev/include/misc.h | 4 --
zdev/src/ccw.c | 20 ++++--------
zdev/src/ccwgroup.c | 7 ++--
zdev/src/chzdev.c | 3 +
zdev/src/ctc_auto.c | 6 ++-
zdev/src/device.c | 5 ++-
zdev/src/devnode.c | 8 +++-
zdev/src/generic_ccw.c | 4 +-
zdev/src/lcs_auto.c | 6 ++-
zdev/src/misc.c | 63 ---------------------------------------
zdev/src/modprobe.c | 8 +++-
zdev/src/module.c | 8 +++-
zdev/src/qeth_auto.c | 4 +-
zdev/src/root.c | 4 +-
zdev/src/scsi.c | 4 +-
zdev/src/select.c | 4 +-
zdev/src/udev.c | 4 +-
zdev/src/udev_ccw.c | 10 +++---
zdev/src/udev_ccwgroup.c | 10 +++---
zdev/src/udev_zfcp_lun.c | 8 +++-
zdev/src/zfcp_lun.c | 16 +++++----
21 files changed, 84 insertions(+), 122 deletions(-)
--- a/zdev/include/misc.h
+++ b/zdev/include/misc.h
@@ -157,10 +157,6 @@ char *misc_asprintf(const char *, ...);
int misc_system(err_t, const char *, ...);
bool misc_read_dir(const char *, struct util_list *,
bool (*)(const char *, void *), void *);
-bool path_exists(const char *);
-bool file_exists(const char *);
-bool file_writable(const char *);
-bool dir_exists(const char *);
bool file_is_devnode(const char *);
exit_code_t remove_file(const char *);
char *misc_read_text_file(const char *, int, err_t);
--- a/zdev/src/ccw.c
+++ b/zdev/src/ccw.c
@@ -14,6 +14,7 @@
#include <string.h>
#include "lib/util_base.h"
+#include "lib/util_path.h"
#include "attrib.h"
#include "ccw.h"
@@ -1165,15 +1166,10 @@ out:
static void read_grouped(struct ccw_devinfo *info, const char *path)
{
- char *file_path;
-
- file_path = misc_asprintf("%s/group_device", path);
- if (path_exists(file_path))
+ if (util_path_exists("%s/group_device", path))
info->grouped = 1;
else
info->grouped = 0;
-
- free(file_path);
}
static void read_cutype(struct ccw_devinfo *info, const char *path)
@@ -1229,7 +1225,7 @@ static struct ccw_devinfo *ccw_devinfo_r
id = ccw_devid_to_str(devid);
path = path_get_ccw_device(NULL, id);
- if (!dir_exists(path))
+ if (!util_path_is_dir(path))
goto out;
info->exists = 1;
@@ -1354,7 +1350,7 @@ bool ccw_exists(const char *drv, const c
if (!path)
return false;
- rc = dir_exists(path);
+ rc = util_path_is_dir(path);
free(path);
return rc;
@@ -1428,7 +1424,7 @@ static exit_code_t ccw_st_read_active(st
state->definable = 0;
path = path_get_ccw_device(drv, id);
- if (path_exists(path)) {
+ if (util_path_exists(path)) {
state->exists = 1;
device_read_active_settings(dev, scope);
} else
@@ -1641,7 +1637,7 @@ static void ccw_st_add_errors(struct sub
if (!path)
return;
- if (!path_exists(path)) {
+ if (!util_path_exists(path)) {
strlist_add(errors, "CCW device %s does not exist", id);
goto out;
}
@@ -1662,9 +1658,7 @@ static void ccw_st_add_errors(struct sub
"paths", id);
goto out;
}
- free(apath);
- apath = misc_asprintf("%s/driver", path);
- if (!path_exists(apath)) {
+ if (!util_path_exists("%s/driver", path)) {
strlist_add(errors, "CCW device %s is not bound to a driver",
id);
goto out;
--- a/zdev/src/ccwgroup.c
+++ b/zdev/src/ccwgroup.c
@@ -12,6 +12,7 @@
#include <string.h>
#include "lib/util_base.h"
+#include "lib/util_path.h"
#include "attrib.h"
#include "ccw.h"
@@ -557,7 +558,7 @@ static bool read_full_id(struct ccwgroup
bool result = false;
path = path_get_ccwgroup_device(drv, id);
- if (!dir_exists(path))
+ if (!util_path_is_dir(path))
goto out;
memset(&devid, 0, sizeof(struct ccwgroup_devid));
@@ -625,7 +626,7 @@ static void ccwgroup_add_ids(const char
path = path_get_ccwgroup_devices(drv);
if (mod)
module_try_load_once(mod, path);
- if (dir_exists(path))
+ if (util_path_is_dir(path))
path_for_each(path, get_ids_cb, &cb_data);
free(path);
}
@@ -663,7 +664,7 @@ static exit_code_t ccwgroup_st_read_acti
state->definable = 0;
path = ccwgroup_get_dev_path_by_devid(drv, devid);
- if (path_exists(path)) {
+ if (util_path_exists(path)) {
state->exists = 1;
device_read_active_settings(dev, scope);
} else
--- a/zdev/src/chzdev.c
+++ b/zdev/src/chzdev.c
@@ -16,6 +16,7 @@
#include <string.h>
#include <unistd.h>
+#include "lib/util_path.h"
#include "lib/zt_common.h"
#include "attrib.h"
@@ -2502,7 +2503,7 @@ static exit_code_t do_export(struct opti
info("Exporting configuration data to standard output\n");
} else {
info("Exporting configuration data to %s\n", opts->export);
- if (!path_exists(opts->export)) {
+ if (!util_path_exists(opts->export)) {
rc = path_create(opts->export);
if (rc)
return rc;
--- a/zdev/src/ctc_auto.c
+++ b/zdev/src/ctc_auto.c
@@ -9,6 +9,8 @@
#include <string.h>
+#include "lib/util_path.h"
+
#include "ccw.h"
#include "ccwgroup.h"
#include "ctc.h"
@@ -125,13 +127,13 @@ static struct util_list *read_sorted_ctc
/* Add CCW devices bound to the CTC CCW device driver. */
module_try_load_once(CTC_MOD_NAME, NULL);
path = path_get_sys_bus_drv(CCW_BUS_NAME, CTC_CCWDRV_NAME);
- if (dir_exists(path))
+ if (util_path_is_dir(path))
path_for_each(path, add_cb, infos);
free(path);
/* Add CCW devices bound to the LCS CCW device driver. */
path = path_get_sys_bus_drv(CCW_BUS_NAME, LCS_CCWDRV_NAME);
- if (dir_exists(path))
+ if (util_path_is_dir(path))
path_for_each(path, add_cb, infos);
free(path);
--- a/zdev/src/device.c
+++ b/zdev/src/device.c
@@ -11,6 +11,8 @@
#include <stdlib.h>
#include <string.h>
+#include "lib/util_path.h"
+
#include "attrib.h"
#include "device.h"
#include "devtype.h"
@@ -480,7 +482,8 @@ void device_read_active_settings(struct
a = attrib_find(st->dev_attribs, name);
s = setting_list_apply_actual(dev->active.settings, a, name,
value);
- if (link || (scope == scope_all && !file_writable(path)))
+ if (link || (scope == scope_all &&
+ !util_path_is_writable(path)))
s->readonly = 1;
if (link)
free(link);
--- a/zdev/src/devnode.c
+++ b/zdev/src/devnode.c
@@ -15,6 +15,8 @@
#include <sys/sysmacros.h>
#include <unistd.h>
+#include "lib/util_path.h"
+
#include "devnode.h"
#include "misc.h"
#include "path.h"
@@ -230,7 +232,7 @@ static exit_code_t add_block_cb(const ch
/* Add additional nodes. */
cb_data->prefix = filename;
- if (dir_exists(path))
+ if (util_path_is_dir(path))
path_for_each(path, add_part_cb, cb_data);
return EXIT_OK;
@@ -249,7 +251,7 @@ int devnode_add_block_from_sysfs(struct
cb_data.prefix = NULL;
blkpath = misc_asprintf("%s/block", path);
- if (dir_exists(blkpath))
+ if (util_path_is_dir(blkpath))
path_for_each(blkpath, add_block_cb, &cb_data);
free(blkpath);
@@ -283,7 +285,7 @@ int devnode_add_net_from_sysfs(struct ut
cb_data.prefix = NULL;
netpath = misc_asprintf("%s/net", path);
- if (dir_exists(netpath))
+ if (util_path_is_dir(netpath))
path_for_each(netpath, add_net_cb, &cb_data);
free(netpath);
--- a/zdev/src/generic_ccw.c
+++ b/zdev/src/generic_ccw.c
@@ -9,6 +9,8 @@
#include <string.h>
+#include "lib/util_path.h"
+
#include "attrib.h"
#include "ccw.h"
#include "ccwgroup.h"
@@ -162,7 +164,7 @@ static void generic_ccw_st_add_devnodes(
cb_data.devnodes = devnodes;
cb_data.id = id;
path = path_get_sys_dev_char_devices();
- if (dir_exists(path))
+ if (util_path_is_dir(path))
path_for_each(path, add_cb, &cb_data);
free(path);
}
--- a/zdev/src/lcs_auto.c
+++ b/zdev/src/lcs_auto.c
@@ -9,6 +9,8 @@
#include <string.h>
+#include "lib/util_path.h"
+
#include "ccw.h"
#include "ccwgroup.h"
#include "ctc.h"
@@ -129,13 +131,13 @@ static struct util_list *read_sorted_lcs
/* Add CCW devices bound to the LCS CCW device driver. */
module_try_load_once(LCS_MOD_NAME, NULL);
path = path_get_sys_bus_drv(CCW_BUS_NAME, LCS_CCWDRV_NAME);
- if (dir_exists(path))
+ if (util_path_is_dir(path))
path_for_each(path, add_cb, infos);
free(path);
/* Add CCW devices bound to the CTC CCW device driver. */
path = path_get_sys_bus_drv(CCW_BUS_NAME, CTC_CCWDRV_NAME);
- if (dir_exists(path))
+ if (util_path_is_dir(path))
path_for_each(path, add_cb, infos);
free(path);
--- a/zdev/src/misc.c
+++ b/zdev/src/misc.c
@@ -889,69 +889,6 @@ void ptrlist_move(struct util_list *to,
util_list_add_tail(to, node);
}
-/* Check if a path exists. */
-bool path_exists(const char *path)
-{
- struct stat s;
-
- debug("Checking if file exists: %s\n", path);
- if (stat(path, &s) != 0)
- return false;
-
- return true;
-}
-
-/* Check if a file exists. */
-bool file_exists(const char *path)
-{
- struct stat s;
-
- debug("Checking if regular file exists: %s\n", path);
- if (stat(path, &s) != 0)
- return false;
-
- if (!S_ISREG(s.st_mode))
- return false;
-
- return true;
-}
-
-/* Check if a file is writable. */
-bool file_writable(const char *path)
-{
- struct stat s;
-
- debug("Checking if regular file is writable: %s\n", path);
- if (stat(path, &s) != 0)
- return false;
-
- if (!S_ISREG(s.st_mode))
- return false;
-
- if (!(s.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
- return false;
-
- return true;
-}
-
-/* Check if a directory exists. */
-bool dir_exists(const char *path)
-{
- bool result = false;
- struct stat s;
-
- debug("Checking if directory exists: %s\n", path);
- if (stat(path, &s) != 0)
- goto out;
- if (!S_ISDIR(s.st_mode))
- goto out;
- result = true;
-out:
- debug("Result: %d\n", result);
-
- return result;
-}
-
/* Check if file is a block or character special file. */
bool file_is_devnode(const char *path)
{
--- a/zdev/src/modprobe.c
+++ b/zdev/src/modprobe.c
@@ -14,6 +14,8 @@
#include <stdlib.h>
#include <string.h>
+#include "lib/util_path.h"
+
#include "attrib.h"
#include "misc.h"
#include "modprobe.h"
@@ -376,7 +378,7 @@ exit_code_t modprobe_read_settings(const
struct modprobe_file *mf;
exit_code_t rc;
- if (!file_exists(path)) {
+ if (!util_path_is_reg_file(path)) {
*settings = NULL;
return EXIT_OK;
}
@@ -398,7 +400,7 @@ exit_code_t modprobe_write_settings(cons
exit_code_t rc;
unsigned long lines;
- if (file_exists(path)) {
+ if (util_path_is_reg_file(path)) {
rc = modprobe_read(path, &mf);
if (rc)
return rc;
@@ -414,7 +416,7 @@ exit_code_t modprobe_write_settings(cons
lines = util_list_len(&mf->lines);
if (lines == 0 || (lines == 1 && find_chzdev_comment(mf))) {
/* Do not write empty files. */
- if (file_exists(path))
+ if (util_path_is_reg_file(path))
rc = remove_file(path);
} else
rc = modprobe_write(mf);
--- a/zdev/src/module.c
+++ b/zdev/src/module.c
@@ -12,6 +12,8 @@
#include <string.h>
#include <sys/types.h>
+#include "lib/util_path.h"
+
#include "attrib.h"
#include "misc.h"
#include "module.h"
@@ -34,7 +36,7 @@ bool module_loaded(const char *mod)
char *path = path_get_sys_module(mod);
bool rc;
- rc = dir_exists(path);
+ rc = util_path_is_dir(path);
free(path);
return rc;
@@ -229,7 +231,7 @@ void module_try_load_once(const char *mo
} else
tried_loading = strlist_new();
strlist_add(tried_loading, mod);
- if (path && path_exists(path))
+ if (path && util_path_exists(path))
return;
if (module_loaded(mod))
return;
@@ -275,7 +277,7 @@ bool module_set_params(const char *mod,
return false;
}
path = path_get_sys_module_param(mod, s->name);
- result = file_writable(path);
+ result = util_path_is_writable(path);
free(path);
if (!result) {
/* Sysfs file is not writable. */
--- a/zdev/src/qeth_auto.c
+++ b/zdev/src/qeth_auto.c
@@ -11,6 +11,8 @@
#include <stdlib.h>
#include <string.h>
+#include "lib/util_path.h"
+
#include "ccw.h"
#include "ccwgroup.h"
#include "device.h"
@@ -277,7 +279,7 @@ static struct util_list *read_sorted_qet
/* Get CHPID information for all devices bound to the QETH driver. */
infos = ptrlist_new();
path = path_get_sys_bus_drv(CCW_BUS_NAME, QETH_CCWDRV_NAME);
- if (dir_exists(path))
+ if (util_path_is_dir(path))
path_for_each(path, add_cb, infos);
free(path);
--- a/zdev/src/root.c
+++ b/zdev/src/root.c
@@ -9,6 +9,8 @@
#include <stdlib.h>
+#include "lib/util_path.h"
+
#include "device.h"
#include "devtype.h"
#include "misc.h"
@@ -74,7 +76,7 @@ exit_code_t root_check(void)
"required.\n");
/* Check if script is available. */
- if (!file_exists(PATH_ROOT_SCRIPT))
+ if (!util_path_is_reg_file(PATH_ROOT_SCRIPT))
goto out;
/* Ask for confirmation. */
--- a/zdev/src/scsi.c
+++ b/zdev/src/scsi.c
@@ -12,6 +12,8 @@
#include <stdlib.h>
#include <string.h>
+#include "lib/util_path.h"
+
#include "misc.h"
#include "path.h"
#include "scsi.h"
@@ -253,7 +255,7 @@ static struct util_list *read_scsi_zfcp_
list = ptrlist_new();
path = path_get_sys_bus_dev("scsi", NULL);
- if (dir_exists(path))
+ if (util_path_is_dir(path))
path_for_each(path, add_ids_cb, list);
free(path);
--- a/zdev/src/select.c
+++ b/zdev/src/select.c
@@ -10,6 +10,8 @@
#include <stdlib.h>
#include <string.h>
+#include "lib/util_path.h"
+
#include "blkinfo.h"
#include "ccw.h"
#include "device.h"
@@ -622,7 +624,7 @@ exit_code_t select_by_path(struct select
struct ptrlist_node *p;
exit_code_t rc;
- if (!path_exists(path)) {
+ if (!util_path_exists(path)) {
err_t_print(err, "Path not found: %s\n", path);
return EXIT_DEVICE_NOT_FOUND;
}
--- a/zdev/src/udev.c
+++ b/zdev/src/udev.c
@@ -13,6 +13,8 @@
#include <stdlib.h>
#include <string.h>
+#include "lib/util_path.h"
+
#include "attrib.h"
#include "ccw.h"
#include "device.h"
@@ -391,7 +393,7 @@ exit_code_t udev_remove_rule(const char
exit_code_t rc = EXIT_OK;
path = path_get_udev_rule(type, id);
- if (file_exists(path))
+ if (util_path_is_reg_file(path))
rc = remove_file(path);
free(path);
--- a/zdev/src/udev_ccw.c
+++ b/zdev/src/udev_ccw.c
@@ -13,6 +13,8 @@
#include <stdlib.h>
#include <string.h>
+#include "lib/util_path.h"
+
#include "attrib.h"
#include "ccw.h"
#include "device.h"
@@ -33,7 +35,7 @@ bool udev_ccw_exists(const char *type, c
return false;
path = path_get_udev_rule(type, normid);
- rc = file_exists(path);
+ rc = util_path_is_reg_file(path);
free(path);
free(normid);
@@ -150,7 +152,7 @@ exit_code_t udev_ccw_write_device(struct
path = path_get_udev_rule(type, id);
debug("Writing %s udev rule file %s\n", type, path);
- if (!path_exists(path)) {
+ if (!util_path_exists(path)) {
rc = path_create(path);
if (rc)
goto out;
@@ -243,7 +245,7 @@ exit_code_t udev_ccw_write_cio_ignore(co
if (!*id_list) {
/* Empty id_list string - remove file. */
- if (!file_exists(path)) {
+ if (!util_path_is_reg_file(path)) {
/* Already removed. */
goto out;
}
@@ -256,7 +258,7 @@ exit_code_t udev_ccw_write_cio_ignore(co
goto out;
debug("Writing cio-ignore udev rule file %s\n", path);
- if (!path_exists(path)) {
+ if (!util_path_exists(path)) {
rc = path_create(path);
if (rc)
goto out;
--- a/zdev/src/udev_ccwgroup.c
+++ b/zdev/src/udev_ccwgroup.c
@@ -13,6 +13,8 @@
#include <stdlib.h>
#include <string.h>
+#include "lib/util_path.h"
+
#include "attrib.h"
#include "ccwgroup.h"
#include "device.h"
@@ -53,7 +55,7 @@ bool udev_ccwgroup_exists(const char *ty
path = get_rule_path(type, id);
if (!path)
return false;
- rc = file_exists(path);
+ rc = util_path_is_reg_file(path);
free(path);
return rc;
@@ -215,7 +217,7 @@ exit_code_t udev_ccwgroup_write_device(s
list = setting_list_get_sorted(dev->persistent.settings);
debug("Writing %s udev rule file %s\n", type, path);
- if (!path_exists(path)) {
+ if (!util_path_exists(path)) {
rc = path_create(path);
if (rc)
goto out;
@@ -364,7 +366,7 @@ void udev_ccwgroup_add_device_ids(const
cb_data.prefix = misc_asprintf("%s-%s-", UDEV_PREFIX, type);
cb_data.ids = list;
- if (dir_exists(path))
+ if (util_path_is_dir(path))
path_for_each(path, get_ids_cb, &cb_data);
free(cb_data.prefix);
@@ -382,7 +384,7 @@ exit_code_t udev_ccwgroup_remove_rule(co
return EXIT_INVALID_ID;
path = path_get_udev_rule(type, partial_id);
- if (file_exists(path))
+ if (util_path_is_reg_file(path))
rc = remove_file(path);
free(path);
free(partial_id);
--- a/zdev/src/udev_zfcp_lun.c
+++ b/zdev/src/udev_zfcp_lun.c
@@ -14,6 +14,8 @@
#include <stdlib.h>
#include <string.h>
+#include "lib/util_path.h"
+
#include "attrib.h"
#include "device.h"
#include "misc.h"
@@ -376,7 +378,7 @@ void udev_zfcp_lun_add_device_ids(struct
cb_data.list = list;
path = path_get_udev_rules();
- if (dir_exists(path))
+ if (util_path_is_dir(path))
path_for_each(path, lun_cb, &cb_data);
free(path);
@@ -497,7 +499,7 @@ static exit_code_t write_luns_rule(const
return EXIT_INTERNAL_ERROR;
hba_id = ccw_devid_to_str(&node->id.fcp_dev);
debug("Writing FCP LUN udev rule file %s\n", path);
- if (!path_exists(path)) {
+ if (!util_path_exists(path)) {
rc = path_create(path);
if (rc)
goto out;
@@ -614,7 +616,7 @@ static exit_code_t update_lun_rule(const
/* Get previous rule data. */
luns = zfcp_lun_node_list_new();
- exists = file_exists(path);
+ exists = util_path_is_reg_file(path);
if (exists)
udev_read_zfcp_lun_rule(path, luns);
--- a/zdev/src/zfcp_lun.c
+++ b/zdev/src/zfcp_lun.c
@@ -13,6 +13,8 @@
#include <stdlib.h>
#include <string.h>
+#include "lib/util_path.h"
+
#include "attrib.h"
#include "ccw.h"
#include "device.h"
@@ -430,7 +432,7 @@ static exit_code_t zfcp_lun_st_read_acti
/* Check for FC unit. */
fc_path = path_get_zfcp_lun_dev(dev->devid);
- fc_exists = path_exists(fc_path);
+ fc_exists = util_path_exists(fc_path);
free(fc_path);
/* Check for SCSI device. */
@@ -478,7 +480,7 @@ static exit_code_t zfcp_lun_add(struct d
/* Check if LUN already exists. */
fcp_dev_id = ccw_devid_to_str(&devid->fcp_dev);
lunpath = path_get_zfcp_lun_dev(devid);
- if (dir_exists(lunpath)) {
+ if (util_path_is_dir(lunpath)) {
hctl = scsi_hctl_from_zfcp_lun_devid(devid);
if (!hctl)
goto check_failed;
@@ -486,7 +488,7 @@ static exit_code_t zfcp_lun_add(struct d
}
portpath = path_get_zfcp_port_dev(devid);
- if (!dir_exists(portpath)) {
+ if (!util_path_is_dir(portpath)) {
delayed_err("Target port not found\n");
rc = EXIT_ZFCP_WWPN_NOT_FOUND;
goto out;
@@ -681,14 +683,14 @@ static exit_code_t zfcp_lun_st_device_un
remove_lun:
path = path_get_zfcp_lun_dev(devid);
- if (!path_exists(path))
+ if (!util_path_exists(path))
goto out;
free(path);
path = NULL;
/* Remove FCP LUN. */
devpath = path_get_zfcp_port_dev(devid);
- if (!dir_exists(devpath)) {
+ if (!util_path_is_dir(devpath)) {
rc = EXIT_ZFCP_WWPN_NOT_FOUND;
goto out;
}
@@ -779,7 +781,7 @@ static bool zfcp_lun_fc_lun_exists(const
if (zfcp_lun_parse_devid(&devid, id, err_ignore) != EXIT_OK)
return false;
path = path_get_zfcp_lun_dev(&devid);
- result = path_exists(path);
+ result = util_path_exists(path);
free(path);
return result;
@@ -910,7 +912,7 @@ static void add_sg_from_sysfs(struct uti
char *sgpath;
sgpath = misc_asprintf("%s/scsi_generic", path);
- if (dir_exists(sgpath))
+ if (util_path_is_dir(sgpath))
path_for_each(sgpath, add_sg_cb, list);
free(sgpath);
}

View File

@ -0,0 +1,287 @@
Subject: zdev: Prepare for firmware configuration file support
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: ab4445c261749caa7aee2154e3b26c767b6c5e60
Problem-ID: LS1604
Upstream-Description:
zdev: Prepare for firmware configuration file support
Apply some changes to existing functions and data structures to simplify
the firmware configuration file support implementation.
- Make qeth and dasd subtype objects non-static
- Change the existing helper functions for reading file contents into
memory to also support binary functions
- Move some configuration file import functions to make them available
for use in other source files
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/dasd.h | 3 ++
zdev/include/device.h | 2 +
zdev/include/export.h | 1
zdev/include/misc.h | 1
zdev/include/qeth.h | 2 +
zdev/src/dasd.c | 4 +--
zdev/src/device.c | 13 +++++++++++
zdev/src/export.c | 17 +-------------
zdev/src/misc.c | 48 ++++++++++++++++++++++++++++++------------
zdev/src/qeth.c | 2 -
10 files changed, 62 insertions(+), 31 deletions(-)
--- a/zdev/include/dasd.h
+++ b/zdev/include/dasd.h
@@ -11,7 +11,10 @@
#define DASD_H
struct devtype;
+struct subtype;
extern struct devtype dasd_devtype;
+extern struct subtype dasd_subtype_eckd;
+extern struct subtype dasd_subtype_fba;
#endif /* DASD_H */
--- a/zdev/include/device.h
+++ b/zdev/include/device.h
@@ -94,5 +94,7 @@ void device_list_add(struct device_list
struct device *device_list_find(struct device_list *, const char *,
struct device *);
void device_list_print(struct device_list *, int);
+struct setting_list *device_get_setting_list(struct device *dev,
+ config_t config);
#endif /* DEVICE_H */
--- a/zdev/include/export.h
+++ b/zdev/include/export.h
@@ -31,6 +31,7 @@ struct export_object {
} ptr;
};
+struct export_object *object_new(export_t type, void *ptr);
exit_code_t export_write_device(FILE *, struct device *, config_t, int *);
exit_code_t export_write_devtype(FILE *, struct devtype *, config_t, int *);
exit_code_t export_read(FILE *, const char *, struct util_list *);
--- a/zdev/include/misc.h
+++ b/zdev/include/misc.h
@@ -159,6 +159,7 @@ bool misc_read_dir(const char *, struct
bool (*)(const char *, void *), void *);
bool file_is_devnode(const char *);
exit_code_t remove_file(const char *);
+exit_code_t misc_read_fd(FILE *fd, void **buffer, size_t *size_ptr);
char *misc_read_text_file(const char *, int, err_t);
char *misc_read_cmd_output(const char *, int, err_t);
char *config_read_cmd_output(const char *, int, err_t);
--- a/zdev/include/qeth.h
+++ b/zdev/include/qeth.h
@@ -17,9 +17,11 @@
#define QETH_NUM_DEVS 3
struct devtype;
+struct subtype;
struct namespace;
extern struct devtype qeth_devtype;
+extern struct subtype qeth_subtype_qeth;
extern struct namespace qeth_namespace;
#endif /* QETH_H */
--- a/zdev/src/dasd.c
+++ b/zdev/src/dasd.c
@@ -589,7 +589,7 @@ static struct ccw_subtype_data dasd_eckd
.mod = "dasd_eckd_mod",
};
-static struct subtype dasd_subtype_eckd = {
+struct subtype dasd_subtype_eckd = {
.super = &ccw_subtype,
.devtype = &dasd_devtype,
.name = "dasd-eckd",
@@ -626,7 +626,7 @@ static struct ccw_subtype_data dasd_fba_
.mod = "dasd_fba_mod",
};
-static struct subtype dasd_subtype_fba = {
+struct subtype dasd_subtype_fba = {
.super = &ccw_subtype,
.devtype = &dasd_devtype,
.name = "dasd-fba",
--- a/zdev/src/device.c
+++ b/zdev/src/device.c
@@ -570,3 +570,16 @@ exit_code_t device_check_settings(struct
return EXIT_OK;
}
+
+struct setting_list *device_get_setting_list(struct device *dev,
+ config_t config)
+{
+ struct setting_list *settings = NULL;
+
+ if (config == config_active)
+ settings = dev->active.settings;
+ else
+ settings = dev->persistent.settings;
+
+ return settings;
+}
--- a/zdev/src/export.c
+++ b/zdev/src/export.c
@@ -282,19 +282,6 @@ static bool parse_setting(const char *li
return true;
}
-static struct setting_list *dev_get_setting_list(struct device *dev,
- config_t config)
-{
- struct setting_list *settings = NULL;
-
- if (config == config_active)
- settings = dev->active.settings;
- else
- settings = dev->persistent.settings;
-
- return settings;
-}
-
static struct setting_list *dt_get_setting_list(struct devtype *dt,
config_t config)
{
@@ -426,7 +413,7 @@ static exit_code_t handle_setting(const
} else if (dev) {
/* We're inside a device section. */
attribs = dev->subtype->dev_attribs;
- list = dev_get_setting_list(dev, config);
+ list = device_get_setting_list(dev, config);
} else
return EXIT_OK;
@@ -444,7 +431,7 @@ static exit_code_t handle_setting(const
return EXIT_OK;
}
-static struct export_object *object_new(export_t type, void *ptr)
+struct export_object *object_new(export_t type, void *ptr)
{
struct export_object *obj;
--- a/zdev/src/misc.c
+++ b/zdev/src/misc.c
@@ -98,26 +98,47 @@ static void dryrun_end_data(void)
#define READ_CHUNK_SIZE 4096
-/* Read text from @fd and return resulting NULL-terminated text buffer.
- * If @chomp is non-zero, remove trailing newline character. Return %NULL
- * on error or when unprintable characters are read. */
-static char *read_fd(FILE *fd, int chomp)
+/* Read all data from @fd and return address of resulting buffer in
+ * @buffer_ptr. If @size_ptr is non-zero, use it to store the size of the
+ * resulting buffer. Return %EXIT_OK on success. */
+exit_code_t misc_read_fd(FILE *fd, void **buffer_ptr, size_t *size_ptr)
{
char *buffer = NULL;
- size_t done, i;
+ size_t done = 0;
- done = 0;
while (!feof(fd)) {
- buffer = realloc(buffer, done + READ_CHUNK_SIZE + 1);
+ buffer = realloc(buffer, done + READ_CHUNK_SIZE);
if (!buffer)
oom();
done += fread(&buffer[done], 1, READ_CHUNK_SIZE, fd);
if (ferror(fd)) {
free(buffer);
- return NULL;
+ return EXIT_RUNTIME_ERROR;
}
}
+ buffer = realloc(buffer, done);
+ if (!buffer && done > 0)
+ oom();
+
+ *buffer_ptr = buffer;
+ if (size_ptr)
+ *size_ptr = done;
+
+ return EXIT_OK;
+}
+
+/* Read text from @fd and return resulting NULL-terminated text buffer.
+ * If @chomp is non-zero, remove trailing newline character. Return %NULL
+ * on error or when unprintable characters are read. */
+static char *read_fd(FILE *fd, int chomp)
+{
+ char *buffer;
+ size_t done, i;
+
+ if (misc_read_fd(fd, (void **) &buffer, &done))
+ return NULL;
+
/* Check if this is a text file at all (required to filter out
* binary sysfs attributes). */
for (i = 0; i < done; i++) {
@@ -131,12 +152,13 @@ static char *read_fd(FILE *fd, int chomp
if (chomp && done > 0 && buffer[done - 1] == '\n')
done--;
- if (buffer) {
- /* NULL-terminate. */
- buffer[done++] = 0;
- }
+ /* NULL-terminate. */
+ buffer = realloc(buffer, done + 1);
+ if (!buffer)
+ oom();
+ buffer[done] = 0;
- return realloc(buffer, done);
+ return buffer;
}
static int count_newline(const char *str)
--- a/zdev/src/qeth.c
+++ b/zdev/src/qeth.c
@@ -1369,7 +1369,7 @@ static struct ccwgroup_subtype_data qeth
.num_devs = QETH_NUM_DEVS,
};
-static struct subtype qeth_subtype_qeth = {
+struct subtype qeth_subtype_qeth = {
.super = &ccwgroup_subtype,
.devtype = &qeth_devtype,
.name = "qeth",

View File

@ -0,0 +1,874 @@
Subject: zdev: Add support for reading firmware configuration files
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: 7d355b0fec964ad84ecaf88eb946121d39486070
Problem-ID: LS1604
Upstream-Description:
zdev: Add support for reading firmware configuration files
Add support for reading firmware-provided I/O configuration data files.
Such configuration files are generated by the Dynamic Partition Manager
and made available via a kernel interface for consumption by Linux.
To read a firmware configuration file, use the existing --import option:
# chzdev --import /sys/firmware/sclp_sd/config/data
This will apply all I/O configuration data found in the specified file
to the persistent configuration.
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/firmware.h | 25 +
zdev/man/chzdev.8 | 16
zdev/src/Makefile | 2
zdev/src/chzdev.c | 21 -
zdev/src/firmware.c | 676 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 730 insertions(+), 10 deletions(-)
--- /dev/null
+++ b/zdev/include/firmware.h
@@ -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.
+ */
+
+#ifndef FIRMWARE_H
+#define FIRMWARE_H
+
+#include <stdio.h>
+#include <stdbool.h>
+
+#include "exit_code.h"
+#include "misc.h"
+
+struct util_list;
+
+bool firmware_detect(FILE *fd);
+exit_code_t firmware_read(FILE *fd, const char *filename, long skip,
+ config_t config, struct util_list *objects);
+
+#endif /* FIRMWARE_H */
--- a/zdev/man/chzdev.8
+++ b/zdev/man/chzdev.8
@@ -409,13 +409,23 @@ default value.
.PP
.
.OD import "" "FILENAME" "|-"
-Import configuration data from a text file.
+Import configuration data from a text or machine-provided file.
Reads configuration data from FILENAME and applies it. If a single hyphen ("-")
is specified as FILENAME data is read from the standard input stream. The
-input format of the data read must be the same format as produced by the
-chzdev \-\-export action.
+input format must be either in the format as produced by the chzdev \-\-export
+action, or in the format of a machine-provided I/O configuration data file.
+.B Machine-provided data:
+Some machine models provide I/O configuration data which is made available
+by the Linux kernel via a sysfs interface. While this data is intended for
+automatic consumption during the boot phase, you can also apply it manually
+using the \-\-import action like in the following example
+
+.B Example:
+.CL chzdev --import /sys/firmware/sclp_sd/config/data
+
+.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
--- 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
+ table_types.o net.o firmware.o
# Devtype Helpers
chzdev_objects += blkinfo.o ccw.o ccwgroup.o findmnt.o modprobe.o module.o \
--- a/zdev/src/chzdev.c
+++ b/zdev/src/chzdev.c
@@ -27,6 +27,7 @@
#include "devnode.h"
#include "devtype.h"
#include "export.h"
+#include "firmware.h"
#include "inuse.h"
#include "misc.h"
#include "module.h"
@@ -2500,9 +2501,9 @@ static exit_code_t do_export(struct opti
/* Open output stream. */
if (strcmp(opts->export, "-") == 0) {
fd = stdout;
- info("Exporting configuration data to standard output\n");
+ info("Exporting data to standard output\n");
} else {
- info("Exporting configuration data to %s\n", opts->export);
+ info("Exporting data to %s\n", opts->export);
if (!util_path_exists(opts->export)) {
rc = path_create(opts->export);
if (rc)
@@ -2735,6 +2736,7 @@ static exit_code_t do_import(struct opti
exit_code_t drc = EXIT_OK;
const char *filename;
int found;
+ bool is_firmware;
/* Open input stream. */
if (strcmp(opts->import, "-") == 0) {
@@ -2744,16 +2746,23 @@ static exit_code_t do_import(struct opti
fd = fopen(opts->import, "r");
filename = opts->import;
}
- info("Importing configuration data from %s\n", filename);
+
if (!fd) {
error("Could not open file %s: %s\n", opts->import,
strerror(errno));
return EXIT_RUNTIME_ERROR;
}
+ is_firmware = firmware_detect(fd);
+ info("Importing data from %s%s\n", filename,
+ is_firmware ? " (firmware format)" : "");
+
/* Read data. */
objects = ptrlist_new();
- rc = export_read(fd, filename, objects);
+ if (is_firmware)
+ rc = firmware_read(fd, filename, -1, opts->config, objects);
+ else
+ rc = export_read(fd, filename, objects);
if (rc)
goto out;
@@ -2766,8 +2775,8 @@ static exit_code_t do_import(struct opti
"selection\n", filename);
rc = EXIT_EMPTY_SELECTION;
} else {
- error("%s: No settings found to import\n", filename);
- rc = EXIT_NO_DATA;
+ info("%s: No settings found to import\n", filename);
+ rc = EXIT_OK;
}
goto out;
}
--- /dev/null
+++ b/zdev/src/firmware.c
@@ -0,0 +1,676 @@
+/*
+ * 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 <err.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "attrib.h"
+#include "ccw.h"
+#include "ccwgroup.h"
+#include "dasd.h"
+#include "device.h"
+#include "export.h"
+#include "firmware.h"
+#include "misc.h"
+#include "qeth.h"
+#include "subtype.h"
+#include "zfcp_host.h"
+#include "zfcp_lun.h"
+
+/* In-memory firmware file representation. */
+struct fw_file {
+ const char *name;
+ char *buffer;
+ size_t size;
+ char *last_access;
+ size_t last_size;
+};
+
+/* Record access to fields of the buffered file for use in warning messages. */
+#define fwacc(f, x) ((f)->last_access = (char *) &(x), \
+ (f)->last_size = sizeof(x), x)
+
+/*
+ * Firmware file format definitions.
+ */
+
+/* Firmware file header. */
+struct fw_filehdr {
+ uint32_t magic;
+ uint16_t ver;
+ uint16_t hdr_len;
+ uint32_t file_len;
+ uint32_t seq;
+ uint32_t zeroes;
+ uint16_t de_count;
+ char unused[10];
+} __packed;
+
+#define FW_HDR_MAGIC 0x7a646576 /* ASCII "zdev" */
+#define FW_HDR_VER_Z14 0x0000
+
+/* I/O device ID. */
+struct fw_iodevid {
+ uint8_t cssid;
+ uint8_t ssid;
+ uint16_t devno;
+} __packed;
+
+#define FW_IODEVID_FLAG_MCSS 0x01
+
+/* Device setting. */
+struct fw_setting {
+ uint16_t len;
+ uint8_t key_type;
+ uint8_t key_len;
+ uint8_t val_type;
+ uint8_t val_len;
+ char data[];
+} __packed;
+
+#define FW_SETTING_KEYTYPE_ASCII 0x00
+#define FW_SETTING_VALTYPE_ASCII 0x00
+#define FW_SETTING_VALTYPE_UINT 0x01
+
+/* Device settings list. */
+struct fw_setlist {
+ uint16_t len;
+ char data[];
+} __packed;
+
+/* Device entry header. */
+struct fw_dehdr {
+ uint16_t type;
+ uint16_t len;
+ uint32_t seq;
+} __packed;
+
+#define FW_DE_HDR_TYPE_DASD 0x0001
+#define FW_DE_HDR_TYPE_ZFCP_HOST 0x0002
+#define FW_DE_HDR_TYPE_ZFCP_LUN 0x0003
+#define FW_DE_HDR_TYPE_QETH 0x0004
+
+/* DASD device entry. */
+struct fw_dasd {
+ struct fw_dehdr hdr;
+ uint8_t id_flags;
+ struct fw_iodevid id;
+ char settings[];
+} __packed;
+
+/* zFCP host device entry. */
+struct fw_zfcp_host {
+ struct fw_dehdr hdr;
+ uint8_t id_flags;
+ struct fw_iodevid id;
+ char settings[];
+} __packed;
+
+/* zFCP LUN device entry. */
+struct fw_zfcp_lun {
+ struct fw_dehdr hdr;
+ uint8_t id_flags;
+ struct fw_iodevid id;
+ uint64_t wwpn;
+ uint64_t fcp_lun;
+ char settings[];
+} __packed;
+
+/* QETH device entry. */
+struct fw_qeth {
+ struct fw_dehdr hdr;
+ uint8_t id_flags;
+ struct fw_iodevid read_id;
+ struct fw_iodevid write_id;
+ struct fw_iodevid data_id;
+ char settings[];
+} __packed;
+
+/* Emit a warning that refers to a position in a firmware file. */
+static void fwwarn(struct fw_file *f, const char *fmt, ...)
+{
+ va_list args;
+ off_t start = (off_t) (f->last_access - f->buffer),
+ end = start + f->last_size - 1;
+
+ fprintf(stderr, "%s: ", f->name);
+ if (start == end)
+ fprintf(stderr, "Byte 0x%zx: ", start);
+ else
+ fprintf(stderr, "Bytes 0x%zx-0x%zx: ", start, end);
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+}
+
+/* Basic file format header sanity check. */
+static bool check_header(struct fw_file *f, struct fw_filehdr *hdr)
+{
+ if (fwacc(f, hdr->magic) != FW_HDR_MAGIC)
+ fwwarn(f, "Invalid file magic (0x%08x)", hdr->magic);
+ else if (fwacc(f, hdr->ver) != FW_HDR_VER_Z14)
+ fwwarn(f, "Unsupported file version (0x%04x)", hdr->ver);
+ else
+ return true;
+
+ return false;
+}
+
+#define READ_RETRY 3
+
+/* Read a firmware configuration file. */
+static exit_code_t read_fw(struct fw_file *file, FILE *fd, const char *filename)
+{
+ struct fw_file f = { NULL };
+ struct fw_filehdr *hdr;
+ char *buffer, *buffer2;
+ size_t size, size2;
+ int retry;
+ exit_code_t rc = EXIT_OK;
+
+ for (retry = 0; retry < READ_RETRY; retry++) {
+ /* Read complete file once */
+ rc = misc_read_fd(fd, (void **) &buffer, &size);
+ if (rc) {
+ warn("%s: Could not read file", filename);
+ return rc;
+ }
+ if (!buffer) {
+ /* Empty file - skip silently as this is the default
+ * on machines without firmware support. */
+ return rc;
+ }
+
+ /* Re-read complete file to detect in-flight modifications. */
+ if (fseek(fd, 0, SEEK_SET) == -1) {
+ /* Could be a pipe, socket, or FIFO - accept v1. */
+ break;
+ }
+ rc = misc_read_fd(fd, (void **) &buffer2, &size2);
+ if (rc || !buffer2) {
+ /* Could not get second version - accept v1. */
+ break;
+ }
+
+ if (size == size2 && memcmp(buffer, buffer2, size) == 0) {
+ /* No change */
+ free(buffer2);
+ break;
+ }
+
+ free(buffer);
+ free(buffer2);
+ }
+
+ if (retry >= READ_RETRY) {
+ warnx("%s: File changed %d times while reading - aborting",
+ filename, retry);
+ return EXIT_RUNTIME_ERROR;
+ }
+
+ /* Perform basic checks */
+ f.name = filename;
+ f.buffer = buffer;
+ f.size = size;
+ hdr = (void *) buffer;
+ if (!check_header(&f, hdr)) {
+ free(buffer);
+ return EXIT_FORMAT_ERROR;
+ }
+ if (fwacc(&f, hdr->file_len) > size) {
+ fwwarn(&f, "File length mismatch (expect %zu) - adjusting",
+ size);
+ hdr->file_len = size;
+ }
+
+ *file = f;
+
+ return EXIT_OK;
+}
+
+/* Return textual representation of a device entry type. */
+static const char *type_to_str(uint16_t type)
+{
+ switch (type) {
+ case FW_DE_HDR_TYPE_DASD:
+ return "dasd";
+ case FW_DE_HDR_TYPE_ZFCP_HOST:
+ return "zfcp-host";
+ case FW_DE_HDR_TYPE_ZFCP_LUN:
+ return "zfcp-lun";
+ case FW_DE_HDR_TYPE_QETH:
+ return "qeth";
+ default:
+ return "<unknown>";
+ }
+}
+
+/* Convert a binary format device setting of the specified length to integer. */
+static unsigned long parse_value(char *data, uint8_t len)
+{
+ switch (len) {
+ case 1:
+ return (unsigned long) *((uint8_t *) data);
+ case 2:
+ return (unsigned long) *((uint16_t *) data);
+ case 4:
+ return (unsigned long) *((uint32_t *) data);
+ case 8:
+ return (unsigned long) *((uint64_t *) data);
+ default:
+ return 0;
+ }
+}
+
+/* Perform sanity checks on device setting. */
+static bool check_setting(struct fw_file *f, struct fw_setting *set)
+{
+ /* Key sanity checks */
+ if (fwacc(f, set->key_type) != FW_SETTING_KEYTYPE_ASCII) {
+ fwwarn(f, "Unsupported key type: %d", set->key_type);
+ return false;
+ }
+ if (fwacc(f, set->key_len) < 1) {
+ fwwarn(f, "Unsupported key length: %d", set->key_len);
+ return false;
+ }
+ if (sizeof(struct fw_setting) + fwacc(f, set->key_len) > set->len) {
+ fwwarn(f, "Key length exceeds setting");
+ return false;
+ }
+ if (fwacc(f, set->data[set->key_len - 1])) {
+ fwwarn(f, "Key not null-terminated");
+ return false;
+ }
+
+ /* Value sanity checks */
+ if (fwacc(f, set->val_type) != FW_SETTING_VALTYPE_UINT &&
+ fwacc(f, set->val_type) != FW_SETTING_VALTYPE_ASCII) {
+ fwwarn(f, "Unsupported value type: %d", set->val_type);
+ return false;
+ }
+ if (fwacc(f, set->val_len) < 1) {
+ fwwarn(f, "Unsupported value length: %d", set->val_len);
+ return false;
+ }
+ if (sizeof(struct fw_setting) + set->key_len +
+ fwacc(f, set->val_len) > set->len) {
+ fwwarn(f, "Value length exceeds setting");
+ return false;
+ }
+ if ((set->val_type == FW_SETTING_VALTYPE_ASCII) &&
+ fwacc(f, set->data[set->key_len + set->val_len - 1])) {
+ fwwarn(f, "Value not null-terminated");
+ return false;
+ }
+ if (set->val_type == FW_SETTING_VALTYPE_UINT) {
+ switch (fwacc(f, set->val_len)) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ break;
+ default:
+ fwwarn(f, "Unsupported integer value length: %d",
+ set->val_len);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Add a setting to the device. Emit a warning if the setting is not known. */
+static void _add_setting(const char *filename, struct device *dev,
+ config_t config, const char *key, const char *value)
+{
+ struct attrib *a;
+ struct setting_list *list;
+
+ list = device_get_setting_list(dev, config);
+ a = attrib_find(dev->subtype->dev_attribs, key);
+ if (!a) {
+ warnx("%s: Applying unknown device setting %s=%s", filename,
+ key, value);
+ }
+ setting_list_apply(list, a, key, value);
+}
+
+static void add_setting(const char *filename, struct device *dev,
+ config_t config, const char *key, const char *value)
+{
+ if (SCOPE_ACTIVE(config))
+ _add_setting(filename, dev, config_active, key, value);
+ if (SCOPE_PERSISTENT(config))
+ _add_setting(filename, dev, config_persistent, key, value);
+}
+
+/* Parse a single device setting in firmware format and apply it to the
+ * specified device. */
+static void parse_setting(struct fw_file *f, struct fw_setting *set,
+ struct device *dev, config_t config)
+{
+ char *ascii_key, *ascii_val;
+ unsigned long ulong_val;
+
+ if (!check_setting(f, set))
+ return;
+
+ ascii_key = &set->data[0];
+ if (set->val_type == FW_SETTING_VALTYPE_UINT) {
+ ulong_val = parse_value(&set->data[set->key_len], set->val_len);
+ ascii_val = misc_asprintf("%lu", ulong_val);
+ add_setting(f->name, dev, config, ascii_key, ascii_val);
+ free(ascii_val);
+ } else {
+ ascii_val = &set->data[set->key_len];
+ add_setting(f->name, dev, config, ascii_key, ascii_val);
+ }
+}
+
+/* Parse a device settings list in firmware format and apply the resulting
+ * settings to the specified device. */
+static void parse_settings(struct fw_file *f, char *data, struct device *dev,
+ config_t config)
+{
+ struct fw_setlist *list = (struct fw_setlist *) data;
+ struct fw_setting *set;
+ uint16_t off;
+
+ for (off = sizeof(struct fw_setlist); off < list->len;
+ off += set->len) {
+ set = (struct fw_setting *) &data[off];
+ if (fwacc(f, set->len) < sizeof(struct fw_setting)) {
+ fwwarn(f, "Setting too short");
+ break;
+ }
+ if (off + fwacc(f, set->len) > list->len) {
+ fwwarn(f, "Setting too long");
+ break;
+ }
+ parse_setting(f, set, dev, config);
+ }
+}
+
+/* Perform sanity checks on an I/O device ID. */
+static bool check_iodevid(struct fw_file *f, uint8_t *flags,
+ struct fw_iodevid *id)
+{
+
+ if (fwacc(f, *flags) & FW_IODEVID_FLAG_MCSS) {
+ fwwarn(f, "Unsupported entry in non-default CSS");
+ return false;
+ }
+ if (fwacc(f, id->cssid) != 0) {
+ fwwarn(f, "Non-zero CSS-ID");
+ return false;
+ }
+ return true;
+}
+
+/* Perform sanity checks on a device entry. */
+static bool check_de_size(struct fw_file *f, struct fw_dehdr *de, size_t size)
+{
+ if (fwacc(f, de->len) < size) {
+ fwwarn(f, "Device entry too short (expect %zu)", size);
+ return false;
+ }
+ return true;
+}
+
+/* Convert an I/O device ID to CCW device ID format. */
+static void io_to_ccw(struct ccw_devid *c, struct fw_iodevid *i)
+{
+ c->cssid = i->cssid;
+ c->ssid = i->ssid;
+ c->devno = i->devno;
+}
+
+/* Register a new device configuration. */
+static struct device *add_device(struct fw_file *f, struct subtype *st,
+ const char *id, config_t config,
+ struct util_list *objects)
+{
+ struct device *dev;
+
+ if (!st->devices)
+ st->devices = device_list_new(st);
+
+ dev = device_list_find(st->devices, id, NULL);
+ if (!dev) {
+ dev = device_new(st, id);
+ if (!dev) {
+ warnx("%s: Skipping invalid %s device ID %s", f->name,
+ st->name, id);
+ return NULL;
+ }
+ device_list_add(st->devices, dev);
+ }
+ ptrlist_add(objects, object_new(export_device, dev));
+
+ /* Prepare device for new settings. */
+ if (SCOPE_ACTIVE(config)) {
+ setting_list_clear(dev->active.settings);
+ if (dev->subtype->support_definable)
+ dev->active.definable = 1;
+ else
+ dev->active.exists = 1;
+ }
+ if (SCOPE_PERSISTENT(config)) {
+ setting_list_clear(dev->persistent.settings);
+ dev->persistent.exists = 1;
+ }
+
+ return dev;
+}
+
+/* Parse a DASD device entry. */
+static void parse_dasd(struct fw_file *f, struct fw_dehdr *de, config_t config,
+ struct util_list *objects)
+{
+ struct fw_dasd *dasd = (struct fw_dasd *) de;
+ struct ccw_devid devid;
+ struct device *dev_eckd, *dev_fba;
+ char *id;
+
+ if (!check_de_size(f, de, sizeof(struct fw_dasd)))
+ return;
+ if (!check_iodevid(f, &dasd->id_flags, &dasd->id))
+ return;
+
+ /* Could be either dasd_eckd or dasd_fba - add both entries */
+ io_to_ccw(&devid, &dasd->id);
+ id = ccw_devid_to_str(&devid);
+ dev_eckd = add_device(f, &dasd_subtype_eckd, id, config, objects);
+ dev_fba = add_device(f, &dasd_subtype_fba, id, config, objects);
+ free(id);
+
+ if (dasd->hdr.len > sizeof(struct fw_dasd)) {
+ if (dev_eckd)
+ parse_settings(f, dasd->settings, dev_eckd, config);
+ if (dev_fba)
+ parse_settings(f, dasd->settings, dev_fba, config);
+ }
+}
+
+/* Parse a zFCP host device entry. */
+static void parse_zfcp_host(struct fw_file *f, struct fw_dehdr *de,
+ config_t config, struct util_list *objects)
+{
+ struct fw_zfcp_host *zfcp_host = (struct fw_zfcp_host *) de;
+ struct ccw_devid devid;
+ struct device *dev;
+ char *id;
+
+ if (!check_de_size(f, de, sizeof(struct fw_zfcp_host)))
+ return;
+ if (!check_iodevid(f, &zfcp_host->id_flags, &zfcp_host->id))
+ return;
+
+ /* Add zfcp_host entry */
+ io_to_ccw(&devid, &zfcp_host->id);
+ id = ccw_devid_to_str(&devid);
+ dev = add_device(f, &zfcp_host_subtype, id, config, objects);
+ free(id);
+
+ if (dev && zfcp_host->hdr.len > sizeof(struct fw_zfcp_host))
+ parse_settings(f, zfcp_host->settings, dev, config);
+}
+
+/* Parse a zFCP LUN device entry. */
+static void parse_zfcp_lun(struct fw_file *f, struct fw_dehdr *de,
+ config_t config, struct util_list *objects)
+{
+ struct fw_zfcp_lun *zfcp_lun = (struct fw_zfcp_lun *) de;
+ struct zfcp_lun_devid devid;
+ struct device *dev;
+ char *id;
+
+ if (!check_de_size(f, de, sizeof(struct fw_zfcp_lun)))
+ return;
+ if (!check_iodevid(f, &zfcp_lun->id_flags, &zfcp_lun->id))
+ return;
+
+ /* Add zfcp_lun entry */
+ io_to_ccw(&devid.fcp_dev, &zfcp_lun->id);
+ devid.wwpn = zfcp_lun->wwpn;
+ devid.lun = zfcp_lun->fcp_lun;
+ id = zfcp_lun_devid_to_str(&devid);
+ dev = add_device(f, &zfcp_lun_subtype, id, config, objects);
+ free(id);
+
+ if (dev && zfcp_lun->hdr.len > sizeof(struct fw_zfcp_lun))
+ parse_settings(f, zfcp_lun->settings, dev, config);
+
+}
+
+/* Parse a QETH device entry. */
+static void parse_qeth(struct fw_file *f, struct fw_dehdr *de, config_t config,
+ struct util_list *objects)
+{
+ struct fw_qeth *qeth = (struct fw_qeth *) de;
+ struct ccwgroup_devid devid;
+ struct device *dev;
+ char *id;
+
+ if (!check_de_size(f, de, sizeof(struct fw_qeth)))
+ return;
+ if (!check_iodevid(f, &qeth->id_flags, &qeth->read_id) ||
+ !check_iodevid(f, &qeth->id_flags, &qeth->write_id) ||
+ !check_iodevid(f, &qeth->id_flags, &qeth->data_id))
+ return;
+
+ /* Add qeth entry */
+ devid.num = 3;
+ io_to_ccw(&devid.devid[0], &qeth->read_id);
+ io_to_ccw(&devid.devid[1], &qeth->write_id);
+ io_to_ccw(&devid.devid[2], &qeth->data_id);
+ id = ccwgroup_devid_to_str(&devid);
+ dev = add_device(f, &qeth_subtype_qeth, id, config, objects);
+ free(id);
+
+ if (dev && qeth->hdr.len > sizeof(struct fw_qeth))
+ parse_settings(f, qeth->settings, dev, config);
+}
+
+/* Parse a firmware file. */
+static void parse_fw(struct fw_file *f, long skip, config_t config,
+ struct util_list *objects)
+{
+ char *data = f->buffer;
+ struct fw_filehdr *hdr = (struct fw_filehdr *) data;
+ struct fw_dehdr *de;
+ uint16_t count = 0;
+ uint32_t off;
+
+ for (off = hdr->hdr_len; off < hdr->file_len; off += de->len) {
+ count++;
+ de = (struct fw_dehdr *) &data[off];
+ if (fwacc(f, de->len) == 0) {
+ fwwarn(f, "Empty device entry");
+ break;
+ }
+ if (off + fwacc(f, de->len) > hdr->file_len) {
+ fwwarn(f, "Device entry too long");
+ break;
+ }
+ if (skip >= 0 && de->seq <= skip) {
+ debug("Skipping %s entry due to sequence (%08x)\n",
+ type_to_str(de->type), de->seq);
+ continue;
+ }
+ switch (fwacc(f, de->type)) {
+ case FW_DE_HDR_TYPE_DASD:
+ parse_dasd(f, de, config, objects);
+ break;
+ case FW_DE_HDR_TYPE_ZFCP_HOST:
+ parse_zfcp_host(f, de, config, objects);
+ break;
+ case FW_DE_HDR_TYPE_ZFCP_LUN:
+ parse_zfcp_lun(f, de, config, objects);
+ break;
+ case FW_DE_HDR_TYPE_QETH:
+ parse_qeth(f, de, config, objects);
+ break;
+ default:
+ fwwarn(f, "Unknown entry (type=%04x)", de->type);
+ break;
+ }
+ }
+
+ if (count != fwacc(f, hdr->de_count))
+ fwwarn(f, "Device entry count mismatch");
+}
+
+/* Read configuration objects from @fd in firmware file format. Add pointers to
+ * newly allocated struct export_objects to ptrlist @objects. If @skip is a
+ * positive number, skip over entries with a sequence number equal to or
+ * greater than @skip. */
+exit_code_t firmware_read(FILE *fd, const char *filename, long skip,
+ config_t config, struct util_list *objects)
+{
+ struct fw_file file;
+ exit_code_t rc;
+
+ rc = read_fw(&file, fd, filename);
+ if (rc)
+ return rc;
+
+ parse_fw(&file, skip, config, objects);
+ free(file.buffer);
+
+ return rc;
+}
+
+/* Check if @fd refers to a file in binary firmware format. */
+bool firmware_detect(FILE *fd)
+{
+ int c;
+
+ c = fgetc(fd);
+ ungetc(c, fd);
+
+ /* Note: A full check would require looking at least at the first 4
+ * bytes, but fd might be non-seekable (e.g. pipe). Since there is no
+ * way that a textual import file can start with a 'z', looking at
+ * the first char should be enough. */
+
+ return c == 'z';
+}

View File

@ -0,0 +1,157 @@
Subject: zdev: Implement --no-settle
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: f32bff96881a04bb68b895c23b13ae50daa9e7b4
Problem-ID: LS1604
Upstream-Description:
zdev: Implement --no-settle
There are some situations where running "udevadm settle" can result in
a deadlock, such as in the early stages of initial RAM-disk processing.
Introduce a new command-line option --no-settle that can be used to
suppress calling "udevadm settle" to allow chzdev to be run in such
situations.
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/udev.h | 1 +
zdev/man/chzdev.8 | 9 +++++++++
zdev/src/chzdev.c | 9 +++++++++
zdev/src/chzdev_usage.txt | 1 +
zdev/src/udev.c | 3 +++
5 files changed, 23 insertions(+)
--- a/zdev/include/udev.h
+++ b/zdev/include/udev.h
@@ -14,6 +14,7 @@
#include "exit_code.h"
extern int udev_need_settle;
+extern int udev_no_settle;
/* Single key-operator-value entry in a udev rule line.*/
struct udev_entry_node {
--- a/zdev/man/chzdev.8
+++ b/zdev/man/chzdev.8
@@ -528,6 +528,15 @@ device configuration persistent. Typical
initial RAM disk, or modifying the kernel command line.
.PP
.
+.OD no-settle "" ""
+Do not wait for udev processing to complete.
+
+Skips all calls to the udevadm tool that are intended to wait for udev to
+finish processing before continuing. There is typically no need to use this
+option unless chzdev is run in an environment where udev is not fully
+functional (such as in the early phase of an initial RAM disk).
+.PP
+.
.OD persistent "p" ""
Apply changes to persistent configuration only.
--- a/zdev/src/chzdev.c
+++ b/zdev/src/chzdev.c
@@ -95,6 +95,7 @@ struct options {
struct util_list *base; /* List of struct strlist_node */
unsigned int verbose:1;
unsigned int quiet:1;
+ unsigned int no_settle:1;
};
/* Makefile converts chzdev_usage.txt into C file which we include here. */
@@ -136,6 +137,7 @@ enum {
OPT_VERSION = 'v',
OPT_VERBOSE = 'V',
OPT_QUIET = 'q',
+ OPT_NO_SETTLE = (OPT_ANONYMOUS_BASE+__COUNTER__),
};
static struct opts_conflict conflict_list[] = {
@@ -217,6 +219,7 @@ static const struct option opt_list[] =
{ "base", required_argument, NULL, OPT_BASE },
{ "verbose", no_argument, NULL, OPT_VERBOSE },
{ "quiet", no_argument, NULL, OPT_QUIET },
+ { "no-settle", no_argument, NULL, OPT_NO_SETTLE },
{ NULL, no_argument, NULL, 0 },
};
@@ -937,6 +940,11 @@ static exit_code_t parse_options(struct
opts->quiet = 1;
break;
+ case OPT_NO_SETTLE:
+ /* --no-settle */
+ opts->no_settle = 1;
+ break;
+
case ':':
/* Missing option argument. */
syntax("Option '%s' requires an argument\n",
@@ -2904,6 +2912,7 @@ int main(int argc, char *argv[])
force = opts.force;
yes = opts.yes;
dryrun = opts.dryrun;
+ udev_no_settle = opts.no_settle;
path_set_base(opts.base);
if (dryrun)
--- a/zdev/src/chzdev_usage.txt
+++ b/zdev/src/chzdev_usage.txt
@@ -54,5 +54,6 @@ OPTIONS
--no-root-update Skip root device update
--dry-run Display changes without applying
--base PATH Use PATH as base for accessing files
+ --no-settle Do not wait for udev to settle
-V, --verbose Print additional run-time information
-q, --quiet Print only minimal run-time information
--- a/zdev/src/udev.c
+++ b/zdev/src/udev.c
@@ -24,6 +24,7 @@
#include "udev.h"
int udev_need_settle = 0;
+int udev_no_settle;
/* Create a newly allocated udev entry. */
static struct udev_entry_node *udev_entry_node_new(const char *key,
@@ -403,5 +404,7 @@ exit_code_t udev_remove_rule(const char
/* Wait for all current udev events to finish. */
void udev_settle(void)
{
+ if (udev_no_settle)
+ return;
misc_system(err_ignore, "%s settle", PATH_UDEVADM);
}

View File

@ -0,0 +1,217 @@
Subject: zdev: Write zfcp-lun udev rules to separate files
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: a86fb8b09118e6de7463882f889eff7e278163cd
Problem-ID: LS1604
Upstream-Description:
zdev: Write zfcp-lun udev rules to separate files
Change chzdev's udev rule generation from the previous approach of
combining all zfcp-lun udev rules associated with an FCP device into a
single file to storing zfcp-lun udev rules in one file per zfcp-lun.
This is done to enable per-device udev rule masking.
With udev rule masking, if a udev rule file by the same name exists in
both /etc and /run, the udev daemon will only consider the rules found
in /etc.
The auto-configuration feature will make use of per-device udev rule
masking to introduce a new class of configuration data (stored in /run)
that is only active if no user-provided configuration data (in /etc)
exists.
In addition, change chzdev to allow the regeneration of udev rules by
using the --force command line like in the following example:
# chzdev zfcp-lun --configured --enable --persistent --force
This can be used to convert all existing zfcp-lun udev rules from the
old format to the new one.
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/src/chzdev.c | 6 +++-
zdev/src/root.c | 2 -
zdev/src/udev_zfcp_lun.c | 56 ++++++++++++++++++++++++++++++++++-----
3 files changed, 55 insertions(+), 9 deletions(-)
--- a/zdev/src/chzdev.c
+++ b/zdev/src/chzdev.c
@@ -1333,7 +1333,7 @@ static exit_code_t cfg_write(struct devi
struct subtype *st = dev->subtype;
exit_code_t rc = EXIT_OK;
- if (!device_needs_writing(dev, config))
+ if (!device_needs_writing(dev, config) && !force)
goto out;
if (check_active && config == config_persistent &&
@@ -1624,6 +1624,10 @@ static exit_code_t print_config_result(s
already = device_needs_writing(dev, config) ? 0 : 1;
}
+ /* Re-do actions if run with --force */
+ if (force)
+ already = 0;
+
if (dev) {
devname = dev->subtype->devname;
devid = dev->id;
--- a/zdev/src/root.c
+++ b/zdev/src/root.c
@@ -60,7 +60,7 @@ exit_code_t root_check(void)
/* Check devices. */
dev = device_list_find(sel->st->devices, sel->id, NULL);
if (dev && dev->persistent.exists &&
- device_needs_writing(dev, config_persistent)) {
+ (device_needs_writing(dev, config_persistent) || force)) {
strlist_add(mod, "%s %s", dev->subtype->devname,
dev->id);
}
--- a/zdev/src/udev_zfcp_lun.c
+++ b/zdev/src/udev_zfcp_lun.c
@@ -385,6 +385,8 @@ void udev_zfcp_lun_add_device_ids(struct
free(cb_data.prefix);
}
+/* 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)
{
char *copy, *e, *path;
@@ -399,6 +401,13 @@ static char *get_zfcp_lun_path(const cha
return path;
}
+/* 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)
+{
+ return path_get_udev_rule(ZFCP_LUN_NAME, id);
+}
+
/* Apply the settings found in NODE to STATE. */
static void zfcp_lun_node_to_state(struct zfcp_lun_node *node,
struct attrib **attribs,
@@ -437,7 +446,12 @@ exit_code_t udev_zfcp_lun_read_device(st
exit_code_t rc = EXIT_OK;
char *path;
- path = get_zfcp_lun_path(dev->id);
+ /* Check for single lun file first then try multi lun file. */
+ path = get_single_zfcp_lun_path(dev->id);
+ if (!util_path_exists(path)) {
+ free(path);
+ path = get_zfcp_lun_path(dev->id);
+ }
/* Get previous rule data. */
luns = zfcp_lun_node_list_new();
@@ -599,8 +613,10 @@ out:
/* Update the udev rule file that configures the zfcp lun with the specified
* ID. If @state is %NULL, remove the rule, otherwise create a rule that
- * applies the corresponding parameters. */
-static exit_code_t update_lun_rule(const char *id, struct device_state *state)
+ * 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)
{
struct zfcp_lun_devid devid;
struct util_list *luns;
@@ -612,7 +628,7 @@ static exit_code_t update_lun_rule(const
rc = zfcp_lun_parse_devid(&devid, id, err_delayed_print);
if (rc)
return rc;
- path = get_zfcp_lun_path(id);
+ path = single ? get_single_zfcp_lun_path(id) : get_zfcp_lun_path(id);
/* Get previous rule data. */
luns = zfcp_lun_node_list_new();
@@ -650,24 +666,50 @@ static exit_code_t update_lun_rule(const
* device state. */
exit_code_t udev_zfcp_lun_write_device(struct device *dev)
{
- return update_lun_rule(dev->id, &dev->persistent);
+ exit_code_t rc;
+
+ rc = update_lun_rule(dev->id, &dev->persistent, true);
+
+ /* We only want single lun rule files so remove any remaining
+ * references in multi lun rule files. */
+ update_lun_rule(dev->id, NULL, false);
+
+ 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)
{
- return update_lun_rule(id, NULL);
+ exit_code_t rc, rc2;
+
+ rc = update_lun_rule(id, NULL, true);
+ rc2 = update_lun_rule(id, NULL, false);
+
+ if (rc)
+ return rc;
+
+ return rc2;
}
/* Determine if a udev rule exists for configuring the specified zfcp lun. */
bool udev_zfcp_lun_exists(const char *id)
{
struct zfcp_lun_devid devid;
- char *path, *rule, *pattern = NULL;
+ char *path, *rule = NULL, *pattern = NULL;
bool rc = false;
if (zfcp_lun_parse_devid(&devid, id, err_ignore) != EXIT_OK)
return false;
+
+ /* Check for single lun rule file first. */
+ path = get_single_zfcp_lun_path(id);
+ if (util_path_exists(path)) {
+ rc = true;
+ goto out;
+ }
+ free(path);
+
+ /* Check multi lun rule file next. */
path = get_zfcp_lun_path(id);
rule = misc_read_text_file(path, 1, err_ignore);
if (!rule)

View File

@ -0,0 +1,155 @@
Subject: zdev: Integrate firmware auto-configuration with dracut
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: 3fb356ebd297e4384208b7688d49cb3eb8f5b3e1
Problem-ID: LS1604
Upstream-Description:
zdev: Integrate firmware auto-configuration with dracut
Add a dracut hook that applies firmware-provided I/O configuration data
as auto-configuration during boot. This way, all I/O devices configured
by DPM are automatically brought online without further user
interaction.
This mechanism is active by default. It can be deactivated by specifying
the following parameter on the kernel command line:
rd.zdev=no-auto
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/dracut/95zdev/module-setup.sh | 19 ++++++++++----
zdev/dracut/95zdev/parse-zdev.sh | 38 +++++++++++++++++++++++++++++
zdev/dracut/Makefile | 3 ++
3 files changed, 55 insertions(+), 5 deletions(-)
--- a/zdev/dracut/95zdev/module-setup.sh
+++ b/zdev/dracut/95zdev/module-setup.sh
@@ -9,7 +9,8 @@
# 95zdev/module_setup.sh
# This module installs configuration files (udev rules and modprobe.conf
# files) required to enable the root device on s390. It will only work when
-# the root device was configured using the chzdev tool.
+# the root device was configured using the chzdev tool. In addition,
+# a hook is installed to parse rd.zdev= kernel parameters.
#
check() {
@@ -29,15 +30,23 @@ depends() {
}
installkernel() {
- local _modules=$(lszdev --by-path / --columns MODULES --no-headings 2>/dev/null)
-
- [ -z "$_modules" ] && return 0
- [ ! -z "$_modules" ] && instmods $_modules
+ # Add modules for all device types supported by chzdev (required for
+ # auto-configuration)
+ instmods lcs qeth qeth_l2 qeth_l3 dasd_mod dasd_eckd_mod dasd_fba_mod \
+ dasd_diag_mod zfcp
}
install() {
local _tempfile
+ # Ensure that required tools are available
+ inst_multiple chzdev lszdev vmcp
+
+ # Hook to parse zdev kernel parameter
+ inst_hook cmdline 95 "$moddir/parse-zdev.sh"
+
+ # Obtain root device configuration
+
# Exit early if root device type is unknown
if ! lszdev --by-path / >/dev/null 2>&1 ; then
return 0
--- /dev/null
+++ b/zdev/dracut/95zdev/parse-zdev.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# 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.
+#
+# 95zdev/parse-zdev.sh
+# Parse the kernel command line for rd.zdev kernel parameters. These
+# parameters are evaluated and used to configure z Systems specific devices.
+#
+# Format:
+# rd.zdev=no-auto
+#
+# where
+#
+# no-auto: Indicates that firmware-provided I/O configuration data
+# should not be applied.
+#
+
+zdev_fw_file="/sys/firmware/sclp_sd/config/data"
+zdev_base_args="--force --yes --no-root-update --no-settle --auto-conf --quiet"
+
+if [ -e "$zdev_fw_file" ] ; then
+ zdev_auto=1
+else
+ zdev_auto=0
+fi
+
+for zdev_arg in $(getargs rd.zdev); do
+ if [ "$zdev_arg" = "no-auto" ] ; then
+ zdev_auto=0
+ fi
+done
+
+if [ $zdev_auto -eq 1 ] ; then
+ chzdev --import "$zdev_fw_file" $zdev_base_args
+fi
--- a/zdev/dracut/Makefile
+++ b/zdev/dracut/Makefile
@@ -11,11 +11,14 @@ ZDEVDIR := 95zdev
# performs the following functions when dracut is run:
#
# - copy the persistent root device configuration to the initial ram disk
+# - install a boot-time hook to apply firmware-provided configuration data
+# to the system
#
ifeq ($(HAVE_DRACUT),1)
install:
$(INSTALL) -m 755 -d $(DESTDIR)$(MODDIR)
$(INSTALL) -m 755 -d $(DESTDIR)$(MODDIR)/$(ZDEVDIR)
$(INSTALL) -m 755 $(ZDEVDIR)/module-setup.sh \
+ $(ZDEVDIR)/parse-zdev.sh \
$(DESTDIR)$(MODDIR)/$(ZDEVDIR)/
endif

View File

@ -0,0 +1,216 @@
Subject: zdev: Integrate firmware auto-configuration with initramfs-tools
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: 3c5644ccfd46aab27df6e0ed783e94a620bc3fe6
Problem-ID: LS1604
Upstream-Description:
zdev: Integrate firmware auto-configuration with initramfs-tools
Add initramfs-tools scripts that apply firmware-provided I/O
configuration data as auto-configuration during boot. This way, all I/O
devices configured by DPM are automatically brought online without
further user interaction.
This mechanism is active by default. It can be deactivated by specifying
the following parameter on the kernel command line:
rd.zdev=no-auto
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>
---
README.md | 1
zdev/Makefile | 1
zdev/initramfs/Makefile | 22 ++++++++
zdev/initramfs/hooks/zdev | 39 +++++++++++++++
zdev/initramfs/scripts/init-top/zdev | 67 +++++++++++++++++++++++++++
5 files changed, 130 insertions(+)
--- a/README.md
+++ b/README.md
@@ -272,6 +272,7 @@ This table lists additional build or ins
| __COMPONENT__ | __OPTION__ | __TOOLS__ |
|----------------|:----------------:|:-------------------------------:|
| dracut | `HAVE_DRACUT` | zdev |
+| initramfs-tools| `HAVE_INITRAMFS` | zdev |
The s390-tools build process uses "pkg-config" if available and hard-coded
compiler and linker options otherwise.
--- a/zdev/Makefile
+++ b/zdev/Makefile
@@ -8,6 +8,7 @@ install: all
$(MAKE) -C src install
$(MAKE) -C man install
$(MAKE) -C dracut install
+ $(MAKE) -C initramfs install
clean:
$(MAKE) -C src clean
--- /dev/null
+++ b/zdev/initramfs/Makefile
@@ -0,0 +1,22 @@
+# Common definitions
+include ../../common.mak
+
+INITRAMFSDIR := /usr/share/initramfs-tools
+HOOKDIR := $(INITRAMFSDIR)/hooks
+INITTOP := $(INITRAMFSDIR)/scripts/init-top
+
+# HAVE_INITRAMFS
+#
+# This install time parameter determines whether the zdev initramfs support is
+# installed (HAVE_INITRAMFS=1) or not (default). When installed, the module
+# performs the following functions when mkinitramfs is run:
+#
+# - install a boot-time hook to apply firmware-provided configuration data
+# to the system
+#
+ifeq ($(HAVE_INITRAMFS),1)
+install:
+ $(INSTALL) -m 755 -d $(DESTDIR)/$(HOOKDIR) $(DESTDIR)/$(INITTOP)
+ $(INSTALL) -m 755 hooks/zdev $(DESTDIR)/$(HOOKDIR)
+ $(INSTALL) -m 755 scripts/init-top/zdev $(DESTDIR)/$(INITTOP)
+endif
--- /dev/null
+++ b/zdev/initramfs/hooks/zdev
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# Copyright IBM Corp. 2016, 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.
+#
+# hooks/zdev
+# This hook script adds files required to apply firmware-provided I/O
+# configuration data during boot.
+#
+
+PREREQ=""
+
+prereqs()
+{
+ echo "$PREREQ"
+}
+
+case $1 in
+ prereqs)
+ prereqs
+ exit 0
+ ;;
+esac
+
+. /usr/share/initramfs-tools/hook-functions
+
+# Add modules for all device types supported by chzdev (required for
+# auto-configuration)
+zdev_modules="lcs qeth qeth_l2 qeth_l3 dasd_mod dasd_eckd_mod dasd_fba_mod dasd_diag_mod zfcp"
+
+for x in $zdev_modules ; do
+ manual_add_modules ${x}
+done
+
+copy_exec /sbin/chzdev
+copy_exec /sbin/lszdev
+copy_exec /sbin/vmcp
--- /dev/null
+++ b/zdev/initramfs/scripts/init-top/zdev
@@ -0,0 +1,67 @@
+#!/bin/sh
+#
+# 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.
+#
+# scripts/init-top/zdev
+# Parse the kernel command line for rd.zdev kernel parameters. These
+# parameters are evaluated and used to configure z Systems specific devices.
+#
+# Format:
+# rd.zdev=no-auto
+#
+# where
+#
+# no-auto: Indicates that firmware-provided I/O configuration data
+# should not be applied.
+#
+
+PREREQ="udev"
+
+prereqs()
+{
+ echo "$PREREQ"
+}
+
+case $1 in
+prereqs)
+ prereqs
+ exit 0
+ ;;
+esac
+
+. /scripts/functions
+
+zdev_fw_file="/sys/firmware/sclp_sd/config/data"
+zdev_base_args="--force --yes --no-root-update --no-settle --auto-conf --quiet"
+
+if [ -e "$zdev_fw_file" ] ; then
+ zdev_auto=1
+else
+ zdev_auto=0
+fi
+
+for x in $(cat /proc/cmdline); do
+ case ${x} in
+ rd.zdev=*)
+ zdev_arg=${x#*=}
+ if [ "$zdev_arg" = "no-auto" ] ; then
+ zdev_auto=0
+ fi
+ ;;
+ esac
+done
+
+if [ $zdev_auto -eq 1 ] ; then
+ log_begin_msg "Starting firmware auto-configuration"
+ chzdev --import "$zdev_fw_file" $zdev_base_args
+ log_end_msg
+
+ # Repeat cold-plug after creating udev rules
+ udevadm control --reload
+ udevadm trigger --type=subsystems --action=add
+ udevadm trigger --action=add
+ udevadm settle || true
+fi

View File

@ -0,0 +1,507 @@
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;
}

View File

@ -0,0 +1,505 @@
Subject: zdev: Implement support for early device configuration
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: 156450f359bb13776fac2130a1cac00a48c2deda
Problem-ID: LS1604
Upstream-Description:
zdev: Implement support for early device configuration
Enable user to specify that a device should be configured early, that is
during the initial RAM-disk boot phase. This may be necessary, e.g. to
override auto-configuration for a device which is also applied during
that boot phase. It may also be used to manually specify devices that
are required to access the root file system, such as networking devices.
Users can mark devices as requiring early configuration by specifying
a value of 1 for the newly added internal attribute zdev:early:
# chzdev dasd-eckd 0.0.1234 -p zdev:early=1
This can be changed back by removing the attribute setting, or by
setting the attribute value to 0:
# chzdev dasd-eckd 0.0.1234 -p -r zdev:early
or
# chzdev dasd-eckd 0.0.1234 -p zdev:early=0
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/dracut/95zdev/module-setup.sh | 21 +------
zdev/include/internal.h | 5 +
zdev/initramfs/hooks/zdev | 19 ++++++
zdev/man/chzdev.8 | 29 ++++++++++
zdev/src/chzdev.c | 4 -
zdev/src/ctc.c | 2
zdev/src/dasd.c | 3 +
zdev/src/generic_ccw.c | 2
zdev/src/internal.c | 13 ++++
zdev/src/lcs.c | 2
zdev/src/qeth.c | 2
zdev/src/root.c | 82 ++++++++++++++++++++++-------
zdev/src/zfcp_host.c | 2
zdev/src/zfcp_lun.c | 2
14 files changed, 152 insertions(+), 36 deletions(-)
--- a/zdev/dracut/95zdev/module-setup.sh
+++ b/zdev/dracut/95zdev/module-setup.sh
@@ -45,23 +45,12 @@ install() {
# Hook to parse zdev kernel parameter
inst_hook cmdline 95 "$moddir/parse-zdev.sh"
- # Obtain root device configuration
-
- # Exit early if root device type is unknown
- if ! lszdev --by-path / >/dev/null 2>&1 ; then
- return 0
- fi
-
+ # Obtain early + root device configuration
_tempfile=$(mktemp --tmpdir dracut-zdev.XXXXXX)
-
- if chzdev --export - --persistent --by-path / >/dev/null 2>&1 ; then
- # Use persistent configuration
- chzdev --export "$_tempfile" --persistent --by-path / --quiet --type
- else
- # Use active configuration
- chzdev --export "$_tempfile" --active --by-path / --quiet --type
- sed -i -e 's/active/persistent/g' "$_tempfile"
- fi
+ chzdev --export "$_tempfile" --persistent --by-path / --quiet \
+ --type 2>/dev/null
+ chzdev --export - --persistent --by-attrib "zdev:early=1" --quiet \
+ --type 2>/dev/null >> "$_tempfile"
# Apply via --import to prevent other devices from being configured
chzdev --import "$_tempfile" --persistent --base "/etc=$initdir/etc" \
--- a/zdev/include/internal.h
+++ b/zdev/include/internal.h
@@ -12,7 +12,12 @@
#include <stdbool.h>
+#include "attrib.h"
+
#define INTERNAL_ATTR_PREFIX "zdev:"
+#define INTERNAL_ATTR_EARLY INTERNAL_ATTR_PREFIX "early"
+
+extern struct attrib internal_attr_early;
const char *internal_get_name(const char *name);
bool internal_by_name(const char *name);
--- a/zdev/initramfs/hooks/zdev
+++ b/zdev/initramfs/hooks/zdev
@@ -10,7 +10,8 @@
# configuration data during boot.
#
-PREREQ=""
+# Needs to run after udev or resulting udev rules could be overwritten
+PREREQ="udev"
prereqs()
{
@@ -37,3 +38,19 @@ done
copy_exec /sbin/chzdev
copy_exec /sbin/lszdev
copy_exec /sbin/vmcp
+
+_tempfile=$(mktemp --tmpdir initramfs-zdev.XXXXXX)
+
+# Obtain early + root device configuration
+chzdev --export "$_tempfile" --persistent --by-path / \
+ --by-attrib "zdev:early=1" --quiet --type 2>/dev/null
+
+# Apply via --import to prevent other devices from being configured.
+# Rename the resulting cio-ignore rule to ensure that it does not override
+# the one copied by the initramfs udev hook to /lib/udev.
+chzdev --import "$_tempfile" --persistent \
+ --base "/etc/udev/rules.d/41-cio-ignore.rules=$DESTDIR/etc/udev/rules.d/41-cio-ignore-root.rules" \
+ --base "/etc=$DESTDIR/etc" --yes --quiet --no-root-update --force \
+ >/dev/null
+
+rm -f "$_tempfile"
--- a/zdev/man/chzdev.8
+++ b/zdev/man/chzdev.8
@@ -334,6 +334,35 @@ a specific attribute.
.PP
.
.
+.SS "Special settings"
+The following special settings affect how devices are handled by chzdev:
+.PP
+.
+.BR zdev:early =0|1
+.RS 4
+Control in which stage of the boot process a device is activated:
+.TP 4
+.B 0
+Device is activated normally during boot (default).
+.PP
+.TP 4
+.B 1
+Device is activated early in the boot process, by the initial RAM-disk.
+.PP
+Specify a value of 1 for this attribute in any of the following situations:
+.TP 4
+\(bu
+To ensure that your settings override auto-configuration settings.
+.PP
+.TP 4
+\(bu
+To ensure that a device required to access the root file system is correctly
+enabled during boot. An example would be a networking device, or a device that
+is intended to extend a logical volume that provides the root file system.
+.PP
+.RE
+.
+.
.SH ACTIONS
You can use one of the action options listed below to specify the
.B main tool action
--- a/zdev/src/chzdev.c
+++ b/zdev/src/chzdev.c
@@ -3025,8 +3025,8 @@ int main(int argc, char *argv[])
if ((pers_mod_devs || pers_mod_devtypes) && !opts.no_root_check &&
!dryrun) {
- /* If the root device/device type has been modified, additional
- * work might be necessary. */
+ /* If the root device/device type or early devices have been
+ * modified, additional work might be necessary. */
rc = root_check();
if (rc && !drc)
drc = rc;
--- a/zdev/src/ctc.c
+++ b/zdev/src/ctc.c
@@ -17,6 +17,7 @@
#include "ctc_auto.h"
#include "device.h"
#include "devtype.h"
+#include "internal.h"
#include "misc.h"
#include "namespace.h"
#include "path.h"
@@ -425,6 +426,7 @@ static struct subtype ctc_subtype = {
&ccw_attr_online,
&ctc_attr_buffer,
&ctc_attr_protocol,
+ &internal_attr_early,
),
.unknown_dev_attribs = 1,
.support_definable = 1,
--- a/zdev/src/dasd.c
+++ b/zdev/src/dasd.c
@@ -16,6 +16,7 @@
#include "dasd.h"
#include "device.h"
#include "devtype.h"
+#include "internal.h"
#include "misc.h"
#include "modprobe.h"
#include "module.h"
@@ -616,6 +617,7 @@ struct subtype dasd_subtype_eckd = {
&dasd_attr_reservation_policy,
&dasd_attr_last_known_reservation_state,
&dasd_attr_safe_offline,
+ &internal_attr_early,
),
.unknown_dev_attribs = 1,
@@ -651,6 +653,7 @@ struct subtype dasd_subtype_fba = {
&dasd_attr_reservation_policy,
&dasd_attr_last_known_reservation_state,
&dasd_attr_safe_offline,
+ &internal_attr_early,
),
.unknown_dev_attribs = 1,
--- a/zdev/src/generic_ccw.c
+++ b/zdev/src/generic_ccw.c
@@ -17,6 +17,7 @@
#include "devnode.h"
#include "devtype.h"
#include "generic_ccw.h"
+#include "internal.h"
#include "namespace.h"
#include "path.h"
#include "subtype.h"
@@ -182,6 +183,7 @@ static struct subtype generic_ccw_subtyp
.dev_attribs = ATTRIB_ARRAY(
&ccw_attr_online,
&ccw_attr_cmb_enable,
+ &internal_attr_early,
),
.unknown_dev_attribs = 1,
.generic = 1,
--- a/zdev/src/internal.c
+++ b/zdev/src/internal.c
@@ -9,9 +9,22 @@
#include <stdbool.h>
+#include "attrib.h"
#include "internal.h"
#include "misc.h"
+struct attrib internal_attr_early = {
+ .name = INTERNAL_ATTR_EARLY,
+ .title = "Activate device early during boot",
+ .desc = "Control the time of activation of a device:\n"
+ " 0: Device is activated normally during boot\n"
+ " 1: Device is activated early in the boot process, by the\n"
+ " initial RAM-disk\n",
+ .defval = "0",
+ .accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
+ .internal = 1,
+};
+
/* Return identifier of internal attribute with specified @name. */
const char *internal_get_name(const char *name)
{
--- a/zdev/src/lcs.c
+++ b/zdev/src/lcs.c
@@ -15,6 +15,7 @@
#include "ccwgroup.h"
#include "device.h"
#include "devtype.h"
+#include "internal.h"
#include "lcs.h"
#include "lcs_auto.h"
#include "misc.h"
@@ -362,6 +363,7 @@ static struct subtype lcs_subtype = {
&ccw_attr_online,
&lcs_attr_lancmd_timeout,
&lcs_attr_recover,
+ &internal_attr_early,
),
.unknown_dev_attribs = 1,
.support_definable = 1,
--- a/zdev/src/qeth.c
+++ b/zdev/src/qeth.c
@@ -15,6 +15,7 @@
#include "ccwgroup.h"
#include "device.h"
#include "devtype.h"
+#include "internal.h"
#include "misc.h"
#include "namespace.h"
#include "nic.h"
@@ -1445,6 +1446,7 @@ struct subtype qeth_subtype_qeth = {
&qeth_attr_vnicc_takeover_learning,
&qeth_attr_vnicc_bridge_invisible,
&qeth_attr_vnicc_rx_bcast,
+ &internal_attr_early,
),
.unknown_dev_attribs = 1,
.support_definable = 1,
--- a/zdev/src/root.c
+++ b/zdev/src/root.c
@@ -8,11 +8,13 @@
*/
#include <stdlib.h>
+#include <string.h>
#include "lib/util_path.h"
#include "device.h"
#include "devtype.h"
+#include "internal.h"
#include "misc.h"
#include "path.h"
#include "root.h"
@@ -20,31 +22,78 @@
#include "setting.h"
#include "subtype.h"
-/* Determine if the root device was modified. If it was modified, run the
- * corresponding root-install scripts. */
+static bool is_early_removed(struct device *dev)
+{
+ struct setting *s;
+
+ s = setting_list_find(dev->persistent.settings,
+ internal_attr_early.name);
+ if (!s || !s->modified)
+ return false;
+ if (!s->actual_value || strcmp(s->actual_value, "1") != 0)
+ return false;
+ if (s->removed || strcmp(s->value, "0") == 0)
+ return true;
+ return false;
+}
+
+static void add_early_removed(struct util_list *selected)
+{
+ int i, j;
+ struct devtype *dt;
+ struct subtype *st;
+ struct device *dev;
+
+ for (i = 0; devtypes[i]; i++) {
+ dt = devtypes[i];
+ for (j = 0; dt->subtypes[j]; j++) {
+ st = dt->subtypes[j];
+ util_list_iterate(&st->devices->hash.list, dev) {
+ if (is_early_removed(dev)) {
+ selected_dev_list_add(selected, dt, st,
+ dev->id, NULL, EXIT_OK);
+ }
+ }
+ }
+ }
+}
+
+/* Determine if initial RAM-disk needs updating. If so, run the corresponding
+ * scripts if available. */
exit_code_t root_check(void)
{
struct util_list *selected, *params, *mod = NULL;
struct selected_dev_node *sel;
struct device *dev;
char *params_str;
- exit_code_t rc;
+ exit_code_t rc = EXIT_OK;
struct strlist_node *s;
struct devtype *dt;
+ struct select_opts *select;
- debug("Checking for modified root device configuration\n");
+ debug("Checking for required initial RAM-disk update\n");
- /* Get list of devices that provide the root device. */
+ /* Get list of devices that provide the root device or require
+ * early configuration. */
selected = selected_dev_list_new();
- rc = select_by_path(NULL, selected, config_active, scope_mandatory,
- NULL, NULL, PATH_ROOT, err_ignore);
- if (rc) {
+ /* First add devices that had zdev:early removed or changed to 0.
+ * The subsequent call to select_devices() will filter out any
+ * duplicates. */
+ add_early_removed(selected);
+ /* Now add devices required for root file system. */
+ if (select_by_path(NULL, selected, config_active, scope_mandatory,
+ NULL, NULL, PATH_ROOT, err_ignore)) {
/* Running from an unknown root device is not an error. */
verb("Note: Could not determine if root device configuration "
"needs to be updated\n");
- rc = 0;
- goto out;
}
+ /* Finally add devices with zdev:early=1. */
+ select = select_opts_new();
+ strlist_add(&select->by_attr, "%s=1", INTERNAL_ATTR_EARLY);
+ select_devices(select, selected, 1, 0, 0,
+ config_active | config_persistent, scope_mandatory,
+ err_ignore);
+ select_opts_free(select);
/* Determine if any of the devices or device types has been modified. */
mod = strlist_new();
@@ -68,19 +117,18 @@ exit_code_t root_check(void)
if (util_list_is_empty(mod))
goto out;
- info("Note: Some of the changes affect devices providing the root "
- "file system:\n");
+ info("Note: The initial RAM-disk must be updated for these changes to take effect:\n");
util_list_iterate(mod, s)
info(" - %s\n", s->str);
- info(" Additional steps such as rebuilding the RAM-disk might be "
- "required.\n");
/* Check if script is available. */
- if (!util_path_is_reg_file(PATH_ROOT_SCRIPT))
+ if (!util_path_is_reg_file(PATH_ROOT_SCRIPT)) {
+ warn("A manual update of the initial RAM-disk is required.\n");
goto out;
+ }
/* Ask for confirmation. */
- if (!confirm("Update persistent root device configuration now?")) {
+ if (!confirm("Update initial RAM-disk now?")) {
rc = EXIT_ABORTED;
goto out;
}
@@ -97,7 +145,7 @@ exit_code_t root_check(void)
/* Run update command. */
if (misc_system(err_delayed_print, "%s %s", PATH_ROOT_SCRIPT,
params_str) != 0) {
- error("Failure while updating root device configuration\n");
+ error("Failure while updating initial RAM-disk\n");
delayed_print(DELAY_INDENT);
rc = EXIT_RUNTIME_ERROR;
}
--- a/zdev/src/zfcp_host.c
+++ b/zdev/src/zfcp_host.c
@@ -17,6 +17,7 @@
#include "ccw.h"
#include "device.h"
#include "devtype.h"
+#include "internal.h"
#include "misc.h"
#include "path.h"
#include "setting.h"
@@ -247,6 +248,7 @@ struct subtype zfcp_host_subtype = {
&zfcp_host_attr_failed,
&zfcp_host_attr_port_remove,
&zfcp_host_attr_port_rescan,
+ &internal_attr_early,
),
.unknown_dev_attribs = 1,
--- a/zdev/src/zfcp_lun.c
+++ b/zdev/src/zfcp_lun.c
@@ -21,6 +21,7 @@
#include "devnode.h"
#include "devtype.h"
#include "misc.h"
+#include "internal.h"
#include "namespace.h"
#include "path.h"
#include "scsi.h"
@@ -1097,6 +1098,7 @@ struct subtype zfcp_lun_subtype = {
&zfcp_lun_attr_scsi_timeout,
&zfcp_lun_attr_scsi_state,
&zfcp_lun_attr_scsi_delete,
+ &internal_attr_early,
),
.prefixes = STRING_ARRAY(SCSI_ATTR_PREFIX),
.unknown_dev_attribs = 1,

View File

@ -0,0 +1,50 @@
Subject: zdev: Add support for handling I/O configuration data
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: -
Problem-ID: LS1604
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
---
zdev/src/zdev-root-update.dracut | 6 ------
1 file changed, 6 deletions(-)
--- a/zdev/src/zdev-root-update.dracut
+++ b/zdev/src/zdev-root-update.dracut
@@ -20,10 +20,4 @@ dracut -f || {
exit 1
}
-echo "Installing IPL record"
-zipl --noninteractive || {
- echo "${TOOLNAME}: Error: Could not install IPL record" >&2
- exit 1
-}
-
exit 0

View File

@ -21,7 +21,7 @@ Signed-off-by: Hans Wippel <hwippel@linux.ibm.com>
--- a/zdev/src/qeth.c --- a/zdev/src/qeth.c
+++ b/zdev/src/qeth.c +++ b/zdev/src/qeth.c
@@ -1170,6 +1170,37 @@ static exit_code_t check_ineffective_set @@ -1171,6 +1171,37 @@ static exit_code_t check_ineffective_set
return rc; return rc;
} }
@ -59,7 +59,7 @@ Signed-off-by: Hans Wippel <hwippel@linux.ibm.com>
/* Check if there are conflicting attribute settings */ /* Check if there are conflicting attribute settings */
static exit_code_t check_conflicting_settings(struct setting_list *list) static exit_code_t check_conflicting_settings(struct setting_list *list)
{ {
@@ -1181,6 +1212,8 @@ static exit_code_t check_conflicting_set @@ -1182,6 +1213,8 @@ static exit_code_t check_conflicting_set
util_list_iterate(&list->list, s) { util_list_iterate(&list->list, s) {
if (s->removed) if (s->removed)
continue; continue;

View File

@ -1,3 +1,24 @@
-------------------------------------------------------------------
Thu Dec 6 21:03:08 UTC 2018 - mpost@suse.com
- Added the following patches for Fate#326825 (bsc#1113329)
I/O device pre-configuration
* s390-tools-sles15sp1-01-zdev-use-libutil-provided-path-functions.patch
* s390-tools-sles15sp1-02-zdev-Prepare-for-firmware-configuration-file-support.patch
* s390-tools-sles15sp1-03-zdev-Add-support-for-reading-firmware-configuration-.patch
* s390-tools-sles15sp1-04-zdev-Implement-no-settle.patch
* s390-tools-sles15sp1-05-zdev-Write-zfcp-lun-udev-rules-to-separate-files.patch
* s390-tools-sles15sp1-06-zdev-Add-support-for-handling-auto-configuration-dat.patch
* s390-tools-sles15sp1-07-zdev-Integrate-firmware-auto-configuration-with-drac.patch
* s390-tools-sles15sp1-08-zdev-Integrate-firmware-auto-configuration-with-init.patch
* s390-tools-sles15sp1-09-zdev-Implement-internal-device-attributes.patch
* s390-tools-sles15sp1-10-zdev-Implement-support-for-early-device-configuratio.patch
* s390-tools-sles15sp1-11-zdev-Do-not-call-zipl-on-initrd-update.patch
- Removed the obsolete customize-zdev-root-update-script.patch
- Replaced s390-tools-sles15-zdev-fix-qeth-BridgePort-and-VNICC-conflict-checking.patch
with s390-tools-sles15sp1-zdev-fix-qeth-BridgePort-and-VNICC-conflict-checking.patch
to fit the current version.
------------------------------------------------------------------- -------------------------------------------------------------------
Thu Nov 29 00:03:01 UTC 2018 - mpost@suse.com Thu Nov 29 00:03:01 UTC 2018 - mpost@suse.com

View File

@ -152,51 +152,60 @@ Patch40: s390-tools-sles15-5-lstape-fix-to-prevent-error-messages-if-ther
Patch41: s390-tools-sles15-6-lstape-fix-description-of-type-and-devbusid-filter-f.patch Patch41: s390-tools-sles15-6-lstape-fix-description-of-type-and-devbusid-filter-f.patch
Patch42: s390-tools-sles15-7-lstape-fix-SCSI-output-description-in-man-page.patch Patch42: s390-tools-sles15-7-lstape-fix-SCSI-output-description-in-man-page.patch
Patch43: s390-tools-sles15-8-lstape-fix-SCSI-HBA-CCW-device-bus-ID-e.g.-for-virti.patch Patch43: s390-tools-sles15-8-lstape-fix-SCSI-HBA-CCW-device-bus-ID-e.g.-for-virti.patch
Patch44: s390-tools-sles15-zdev-fix-qeth-BridgePort-and-VNICC-conflict-checking.patch Patch44: s390-tools-sles15sp1-0001-zkey-Add-properties-file-handling-routines.patch
Patch45: s390-tools-sles15sp1-0001-zkey-Add-properties-file-handling-routines.patch Patch45: s390-tools-sles15sp1-0002-zkey-Add-build-dependency-to-OpenSSL-libcrypto.patch
Patch46: s390-tools-sles15sp1-0002-zkey-Add-build-dependency-to-OpenSSL-libcrypto.patch Patch46: s390-tools-sles15sp1-0003-zkey-Add-helper-functions-for-comma-separated-string.patch
Patch47: s390-tools-sles15sp1-0003-zkey-Add-helper-functions-for-comma-separated-string.patch Patch47: s390-tools-sles15sp1-0004-zkey-Externalize-secure-key-back-end-functions.patch
Patch48: s390-tools-sles15sp1-0004-zkey-Externalize-secure-key-back-end-functions.patch Patch48: s390-tools-sles15sp1-0005-zkey-Add-keystore-implementation.patch
Patch49: s390-tools-sles15sp1-0005-zkey-Add-keystore-implementation.patch Patch49: s390-tools-sles15sp1-0006-zkey-Add-keystore-related-commands.patch
Patch50: s390-tools-sles15sp1-0006-zkey-Add-keystore-related-commands.patch Patch50: s390-tools-sles15sp1-0007-zkey-Create-key-repository-and-group-during-make-ins.patch
Patch51: s390-tools-sles15sp1-0007-zkey-Create-key-repository-and-group-during-make-ins.patch Patch51: s390-tools-sles15sp1-0008-zkey-Man-page-updates.patch
Patch52: s390-tools-sles15sp1-0008-zkey-Man-page-updates.patch Patch52: s390-tools-sles15sp1-0009-zkey-let-packaging-create-the-zkeyadm-group-and-perm.patch
Patch53: s390-tools-sles15sp1-0009-zkey-let-packaging-create-the-zkeyadm-group-and-perm.patch Patch53: s390-tools-sles15sp1-0010-zkey-Update-README-to-add-info-about-packaging-requi.patch
Patch54: s390-tools-sles15sp1-0010-zkey-Update-README-to-add-info-about-packaging-requi.patch Patch54: s390-tools-sles15sp1-0011-zkey-Typo-in-message.patch
Patch55: s390-tools-sles15sp1-0011-zkey-Typo-in-message.patch Patch55: s390-tools-sles15sp1-0012-zkey-Fix-memory-leak.patch
Patch56: s390-tools-sles15sp1-0012-zkey-Fix-memory-leak.patch Patch56: s390-tools-sles15sp1-0013-zkey-Fix-APQN-validation-routine.patch
Patch57: s390-tools-sles15sp1-0013-zkey-Fix-APQN-validation-routine.patch Patch57: s390-tools-sles15sp1-0014-zkey-Fix-generate-and-import-leaving-key-in-an-incon.patch
Patch58: s390-tools-sles15sp1-0014-zkey-Fix-generate-and-import-leaving-key-in-an-incon.patch Patch58: s390-tools-sles15sp1-0015-zkey-Add-zkey-cryptsetup-tool.patch
Patch59: s390-tools-sles15sp1-0015-zkey-Add-zkey-cryptsetup-tool.patch Patch59: s390-tools-sles15sp1-0016-zkey-Add-man-page-for-zkey-cryptsetup.patch
Patch60: s390-tools-sles15sp1-0016-zkey-Add-man-page-for-zkey-cryptsetup.patch Patch60: s390-tools-sles15sp1-0017-zkey-Add-build-dependency-for-libcryptsetup-and-json.patch
Patch61: s390-tools-sles15sp1-0017-zkey-Add-build-dependency-for-libcryptsetup-and-json.patch Patch61: s390-tools-sles15sp1-0018-zkey-Add-key-verification-pattern-property.patch
Patch62: s390-tools-sles15sp1-0018-zkey-Add-key-verification-pattern-property.patch Patch62: s390-tools-sles15sp1-0019-zkey-Add-volume-type-property-to-support-LUKS2-volum.patch
Patch63: s390-tools-sles15sp1-0019-zkey-Add-volume-type-property-to-support-LUKS2-volum.patch Patch63: s390-tools-sles15sp1-01-lszcrypt-CEX6S-exploitation.patch
Patch64: s390-tools-sles15sp1-01-lszcrypt-CEX6S-exploitation.patch Patch64: s390-tools-sles15sp1-02-lszcrypt-fix-date-and-wrong-indentation.patch
Patch65: s390-tools-sles15sp1-02-lszcrypt-fix-date-and-wrong-indentation.patch Patch65: s390-tools-sles15sp1-01-chzcrypt-Corrections-at-the-chzcrypt-man-page.patch
Patch66: s390-tools-sles15sp1-01-chzcrypt-Corrections-at-the-chzcrypt-man-page.patch Patch66: s390-tools-sles15sp1-02-lszcrypt-support-for-alternate-zcrypt-device-drivers.patch
Patch67: s390-tools-sles15sp1-02-lszcrypt-support-for-alternate-zcrypt-device-drivers.patch Patch67: s390-tools-sles15sp1-01-zcryptctl-new-tool-zcryptctl-for-multiple-zcrypt-node.patch
Patch68: s390-tools-sles15sp1-01-zcryptctl-new-tool-zcryptctl-for-multiple-zcrypt-node.patch Patch68: s390-tools-sles15sp1-01-cpumf-Add-extended-counter-defintion-files-for-IBM-z.patch
Patch69: s390-tools-sles15sp1-01-cpumf-Add-extended-counter-defintion-files-for-IBM-z.patch Patch69: s390-tools-sles15sp1-02-cpumf-z14-split-counter-sets-according-to-CFVN-CSVN-.patch
Patch70: s390-tools-sles15sp1-02-cpumf-z14-split-counter-sets-according-to-CFVN-CSVN-.patch Patch70: s390-tools-sles15sp1-03-cpumf-cpumf_helper-read-split-counter-sets-part-2-2.patch
Patch71: s390-tools-sles15sp1-03-cpumf-cpumf_helper-read-split-counter-sets-part-2-2.patch Patch71: s390-tools-sles15sp1-04-cpumf-correct-z14-counter-number.patch
Patch72: s390-tools-sles15sp1-04-cpumf-correct-z14-counter-number.patch Patch72: s390-tools-sles15sp1-05-cpumf-add-missing-Description-tag-for-z13-z14-ctr-12.patch
Patch73: s390-tools-sles15sp1-05-cpumf-add-missing-Description-tag-for-z13-z14-ctr-12.patch Patch73: s390-tools-sles15sp1-06-cpumf-correct-counter-name-for-z13-and-z14.patch
Patch74: s390-tools-sles15sp1-06-cpumf-correct-counter-name-for-z13-and-z14.patch Patch74: s390-tools-sles15sp1-07-cpumf-Add-IBM-z14-ZR1-to-the-CPU-Measurement-Facilit.patch
Patch75: s390-tools-sles15sp1-07-cpumf-Add-IBM-z14-ZR1-to-the-CPU-Measurement-Facilit.patch Patch75: s390-tools-sles15sp1-01-util_path-add-function-to-check-if-a-path-exists.patch
Patch76: s390-tools-sles15sp1-01-util_path-add-function-to-check-if-a-path-exists.patch Patch76: s390-tools-sles15sp1-02-util_path-Add-description-for-util_path_exists.patch
Patch77: s390-tools-sles15sp1-02-util_path-Add-description-for-util_path_exists.patch Patch77: s390-tools-sles15sp1-03-util_path-Make-true-false-handling-consistent-with-o.patch
Patch78: s390-tools-sles15sp1-03-util_path-Make-true-false-handling-consistent-with-o.patch Patch78: s390-tools-sles15sp1-04-zpcictl-Introduce-new-tool-zpcictl.patch
Patch79: s390-tools-sles15sp1-04-zpcictl-Introduce-new-tool-zpcictl.patch Patch79: s390-tools-sles15sp1-05-zpcictl-include-sys-sysmacros.h-to-avoid-minor-major.patch
Patch80: s390-tools-sles15sp1-05-zpcictl-include-sys-sysmacros.h-to-avoid-minor-major.patch Patch80: s390-tools-sles15sp1-06-zpcictl-Rephrase-man-page-entries-and-tool-output.patch
Patch81: s390-tools-sles15sp1-06-zpcictl-Rephrase-man-page-entries-and-tool-output.patch Patch81: s390-tools-sles15sp1-07-zpcictl-Use-fopen-instead-of-open-for-writes.patch
Patch82: s390-tools-sles15sp1-07-zpcictl-Use-fopen-instead-of-open-for-writes.patch Patch82: s390-tools-sles15sp1-08-zpcictl-Read-device-link-to-obtain-device-address.patch
Patch83: s390-tools-sles15sp1-08-zpcictl-Read-device-link-to-obtain-device-address.patch Patch83: s390-tools-sles15sp1-09-zpcictl-Make-device-node-for-NVMe-optional.patch
Patch84: s390-tools-sles15sp1-09-zpcictl-Make-device-node-for-NVMe-optional.patch Patch84: s390-tools-sles15sp1-10-zpcictl-Change-wording-of-man-page-and-help-output.patch
Patch85: s390-tools-sles15sp1-10-zpcictl-Change-wording-of-man-page-and-help-output.patch Patch85: s390-tools-sles15sp1-dbginfo-gather-nvme-related-data.patch
Patch86: s390-tools-sles15sp1-dbginfo-gather-nvme-related-data.patch Patch86: s390-tools-sles15sp1-01-zdev-use-libutil-provided-path-functions.patch
Patch87: s390-tools-sles15sp1-02-zdev-Prepare-for-firmware-configuration-file-support.patch
Patch999: customize-zdev-root-update-script.patch Patch88: s390-tools-sles15sp1-03-zdev-Add-support-for-reading-firmware-configuration-.patch
Patch89: s390-tools-sles15sp1-04-zdev-Implement-no-settle.patch
Patch90: s390-tools-sles15sp1-05-zdev-Write-zfcp-lun-udev-rules-to-separate-files.patch
Patch91: s390-tools-sles15sp1-06-zdev-Add-support-for-handling-auto-configuration-dat.patch
Patch92: s390-tools-sles15sp1-07-zdev-Integrate-firmware-auto-configuration-with-drac.patch
Patch93: s390-tools-sles15sp1-08-zdev-Integrate-firmware-auto-configuration-with-init.patch
Patch94: s390-tools-sles15sp1-09-zdev-Implement-internal-device-attributes.patch
Patch95: s390-tools-sles15sp1-10-zdev-Implement-support-for-early-device-configuratio.patch
Patch96: s390-tools-sles15sp1-11-zdev-Do-not-call-zipl-on-initrd-update.patch
Patch97: s390-tools-sles15sp1-zdev-fix-qeth-BridgePort-and-VNICC-conflict-checking.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRoot: %{_tmppath}/%{name}-%{version}-build
ExclusiveArch: s390x ExclusiveArch: s390x
@ -339,8 +348,17 @@ to list files and directories.
%patch84 -p1 %patch84 -p1
%patch85 -p1 %patch85 -p1
%patch86 -p1 %patch86 -p1
%patch87 -p1
%patch999 -p1 %patch88 -p1
%patch89 -p1
%patch90 -p1
%patch91 -p1
%patch92 -p1
%patch93 -p1
%patch94 -p1
%patch95 -p1
%patch96 -p1
%patch97 -p1
cp -vi %{S:22} CAUTION cp -vi %{S:22} CAUTION