diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h index 7f5fd12fc..4069b6116 100644 --- a/lib/commands/toolcontext.h +++ b/lib/commands/toolcontext.h @@ -207,6 +207,7 @@ struct cmd_context { unsigned udevoutput:1; unsigned online_vg_file_removed:1; unsigned disable_dm_devs:1; /* temporarily disable use of dm devs cache */ + unsigned filter_regex_set_preferred_name_disable:1; /* prevent dev_set_preferred_name */ /* * Devices and filtering. diff --git a/lib/filters/filter-regex.c b/lib/filters/filter-regex.c index 05c5b3f2d..d9ed0104c 100644 --- a/lib/filters/filter-regex.c +++ b/lib/filters/filter-regex.c @@ -179,7 +179,7 @@ static int _accept_p(struct cmd_context *cmd, struct dev_filter *f, struct devic if (m >= 0) { if (dm_bit(rf->accept, m)) { - if (!first) + if (!first && !cmd->filter_regex_set_preferred_name_disable) dev_set_preferred_name(sl, dev); return 1; diff --git a/man/lvmautoactivation.7_main b/man/lvmautoactivation.7_main index 808ea0d9f..0f7734557 100644 --- a/man/lvmautoactivation.7_main +++ b/man/lvmautoactivation.7_main @@ -184,6 +184,19 @@ system from booting. A custom systemd service could be written to run autoactivation during system startup, in which case disabling event autoactivation may be useful. . +.SS lvm.conf filter +.P +Device symlinks from /dev/disk/ can be used in the lvm.conf filter to +guard against changes in kernel device names. The /dev/disk/by-path/ or +/dev/disk/by-id/ prefixes should be included in the filter names; these +prefixes help lvm detect that symlink names are used. Filters containing +symlinks require special matching by commands run in the lvm udev rule. +.P +Common symlinks, e.g. beginning with wwn-, scsi-, pci-, or lvm-pv-uuid-, +are recommended. Uncommon or custom symlinks created by custom udev rules +may be less reliable. If a custom udev rule creates symlinks used in the +lvm filter, then the udev rule should be started prior to the lvm rule. +. .SH EXAMPLES .P VG "vg" contains two PVs: diff --git a/tools/pvscan.c b/tools/pvscan.c index 773862227..71485610b 100644 --- a/tools/pvscan.c +++ b/tools/pvscan.c @@ -910,30 +910,6 @@ static int _get_args_devs(struct cmd_context *cmd, struct dm_list *pvscan_args, struct pvscan_arg *arg; struct device_list *devl; - /* - * If no devices file is used, and lvm.conf filter is set to - * accept /dev/disk/by-id/lvm-pv-uuid-xyz or another symlink, - * but pvscan --cache is passed devname or major:minor, so - * pvscan needs to match its arg device to the filter symlink. - * setup_dev_in_dev_cache() adds /dev/sda2 to dev-cache which - * does not match a symlink to /dev/sda2, so we need a full - * dev_cache_scan that will associate all symlinks to sda2, - * which allows filter-regex to work. This case could be - * optimized if needed by adding dev-cache entries for each - * filter "a" entry (filter symlink patterns would still need - * a full dev_cache_scan.) - * (When no devices file is used and 69-dm-lvm.rules is - * used which calls pvscan directly, symlinks may not - * have been created by other rules when pvscan runs, so - * the full dev_cache_scan may still not find them.) - */ - if (!cmd->enable_devices_file && !cmd->enable_devices_list && - (_filter_uses_symlinks(cmd, devices_filter_CFG) || - _filter_uses_symlinks(cmd, devices_global_filter_CFG))) { - log_print_pvscan(cmd, "finding all devices for filter symlinks."); - dev_cache_scan(cmd); - } - /* pass NULL filter when getting devs from dev-cache, filtering is done separately */ /* in common usage, no dev will be found for a devno */ @@ -1550,6 +1526,42 @@ static int _pvscan_cache_args(struct cmd_context *cmd, int argc, char **argv, cmd->filter_nodata_only = 1; + /* + * Hack to handle regex filter that contains a symlink name for dev arg. + * pvscan --cache is called by our udev rule at a time when the + * symlinks for may not all be created yet (by other udev rules.) + * The regex filter in lvm.conf may refer to using a symlink name, + * so we need to know all the symlinks for in order for the filter + * to work correctly. Scanning /dev with dev_cache_scan() would usually + * find all the symlink names for , adding them to dev->aliases, + * which would let the filter work, but all symlinks aren't created yet. + * But, the DEVLINKS env var, set by udev, contains all the symlink + * names for that have been or *will be* created. So, we add all + * these symlink names to dev->aliases, as if we had found them in /dev. + * This allows to be recognized by a regex filter containing a + * symlink for . We have to tell filter-regex to not set the + * preferred name for to a symlink name since the may not + * be usable by that symlink name yet. + */ + if ((dm_list_size(&pvscan_devs) == 1) && + !cmd->enable_devices_file && !cmd->enable_devices_list && + (_filter_uses_symlinks(cmd, devices_filter_CFG) || + _filter_uses_symlinks(cmd, devices_global_filter_CFG))) { + char *env_str; + struct dm_list *env_aliases; + devl = dm_list_item(dm_list_first(&pvscan_devs), struct device_list); + if ((env_str = getenv("DEVLINKS"))) { + log_debug("Finding symlink names from DEVLINKS for filter regex."); + log_debug("DEVLINKS %s", env_str); + env_aliases = str_to_str_list(cmd->mem, env_str, " ", 0); + dm_list_splice(&devl->dev->aliases, env_aliases); + } else { + log_debug("Finding symlink names from /dev for filter regex."); + dev_cache_scan(cmd); + } + cmd->filter_regex_set_preferred_name_disable = 1; + } + dm_list_iterate_items_safe(devl, devl2, &pvscan_devs) { if (!cmd->filter->passes_filter(cmd, cmd->filter, devl->dev, NULL)) { log_print_pvscan(cmd, "%s excluded: %s.",