summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2023-01-19 17:37:31 -0600
committerDavid Teigland <teigland@redhat.com>2023-01-31 15:30:35 -0600
commit17a3585cbb55d9a15ced9775a18b50c53a50ee8e (patch)
tree6a4d9620ead498a87456174b494a810e67c78a67
parentd9f8acb65a78c20ac806efaeb7a1e39208e1a443 (diff)
downloadlvm2-17a3585cbb55d9a15ced9775a18b50c53a50ee8e.tar.gz
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>.
-rw-r--r--lib/commands/toolcontext.h1
-rw-r--r--lib/filters/filter-regex.c2
-rw-r--r--man/lvmautoactivation.7_main13
-rw-r--r--tools/pvscan.c60
4 files changed, 51 insertions, 25 deletions
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 <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.",