diff --git a/SOURCES/0001-Revert-new-udev-autoactivation.patch b/SOURCES/0001-Revert-new-udev-autoactivation.patch index 122a417..2b096a7 100644 --- a/SOURCES/0001-Revert-new-udev-autoactivation.patch +++ b/SOURCES/0001-Revert-new-udev-autoactivation.patch @@ -1,7 +1,7 @@ -From 8b83a498fda9a8bcaaca3ee179832ab8f598a1a2 Mon Sep 17 00:00:00 2001 -From: Marian Csontos -Date: Fri, 3 Dec 2021 17:07:50 +0100 -Subject: [PATCH 1/2] Revert "new udev autoactivation" +From 63c4458aaf67d114c677baf657a7e9e43440f349 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Mon, 20 Dec 2021 14:22:02 -0600 +Subject: [PATCH 01/23] Revert "new udev autoactivation" This reverts commit 67722b312390cdab29c076c912e14bd739c5c0f6. --- diff --git a/SOURCES/0002-Revert-pvscan-only-add-device-args-to-dev-cache.patch b/SOURCES/0002-Revert-pvscan-only-add-device-args-to-dev-cache.patch index 700fa84..8e73676 100644 --- a/SOURCES/0002-Revert-pvscan-only-add-device-args-to-dev-cache.patch +++ b/SOURCES/0002-Revert-pvscan-only-add-device-args-to-dev-cache.patch @@ -1,7 +1,7 @@ -From 55bea5a26812ed573bc6f5c534113e140fcbbd4e Mon Sep 17 00:00:00 2001 -From: Marian Csontos -Date: Fri, 3 Dec 2021 17:11:27 +0100 -Subject: [PATCH 2/2] Revert "pvscan: only add device args to dev cache" +From 2091305b796d5552fd991c527a0359a0b4d8fde0 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Mon, 20 Dec 2021 13:38:23 -0600 +Subject: [PATCH 02/23] Revert "pvscan: only add device args to dev cache" This reverts commit 33e47182f773c1a902b533580b63a803906de55d. --- diff --git a/SOURCES/0003-pvscan-fix-messages-from-coverity-changes.patch b/SOURCES/0003-pvscan-fix-messages-from-coverity-changes.patch new file mode 100644 index 0000000..5ff1c9d --- /dev/null +++ b/SOURCES/0003-pvscan-fix-messages-from-coverity-changes.patch @@ -0,0 +1,34 @@ +From a5a2d5fa1ec47a5a548db4cf435dc84de7ce7c31 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Wed, 20 Oct 2021 16:12:41 -0500 +Subject: [PATCH 03/23] pvscan: fix messages from coverity changes + +--- + tools/pvscan.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/pvscan.c b/tools/pvscan.c +index 8e2611361..f60c4a2ca 100644 +--- a/tools/pvscan.c ++++ b/tools/pvscan.c +@@ -1354,7 +1354,7 @@ static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvs + devsize = dev->size; + if (!devsize && + !dev_get_size(dev, &devsize)) { +- log_print("pvscan[%d] PV %s can get device size.", getpid(), dev_name(dev)); ++ log_print_pvscan(cmd, "PV %s missing device size.", dev_name(dev)); + release_vg(vg); + continue; + } +@@ -1786,7 +1786,7 @@ static int _pvscan_cache_args(struct cmd_context *cmd, int argc, char **argv, + int has_pvid; + + if (!label_read_pvid(devl->dev, &has_pvid)) { +- log_print("pvscan[%d] %s cannot read.", getpid(), dev_name(devl->dev)); ++ log_print_pvscan(cmd, "%s cannot read label.", dev_name(devl->dev)); + dm_list_del(&devl->list); + continue; + } +-- +2.31.1 + diff --git a/SOURCES/0004-vgimportdevices-skip-lvmlockd-locking.patch b/SOURCES/0004-vgimportdevices-skip-lvmlockd-locking.patch new file mode 100644 index 0000000..d84d9d9 --- /dev/null +++ b/SOURCES/0004-vgimportdevices-skip-lvmlockd-locking.patch @@ -0,0 +1,39 @@ +From 074fce5c73c55e7a1547d5efff65a9f96e6db3b1 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Mon, 25 Oct 2021 12:11:17 -0500 +Subject: [PATCH 04/23] vgimportdevices: skip lvmlockd locking + +Help bootstrapping existing shared vgs into the devices file. +Reading the vg in vgimportdevices would require locking to be +started, but vgchange lockstart won't see the vg if it's not +in the devices file. The lvmlockd locks are not protecting +vg modifications so skipping them here won't be a problem. +--- + tools/vgimportdevices.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/tools/vgimportdevices.c b/tools/vgimportdevices.c +index 3f315f98f..2580613c4 100644 +--- a/tools/vgimportdevices.c ++++ b/tools/vgimportdevices.c +@@ -172,6 +172,17 @@ int vgimportdevices(struct cmd_context *cmd, int argc, char **argv) + cmd->filter_regex_with_devices_file = 1; + cmd->create_edit_devices_file = 1; + ++ /* ++ * This helps a user bootstrap existing shared VGs into the devices ++ * file. Reading the vg to import devices requires locking, but ++ * lockstart won't find the vg before it's in the devices file. ++ * So, allow importing devices without an lvmlockd lock (in a ++ * a shared vg the vg metadata won't be updated with device ids, ++ * so the lvmlockd lock isn't protecting vg modification.) ++ */ ++ cmd->lockd_gl_disable = 1; ++ cmd->lockd_vg_disable = 1; ++ + /* + * For each VG: + * device_id_add() each PV in the VG +-- +2.31.1 + diff --git a/SOURCES/0005-hints-remove-the-cmd-hints-list.patch b/SOURCES/0005-hints-remove-the-cmd-hints-list.patch new file mode 100644 index 0000000..09ef5d4 --- /dev/null +++ b/SOURCES/0005-hints-remove-the-cmd-hints-list.patch @@ -0,0 +1,95 @@ +From 00ebabfe6e1ebfceffcef335d44a6156a1c15418 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Mon, 1 Nov 2021 16:01:09 -0500 +Subject: [PATCH 05/23] hints: remove the cmd hints list + +which is no longer used after commit +"toollib: remove all devices list from process_each_pv" +--- + lib/commands/toolcontext.c | 2 -- + lib/commands/toolcontext.h | 1 - + lib/label/hints.c | 1 - + lib/label/label.c | 8 ++------ + 4 files changed, 2 insertions(+), 10 deletions(-) + +diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c +index 105aecd5d..1b7170de1 100644 +--- a/lib/commands/toolcontext.c ++++ b/lib/commands/toolcontext.c +@@ -1605,7 +1605,6 @@ struct cmd_context *create_config_context(void) + + dm_list_init(&cmd->config_files); + dm_list_init(&cmd->tags); +- dm_list_init(&cmd->hints); + + if (!_init_lvm_conf(cmd)) + goto_out; +@@ -1670,7 +1669,6 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd, + dm_list_init(&cmd->formats); + dm_list_init(&cmd->segtypes); + dm_list_init(&cmd->tags); +- dm_list_init(&cmd->hints); + dm_list_init(&cmd->config_files); + label_init(); + +diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h +index 701b7a739..356c79f8a 100644 +--- a/lib/commands/toolcontext.h ++++ b/lib/commands/toolcontext.h +@@ -206,7 +206,6 @@ struct cmd_context { + * Devices and filtering. + */ + struct dev_filter *filter; +- struct dm_list hints; + struct dm_list use_devices; /* struct dev_use for each entry in devices file */ + const char *md_component_checks; + const char *search_for_devnames; /* config file setting */ +diff --git a/lib/label/hints.c b/lib/label/hints.c +index 3dba9f8ec..e444a0c82 100644 +--- a/lib/label/hints.c ++++ b/lib/label/hints.c +@@ -365,7 +365,6 @@ static void _unlock_hints(struct cmd_context *cmd) + + void hints_exit(struct cmd_context *cmd) + { +- free_hints(&cmd->hints); + if (_hints_fd == -1) + return; + _unlock_hints(cmd); +diff --git a/lib/label/label.c b/lib/label/label.c +index 3cd912270..479a5037a 100644 +--- a/lib/label/label.c ++++ b/lib/label/label.c +@@ -1207,8 +1207,6 @@ int label_scan(struct cmd_context *cmd) + (unsigned long long)want_size_kb); + } + +- dm_list_init(&cmd->hints); +- + /* + * If we're using hints to limit which devs we scanned, verify + * that those hints were valid, and if not we need to scan the +@@ -1220,18 +1218,16 @@ int label_scan(struct cmd_context *cmd) + _scan_list(cmd, cmd->filter, &all_devs, 0, NULL); + /* scan_devs are the devs that have been scanned */ + dm_list_splice(&scan_devs, &all_devs); +- free_hints(&hints_list); + using_hints = 0; + create_hints = 0; + /* invalid hints means a new dev probably appeared and + we should search for any missing pvids again. */ + unlink_searched_devnames(cmd); +- } else { +- /* The hints may be used by another device iteration. */ +- dm_list_splice(&cmd->hints, &hints_list); + } + } + ++ free_hints(&hints_list); ++ + /* + * Check if the devices_file content is up to date and + * if not update it. +-- +2.31.1 + diff --git a/SOURCES/0006-filter-sysfs-skip-when-device-id-is-set.patch b/SOURCES/0006-filter-sysfs-skip-when-device-id-is-set.patch new file mode 100644 index 0000000..61d8fe7 --- /dev/null +++ b/SOURCES/0006-filter-sysfs-skip-when-device-id-is-set.patch @@ -0,0 +1,422 @@ +From f73be4480a5dd104a77e3ef84d7dcc80b834e593 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Tue, 2 Nov 2021 15:42:26 -0500 +Subject: [PATCH 06/23] filter-sysfs: skip when device id is set + +When a device id is set for a device, using an idtype other +than devname, it means that sysfs has been used with the device +to match the device id. So, checking for a sysfs entry for the +device in filter-sysfs is redundant. For any other cases not +covered by this (e.g. devname ids), have filter-sysfs simply +stat /sys/dev/block/major:minor to test if the device exists +in sysfs. + +The extensive processing done by filter-sysfs init is removed. +It was taking an immense amount of time with many devices, e.g. +. 1024 PVs in 520 VGs +. 520 concurrent vgchange -ay commands +. vgchange scans only PVs in the named VG (based on pvs_online + files from a pending patch) + +A large number of the vgchange commands were taking over 1 min, +and nearly half of that time was used by filter-sysfs init. +With this patch, the vgchange commands take about half the time. +--- + lib/commands/toolcontext.c | 24 ++- + lib/filters/filter-sysfs.c | 296 +++---------------------------------- + 2 files changed, 32 insertions(+), 288 deletions(-) + +diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c +index 1b7170de1..a0c78ddd6 100644 +--- a/lib/commands/toolcontext.c ++++ b/lib/commands/toolcontext.c +@@ -1143,19 +1143,6 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd) + * Update MAX_FILTERS definition above when adding new filters. + */ + +- /* +- * sysfs filter. Only available on 2.6 kernels. Non-critical. +- * Listed first because it's very efficient at eliminating +- * unavailable devices. +- * +- * TODO: I suspect that using the lvm_type and device_id +- * filters before this one may be more efficient. +- */ +- if (find_config_tree_bool(cmd, devices_sysfs_scan_CFG, NULL)) { +- if ((filters[nr_filt] = sysfs_filter_create())) +- nr_filt++; +- } +- + /* internal filter used by command processing. */ + if (!(filters[nr_filt] = internal_filter_create())) { + log_error("Failed to create internal device filter"); +@@ -1195,6 +1182,17 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd) + } + nr_filt++; + ++ /* ++ * sysfs filter. Only available on 2.6 kernels. Non-critical. ++ * Eliminates unavailable devices. ++ * TODO: this may be unnecessary now with device ids ++ * (currently not used for devs match to device id using syfs) ++ */ ++ if (find_config_tree_bool(cmd, devices_sysfs_scan_CFG, NULL)) { ++ if ((filters[nr_filt] = sysfs_filter_create())) ++ nr_filt++; ++ } ++ + /* usable device filter. Required. */ + if (!(filters[nr_filt] = usable_filter_create(cmd, cmd->dev_types, FILTER_MODE_NO_LVMETAD))) { + log_error("Failed to create usabled device filter"); +diff --git a/lib/filters/filter-sysfs.c b/lib/filters/filter-sysfs.c +index 32ac324dd..672211057 100644 +--- a/lib/filters/filter-sysfs.c ++++ b/lib/filters/filter-sysfs.c +@@ -17,288 +17,49 @@ + + #ifdef __linux__ + +-#include +-#include +- +-static int _locate_sysfs_blocks(const char *sysfs_dir, char *path, size_t len, +- unsigned *sysfs_depth) ++static int _accept_p(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name) + { ++ char path[PATH_MAX]; ++ const char *sysfs_dir; + struct stat info; +- unsigned i; +- static const struct dir_class { +- const char path[32]; +- int depth; +- } classes[] = { +- /* +- * unified classification directory for all kernel subsystems +- * +- * /sys/subsystem/block/devices +- * |-- sda -> ../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda +- * |-- sda1 -> ../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1 +- * `-- sr0 -> ../../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0 +- * +- */ +- { "subsystem/block/devices", 0 }, +- +- /* +- * block subsystem as a class +- * +- * /sys/class/block +- * |-- sda -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda +- * |-- sda1 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1 +- * `-- sr0 -> ../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0 +- * +- */ +- { "class/block", 0 }, +- +- /* +- * old block subsystem layout with nested directories +- * +- * /sys/block/ +- * |-- sda +- * | |-- capability +- * | |-- dev +- * ... +- * | |-- sda1 +- * | | |-- dev +- * ... +- * | +- * `-- sr0 +- * |-- capability +- * |-- dev +- * ... +- * +- */ +- +- { "block", 1 } +- }; +- +- for (i = 0; i < DM_ARRAY_SIZE(classes); ++i) +- if ((dm_snprintf(path, len, "%s%s", sysfs_dir, classes[i].path) >= 0) && +- (stat(path, &info) == 0)) { +- *sysfs_depth = classes[i].depth; +- return 1; +- } +- +- return 0; +-} +- +-/*---------------------------------------------------------------- +- * We need to store a set of dev_t. +- *--------------------------------------------------------------*/ +-struct entry { +- struct entry *next; +- dev_t dev; +-}; +- +-#define SET_BUCKETS 64 +-struct dev_set { +- struct dm_pool *mem; +- const char *sys_block; +- unsigned sysfs_depth; +- int initialised; +- struct entry *slots[SET_BUCKETS]; +-}; +- +-static struct dev_set *_dev_set_create(struct dm_pool *mem, +- const char *sys_block, +- unsigned sysfs_depth) +-{ +- struct dev_set *ds; +- +- if (!(ds = dm_pool_zalloc(mem, sizeof(*ds)))) +- return NULL; +- +- ds->mem = mem; +- if (!(ds->sys_block = dm_pool_strdup(mem, sys_block))) +- return NULL; +- +- ds->sysfs_depth = sysfs_depth; +- ds->initialised = 0; +- +- return ds; +-} +- +-static unsigned _hash_dev(dev_t dev) +-{ +- return (major(dev) ^ minor(dev)) & (SET_BUCKETS - 1); +-} + +-/* +- * Doesn't check that the set already contains dev. +- */ +-static int _set_insert(struct dev_set *ds, dev_t dev) +-{ +- struct entry *e; +- unsigned h = _hash_dev(dev); +- +- if (!(e = dm_pool_alloc(ds->mem, sizeof(*e)))) +- return 0; +- +- e->next = ds->slots[h]; +- e->dev = dev; +- ds->slots[h] = e; +- +- return 1; +-} ++ dev->filtered_flags &= ~DEV_FILTERED_SYSFS; + +-static int _set_lookup(struct dev_set *ds, dev_t dev) +-{ +- unsigned h = _hash_dev(dev); +- struct entry *e; ++ /* ++ * Any kind of device id other than devname has been set ++ * using sysfs so we know that sysfs info exists for dev. ++ */ ++ if (dev->id && dev->id->idtype && (dev->id->idtype != DEV_ID_TYPE_DEVNAME)) ++ return 1; + +- for (e = ds->slots[h]; e; e = e->next) +- if (e->dev == dev) ++ sysfs_dir = dm_sysfs_dir(); ++ if (sysfs_dir && *sysfs_dir) { ++ if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d", ++ sysfs_dir, (int)MAJOR(dev->dev), (int)MINOR(dev->dev)) < 0) { ++ log_debug("failed to create sysfs path"); + return 1; +- +- return 0; +-} +- +-/*---------------------------------------------------------------- +- * filter methods +- *--------------------------------------------------------------*/ +-static int _parse_dev(const char *file, FILE *fp, dev_t *result) +-{ +- unsigned major, minor; +- char buffer[64]; +- +- if (!fgets(buffer, sizeof(buffer), fp)) { +- log_error("Empty sysfs device file: %s", file); +- return 0; +- } +- +- if (sscanf(buffer, "%u:%u", &major, &minor) != 2) { +- log_error("Incorrect format for sysfs device file: %s.", file); +- return 0; +- } +- +- *result = makedev(major, minor); +- return 1; +-} +- +-static int _read_dev(const char *file, dev_t *result) +-{ +- int r; +- FILE *fp; +- +- if (!(fp = fopen(file, "r"))) { +- log_sys_error("fopen", file); +- return 0; +- } +- +- r = _parse_dev(file, fp, result); +- +- if (fclose(fp)) +- log_sys_error("fclose", file); +- +- return r; +-} +- +-/* +- * Recurse through sysfs directories, inserting any devs found. +- */ +-static int _read_devs(struct dev_set *ds, const char *dir, unsigned sysfs_depth) +-{ +- struct dirent *d; +- DIR *dr; +- struct stat info; +- char path[PATH_MAX]; +- char file[PATH_MAX]; +- dev_t dev = { 0 }; +- int r = 1; +- +- if (!(dr = opendir(dir))) { +- log_sys_error("opendir", dir); +- return 0; +- } +- +- while ((d = readdir(dr))) { +- if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) +- continue; +- +- if (dm_snprintf(path, sizeof(path), "%s/%s", dir, +- d->d_name) < 0) { +- log_warn("WARNING: sysfs path name too long: %s in %s.", +- d->d_name, dir); +- continue; + } + +- /* devices have a "dev" file */ +- if (dm_snprintf(file, sizeof(file), "%s/dev", path) < 0) { +- log_warn("WARNING: sysfs path name too long: %s in %s.", +- d->d_name, dir); +- continue; +- } +- +- if (!stat(file, &info)) { +- /* recurse if we found a device and expect subdirs */ +- if (sysfs_depth) +- _read_devs(ds, path, sysfs_depth - 1); +- +- /* add the device we have found */ +- if (_read_dev(file, &dev)) +- _set_insert(ds, dev); ++ if (lstat(path, &info)) { ++ log_debug_devs("%s: Skipping (sysfs)", dev_name(dev)); ++ dev->filtered_flags |= DEV_FILTERED_SYSFS; ++ return 0; + } + } + +- if (closedir(dr)) +- log_sys_debug("closedir", dir); +- +- return r; +-} +- +-static int _init_devs(struct dev_set *ds) +-{ +- if (!_read_devs(ds, ds->sys_block, ds->sysfs_depth)) { +- ds->initialised = -1; +- return 0; +- } +- +- ds->initialised = 1; +- +- return 1; +-} +- +- +-static int _accept_p(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name) +-{ +- struct dev_set *ds = (struct dev_set *) f->private; +- +- dev->filtered_flags &= ~DEV_FILTERED_SYSFS; +- +- if (!ds->initialised) +- _init_devs(ds); +- +- /* Pass through if initialisation failed */ +- if (ds->initialised != 1) +- return 1; +- +- if (!_set_lookup(ds, dev->dev)) { +- log_debug_devs("%s: Skipping (sysfs)", dev_name(dev)); +- dev->filtered_flags |= DEV_FILTERED_SYSFS; +- return 0; +- } +- + return 1; + } + + static void _destroy(struct dev_filter *f) + { +- struct dev_set *ds = (struct dev_set *) f->private; +- + if (f->use_count) + log_error(INTERNAL_ERROR "Destroying sysfs filter while in use %u times.", f->use_count); +- +- dm_pool_destroy(ds->mem); ++ free(f); + } + + struct dev_filter *sysfs_filter_create(void) + { + const char *sysfs_dir = dm_sysfs_dir(); +- char sys_block[PATH_MAX]; +- unsigned sysfs_depth; +- struct dm_pool *mem; +- struct dev_set *ds; + struct dev_filter *f; + + if (!*sysfs_dir) { +@@ -306,26 +67,12 @@ struct dev_filter *sysfs_filter_create(void) + return NULL; + } + +- if (!_locate_sysfs_blocks(sysfs_dir, sys_block, sizeof(sys_block), &sysfs_depth)) +- return NULL; +- +- if (!(mem = dm_pool_create("sysfs", 256))) { +- log_error("sysfs pool creation failed"); +- return NULL; +- } +- +- if (!(ds = _dev_set_create(mem, sys_block, sysfs_depth))) { +- log_error("sysfs dev_set creation failed"); +- goto bad; +- } +- +- if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) ++ if (!(f = zalloc(sizeof(*f)))) + goto_bad; + + f->passes_filter = _accept_p; + f->destroy = _destroy; + f->use_count = 0; +- f->private = ds; + f->name = "sysfs"; + + log_debug_devs("Sysfs filter initialised."); +@@ -333,7 +80,6 @@ struct dev_filter *sysfs_filter_create(void) + return f; + + bad: +- dm_pool_destroy(mem); + return NULL; + } + +-- +2.31.1 + diff --git a/SOURCES/0007-lvmdevices-increase-open-file-limit.patch b/SOURCES/0007-lvmdevices-increase-open-file-limit.patch new file mode 100644 index 0000000..6a586d7 --- /dev/null +++ b/SOURCES/0007-lvmdevices-increase-open-file-limit.patch @@ -0,0 +1,61 @@ +From f732f3d53faee3732d0f4a666c378709e6c2f5e9 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Fri, 29 Oct 2021 14:49:36 -0500 +Subject: [PATCH 07/23] lvmdevices: increase open file limit + +--- + lib/label/label.c | 4 ++-- + lib/label/label.h | 2 ++ + tools/lvmdevices.c | 3 +++ + 3 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/lib/label/label.c b/lib/label/label.c +index 479a5037a..9fac3e464 100644 +--- a/lib/label/label.c ++++ b/lib/label/label.c +@@ -891,7 +891,7 @@ static int _setup_bcache(void) + + #define BASE_FD_COUNT 32 /* Number of open files we want apart from devs */ + +-static void _prepare_open_file_limit(struct cmd_context *cmd, unsigned int num_devs) ++void prepare_open_file_limit(struct cmd_context *cmd, unsigned int num_devs) + { + #ifdef HAVE_PRLIMIT + struct rlimit old = { 0 }, new; +@@ -1165,7 +1165,7 @@ int label_scan(struct cmd_context *cmd) + * which we want to keep open) is higher than the current + * soft limit. + */ +- _prepare_open_file_limit(cmd, dm_list_size(&scan_devs)); ++ prepare_open_file_limit(cmd, dm_list_size(&scan_devs)); + + /* + * Do the main scan. +diff --git a/lib/label/label.h b/lib/label/label.h +index 8b510eb79..34563efd0 100644 +--- a/lib/label/label.h ++++ b/lib/label/label.h +@@ -134,4 +134,6 @@ void dev_invalidate(struct device *dev); + void dev_set_last_byte(struct device *dev, uint64_t offset); + void dev_unset_last_byte(struct device *dev); + ++void prepare_open_file_limit(struct cmd_context *cmd, unsigned int num_devs); ++ + #endif +diff --git a/tools/lvmdevices.c b/tools/lvmdevices.c +index 8d9634848..3f104f7de 100644 +--- a/tools/lvmdevices.c ++++ b/tools/lvmdevices.c +@@ -176,6 +176,9 @@ int lvmdevices(struct cmd_context *cmd, int argc, char **argv) + log_error("Failed to read the devices file."); + return ECMD_FAILED; + } ++ ++ prepare_open_file_limit(cmd, dm_list_size(&cmd->use_devices)); ++ + dev_cache_scan(cmd); + device_ids_match(cmd); + +-- +2.31.1 + diff --git a/SOURCES/0008-filter-sysfs-support-old-kernels-without-sys-dev-blo.patch b/SOURCES/0008-filter-sysfs-support-old-kernels-without-sys-dev-blo.patch new file mode 100644 index 0000000..cd4a4e3 --- /dev/null +++ b/SOURCES/0008-filter-sysfs-support-old-kernels-without-sys-dev-blo.patch @@ -0,0 +1,73 @@ +From fad2b3dc8c44ba1222508ee78b5f161994efe638 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Tue, 9 Nov 2021 11:54:48 -0600 +Subject: [PATCH 08/23] filter-sysfs: support old kernels without sys/dev/block + +rhel5 for example doesn't have /sys/dev/block +--- + lib/filters/filter-sysfs.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/lib/filters/filter-sysfs.c b/lib/filters/filter-sysfs.c +index 672211057..d8de7940b 100644 +--- a/lib/filters/filter-sysfs.c ++++ b/lib/filters/filter-sysfs.c +@@ -15,6 +15,8 @@ + #include "lib/misc/lib.h" + #include "lib/filters/filter.h" + ++static int _sys_dev_block_found; ++ + #ifdef __linux__ + + static int _accept_p(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name) +@@ -23,6 +25,9 @@ static int _accept_p(struct cmd_context *cmd, struct dev_filter *f, struct devic + const char *sysfs_dir; + struct stat info; + ++ if (!_sys_dev_block_found) ++ return 1; ++ + dev->filtered_flags &= ~DEV_FILTERED_SYSFS; + + /* +@@ -57,6 +62,26 @@ static void _destroy(struct dev_filter *f) + free(f); + } + ++static void _check_sys_dev_block(void) ++{ ++ char path[PATH_MAX]; ++ const char *sysfs_dir; ++ struct stat info; ++ ++ sysfs_dir = dm_sysfs_dir(); ++ if (sysfs_dir && *sysfs_dir) { ++ if (dm_snprintf(path, sizeof(path), "%sdev/block", sysfs_dir) < 0) ++ return; ++ ++ if (lstat(path, &info)) { ++ log_debug("filter-sysfs disabled: /sys/dev/block not found"); ++ _sys_dev_block_found = 0; ++ } else { ++ _sys_dev_block_found = 1; ++ } ++ } ++} ++ + struct dev_filter *sysfs_filter_create(void) + { + const char *sysfs_dir = dm_sysfs_dir(); +@@ -67,6 +92,9 @@ struct dev_filter *sysfs_filter_create(void) + return NULL; + } + ++ /* support old kernels that don't have this */ ++ _check_sys_dev_block(); ++ + if (!(f = zalloc(sizeof(*f)))) + goto_bad; + +-- +2.31.1 + diff --git a/SOURCES/0009-device_id-match-different-dm-device-names.patch b/SOURCES/0009-device_id-match-different-dm-device-names.patch new file mode 100644 index 0000000..94ec305 --- /dev/null +++ b/SOURCES/0009-device_id-match-different-dm-device-names.patch @@ -0,0 +1,155 @@ +From 459d931a9bfe4c9adcbbf2e76fdf35fda5b13c61 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Fri, 12 Nov 2021 16:42:51 -0600 +Subject: [PATCH 09/23] device_id: match different dm device names + +If a devices file entry for a dm device is using the devname +for the device id, then recognize different dm names as matching. +--- + lib/device/device_id.c | 81 +++++++++++++++++++++++++++++++++++------- + 1 file changed, 69 insertions(+), 12 deletions(-) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index eb06109ff..dea739fc4 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -1360,6 +1360,10 @@ void device_id_update_vg_uuid(struct cmd_context *cmd, struct volume_group *vg, + + static int _idtype_compatible_with_major_number(struct cmd_context *cmd, int idtype, int major) + { ++ /* devname can be used with any kind of device */ ++ if (idtype == DEV_ID_TYPE_DEVNAME) ++ return 1; ++ + if (idtype == DEV_ID_TYPE_MPATH_UUID || + idtype == DEV_ID_TYPE_CRYPT_UUID || + idtype == DEV_ID_TYPE_LVMLV_UUID) +@@ -1388,6 +1392,43 @@ static int _idtype_compatible_with_major_number(struct cmd_context *cmd, int idt + return 1; + } + ++static int _match_dm_devnames(struct cmd_context *cmd, struct device *dev, ++ struct dev_id *id, struct dev_use *du) ++{ ++ struct stat buf; ++ ++ if (MAJOR(dev->dev) != cmd->dev_types->device_mapper_major) ++ return 0; ++ ++ if (id->idname && du->idname && !strcmp(id->idname, du->idname)) ++ return 1; ++ ++ if (du->idname && !strcmp(du->idname, dev_name(dev))) { ++ log_debug("Match device_id %s %s to %s: ignoring idname %s", ++ idtype_to_str(du->idtype), du->idname, dev_name(dev), id->idname ?: "."); ++ return 1; ++ } ++ ++ if (!du->idname) ++ return 0; ++ ++ /* detect that a du entry is for a dm device */ ++ ++ if (!strncmp(du->idname, "/dev/dm-", 8) || !strncmp(du->idname, "/dev/mapper/", 12)) { ++ if (stat(du->idname, &buf)) ++ return 0; ++ ++ if ((MAJOR(buf.st_rdev) == cmd->dev_types->device_mapper_major) && ++ (MINOR(buf.st_rdev) == MINOR(dev->dev))) { ++ log_debug("Match device_id %s %s to %s: using other dm name, ignoring %s", ++ idtype_to_str(du->idtype), du->idname, dev_name(dev), id->idname ?: "."); ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ + /* + * check for dev->ids entry with du->idtype, if found compare it, + * if not, system_read of this type and add entry to dev->ids, compare it. +@@ -1408,35 +1449,52 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct + * so we can skip trying to match certain du entries based simply on + * the major number of dev. + */ +- if (!_idtype_compatible_with_major_number(cmd, du->idtype, (int)MAJOR(dev->dev))) ++ if (!_idtype_compatible_with_major_number(cmd, du->idtype, (int)MAJOR(dev->dev))) { ++ /* ++ log_debug("Mismatch device_id %s %s to %s: wrong major", ++ idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev)); ++ */ + return 0; ++ } + + if (!dev_get_partition_number(dev, &part)) { +- log_debug("compare %s failed to get dev partition", dev_name(dev)); ++ /* ++ log_debug("Mismatch device_id %s %s to %s: no partition", ++ idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev)); ++ */ + return 0; + } + if (part != du->part) { + /* +- log_debug("compare mis %s %s part %d to %s part %d", +- idtype_to_str(du->idtype), du->idname ?: ".", du->part, dev_name(dev), part); ++ log_debug("Mismatch device_id %s %s to %s: wrong partition %d vs %d", ++ idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev), du->part, part); + */ + return 0; + } + + dm_list_iterate_items(id, &dev->ids) { + if (id->idtype == du->idtype) { +- if (id->idname && !strcmp(id->idname, du->idname)) { ++ if ((id->idtype == DEV_ID_TYPE_DEVNAME) && _match_dm_devnames(cmd, dev, id, du)) { ++ /* dm devs can have differing names that we know still match */ ++ du->dev = dev; ++ dev->id = id; ++ dev->flags |= DEV_MATCHED_USE_ID; ++ log_debug("Match device_id %s %s to %s: dm names", ++ idtype_to_str(du->idtype), du->idname, dev_name(dev)); ++ return 1; ++ ++ } else if (id->idname && !strcmp(id->idname, du->idname)) { + du->dev = dev; + dev->id = id; + dev->flags |= DEV_MATCHED_USE_ID; + log_debug("Match device_id %s %s to %s", + idtype_to_str(du->idtype), du->idname, dev_name(dev)); + return 1; ++ + } else { + /* +- log_debug("compare mis %s %s to %s %s", +- idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev), +- ((id->idtype != DEV_ID_TYPE_DEVNAME) && id->idname) ? id->idname : ""); ++ log_debug("Mismatch device_id %s %s to %s: idname %s", ++ idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev), id->idname ?: ":"); + */ + return 0; + } +@@ -1456,7 +1514,7 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct + id->dev = dev; + dm_list_add(&dev->ids, &id->list); + /* +- log_debug("compare mis %s %s to %s no idtype", ++ log_debug("Mismatch device_id %s %s to %s: no idtype", + idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev)); + */ + return 0; +@@ -1481,9 +1539,8 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct + } + + /* +- log_debug("compare mis %s %s to %s %s", +- idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev), +- ((id->idtype != DEV_ID_TYPE_DEVNAME) && id->idname) ? id->idname : ""); ++ log_debug("Mismatch device_id %s %s to %s: idname %s", ++ idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev), idname); + */ + return 0; + } +-- +2.31.1 + diff --git a/SOURCES/0010-device_id-fix-search-on-filtered-device.patch b/SOURCES/0010-device_id-fix-search-on-filtered-device.patch new file mode 100644 index 0000000..edc2d3e --- /dev/null +++ b/SOURCES/0010-device_id-fix-search-on-filtered-device.patch @@ -0,0 +1,134 @@ +From 5533cd7bf4c1edc5d8fb0e95d2f83b2b2d446339 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Tue, 16 Nov 2021 09:29:24 -0600 +Subject: [PATCH 10/23] device_id: fix search on filtered device + +When devnames are used as device ids and devnames change, +then new devices need to be located for the PVs. If the old +devname is now used by a filtered device, this was preventing +the code from searching for the new device, so the PV was +reported as missing. +--- + lib/device/device_id.c | 16 ++++++- + test/shell/devicesfile-devname.sh | 69 +++++++++++++++++++++++++++++++ + 2 files changed, 83 insertions(+), 2 deletions(-) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index dea739fc4..48f1682a3 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -2025,12 +2025,19 @@ void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_l + search_auto = !strcmp(cmd->search_for_devnames, "auto"); + + dm_list_iterate_items(du, &cmd->use_devices) { +- if (du->dev) +- continue; + if (!du->pvid) + continue; + if (du->idtype != DEV_ID_TYPE_DEVNAME) + continue; ++ ++ /* ++ * if the old incorrect devname is now a device that's ++ * filtered and not scanned, e.g. an mpath component, ++ * then we want to look for the pvid on a new device. ++ */ ++ if (du->dev && !du->dev->filtered_flags) ++ continue; ++ + if (!(dil = dm_pool_zalloc(cmd->mem, sizeof(*dil)))) + continue; + +@@ -2055,6 +2062,11 @@ void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_l + * the searched file, so a subsequent lvm command will do the search + * again. In future perhaps we could add a policy to automatically + * remove a devices file entry that's not been found for some time. ++ * ++ * TODO: like the hint file, add a hash of all devnames to the searched ++ * file so it can be ignored and removed if the devs/hash change. ++ * If hints are enabled, the hints invalidation could also remove the ++ * searched file. + */ + if (_searched_devnames_exists(cmd)) { + log_debug("Search for PVIDs skipped for %s", _searched_file); +diff --git a/test/shell/devicesfile-devname.sh b/test/shell/devicesfile-devname.sh +index f95be52b1..a99fe3e9a 100644 +--- a/test/shell/devicesfile-devname.sh ++++ b/test/shell/devicesfile-devname.sh +@@ -545,4 +545,73 @@ grep "$PVID2" "$DF" |tee out + grep "$dev2" out + not grep "$dev1" out + ++vgchange -an $vg1 ++vgchange -an $vg2 ++vgremove -ff $vg1 ++vgremove -ff $vg2 ++ ++# devnames change so the new devname now refers to a filtered device, ++# e.g. an mpath or md component, which is not scanned ++ ++wait_md_create() { ++ local md=$1 ++ ++ while :; do ++ if ! grep "$(basename $md)" /proc/mdstat; then ++ echo "$md not ready" ++ cat /proc/mdstat ++ sleep 2 ++ else ++ break ++ fi ++ done ++ echo "$md" > WAIT_MD_DEV ++} ++ ++aux wipefs_a "$dev1" ++aux wipefs_a "$dev2" ++aux wipefs_a "$dev3" ++aux wipefs_a "$dev4" ++ ++mddev="/dev/md33" ++not grep $mddev /proc/mdstat || skip ++ ++rm "$DF" ++touch "$DF" ++vgcreate $vg1 "$dev1" "$dev2" ++cat "$DF" ++cp "$DF" "$ORIG" ++ ++# PVID with dashes for matching pvs -o+uuid output ++OPVID1=`pvs "$dev1" --noheading -o uuid | awk '{print $1}'` ++OPVID2=`pvs "$dev2" --noheading -o uuid | awk '{print $1}'` ++ ++# PVID without dashes for matching devices file fields ++PVID1=`pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}'` ++PVID2=`pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}'` ++ ++mdadm --create --metadata=1.0 "$mddev" --level 1 --chunk=64 --raid-devices=2 "$dev3" "$dev4" ++wait_md_create "$mddev" ++ ++sed -e "s|DEVNAME=$dev1|DEVNAME=$dev3|" "$ORIG" > tmp1.devices ++sed -e "s|IDNAME=$dev1|IDNAME=$dev3|" tmp1.devices > "$DF" ++cat "$DF" ++pvs -o+uuid |tee out ++grep "$dev1" out ++grep "$dev2" out ++grep "$OPVID1" out ++grep "$OPVID2" out ++not grep "$dev3" out ++not grep "$dev4" out ++ ++grep "$dev1" "$DF" ++grep "$dev2" "$DF" ++grep "$PVID1" "$DF" ++grep "$PVID2" "$DF" ++not grep "$dev3" "$DF" ++not grep "$dev4" "$DF" ++ ++mdadm --stop "$mddev" ++aux udev_wait ++ + vgremove -ff $vg1 +-- +2.31.1 + diff --git a/SOURCES/0011-device_id-searched_devnames-improvements.patch b/SOURCES/0011-device_id-searched_devnames-improvements.patch new file mode 100644 index 0000000..d8a658e --- /dev/null +++ b/SOURCES/0011-device_id-searched_devnames-improvements.patch @@ -0,0 +1,102 @@ +From 39adf3e513ac7b1cbbbf0189f973573ade3c8939 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Tue, 16 Nov 2021 11:26:41 -0600 +Subject: [PATCH 11/23] device_id: searched_devnames improvements + +Remove the searched_devnames file in a couple more places: +. When hints need refreshing it's possible that a missing + devices file entry could be found by searching devices + again. +. When a devices file entry devname is first found to be + incorrect, a new search for missing entries may be + useful. +--- + lib/device/device_id.c | 28 ++++++++++++++++++++++++++-- + lib/label/hints.c | 10 ++++++++++ + 2 files changed, 36 insertions(+), 2 deletions(-) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index 48f1682a3..ce7ded154 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -74,6 +74,8 @@ void unlink_searched_devnames(struct cmd_context *cmd) + + if (unlink(_searched_file)) + log_debug("unlink %s errno %d", _searched_file, errno); ++ else ++ log_debug("unlink %s", _searched_file); + } + + static int _searched_devnames_exists(struct cmd_context *cmd) +@@ -780,7 +782,7 @@ static void _device_ids_update_try(struct cmd_context *cmd) + + /* Defer updates to non-pvscan-cache commands. */ + if (cmd->pvscan_cache_single) { +- log_print("pvscan[%d] skip updating devices file.", getpid()); ++ log_print("Devices file update skipped."); + return; + } + +@@ -1441,8 +1443,22 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct + const char *idname; + int part; + +- if (!du->idname || !du->idtype) ++ /* ++ * The idname will be removed from an entry with devname type when the ++ * devname is read and found to hold a different PVID than the PVID in ++ * the entry. At that point we only have the PVID and no known ++ * location for it. ++ */ ++ if (!du->idname || !du->idtype) { ++ /* ++ log_debug("Mismatch device_id %s %s %s to %s", ++ du->idtype ? idtype_to_str(du->idtype) : "idtype_missing", ++ du->idname ? du->idname : "idname_missing", ++ du->devname ? du->devname : "devname_missing", ++ dev_name(dev)); ++ */ + return 0; ++ } + + /* + * Some idtypes can only match devices with a specific major number, +@@ -1957,6 +1973,14 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs, + *device_ids_invalid = 1; + } + ++ /* ++ * When a new devname/pvid mismatch is discovered, a new search for the ++ * pvid should be permitted (searched_devnames may exist to suppress ++ * searching for other pvids.) ++ */ ++ if (update_file) ++ unlink_searched_devnames(cmd); ++ + /* FIXME: for wrong devname cases, wait to write new until device_ids_find_renamed_devs? */ + + /* +diff --git a/lib/label/hints.c b/lib/label/hints.c +index e444a0c82..3ce9634f2 100644 +--- a/lib/label/hints.c ++++ b/lib/label/hints.c +@@ -1390,6 +1390,16 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints, + log_debug("get_hints: needs refresh"); + free_hints(&hints_list); + ++ /* ++ * This is not related to hints, and is probably unnecessary, ++ * but it could possibly help. When hints become invalid it's ++ * usually becaues devs on the system have changed, and that ++ * also means that a missing devices file entry might be found ++ * by searching devices again. (the searched_devnames ++ * mechanism should eventually be replaced) ++ */ ++ unlink_searched_devnames(cmd); ++ + if (!_lock_hints(cmd, LOCK_EX, NONBLOCK)) + return 0; + +-- +2.31.1 + diff --git a/SOURCES/0012-tests-pv-ext-flags-work-with-devices-file.patch b/SOURCES/0012-tests-pv-ext-flags-work-with-devices-file.patch new file mode 100644 index 0000000..1e421c0 --- /dev/null +++ b/SOURCES/0012-tests-pv-ext-flags-work-with-devices-file.patch @@ -0,0 +1,40 @@ +From 9c9bf13186d387d807f279c112745768c8b32513 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Tue, 16 Nov 2021 14:21:07 -0600 +Subject: [PATCH 12/23] tests pv-ext-flags: work with devices file + +--- + test/shell/pv-ext-flags.sh | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/test/shell/pv-ext-flags.sh b/test/shell/pv-ext-flags.sh +index 3e6bcff76..ae4d6b7ff 100644 +--- a/test/shell/pv-ext-flags.sh ++++ b/test/shell/pv-ext-flags.sh +@@ -57,9 +57,11 @@ dd if="$dev1" of=dev1_backup bs=1M + + # pvcreate and pvremove can be forced even if the PV is marked as used + pvremove -ff -y "$dev1" ++lvmdevices --deldev "$dev1" || true + dd if=dev1_backup of="$dev1" bs=1M + pvcreate -ff -y "$dev1" + dd if=dev1_backup of="$dev1" bs=1M ++lvmdevices --adddev "$dev1" || true + + # prepare a VG with $dev1 and $dev both having 1 MDA + aux enable_dev "$dev2" +@@ -116,9 +118,11 @@ dd if="$dev1" of=dev1_backup bs=1M + + # pvcreate and pvremove can be forced even if the PV is marked as used + pvremove -ff -y "$dev1" ++lvmdevices --deldev "$dev1" || true + dd if=dev1_backup of="$dev1" bs=1M + pvcreate -ff -y "$dev1" + dd if=dev1_backup of="$dev1" bs=1M ++lvmdevices --adddev "$dev1" || true + + # prepare a VG with $dev1 and $dev both having 1 MDA + aux enable_dev "$dev2" +-- +2.31.1 + diff --git a/SOURCES/0013-display-ignore-reportformat.patch b/SOURCES/0013-display-ignore-reportformat.patch new file mode 100644 index 0000000..f7dc091 --- /dev/null +++ b/SOURCES/0013-display-ignore-reportformat.patch @@ -0,0 +1,91 @@ +From 594c1fec1644fdf291aa0ff23de20db65c4cfadf Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Wed, 17 Nov 2021 10:40:27 -0600 +Subject: [PATCH 13/23] display: ignore --reportformat + +Using the option would do nothing useful but would +print extraneous braces. +--- + tools/command-lines.in | 12 ++++++------ + tools/lvmcmdline.c | 15 +++++++++++++++ + 2 files changed, 21 insertions(+), 6 deletions(-) + +diff --git a/tools/command-lines.in b/tools/command-lines.in +index 10b23e75d..00ac08934 100644 +--- a/tools/command-lines.in ++++ b/tools/command-lines.in +@@ -1359,10 +1359,10 @@ OO: --aligned, --all, --binary, --colon, --columns, + --configreport ConfigReport, --foreign, --history, --ignorelockingfailure, + --logonly, --maps, --noheadings, + --nosuffix, --options String, --sort String, --readonly, +---reportformat ReportFmt, --segments, --select String, --separator String, ++--segments, --select String, --separator String, + --shared, --unbuffered, --units Units + OP: VG|LV|Tag ... +-IO: --partial, --ignoreskippedcluster ++IO: --partial, --ignoreskippedcluster, --reportformat ReportFmt + ID: lvdisplay_general + + --- +@@ -1590,10 +1590,10 @@ pvdisplay + OO: --aligned, --all, --binary, --colon, --columns, --configreport ConfigReport, + --foreign, --ignorelockingfailure, + --logonly, --maps, --noheadings, --nosuffix, --options String, +---readonly, --reportformat ReportFmt, --select String, --separator String, --shared, ++--readonly, --select String, --separator String, --shared, + --short, --sort String, --unbuffered, --units Units + OP: PV|Tag ... +-IO: --ignoreskippedcluster ++IO: --ignoreskippedcluster, --reportformat ReportFmt + ID: pvdisplay_general + + --- +@@ -1809,10 +1809,10 @@ vgdisplay + OO: --activevolumegroups, --aligned, --binary, --colon, --columns, + --configreport ConfigReport, --foreign, --ignorelockingfailure, + --logonly, --noheadings, --nosuffix, +---options String, --readonly, --reportformat ReportFmt, --select String, ++--options String, --readonly, --select String, + --shared, --short, --separator String, --sort String, --unbuffered, --units Units + OP: VG|Tag ... +-IO: --partial, --ignoreskippedcluster ++IO: --partial, --ignoreskippedcluster, --reportformat ReportFmt + ID: vgdisplay_general + + --- +diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c +index 1e12bedca..1727ba089 100644 +--- a/tools/lvmcmdline.c ++++ b/tools/lvmcmdline.c +@@ -3058,6 +3058,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) + int i; + int skip_hyphens; + int refresh_done = 0; ++ int io; + + /* Avoid excessive access to /etc/localtime and set TZ variable for glibc + * so it does not need to check /etc/localtime everytime that needs that info */ +@@ -3140,6 +3141,20 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) + if (!(cmd->command = _find_command(cmd, cmd->name, &argc, argv))) + return EINVALID_CMD_LINE; + ++ /* ++ * If option --foo is set which is listed in IO (ignore option) in ++ * command-lines.in, then unset foo. Commands won't usually use an ++ * ignored option, but there can be shared code that checks for --foo, ++ * and should not find it to be set. ++ */ ++ for (io = 0; io < cmd->command->io_count; io++) { ++ int opt = cmd->command->ignore_opt_args[io].opt; ++ if (arg_is_set(cmd, opt)) { ++ log_debug("Ignore opt %d", opt); ++ cmd->opt_arg_values[opt].count = 0; ++ } ++ } ++ + /* + * Remaining position args after command name and --options are removed. + */ +-- +2.31.1 + diff --git a/SOURCES/0014-fix-spelling-of-pruning.patch b/SOURCES/0014-fix-spelling-of-pruning.patch new file mode 100644 index 0000000..e24450a --- /dev/null +++ b/SOURCES/0014-fix-spelling-of-pruning.patch @@ -0,0 +1,25 @@ +From 7ac0b3c119b1cbb8e0b4969ece0b279637ace8c3 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Fri, 19 Nov 2021 12:02:35 -0600 +Subject: [PATCH 14/23] fix spelling of pruning + +--- + lib/format_text/archive.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/format_text/archive.c b/lib/format_text/archive.c +index 09a472b4c..2e8792a93 100644 +--- a/lib/format_text/archive.c ++++ b/lib/format_text/archive.c +@@ -219,7 +219,7 @@ static void _remove_expired(const char *dir, const char *vgname, + + sum /= 1024 * 1024; + if (sum > 128 || archives_size > 8192) +- log_print_unless_silent("Consider prunning %s VG archive with more then %u MiB in %u files (check archiving is needed in lvm.conf).", ++ log_print_unless_silent("Consider pruning %s VG archive with more then %u MiB in %u files (check archiving is needed in lvm.conf).", + vgname, (unsigned)sum, archives_size); + } + +-- +2.31.1 + diff --git a/SOURCES/0015-man-lvmautoactivation.patch b/SOURCES/0015-man-lvmautoactivation.patch new file mode 100644 index 0000000..0128098 --- /dev/null +++ b/SOURCES/0015-man-lvmautoactivation.patch @@ -0,0 +1,416 @@ +From 25dbe3dd825a629ff7f67cb43342cc345071d3f7 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Wed, 24 Nov 2021 16:03:39 -0600 +Subject: [PATCH 15/23] man: lvmautoactivation + +new topical man page describing autoactivation +--- + man/Makefile.in | 2 +- + man/lvm.8_main | 1 + + man/lvmautoactivation.7_main | 280 +++++++++++++++++++++++++++++++++++ + man/pvscan.8_des | 63 ++++---- + 4 files changed, 309 insertions(+), 37 deletions(-) + create mode 100644 man/lvmautoactivation.7_main + +diff --git a/man/Makefile.in b/man/Makefile.in +index 40248d640..ba6f2046f 100644 +--- a/man/Makefile.in ++++ b/man/Makefile.in +@@ -33,7 +33,7 @@ CMIRRORDMAN = cmirrord.8 + LVMDBUSDMAN = lvmdbusd.8 + + MAN5=lvm.conf.5 +-MAN7=lvmsystemid.7 lvmreport.7 lvmraid.7 ++MAN7=lvmsystemid.7 lvmreport.7 lvmraid.7 lvmautoactivation.7 + + MAN8=lvm.8 lvmdump.8 lvm-fullreport.8 lvm-lvpoll.8 \ + lvcreate.8 lvchange.8 lvmconfig.8 lvconvert.8 lvdisplay.8 \ +diff --git a/man/lvm.8_main b/man/lvm.8_main +index 6f86d0353..a008a3bc0 100644 +--- a/man/lvm.8_main ++++ b/man/lvm.8_main +@@ -579,6 +579,7 @@ Prepends source file name and code line number with libdm debugging. + .BR lvmraid (7), + .BR lvmthin (7), + .BR lvmcache (7), ++.BR lvmautoactivation (7), + .P + .BR dmsetup (8), + .BR dmstats (8), +diff --git a/man/lvmautoactivation.7_main b/man/lvmautoactivation.7_main +new file mode 100644 +index 000000000..87c15a3d1 +--- /dev/null ++++ b/man/lvmautoactivation.7_main +@@ -0,0 +1,280 @@ ++.TH "LVMAUTOACTIVATION" "7" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\"" ++. ++.SH NAME ++. ++lvmautoactivation \(em LVM autoactivation ++. ++.SH DESCRIPTION ++. ++Autoactivation is the activation of LVs performed automatically by the ++system in response to LVM devices being attached to the machine. When all ++PVs in a VG have been attached, the VG is complete, and LVs in the VG are ++activated. ++.P ++Autoactivation of VGs, or specific LVs, can be prevented using vgchange or ++lvchange --setautoactivation n. The lvm.conf auto_activation_volume_list ++is another way to limit autoactivation. ++.P ++The most common form of autoactivation is "event based", in which complete ++VGs are activated in response to uevents which occur during system startup ++or at any time after the system has started. Another form of ++autoactivation is "service based" in which complete VGs are activated at a ++fixed point during system startup by a systemd service, and are not ++activated in response to uevents. This can be controlled with the ++lvm.conf setting event_activation. ++.P ++Event based autoactivation is driven by udev, udev rules, and systemd. ++When a device is attached to a machine, a uevent is generated by the ++kernel to notify userspace of the new device. systemd-udev runs udev ++rules to process the new device. Udev rules use blkid to identify the ++device as an LVM PV and then execute the lvm-specific udev rule for the ++device, which triggers autoactivation. ++.P ++There are two variations of event based autoactivation that may be used a ++system, depending on the LVM udev rule that is installed (found in ++/lib/udev/rules.d/.) The following summarizes the steps in each rule ++which lead to autoactivation: ++.P ++.B 69-dm-lvm-metad.rules ++. ++.IP \[bu] 2 ++device /dev/name with major:minor X:Y is attached to the machine ++. ++.IP \[bu] 2 ++systemd/udev runs blkid to identify /dev/name as an LVM PV ++. ++.IP \[bu] 2 ++udev rule 69-dm-lvm-metad.rules is run for /dev/name ++. ++.IP \[bu] 2 ++the lvm udev rule runs the systemd service lvm2-pvscan@X:Yservice ++. ++.IP \[bu] 2 ++the lvm2-pvscan service runs: ++.br ++pvscan --cache -aay --major X --minor Y ++. ++.IP \[bu] 2 ++pvscan reads the device, records that the PV is online ++(see pvs_online), and checks if the VG is complete. ++. ++.IP \[bu] 2 ++if the VG is complete, pvscan creates the vgs_online temp file, ++and activates the VG. ++. ++.IP \[bu] 2 ++the activation command output can be seen from ++systemctl status lvm2-pvscan* ++.P ++.B 69-dm-lvm.rules ++. ++.IP \[bu] 2 ++device /dev/name with major:minor X:Y is attached to the machine ++. ++.IP \[bu] 2 ++systemd/udev runs blkid to identify /dev/name as an LVM PV ++. ++.IP \[bu] 2 ++udev rule 69-dm-lvm.rules is run for /dev/name ++. ++.IP \[bu] 2 ++the lvm udev rule runs: ++.br ++pvscan --cache --listvg --checkcomplete --vgonline ++.br ++--autoactivation event --udevoutput --journal=output /dev/name ++. ++.IP \[bu] 2 ++pvscan reads the device, records that the PV is online ++(see pvs_online), and checks if the VG is complete. ++. ++.IP \[bu] 2 ++if the VG is complete, pvscan creates the vgs_online temp file, ++and prints the name of the VG for the udev rule to import: ++LVM_VG_NAME_COMPLETE='vgname' ++. ++.IP \[bu] 2 ++if the lvm udev rule sees LVM_VG_NAME_COMPLETE from pvscan, ++it activates the VG using a transient systemd service named ++lvm-activate-. ++. ++.IP \[bu] 2 ++the lvm-activate- service runs ++.br ++vgchange -aay --autoactivation event ++. ++.IP \[bu] 2 ++the activation command output can be seen from ++systemctl status lvm-activate- ++.P ++. ++.SS pvscan options ++.P ++.B --cache ++.br ++Read the arg (and only that device), and record that ++the PV is online by creating the /run/lvm/pvs_online/ ++file containing the name of the VG and the device for the PV. ++.P ++.B -aay ++.br ++Activate the VG from the pvscan command ++(includes implicit --checkcomplete and --vgonline.) ++.P ++.B --checkcomplete ++.br ++Check if the VG is complete, i.e. all PVs are present on ++the system, by checking /run/lvm/pvs_online/ files. ++.P ++.B --vgonline ++.br ++Create /run/lvm/vgs_online/ if the VG is complete ++(used to ensure only one command performs activation.) ++.P ++.B --autoactivation event ++.br ++Inform the command it is used for event based autoactivation. ++.P ++.B --listvg ++.br ++Print the name of the VG using the device. ++.P ++.B --udevoutput ++.br ++Only print output that can be imported to the udev rule, ++using the udev environment key format, i.e. NAME='value'. ++.P ++.B --journal=output ++.br ++Send standard command output to the journal (when stdout ++is reserved for udev output.) ++.P ++.SS Temp files ++.P ++Autoactivation commands use a number of temp files in /run/lvm (with the ++expectation that /run is cleared between boots.) ++.P ++.B pvs_online ++.br ++pvscan --cache creates a file here for each PV that is attached. The file ++is named with the PVID and contains the VG name and device information. ++The existence of the file is used to determine when all PVs for a given VG ++are present. The device information in these files is also used to ++optimize locating devices for a VG when the VG is activated. ++.P ++.B pvs_lookup ++.br ++pvscan --cache creates a file here named for a VG (if one doesn't already ++exist.) The file contains a list of PVIDs in the VG. This is needed when ++a PV is processed which has no VG metadata, in which case the list of ++PVIDs from the lookup file is used to check if the VG is complete. ++.P ++.B vgs_online ++.br ++The first activation command (pvscan or vgchange) to create a file here, ++named for the VG, will activate the VG. This resolves a race when ++concurrent commands attempt to activate a VG at once. ++. ++.SH EXAMPLES ++.P ++VG "vg" contains two PVs: ++.nf ++$ pvs -o name,vgname,uuid /dev/sdb /dev/sdc ++ PV VG PV UUID ++ /dev/sdb vg 1uKpaT-lFOZ-NLHX-j4jI-OBi1-QpdE-HZ5hZY ++ /dev/sdc vg 5J3tM8-aIPe-2vbd-DBe7-bvRq-TGj0-DaKV2G ++.fi ++.P ++use of --cache: ++.nf ++$ pvscan --cache /dev/sdb ++ pvscan[12922] PV /dev/sdb online. ++$ pvscan --cache /dev/sdc ++ pvscan[12923] PV /dev/sdc online. ++ ++$ cat /run/lvm/pvs_online/1uKpaTlFOZNLHXj4jIOBi1QpdEHZ5hZY ++8:16 ++vg:vg ++dev:/dev/sdb ++$ cat /run/lvm/pvs_online/5J3tM8aIPe2vbdDBe7bvRqTGj0DaKV2G ++8:32 ++vg:vg ++dev:/dev/sdc ++.fi ++.P ++use of -aay: ++.nf ++$ pvscan --cache -aay /dev/sdb ++ pvscan[12935] PV /dev/sdb online, VG vg incomplete (need 1). ++$ pvscan --cache -aay /dev/sdc ++ pvscan[12936] PV /dev/sdc online, VG vg is complete. ++ pvscan[12936] VG vg run autoactivation. ++ 1 logical volume(s) in volume group "vg" now active ++ ++$ cat /run/lvm/pvs_online/1uKpaTlFOZNLHXj4jIOBi1QpdEHZ5hZY ++8:16 ++vg:vg ++dev:/dev/sdb ++$ cat /run/lvm/pvs_online/5J3tM8aIPe2vbdDBe7bvRqTGj0DaKV2G ++8:32 ++vg:vg ++dev:/dev/sdc ++$ ls /run/lvm/vgs_online/vg ++/run/lvm/vgs_online/vg ++.fi ++.P ++use of --listvg: ++.nf ++$ pvscan --cache --listvg /dev/sdb ++ VG vg ++$ pvscan --cache --listvg /dev/sdc ++ VG vg ++ ++$ cat /run/lvm/pvs_online/1uKpaTlFOZNLHXj4jIOBi1QpdEHZ5hZY ++8:16 ++vg:vg ++dev:/dev/sdb ++$ cat /run/lvm/pvs_online/5J3tM8aIPe2vbdDBe7bvRqTGj0DaKV2G ++8:32 ++vg:vg ++dev:/dev/sdc ++.fi ++.P ++use of --checkcomplete: ++.nf ++$ pvscan --cache --listvg --checkcomplete --vgonline /dev/sdb ++ pvscan[12996] PV /dev/sdb online, VG vg incomplete (need 1). ++ VG vg incomplete ++$ pvscan --cache --listvg --checkcomplete --vgonline /dev/sdc ++ pvscan[12997] PV /dev/sdc online, VG vg is complete. ++ VG vg complete ++.fi ++.P ++use of --udevoutput: ++.nf ++$ pvscan --cache --listvg --checkcomplete --vgonline --udevoutput /dev/sdb ++LVM_VG_NAME_INCOMPLETE='vg' ++$ pvscan --cache --listvg --checkcomplete --vgonline --udevoutput /dev/sdc ++LVM_VG_NAME_COMPLETE='vg' ++.fi ++.P ++use of --listlvs: ++.nf ++$ lvs -o name,devices vg ++ LV Devices ++ lvol0 /dev/sdb(0) ++ lvol1 /dev/sdc(0) ++ lvol2 /dev/sdb(1),/dev/sdc(1) ++ ++$ pvscan --cache --listlvs --checkcomplete /dev/sdb ++ pvscan[13288] PV /dev/sdb online, VG vg incomplete (need 1). ++ VG vg incomplete ++ LV vg/lvol0 complete ++ LV vg/lvol2 incomplete ++$ pvscan --cache --listlvs --checkcomplete /dev/sdc ++ pvscan[13289] PV /dev/sdc online, VG vg is complete. ++ VG vg complete ++ LV vg/lvol1 complete ++ LV vg/lvol2 complete ++.fi ++ +diff --git a/man/pvscan.8_des b/man/pvscan.8_des +index b20b987da..4c5929955 100644 +--- a/man/pvscan.8_des ++++ b/man/pvscan.8_des +@@ -4,56 +4,47 @@ like + or + .BR pvdisplay (8). + .P +-When the --cache and -aay options are used, pvscan records which PVs are +-available on the system, and activates LVs in completed VGs. A VG is +-complete when pvscan sees that the final PV in the VG has appeared. This +-is used by event-based system startup (systemd, udev) to activate LVs. +-.P +-The four main variations of this are: ++When --cache is used, pvscan updates runtime lvm state on the system, or ++with -aay performs autoactivation. + .P + .B pvscan --cache + .I device + .P +-If device is present, lvm adds a record that the PV on device is online. ++If device is present, lvm records that the PV on device is online. + If device is not present, lvm removes the online record for the PV. +-In most cases, the pvscan will only read the named devices. ++pvscan only reads the named device. + .P +-.B pvscan --cache -aay +-.IR device ... ++.B pvscan --cache + .P +-This begins by performing the same steps as above. Afterward, if the VG +-for the specified PV is complete, then pvscan will activate LVs in the VG +-(the same as vgchange -aay vgname would do.) ++Updates the runtime state for all lvm devices. + .P +-.B pvscan --cache ++.B pvscan --cache -aay ++.I device + .P +-This first clears all existing PV online records, then scans all devices +-on the system, adding PV online records for any PVs that are found. ++Performs the --cache steps for the device, then checks if the VG using the ++device is complete. If so, LVs in the VG are autoactivated, the same as ++vgchange -aay vgname would do. (A device name may be replaced with major ++and minor numbers.) + .P + .B pvscan --cache -aay + .P +-This begins by performing the same steps as pvscan --cache. Afterward, it +-activates LVs in any complete VGs. ++Performs the --cache steps for all devices, then autoactivates any complete VGs. + .P +-To prevent devices from being scanned by pvscan --cache, add them +-to +-.BR lvm.conf (5) +-.B devices/global_filter. +-For more information, see: +-.br +-.B lvmconfig --withcomments devices/global_filter ++.B pvscan --cache --listvg|--listlvs ++.I device ++.P ++Performs the --cache steps for the device, then prints the name of the VG ++using the device, or the names of LVs using the device. --checkcomplete ++is usually included to check if all PVs for the VG or LVs are online. ++When this command is called by a udev rule, the output must conform to ++udev rule specifications (see --udevoutput.) The udev rule will use the ++results to perform autoactivation. + .P +-Auto-activation of VGs or LVs can be enabled/disabled using: +-.br ++Autoactivation of VGs or LVs can be enabled/disabled using vgchange or ++lvchange with --setautoactivation y|n, or by adding names to + .BR lvm.conf (5) + .B activation/auto_activation_volume_list + .P +-For more information, see: +-.br +-.B lvmconfig --withcomments activation/auto_activation_volume_list +-.P +-To disable auto-activation, explicitly set this list to an empty list, +-i.e. auto_activation_volume_list = [ ]. +-.P +-When this setting is undefined (e.g. commented), then all LVs are +-auto-activated. ++See ++.BR lvmautoactivation (7) ++for more information about how pvscan is used for autoactivation. +-- +2.31.1 + diff --git a/SOURCES/0017-tests-devicesfile-devname.sh-drop-mdadm-chunk.patch b/SOURCES/0017-tests-devicesfile-devname.sh-drop-mdadm-chunk.patch new file mode 100644 index 0000000..ef22830 --- /dev/null +++ b/SOURCES/0017-tests-devicesfile-devname.sh-drop-mdadm-chunk.patch @@ -0,0 +1,25 @@ +From 10a4478e9b778dd8d4ff9737a503474b00ce9510 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Wed, 1 Dec 2021 08:56:05 -0600 +Subject: [PATCH 17/23] tests devicesfile-devname.sh drop mdadm chunk + +--- + test/shell/devicesfile-devname.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test/shell/devicesfile-devname.sh b/test/shell/devicesfile-devname.sh +index a99fe3e9a..338637275 100644 +--- a/test/shell/devicesfile-devname.sh ++++ b/test/shell/devicesfile-devname.sh +@@ -590,7 +590,7 @@ OPVID2=`pvs "$dev2" --noheading -o uuid | awk '{print $1}'` + PVID1=`pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}'` + PVID2=`pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}'` + +-mdadm --create --metadata=1.0 "$mddev" --level 1 --chunk=64 --raid-devices=2 "$dev3" "$dev4" ++mdadm --create --metadata=1.0 "$mddev" --level 1 --raid-devices=2 "$dev3" "$dev4" + wait_md_create "$mddev" + + sed -e "s|DEVNAME=$dev1|DEVNAME=$dev3|" "$ORIG" > tmp1.devices +-- +2.31.1 + diff --git a/SOURCES/0018-devices-file-don-t-write-in-test-mode.patch b/SOURCES/0018-devices-file-don-t-write-in-test-mode.patch new file mode 100644 index 0000000..feb3bf7 --- /dev/null +++ b/SOURCES/0018-devices-file-don-t-write-in-test-mode.patch @@ -0,0 +1,26 @@ +From 04770589b49effdb064c9b3790e8dd2fee2c3547 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Wed, 1 Dec 2021 10:08:08 -0600 +Subject: [PATCH 18/23] devices file: don't write in test mode + +--- + lib/device/device_id.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index ce7ded154..4c2b5a3dd 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -673,6 +673,9 @@ int device_ids_write(struct cmd_context *cmd) + cmd->enable_devices_file = 1; + } + ++ if (test_mode()) ++ return 1; ++ + if (_devices_file_version[0]) { + if (sscanf(_devices_file_version, "%u.%u.%u", &df_major, &df_minor, &df_counter) != 3) { + /* don't update a file we can't parse */ +-- +2.31.1 + diff --git a/SOURCES/0019-print-warning-about-unrecognized-journal-option-valu.patch b/SOURCES/0019-print-warning-about-unrecognized-journal-option-valu.patch new file mode 100644 index 0000000..5fc92af --- /dev/null +++ b/SOURCES/0019-print-warning-about-unrecognized-journal-option-valu.patch @@ -0,0 +1,24 @@ +From 604fd528fb4f00a9f77e084a1b22eff2aeef0259 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Thu, 2 Dec 2021 12:40:52 -0600 +Subject: [PATCH 19/23] print warning about unrecognized journal option value + +--- + lib/log/log.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/log/log.c b/lib/log/log.c +index 7b4d537b3..5771a1d01 100644 +--- a/lib/log/log.c ++++ b/lib/log/log.c +@@ -892,6 +892,7 @@ uint32_t log_journal_str_to_val(const char *str) + return LOG_JOURNAL_OUTPUT; + if (!strcasecmp(str, "debug")) + return LOG_JOURNAL_DEBUG; ++ log_warn("Ignoring unrecognized journal value."); + return 0; + } + +-- +2.31.1 + diff --git a/SOURCES/0020-device_id-handle-wwid-with-spaces-or-control-charact.patch b/SOURCES/0020-device_id-handle-wwid-with-spaces-or-control-charact.patch new file mode 100644 index 0000000..e254e36 --- /dev/null +++ b/SOURCES/0020-device_id-handle-wwid-with-spaces-or-control-charact.patch @@ -0,0 +1,50 @@ +From 357a807e81bbd1430b045eb2601a64b17d588400 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Thu, 2 Dec 2021 13:30:36 -0600 +Subject: [PATCH 20/23] device_id: handle wwid with spaces or control + characters + +non-standard wwid can be reported from sysfs with spaces/etc. +replace with "_" +--- + lib/device/device_id.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index 4c2b5a3dd..0621bc858 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -304,6 +304,7 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u + { + char sysbuf[PATH_MAX] = { 0 }; + const char *idname = NULL; ++ int i; + + if (idtype == DEV_ID_TYPE_SYS_WWID) { + read_sys_block(cmd, dev, "device/wwid", sysbuf, sizeof(sysbuf)); +@@ -311,10 +312,6 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u + if (!sysbuf[0]) + read_sys_block(cmd, dev, "wwid", sysbuf, sizeof(sysbuf)); + +- /* scsi_debug wwid begins "t10.Linux scsi_debug ..." */ +- if (strstr(sysbuf, "scsi_debug")) +- sysbuf[0] = '\0'; +- + /* qemu wwid begins "t10.ATA QEMU HARDDISK ..." */ + if (strstr(sysbuf, "QEMU HARDDISK")) + sysbuf[0] = '\0'; +@@ -355,6 +352,11 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u + return idname; + } + ++ for (i = 0; i < strlen(sysbuf); i++) { ++ if (isblank(sysbuf[i]) || isspace(sysbuf[i]) || iscntrl(sysbuf[i])) ++ sysbuf[i] = '_'; ++ } ++ + if (!sysbuf[0]) + goto_bad; + +-- +2.31.1 + diff --git a/SOURCES/0021-man-add-section-about-static-autoactivation.patch b/SOURCES/0021-man-add-section-about-static-autoactivation.patch new file mode 100644 index 0000000..a6d10cf --- /dev/null +++ b/SOURCES/0021-man-add-section-about-static-autoactivation.patch @@ -0,0 +1,96 @@ +From 7631c5b826b5a3eddfcd22db9b80574b249794c1 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Mon, 6 Dec 2021 13:20:32 -0600 +Subject: [PATCH 21/23] man: add section about static autoactivation + +--- + man/lvmautoactivation.7_main | 48 ++++++++++++++++++++++++++++++------ + 1 file changed, 41 insertions(+), 7 deletions(-) + +diff --git a/man/lvmautoactivation.7_main b/man/lvmautoactivation.7_main +index 87c15a3d1..bf885991d 100644 +--- a/man/lvmautoactivation.7_main ++++ b/man/lvmautoactivation.7_main +@@ -14,14 +14,16 @@ activated. + Autoactivation of VGs, or specific LVs, can be prevented using vgchange or + lvchange --setautoactivation n. The lvm.conf auto_activation_volume_list + is another way to limit autoactivation. ++. ++.SS event autoactivation + .P + The most common form of autoactivation is "event based", in which complete + VGs are activated in response to uevents which occur during system startup + or at any time after the system has started. Another form of +-autoactivation is "service based" in which complete VGs are activated at a +-fixed point during system startup by a systemd service, and are not +-activated in response to uevents. This can be controlled with the +-lvm.conf setting event_activation. ++autoactivation is "static" in which complete VGs are activated at a fixed ++point during system startup by a systemd service, and not in response to ++events. This can be controlled with the lvm.conf setting ++event_activation. + .P + Event based autoactivation is driven by udev, udev rules, and systemd. + When a device is attached to a machine, a uevent is generated by the +@@ -30,8 +32,8 @@ rules to process the new device. Udev rules use blkid to identify the + device as an LVM PV and then execute the lvm-specific udev rule for the + device, which triggers autoactivation. + .P +-There are two variations of event based autoactivation that may be used a +-system, depending on the LVM udev rule that is installed (found in ++There are two variations of event baed autoactivation that may be used on ++a system, depending on the LVM udev rule that is installed (found in + /lib/udev/rules.d/.) The following summarizes the steps in each rule + which lead to autoactivation: + .P +@@ -149,7 +151,7 @@ using the udev environment key format, i.e. NAME='value'. + Send standard command output to the journal (when stdout + is reserved for udev output.) + .P +-.SS Temp files ++.SS run files + .P + Autoactivation commands use a number of temp files in /run/lvm (with the + expectation that /run is cleared between boots.) +@@ -175,6 +177,38 @@ The first activation command (pvscan or vgchange) to create a file here, + named for the VG, will activate the VG. This resolves a race when + concurrent commands attempt to activate a VG at once. + . ++.SS static autoactivation ++.P ++When event autoactivation is disabled by setting lvm.conf ++event_activation=0, autoactivation is performed at one or more static ++points during system startup. At these points, a vgchange -aay command is ++run to activate complete VGs from devices that are present on the system ++at that time. pvscan commands (and lvm2-pvscan services) do not perform ++autoactivation in this mode. pvscan commands may still be run from ++uevents but will do nothing when they read the event_activation=0 setting. ++.P ++The static vgchange -aay commands are run by three systemd services at ++three points during startup: lvm2-activation-early, lvm2-activation, and ++lvm2-activation-net. These static activation services are "generated ++services", so the service files are created at run time by the ++lvm2-activation-generator command (run by systemd). ++lvm2-activation-generator creates the services if lvm.conf ++event_activation=0. ++.P ++The limitation of this method is that devices may not be attached to the ++system (or set up) at a reliable point in time during startup, and they ++may not be present when the services run vgchange. In this case, the VGs ++will not be autoactivated. So, the timing of device attachment/setup ++determines whether static autoactivation will produce the same results as ++event autoactivation. For this reason, static autoactivation is not ++recommended. ++.P ++Sometimes, static autoactivation is mistakenly expected to disable all ++autoactivation of particular VGs. This may appear to be effective if those ++VGs are slow to be attached or set up. But, the only correct and reliable ++way to disable autoactivation is using vgchange/lvchange ++--setautoactivation n, or lvm.conf auto_activation_volume_list. ++. + .SH EXAMPLES + .P + VG "vg" contains two PVs: +-- +2.31.1 + diff --git a/SOURCES/0022-lvcreate-include-recent-options.patch b/SOURCES/0022-lvcreate-include-recent-options.patch new file mode 100644 index 0000000..38a729d --- /dev/null +++ b/SOURCES/0022-lvcreate-include-recent-options.patch @@ -0,0 +1,35 @@ +From af4bfa1f1f84194000bc50f43ddc906c0cd4b104 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Mon, 13 Dec 2021 08:59:31 -0600 +Subject: [PATCH 22/23] lvcreate: include recent options + +The permitted option list in lvcreate has not kept +up with command-lines.in. +--- + tools/lvcreate.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tools/lvcreate.c b/tools/lvcreate.c +index 0121c09a8..79af42685 100644 +--- a/tools/lvcreate.c ++++ b/tools/lvcreate.c +@@ -824,12 +824,16 @@ static int _lvcreate_params(struct cmd_context *cmd, + autobackup_ARG,\ + available_ARG,\ + contiguous_ARG,\ ++ devices_ARG,\ ++ devicesfile_ARG,\ + ignoreactivationskip_ARG,\ + ignoremonitoring_ARG,\ ++ journal_ARG,\ + metadataprofile_ARG,\ + monitor_ARG,\ + mirrors_ARG,\ + name_ARG,\ ++ nohints_ARG,\ + noudevsync_ARG,\ + permission_ARG,\ + persistent_ARG,\ +-- +2.31.1 + diff --git a/SOURCES/0023-man-lvmautoactivation-replace-systemctl-with-journal.patch b/SOURCES/0023-man-lvmautoactivation-replace-systemctl-with-journal.patch new file mode 100644 index 0000000..16b08c43 --- /dev/null +++ b/SOURCES/0023-man-lvmautoactivation-replace-systemctl-with-journal.patch @@ -0,0 +1,26 @@ +From 61833dd5b6117e8ace84289cff656d1dfb0ed123 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Tue, 14 Dec 2021 12:02:08 -0600 +Subject: [PATCH 23/23] man lvmautoactivation: replace systemctl with + journalctl + +--- + man/lvmautoactivation.7_main | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/man/lvmautoactivation.7_main b/man/lvmautoactivation.7_main +index bf885991d..54dab718b 100644 +--- a/man/lvmautoactivation.7_main ++++ b/man/lvmautoactivation.7_main +@@ -107,7 +107,7 @@ vgchange -aay --autoactivation event + . + .IP \[bu] 2 + the activation command output can be seen from +-systemctl status lvm-activate- ++journalctl -u lvm-activate- + .P + . + .SS pvscan options +-- +2.31.1 + diff --git a/SOURCES/0024-make-generate.patch b/SOURCES/0024-make-generate.patch new file mode 100644 index 0000000..f5a15ad --- /dev/null +++ b/SOURCES/0024-make-generate.patch @@ -0,0 +1,196 @@ +From 4b26fb3543049f3d179b620ff937c44e922ada58 Mon Sep 17 00:00:00 2001 +From: Marian Csontos +Date: Tue, 4 Jan 2022 17:15:56 +0100 +Subject: [PATCH] make: generate + +--- + man/lvdisplay.8_pregen | 12 -------- + man/pvdisplay.8_pregen | 12 -------- + man/pvscan.8_pregen | 63 ++++++++++++++++++------------------------ + man/vgdisplay.8_pregen | 12 -------- + 4 files changed, 27 insertions(+), 72 deletions(-) + +diff --git a/man/lvdisplay.8_pregen b/man/lvdisplay.8_pregen +index a1740ebed..04aab4c09 100644 +--- a/man/lvdisplay.8_pregen ++++ b/man/lvdisplay.8_pregen +@@ -61,8 +61,6 @@ and more, using a more compact and configurable output format. + .br + [ \fB--readonly\fP ] + .br +-[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ] +-.br + [ \fB--segments\fP ] + .br + [ \fB--separator\fP \fIString\fP ] +@@ -332,16 +330,6 @@ device-mapper kernel driver, so this option is unable to report whether + or not LVs are actually in use. + . + .HP +-\fB--reportformat\fP \fBbasic\fP|\fBjson\fP +-.br +-Overrides current output format for reports which is defined globally by +-the report/output_format setting in \fBlvm.conf\fP(5). +-\fBbasic\fP is the original format with columns and rows. +-If there is more than one report per command, each report is prefixed +-with the report name for identification. \fBjson\fP produces report +-output in JSON format. See \fBlvmreport\fP(7) for more information. +-. +-.HP + \fB--segments\fP + .br + . +diff --git a/man/pvdisplay.8_pregen b/man/pvdisplay.8_pregen +index 22a0992b5..2f26a8727 100644 +--- a/man/pvdisplay.8_pregen ++++ b/man/pvdisplay.8_pregen +@@ -61,8 +61,6 @@ and more, using a more compact and configurable output format. + .br + [ \fB--readonly\fP ] + .br +-[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ] +-.br + [ \fB--separator\fP \fIString\fP ] + .br + [ \fB--shared\fP ] +@@ -320,16 +318,6 @@ device-mapper kernel driver, so this option is unable to report whether + or not LVs are actually in use. + . + .HP +-\fB--reportformat\fP \fBbasic\fP|\fBjson\fP +-.br +-Overrides current output format for reports which is defined globally by +-the report/output_format setting in \fBlvm.conf\fP(5). +-\fBbasic\fP is the original format with columns and rows. +-If there is more than one report per command, each report is prefixed +-with the report name for identification. \fBjson\fP produces report +-output in JSON format. See \fBlvmreport\fP(7) for more information. +-. +-.HP + \fB-S\fP|\fB--select\fP \fIString\fP + .br + Select objects for processing and reporting based on specified criteria. +diff --git a/man/pvscan.8_pregen b/man/pvscan.8_pregen +index 9eb6b5bf9..1c96d5aab 100644 +--- a/man/pvscan.8_pregen ++++ b/man/pvscan.8_pregen +@@ -91,59 +91,50 @@ like + or + .BR pvdisplay (8). + .P +-When the --cache and -aay options are used, pvscan records which PVs are +-available on the system, and activates LVs in completed VGs. A VG is +-complete when pvscan sees that the final PV in the VG has appeared. This +-is used by event-based system startup (systemd, udev) to activate LVs. +-.P +-The four main variations of this are: ++When --cache is used, pvscan updates runtime lvm state on the system, or ++with -aay performs autoactivation. + .P + .B pvscan --cache + .I device + .P +-If device is present, lvm adds a record that the PV on device is online. ++If device is present, lvm records that the PV on device is online. + If device is not present, lvm removes the online record for the PV. +-In most cases, the pvscan will only read the named devices. ++pvscan only reads the named device. + .P +-.B pvscan --cache -aay +-.IR device ... ++.B pvscan --cache + .P +-This begins by performing the same steps as above. Afterward, if the VG +-for the specified PV is complete, then pvscan will activate LVs in the VG +-(the same as vgchange -aay vgname would do.) ++Updates the runtime state for all lvm devices. + .P +-.B pvscan --cache ++.B pvscan --cache -aay ++.I device + .P +-This first clears all existing PV online records, then scans all devices +-on the system, adding PV online records for any PVs that are found. ++Performs the --cache steps for the device, then checks if the VG using the ++device is complete. If so, LVs in the VG are autoactivated, the same as ++vgchange -aay vgname would do. (A device name may be replaced with major ++and minor numbers.) + .P + .B pvscan --cache -aay + .P +-This begins by performing the same steps as pvscan --cache. Afterward, it +-activates LVs in any complete VGs. ++Performs the --cache steps for all devices, then autoactivates any complete VGs. + .P +-To prevent devices from being scanned by pvscan --cache, add them +-to +-.BR lvm.conf (5) +-.B devices/global_filter. +-For more information, see: +-.br +-.B lvmconfig --withcomments devices/global_filter ++.B pvscan --cache --listvg|--listlvs ++.I device + .P +-Auto-activation of VGs or LVs can be enabled/disabled using: +-.br ++Performs the --cache steps for the device, then prints the name of the VG ++using the device, or the names of LVs using the device. --checkcomplete ++is usually included to check if all PVs for the VG or LVs are online. ++When this command is called by a udev rule, the output must conform to ++udev rule specifications (see --udevoutput.) The udev rule will use the ++results to perform autoactivation. ++.P ++Autoactivation of VGs or LVs can be enabled/disabled using vgchange or ++lvchange with --setautoactivation y|n, or by adding names to + .BR lvm.conf (5) + .B activation/auto_activation_volume_list + .P +-For more information, see: +-.br +-.B lvmconfig --withcomments activation/auto_activation_volume_list +-.P +-To disable auto-activation, explicitly set this list to an empty list, +-i.e. auto_activation_volume_list = [ ]. +-.P +-When this setting is undefined (e.g. commented), then all LVs are +-auto-activated. ++See ++.BR lvmautoactivation (7) ++for more information about how pvscan is used for autoactivation. + . + .SH USAGE + . +diff --git a/man/vgdisplay.8_pregen b/man/vgdisplay.8_pregen +index 9c694921d..0a12b3c39 100644 +--- a/man/vgdisplay.8_pregen ++++ b/man/vgdisplay.8_pregen +@@ -58,8 +58,6 @@ and more, using a more compact and configurable output format. + .br + [ \fB--readonly\fP ] + .br +-[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ] +-.br + [ \fB--shared\fP ] + .br + [ \fB--separator\fP \fIString\fP ] +@@ -312,16 +310,6 @@ device-mapper kernel driver, so this option is unable to report whether + or not LVs are actually in use. + . + .HP +-\fB--reportformat\fP \fBbasic\fP|\fBjson\fP +-.br +-Overrides current output format for reports which is defined globally by +-the report/output_format setting in \fBlvm.conf\fP(5). +-\fBbasic\fP is the original format with columns and rows. +-If there is more than one report per command, each report is prefixed +-with the report name for identification. \fBjson\fP produces report +-output in JSON format. See \fBlvmreport\fP(7) for more information. +-. +-.HP + \fB-S\fP|\fB--select\fP \fIString\fP + .br + Select objects for processing and reporting based on specified criteria. +-- +2.31.1 + diff --git a/SOURCES/lvm2-set-default-preferred_names.patch b/SOURCES/lvm2-set-default-preferred_names.patch deleted file mode 100644 index 0653e9c..0000000 --- a/SOURCES/lvm2-set-default-preferred_names.patch +++ /dev/null @@ -1,33 +0,0 @@ - conf/example.conf.in | 5 +++-- - lib/config/config_settings.h | 2 +- - 2 files changed, 4 insertions(+), 3 deletions(-) - -diff --git a/conf/example.conf.in b/conf/example.conf.in -index a78ed73..2c6ff25 100644 ---- a/conf/example.conf.in -+++ b/conf/example.conf.in -@@ -116,8 +116,9 @@ devices { - # - # Example - # preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ] -- # -- # This configuration option does not have a default value defined. -+ # -+ # This configuration option has an automatic default value. -+ # preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ] - - # Configuration option devices/use_devicesfile. - # Enable or disable the use of a devices file. -diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h -index d280e7a..1e6c20f 100644 ---- a/lib/config/config_settings.h -+++ b/lib/config/config_settings.h -@@ -257,7 +257,7 @@ cfg(devices_hints_CFG, "hints", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_ - " Use no hints.\n" - "#\n") - --cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED , CFG_TYPE_STRING, NULL, vsn(1, 2, 19), NULL, 0, NULL, -+cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "#S^/dev/mpath/#S^/dev/mapper/mpath#S^/dev/[hs]d", vsn(1, 2, 19), NULL, 0, NULL, - "Select which path name to display for a block device.\n" - "If multiple path names exist for a block device, and LVM needs to\n" - "display a name for the device, the path names are matched against\n" diff --git a/SPECS/lvm2.spec b/SPECS/lvm2.spec index 0df5b4c..52a8c2a 100644 --- a/SPECS/lvm2.spec +++ b/SPECS/lvm2.spec @@ -68,7 +68,7 @@ Version: 2.03.14 %if 0%{?from_snapshot} Release: 0.1.20210426git%{shortcommit}%{?dist}%{?rel_suffix} %else -Release: 2%{?dist}%{?rel_suffix} +Release: 3%{?dist}%{?rel_suffix} %endif License: GPLv2 URL: http://sourceware.org/lvm2 @@ -78,10 +78,31 @@ Source0: lvm2-%{shortcommit}.tgz Source0: ftp://sourceware.org/pub/lvm2/releases/LVM2.%{version}.tgz Patch0: lvm2-rhel8.patch %endif -Patch1: lvm2-set-default-preferred_names.patch -Patch2: lvm2-test-skip-problematic-tests.patch -Patch3: 0001-Revert-new-udev-autoactivation.patch -Patch4: 0002-Revert-pvscan-only-add-device-args-to-dev-cache.patch +Patch1: lvm2-test-skip-problematic-tests.patch +Patch2: 0001-Revert-new-udev-autoactivation.patch +Patch3: 0002-Revert-pvscan-only-add-device-args-to-dev-cache.patch +Patch4: 0003-pvscan-fix-messages-from-coverity-changes.patch +Patch5: 0004-vgimportdevices-skip-lvmlockd-locking.patch +Patch6: 0005-hints-remove-the-cmd-hints-list.patch +Patch7: 0006-filter-sysfs-skip-when-device-id-is-set.patch +Patch8: 0007-lvmdevices-increase-open-file-limit.patch +Patch9: 0008-filter-sysfs-support-old-kernels-without-sys-dev-blo.patch +Patch10: 0009-device_id-match-different-dm-device-names.patch +Patch11: 0010-device_id-fix-search-on-filtered-device.patch +Patch12: 0011-device_id-searched_devnames-improvements.patch +Patch13: 0012-tests-pv-ext-flags-work-with-devices-file.patch +Patch14: 0013-display-ignore-reportformat.patch +Patch15: 0014-fix-spelling-of-pruning.patch +Patch16: 0015-man-lvmautoactivation.patch +#Patch17: 0016-spec-Add-lvmautoactivation-man-page.patch +Patch18: 0017-tests-devicesfile-devname.sh-drop-mdadm-chunk.patch +Patch19: 0018-devices-file-don-t-write-in-test-mode.patch +Patch20: 0019-print-warning-about-unrecognized-journal-option-valu.patch +Patch21: 0020-device_id-handle-wwid-with-spaces-or-control-charact.patch +Patch22: 0021-man-add-section-about-static-autoactivation.patch +Patch23: 0022-lvcreate-include-recent-options.patch +Patch24: 0023-man-lvmautoactivation-replace-systemctl-with-journal.patch +Patch25: 0024-make-generate.patch BuildRequires: gcc %if %{enable_testsuite} @@ -146,6 +167,27 @@ or more physical volumes and creating one or more logical volumes %patch2 -p1 -b .backup2 %patch3 -p1 -b .backup3 %patch4 -p1 -b .backup4 +%patch5 -p1 -b .backup5 +%patch6 -p1 -b .backup6 +%patch7 -p1 -b .backup7 +%patch8 -p1 -b .backup8 +%patch9 -p1 -b .backup9 +%patch10 -p1 -b .backup10 +%patch11 -p1 -b .backup11 +%patch12 -p1 -b .backup12 +%patch13 -p1 -b .backup13 +%patch14 -p1 -b .backup14 +%patch15 -p1 -b .backup15 +%patch16 -p1 -b .backup16 +#%%patch17 -p1 -b .backup17 +%patch18 -p1 -b .backup18 +%patch19 -p1 -b .backup19 +%patch20 -p1 -b .backup20 +%patch21 -p1 -b .backup21 +%patch22 -p1 -b .backup22 +%patch23 -p1 -b .backup23 +%patch24 -p1 -b .backup24 +%patch25 -p1 -b .backup25 %build %global _default_pid_dir /run @@ -321,6 +363,7 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || : %{_sbindir}/vgscan %{_sbindir}/vgsplit %{_mandir}/man5/lvm.conf.5.gz +%{_mandir}/man7/lvmautoactivation.7.gz %{_mandir}/man7/lvmcache.7.gz %{_mandir}/man7/lvmraid.7.gz %{_mandir}/man7/lvmreport.7.gz @@ -763,6 +806,9 @@ An extensive functional testsuite for LVM2. %endif %changelog +* Tue Jan 04 2022 Marian Csontos - 2.03.14-3 +- Fix devices file and autoactivation related issues. + * Fri Dec 17 2021 Marian Csontos - 2.03.14-2 - Revert autoactivation changes.