1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-10-26 17:25:10 +03:00

pvscan: use alternate device names from DEVLINKS to check filter

pvscan --cache <dev> is called by our udev rule at a time when all
the symlinks for <dev> may not be created yet (by other udev rules.)
The regex filter in lvm.conf may refer to <dev> using a symlink name
that hasn't yet been created, which would cause <dev> to not match
the filter regex.  The DEVLINKS env var, set by udev, contains all
the symlink names for <dev> 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 <dev> to be recognized by a regex
filter containing a symlink for <dev>.
This commit is contained in:
David Teigland 2023-01-19 17:37:31 -06:00
parent d9f8acb65a
commit 17a3585cbb
4 changed files with 51 additions and 25 deletions

View File

@ -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.

View File

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

View File

@ -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:

View File

@ -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 <dev> is called by our udev rule at a time when the
* symlinks for <dev> may not all be created yet (by other udev rules.)
* The regex filter in lvm.conf may refer to <dev> using a symlink name,
* so we need to know all the symlinks for <dev> in order for the filter
* to work correctly. Scanning /dev with dev_cache_scan() would usually
* find all the symlink names for <dev>, 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 <dev> 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 <dev> to be recognized by a regex filter containing a
* symlink for <dev>. We have to tell filter-regex to not set the
* preferred name for <dev> to a symlink name since the <dev> 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.",