File s390-tools-sles15sp1-05-zdev-Write-zfcp-lun-udev-rules-to-separate-files.patch of Package s390-tools.13271

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)
openSUSE Build Service is sponsored by