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>
This commit is contained in:
Peter Oberparleiter
2017-09-01 11:05:54 +02:00
committed by Jan Höppner
parent f32bff9688
commit a86fb8b091
3 changed files with 55 additions and 9 deletions

View File

@@ -1333,7 +1333,7 @@ static exit_code_t cfg_write(struct device *dev, int prereq, config_t config,
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(struct selected_dev_node *sel,
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;

View File

@@ -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);
}

View File

@@ -385,6 +385,8 @@ void udev_zfcp_lun_add_device_ids(struct util_list *list)
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 char *id)
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(struct device *dev)
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 char *id, struct device_state *state)
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 char *id, struct device_state *state)
* 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)