import lvm2-2.03.16-3.el9

This commit is contained in:
CentOS Sources 2022-09-27 10:22:21 -04:00 committed by Stepan Oksanichenko
parent b187147277
commit a0f6c09d36
21 changed files with 1900 additions and 151 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/lvm2-4a1f617.tgz
SOURCES/LVM2.2.03.16.tgz

View File

@ -1 +1 @@
b87a5a886c6cceb6e38028f1ea20d5d1d6bd23a8 SOURCES/lvm2-4a1f617.tgz
a99cfcbcb2cf665824acde03775dccc9ef54a836 SOURCES/LVM2.2.03.16.tgz

View File

@ -1,144 +0,0 @@
From 611c3f868699471c474e12280825242978c0bed8 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Thu, 10 Feb 2022 14:00:25 -0600
Subject: [PATCH] devices file: do not clear PVID of unread devices
In a certain disconnected state, a block device is present on
the system, can be opened, reports a valid size, reports the
correct device id (wwid), and matches a devices file entry.
But, reading the device can still fail. In this case,
device_ids_validate() was misinterpreting the read error as
the device having no data/label on it (and no PVID).
The validate function would then clear the PVID from the
devices file entry for the device, thinking that it was
fixing the devices file (making it consistent with the on disk
state.) Fix this by not attempting to check and correct a
devices file entry that cannot be read. Also make this case
explicit in the hints validation code (which was doing the
right thing but indirectly.)
---
lib/device/device.h | 1 +
lib/device/device_id.c | 14 ++++++++++++++
lib/label/hints.c | 14 ++++++++++++++
lib/label/label.c | 8 ++++++++
4 files changed, 37 insertions(+)
diff --git a/lib/device/device.h b/lib/device/device.h
index 9e471a9b5..8c3a8c30e 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -40,6 +40,7 @@
#define DEV_IS_NVME 0x00040000 /* set if dev is nvme */
#define DEV_MATCHED_USE_ID 0x00080000 /* matched an entry from cmd->use_devices */
#define DEV_SCAN_FOUND_NOLABEL 0x00100000 /* label_scan read, passed filters, but no lvm label */
+#define DEV_SCAN_NOT_READ 0x00200000 /* label_scan not able to read dev */
/*
* Support for external device info.
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index 4618247ba..003f10a96 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -1746,6 +1746,13 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
if (scanned_devs && !dev_in_device_list(dev, scanned_devs))
continue;
+ /*
+ * The matched device could not be read so we do not have
+ * the PVID from disk and cannot verify the devices file entry.
+ */
+ if (dev->flags & DEV_SCAN_NOT_READ)
+ continue;
+
/*
* du and dev may have been matched, but the dev could still
* have been excluded by other filters during label scan.
@@ -1828,6 +1835,13 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
if (scanned_devs && !dev_in_device_list(dev, scanned_devs))
continue;
+ /*
+ * The matched device could not be read so we do not have
+ * the PVID from disk and cannot verify the devices file entry.
+ */
+ if (dev->flags & DEV_SCAN_NOT_READ)
+ continue;
+
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "persistent")) {
log_warn("Devices file %s is excluded by filter: %s.",
dev_name(dev), dev_filtered_reason(dev));
diff --git a/lib/label/hints.c b/lib/label/hints.c
index 93dfdd5c1..35ae7f5cc 100644
--- a/lib/label/hints.c
+++ b/lib/label/hints.c
@@ -236,6 +236,7 @@ static int _touch_newhints(void)
return_0;
if (fclose(fp))
stack;
+ log_debug("newhints created");
return 1;
}
@@ -506,6 +507,19 @@ int validate_hints(struct cmd_context *cmd, struct dm_list *hints)
if (!hint->chosen)
continue;
+ /*
+ * label_scan was unable to read the dev so we don't know its pvid.
+ * Since we are unable to verify the hint is correct, it's possible
+ * that the PVID is actually found on a different device, so don't
+ * depend on hints. (This would also fail the following pvid check.)
+ */
+ if (dev->flags & DEV_SCAN_NOT_READ) {
+ log_debug("Uncertain hint for unread device %d:%d %s",
+ major(hint->devt), minor(hint->devt), dev_name(dev));
+ ret = 0;
+ continue;
+ }
+
if (strcmp(dev->pvid, hint->pvid)) {
log_debug("Invalid hint device %d:%d %s pvid %s had hint pvid %s",
major(hint->devt), minor(hint->devt), dev_name(dev),
diff --git a/lib/label/label.c b/lib/label/label.c
index 5c77a6923..4f29d6208 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -687,6 +687,8 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
dm_list_iterate_items_safe(devl, devl2, devs) {
+ devl->dev->flags &= ~DEV_SCAN_NOT_READ;
+
/*
* If we prefetch more devs than blocks in the cache, then the
* cache will wait for earlier reads to complete, toss the
@@ -702,6 +704,7 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
log_debug_devs("Scan failed to open %s.", dev_name(devl->dev));
dm_list_del(&devl->list);
dm_list_add(&reopen_devs, &devl->list);
+ devl->dev->flags |= DEV_SCAN_NOT_READ;
continue;
}
}
@@ -725,6 +728,7 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
log_debug_devs("Scan failed to read %s.", dev_name(devl->dev));
scan_read_errors++;
scan_failed_count++;
+ devl->dev->flags |= DEV_SCAN_NOT_READ;
lvmcache_del_dev(devl->dev);
if (bb)
bcache_put(bb);
@@ -1389,6 +1393,10 @@ int label_scan(struct cmd_context *cmd)
* filter", and this result needs to be cleared (wiped) so that the
* complete set of filters (including those that require data) can be
* checked in _process_block, where headers have been read.
+ *
+ * FIXME: devs that are filtered with data in _process_block
+ * are not moved to the filtered_devs list like devs filtered
+ * here without data. Does that have any effect?
*/
log_debug_devs("Filtering devices to scan (nodata)");
--
2.34.1

View File

@ -0,0 +1,49 @@
From 28a4df481fa47d0b71996a25ac08546c4bd094f8 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Fri, 27 May 2022 12:38:43 -0500
Subject: [PATCH 1/7] devices file: move clean up after command is run
devices_file_exit wasn't being called between lvm_shell
commands, so the file lock wouldn't be released.
(cherry picked from commit 9dfa6f38793f6b5f7de2a4148ab2f7790e3c39da)
---
lib/commands/toolcontext.c | 2 --
tools/lvmcmdline.c | 1 +
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 4cb81bf94..2666d7b42 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -1905,7 +1905,6 @@ int refresh_toolcontext(struct cmd_context *cmd)
_destroy_segtypes(&cmd->segtypes);
_destroy_formats(cmd, &cmd->formats);
- devices_file_exit(cmd);
if (!dev_cache_exit())
stack;
_destroy_dev_types(cmd);
@@ -2034,7 +2033,6 @@ void destroy_toolcontext(struct cmd_context *cmd)
_destroy_segtypes(&cmd->segtypes);
_destroy_formats(cmd, &cmd->formats);
_destroy_filters(cmd);
- devices_file_exit(cmd);
dev_cache_exit();
_destroy_dev_types(cmd);
_destroy_tags(cmd);
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 1e3547ed7..b052d698f 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -3305,6 +3305,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
hints_exit(cmd);
lvmcache_destroy(cmd, 1, 1);
label_scan_destroy(cmd);
+ devices_file_exit(cmd);
if ((config_string_cft = remove_config_tree_by_source(cmd, CONFIG_STRING)))
dm_config_destroy(config_string_cft);
--
2.34.3

View File

@ -0,0 +1,55 @@
From 9a79248fe21554e6cb99dd6ed044e7cbff18f777 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Fri, 27 May 2022 14:27:03 -0500
Subject: [PATCH 2/7] devices file: fail if --devicesfile filename doesn't
exist
A typo of the filename after --devicesfile should result in a
command error rather than the command falling back to using no
devices file at all. Exception is vgcreate|pvcreate which
create a new devices file if the file name doesn't exist.
(cherry picked from commit bfe072e4388b530cbf5369be8a8f1305220198bf)
---
lib/device/dev-cache.c | 9 +++++++++
test/shell/devicesfile-basic.sh | 4 ++++
2 files changed, 13 insertions(+)
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index 3aaf6a2e5..ed9c726c9 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -1863,6 +1863,15 @@ int setup_devices(struct cmd_context *cmd)
file_exists = devices_file_exists(cmd);
+ /*
+ * Fail if user specifies a file name that doesn't exist and
+ * the command is not creating a new devices file.
+ */
+ if (!file_exists && !cmd->create_edit_devices_file && cmd->devicesfile && strlen(cmd->devicesfile)) {
+ log_error("Devices file not found: %s", cmd->devices_file_path);
+ return 0;
+ }
+
/*
* Removing the devices file is another way of disabling the use of
* a devices file, unless the command creates the devices file.
diff --git a/test/shell/devicesfile-basic.sh b/test/shell/devicesfile-basic.sh
index 9c3455c76..77fe265a0 100644
--- a/test/shell/devicesfile-basic.sh
+++ b/test/shell/devicesfile-basic.sh
@@ -104,6 +104,10 @@ not ls "$DFDIR/system.devices"
vgs --devicesfile test.devices $vg1
not vgs --devicesfile test.devices $vg2
+# misspelled override name fails
+not vgs --devicesfile doesnotexist $vg1
+not vgs --devicesfile doesnotexist $vg2
+
# devicesfile and devices cannot be used together
not vgs --devicesfile test.devices --devices "$dev1","$dev1" $vg1
--
2.34.3

View File

@ -0,0 +1,54 @@
From 1e78ed5a0d9a8296b42578cfc250a3a281a32878 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Mon, 6 Jun 2022 11:39:02 -0500
Subject: [PATCH 3/7] filter-mpath: handle other wwid types in blacklist
Fixes commit 494372b4eed0c8f6040e3357939eb7511ac25745
"filter-mpath: use multipath blacklist"
to handle wwids with initial type digits 1 and 2 used
for t10 and eui ids. Originally recognized type 3 naa.
(cherry picked from commit c302903dbab1d5fd05b344c654bed83c9ecb69f8)
---
lib/device/dev-mpath.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/lib/device/dev-mpath.c b/lib/device/dev-mpath.c
index 270366ad7..846f6c8ba 100644
--- a/lib/device/dev-mpath.c
+++ b/lib/device/dev-mpath.c
@@ -54,7 +54,7 @@ static void _read_blacklist_file(const char *path)
int section_black = 0;
int section_exceptions = 0;
int found_quote;
- int found_three;
+ int found_type;
int i, j;
if (!(fp = fopen(path, "r")))
@@ -114,7 +114,7 @@ static void _read_blacklist_file(const char *path)
memset(wwid, 0, sizeof(wwid));
found_quote = 0;
- found_three = 0;
+ found_type = 0;
j = 0;
for (; i < MAX_WWID_LINE; i++) {
@@ -132,9 +132,10 @@ static void _read_blacklist_file(const char *path)
/* second quote is end of wwid */
if ((line[i] == '"') && found_quote)
break;
- /* ignore first "3" in wwid */
- if ((line[i] == '3') && !found_three) {
- found_three = 1;
+ /* exclude initial 3/2/1 for naa/eui/t10 */
+ if (!j && !found_type &&
+ ((line[i] == '3') || (line[i] == '2') || (line[i] == '1'))) {
+ found_type = 1;
continue;
}
--
2.34.3

View File

@ -0,0 +1,743 @@
From 2966df2bcbbf553d86d0a608852dcc140df28fc0 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Mon, 6 Jun 2022 14:04:20 -0500
Subject: [PATCH 4/7] filter-mpath: get wwids from sysfs vpd_pg83
to compare with wwids in /etc/multipath/wwids when
excluding multipath components. The wwid printed
from the sysfs wwid file may not be the wwid used
in multipath wwids. Save the wwids found for each
device on dev->wwids to avoid repeating reading
and parsing the sysfs files.
(cherry picked from commit 3b0f9cec7e999c33f17714358d2b469bda6967d2)
---
lib/Makefile.in | 1 +
lib/device/dev-cache.c | 18 ++++
lib/device/dev-cache.h | 1 +
lib/device/dev-mpath.c | 232 ++++++++++++++++++++++++++++++++++-------
lib/device/device.h | 13 +++
lib/device/device_id.c | 31 +++++-
lib/device/device_id.h | 2 +
lib/device/parse_vpd.c | 199 +++++++++++++++++++++++++++++++++++
8 files changed, 454 insertions(+), 43 deletions(-)
create mode 100644 lib/device/parse_vpd.c
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 22b96134b..3ab5cb2f1 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -41,6 +41,7 @@ SOURCES =\
device/dev-dasd.c \
device/dev-lvm1-pool.c \
device/online.c \
+ device/parse_vpd.c \
display/display.c \
error/errseg.c \
unknown/unknown.c \
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index ed9c726c9..193eb7585 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -80,6 +80,7 @@ static void _dev_init(struct device *dev)
dm_list_init(&dev->aliases);
dm_list_init(&dev->ids);
+ dm_list_init(&dev->wwids);
}
void dev_destroy_file(struct device *dev)
@@ -383,6 +384,22 @@ out:
return 1;
}
+int get_sysfs_binary(const char *path, char *buf, size_t buf_size, int *retlen)
+{
+ int ret;
+ int fd;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return 0;
+ ret = read(fd, buf, buf_size);
+ close(fd);
+ if (ret <= 0)
+ return 0;
+ *retlen = ret;
+ return 1;
+}
+
int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value)
{
FILE *fp;
@@ -1336,6 +1353,7 @@ int dev_cache_exit(void)
dm_hash_iterate(n, _cache.names) {
dev = (struct device *) dm_hash_get_data(_cache.names, n);
free_dids(&dev->ids);
+ free_wwids(&dev->wwids);
}
}
diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h
index 46b1da72c..7ffe01152 100644
--- a/lib/device/dev-cache.h
+++ b/lib/device/dev-cache.h
@@ -74,6 +74,7 @@ void dev_cache_failed_path(struct device *dev, const char *path);
bool dev_cache_has_md_with_end_superblock(struct dev_types *dt);
int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value);
+int get_sysfs_binary(const char *path, char *buf, size_t buf_size, int *retlen);
int get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int minor);
int setup_devices_file(struct cmd_context *cmd);
diff --git a/lib/device/dev-mpath.c b/lib/device/dev-mpath.c
index 846f6c8ba..27b0f41a6 100644
--- a/lib/device/dev-mpath.c
+++ b/lib/device/dev-mpath.c
@@ -200,11 +200,12 @@ static void _read_wwid_exclusions(void)
log_debug("multipath config ignored %d wwids", rem_count);
}
-static void _read_wwid_file(const char *config_wwids_file)
+static void _read_wwid_file(const char *config_wwids_file, int *entries)
{
FILE *fp;
char line[MAX_WWID_LINE];
char *wwid, *p;
+ char typestr[2] = { 0 };
int count = 0;
if (config_wwids_file[0] != '/') {
@@ -226,8 +227,17 @@ static void _read_wwid_file(const char *config_wwids_file)
if (line[0] == '/')
wwid++;
- /* skip the initial '3' */
- wwid++;
+
+ /*
+ * the initial character is the id type,
+ * 1 is t10, 2 is eui, 3 is naa, 8 is scsi name.
+ * wwids are stored in the hash table without the type charater.
+ * It seems that sometimes multipath does not include
+ * the type charater (seen with t10 scsi_debug devs).
+ */
+ typestr[0] = *wwid;
+ if (typestr[0] == '1' || typestr[0] == '2' || typestr[0] == '3')
+ wwid++;
if ((p = strchr(wwid, '/')))
*p = '\0';
@@ -240,6 +250,7 @@ static void _read_wwid_file(const char *config_wwids_file)
stack;
log_debug("multipath wwids read %d from %s", count, config_wwids_file);
+ *entries = count;
}
int dev_mpath_init(const char *config_wwids_file)
@@ -247,6 +258,7 @@ int dev_mpath_init(const char *config_wwids_file)
struct dm_pool *mem;
struct dm_hash_table *minor_tab;
struct dm_hash_table *wwid_tab;
+ int entries = 0;
dm_list_init(&_ignored);
dm_list_init(&_ignored_exceptions);
@@ -283,10 +295,16 @@ int dev_mpath_init(const char *config_wwids_file)
_wwid_hash_tab = wwid_tab;
if (config_wwids_file) {
- _read_wwid_file(config_wwids_file);
+ _read_wwid_file(config_wwids_file, &entries);
_read_wwid_exclusions();
}
+ if (!entries) {
+ /* reading dev wwids is skipped with null wwid_hash_tab */
+ dm_hash_destroy(_wwid_hash_tab);
+ _wwid_hash_tab = NULL;
+ }
+
return 1;
}
@@ -434,10 +452,10 @@ static int _dev_is_mpath_component_udev(struct device *dev)
/* mpath_devno is major:minor of the dm multipath device currently using the component dev. */
-static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device *dev, dev_t *mpath_devno)
+static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device *dev,
+ int primary_result, dev_t primary_dev, dev_t *mpath_devno)
{
struct dev_types *dt = cmd->dev_types;
- const char *part_name;
const char *name; /* e.g. "sda" for "/dev/sda" */
char link_path[PATH_MAX]; /* some obscure, unpredictable sysfs path */
char holders_path[PATH_MAX]; /* e.g. "/sys/block/sda/holders/" */
@@ -451,25 +469,15 @@ static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device
int dm_dev_major;
int dm_dev_minor;
struct stat info;
- dev_t primary_dev;
int is_mpath_component = 0;
- /* multipathing is only known to exist for SCSI or NVME devices */
- if (!major_is_scsi_device(dt, dev_major) && !dev_is_nvme(dt, dev))
- return 0;
-
- switch (dev_get_primary_dev(dt, dev, &primary_dev)) {
+ switch (primary_result) {
case 2: /* The dev is partition. */
- part_name = dev_name(dev); /* name of original dev for log_debug msg */
/* gets "foo" for "/dev/foo" where "/dev/foo" comes from major:minor */
if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, link_path, sizeof(link_path))))
return_0;
-
- log_debug_devs("%s: Device is a partition, using primary "
- "device %s for mpath component detection",
- part_name, name);
break;
case 1: /* The dev is already a primary dev. Just continue with the dev. */
@@ -593,47 +601,189 @@ static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device
return is_mpath_component;
}
-static int _dev_in_wwid_file(struct cmd_context *cmd, struct device *dev)
+static int _read_sys_wwid(struct cmd_context *cmd, struct device *dev,
+ char *idbuf, int idbufsize)
{
- char sysbuf[PATH_MAX] = { 0 };
- char *wwid;
- long look;
+ char idtmp[DEV_WWID_SIZE];
- if (!_wwid_hash_tab)
+ if (!read_sys_block(cmd, dev, "device/wwid", idbuf, idbufsize)) {
+ /* the wwid file is not under device for nvme devs */
+ if (!read_sys_block(cmd, dev, "wwid", idbuf, idbufsize))
+ return 0;
+ }
+ if (!idbuf[0])
return 0;
- if (!read_sys_block(cmd, dev, "device/wwid", sysbuf, sizeof(sysbuf)))
+ /* in t10 id, replace series of spaces with one _ like multipath */
+ if (!strncmp(idbuf, "t10.", 4) && strchr(idbuf, ' ')) {
+ if (idbufsize < DEV_WWID_SIZE)
+ return 0;
+ memcpy(idtmp, idbuf, DEV_WWID_SIZE);
+ memset(idbuf, 0, idbufsize);
+ format_t10_id((const unsigned char *)idtmp, DEV_WWID_SIZE, (unsigned char *)idbuf, idbufsize);
+ }
+ return 1;
+}
+
+#define VPD_SIZE 4096
+
+static int _read_sys_vpd_wwids(struct cmd_context *cmd, struct device *dev,
+ struct dm_list *ids)
+{
+ unsigned char vpd_data[VPD_SIZE] = { 0 };
+ int vpd_datalen = 0;
+
+ if (!read_sys_block_binary(cmd, dev, "device/vpd_pg83", (char *)vpd_data, VPD_SIZE, &vpd_datalen))
+ return 0;
+ if (!vpd_datalen)
return 0;
- if (!sysbuf[0])
+ /* adds dev_wwid entry to dev->wwids for each id in vpd data */
+ parse_vpd_ids(vpd_data, vpd_datalen, ids);
+ return 1;
+}
+
+void free_wwids(struct dm_list *ids)
+{
+ struct dev_wwid *dw, *safe;
+
+ dm_list_iterate_items_safe(dw, safe, ids) {
+ dm_list_del(&dw->list);
+ free(dw);
+ }
+}
+
+static int _wwid_type_num(char *id)
+{
+ if (!strncmp(id, "naa.", 4))
+ return 3;
+ else if (!strncmp(id, "eui.", 4))
+ return 2;
+ else if (!strncmp(id, "t10.", 4))
+ return 1;
+ else
+ return -1;
+}
+
+/*
+ * TODO: if each of the different wwid types (naa/eui/t10) were
+ * represented by different DEV_ID_TYPE_FOO values, and used
+ * as device_id types, then we could drop struct dev_wwid and
+ * drop dev->wwids, and just use dev->ids for each of the
+ * different wwids found in vpd_pg83. This would also require
+ * the ability to handle both the original method of replacing
+ * every space in the id string with _ and the new/multipath
+ * format_t10_id replacing series of spaces with one _.
+ */
+struct dev_wwid *add_wwid(char *id, int id_type, struct dm_list *ids)
+{
+ struct dev_wwid *dw;
+ int len;
+
+ if (!id_type) {
+ id_type = _wwid_type_num(id);
+ if (id_type == -1)
+ log_debug("unknown wwid type %s", id);
+ }
+
+ if (!(dw = zalloc(sizeof(struct dev_wwid))))
+ return NULL;
+ len = strlen(id);
+ if (len >= DEV_WWID_SIZE)
+ len = DEV_WWID_SIZE - 1;
+ memcpy(dw->id, id, len);
+ dw->type = id_type;
+ dm_list_add(ids, &dw->list);
+ return dw;
+}
+
+/*
+ * we save ids with format: naa.<value>, eui.<value>, t10.<value>.
+ * multipath wwids file uses format: 3<value>, 2<value>, 1<value>.
+ * The values are saved in wwid_hash_tab without the type prefix.
+ */
+
+static int _dev_in_wwid_file(struct cmd_context *cmd, struct device *dev,
+ int primary_result, dev_t primary_dev)
+{
+ char idbuf[DEV_WWID_SIZE] = { 0 };
+ struct dev_wwid *dw;
+ char *wwid;
+
+ if (!_wwid_hash_tab)
return 0;
/*
- * sysfs prints wwid as <typestr>.<value>
- * multipath wwid uses '3'<value>
- * does "<typestr>." always correspond to "3"?
+ * Check the primary device, not the partition.
*/
- if (!(wwid = strchr(sysbuf, '.')))
- return 0;
+ if (primary_result == 2) {
+ if (!(dev = dev_cache_get_by_devt(cmd, primary_dev))) {
+ log_debug("dev_is_mpath_component %s no primary dev", dev_name(dev));
+ return 0;
+ }
+ }
- /* skip the type and dot, just as '3' was skipped from wwids entry */
- wwid++;
-
- look = (long) dm_hash_lookup_binary(_wwid_hash_tab, wwid, strlen(wwid));
+ /*
+ * This function may be called multiple times for the same device, in
+ * particular if partitioned for each partition.
+ */
+ if (!dm_list_empty(&dev->wwids))
+ goto lookup;
- if (look) {
- log_debug_devs("dev_is_mpath_component %s multipath wwid %s", dev_name(dev), wwid);
- return 1;
+ /*
+ * Get all the ids for the device from vpd_pg83 and check if any of
+ * those are in /etc/multipath/wwids. These ids should include the
+ * value printed from the sysfs wwid file.
+ */
+ _read_sys_vpd_wwids(cmd, dev, &dev->wwids);
+ if (!dm_list_empty(&dev->wwids))
+ goto lookup;
+
+ /*
+ * This will read the sysfs wwid file, nvme devices in particular have
+ * a wwid file but not a vpd_pg83 file.
+ */
+ if (_read_sys_wwid(cmd, dev, idbuf, sizeof(idbuf)))
+ add_wwid(idbuf, 0, &dev->wwids);
+
+ lookup:
+ dm_list_iterate_items(dw, &dev->wwids) {
+ if (dw->type == 1 || dw->type == 2 || dw->type == 3)
+ wwid = &dw->id[4];
+ else
+ wwid = dw->id;
+
+ if (dm_hash_lookup_binary(_wwid_hash_tab, wwid, strlen(wwid))) {
+ log_debug_devs("dev_is_mpath_component %s %s in wwids file", dev_name(dev), dw->id);
+ return 1;
+ }
}
+
return 0;
}
int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev, dev_t *holder_devno)
{
- if (_dev_is_mpath_component_sysfs(cmd, dev, holder_devno) == 1)
+ struct dev_types *dt = cmd->dev_types;
+ int primary_result;
+ dev_t primary_dev;
+
+ /*
+ * multipath only uses SCSI or NVME devices
+ */
+ if (!major_is_scsi_device(dt, MAJOR(dev->dev)) && !dev_is_nvme(dt, dev))
+ return 0;
+
+ /*
+ * primary_result 2: dev is a partition, primary_dev is the whole device
+ * primary_result 1: dev is a whole device
+ */
+ primary_result = dev_get_primary_dev(dt, dev, &primary_dev);
+
+ if (_dev_is_mpath_component_sysfs(cmd, dev, primary_result, primary_dev, holder_devno) == 1)
goto found;
- if (_dev_in_wwid_file(cmd, dev))
+ if (_dev_in_wwid_file(cmd, dev, primary_result, primary_dev))
goto found;
if (external_device_info_source() == DEV_EXT_UDEV) {
@@ -641,6 +791,12 @@ int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev, dev_t *h
goto found;
}
+ /*
+ * TODO: save the result of this function in dev->flags and use those
+ * flags on repeated calls to avoid repeating the work multiple times
+ * for the same device when there are partitions on the device.
+ */
+
return 0;
found:
return 1;
diff --git a/lib/device/device.h b/lib/device/device.h
index d0d670ec3..06440f44b 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -59,6 +59,14 @@ struct dev_ext {
void *handle;
};
+#define DEV_WWID_SIZE 128
+
+struct dev_wwid {
+ struct dm_list list;
+ int type;
+ char id[DEV_WWID_SIZE];
+};
+
#define DEV_ID_TYPE_SYS_WWID 0x0001
#define DEV_ID_TYPE_SYS_SERIAL 0x0002
#define DEV_ID_TYPE_MPATH_UUID 0x0003
@@ -105,6 +113,7 @@ struct dev_use {
*/
struct device {
struct dm_list aliases; /* struct dm_str_list */
+ struct dm_list wwids; /* struct dev_wwid, used for multipath component detection */
struct dm_list ids; /* struct dev_id, different entries for different idtypes */
struct dev_id *id; /* points to the the ids entry being used for this dev */
dev_t dev;
@@ -206,5 +215,9 @@ void dev_destroy_file(struct device *dev);
int dev_mpath_init(const char *config_wwids_file);
void dev_mpath_exit(void);
+struct dev_wwid *add_wwid(char *id, int id_type, struct dm_list *ids);
+void free_wwids(struct dm_list *ids);
+int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list *ids);
+int format_t10_id(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes);
#endif
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index f1928347c..9dec9f884 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -182,7 +182,9 @@ void free_dids(struct dm_list *ids)
}
}
-int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suffix, char *sysbuf, int sysbufsize)
+static int _read_sys_block(struct cmd_context *cmd, struct device *dev,
+ const char *suffix, char *sysbuf, int sysbufsize,
+ int binary, int *retlen)
{
char path[PATH_MAX];
dev_t devt = dev->dev;
@@ -196,11 +198,17 @@ int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suff
return 0;
}
- get_sysfs_value(path, sysbuf, sysbufsize, 0);
+ if (binary) {
+ ret = get_sysfs_binary(path, sysbuf, sysbufsize, retlen);
+ if (ret && !*retlen)
+ ret = 0;
+ } else {
+ ret = get_sysfs_value(path, sysbuf, sysbufsize, 0);
+ if (ret && !sysbuf[0])
+ ret = 0;
+ }
- if (sysbuf[0]) {
- if (prim)
- log_debug("Using primary device_id for partition %s.", dev_name(dev));
+ if (ret) {
sysbuf[sysbufsize - 1] = '\0';
return 1;
}
@@ -220,6 +228,19 @@ int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suff
return 0;
}
+int read_sys_block(struct cmd_context *cmd, struct device *dev,
+ const char *suffix, char *sysbuf, int sysbufsize)
+{
+ return _read_sys_block(cmd, dev, suffix, sysbuf, sysbufsize, 0, NULL);
+}
+
+int read_sys_block_binary(struct cmd_context *cmd, struct device *dev,
+ const char *suffix, char *sysbuf, int sysbufsize,
+ int *retlen)
+{
+ return _read_sys_block(cmd, dev, suffix, sysbuf, sysbufsize, 1, retlen);
+}
+
static int _dm_uuid_has_prefix(char *sysbuf, const char *prefix)
{
if (!strncmp(sysbuf, prefix, strlen(prefix)))
diff --git a/lib/device/device_id.h b/lib/device/device_id.h
index 94773a65e..9b9c9ce03 100644
--- a/lib/device/device_id.h
+++ b/lib/device/device_id.h
@@ -58,6 +58,8 @@ void devices_file_exit(struct cmd_context *cmd);
void unlink_searched_devnames(struct cmd_context *cmd);
int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suffix, char *sysbuf, int sysbufsize);
+int read_sys_block_binary(struct cmd_context *cmd, struct device *dev,
+ const char *suffix, char *sysbuf, int sysbufsize, int *retlen);
int dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, const char **idname_out);
diff --git a/lib/device/parse_vpd.c b/lib/device/parse_vpd.c
new file mode 100644
index 000000000..4bafa7b9e
--- /dev/null
+++ b/lib/device/parse_vpd.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2022 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "base/memory/zalloc.h"
+#include "lib/misc/lib.h"
+#include "lib/device/device.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <limits.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <assert.h>
+
+/*
+ * Replace series of spaces with a single _.
+ */
+int format_t10_id(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes)
+{
+ int in_space = 0;
+ int retlen = 0;
+ int j = 0;
+ int i;
+
+ for (i = 0; i < in_bytes; i++) {
+ if (!in[i])
+ break;
+ if (j >= (out_bytes - 2))
+ break;
+ /* skip leading spaces */
+ if (!retlen && (in[i] == ' '))
+ continue;
+ /* replace one or more spaces with _ */
+ if (in[i] == ' ') {
+ in_space = 1;
+ continue;
+ }
+ /* spaces are finished so insert _ */
+ if (in_space) {
+ out[j++] = '_';
+ in_space = 0;
+ retlen++;
+ }
+ out[j++] = in[i];
+ retlen++;
+ }
+ return retlen;
+}
+
+static int _to_hex(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes)
+{
+ int off = 0;
+ int num;
+ int i;
+
+ for (i = 0; i < in_bytes; i++) {
+ num = sprintf((char *)out + off, "%02x", in[i]);
+ if (num < 0)
+ break;
+ off += num;
+ if (off + 2 >= out_bytes)
+ break;
+ }
+ return off;
+}
+
+#define ID_BUFSIZE 1024
+
+/*
+ * based on linux kernel function
+ */
+int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list *ids)
+{
+ char id[ID_BUFSIZE];
+ unsigned char tmp_str[ID_BUFSIZE];
+ const unsigned char *d, *cur_id_str;
+ size_t id_len = ID_BUFSIZE;
+ int id_size = -1;
+ uint8_t cur_id_size = 0;
+
+ memset(id, 0, ID_BUFSIZE);
+ for (d = vpd_data + 4;
+ d < vpd_data + vpd_datalen;
+ d += d[3] + 4) {
+ memset(tmp_str, 0, sizeof(tmp_str));
+
+ switch (d[1] & 0xf) {
+ case 0x1:
+ /* T10 Vendor ID */
+ cur_id_size = d[3];
+ if (cur_id_size + 4 > id_len)
+ cur_id_size = id_len - 4;
+ cur_id_str = d + 4;
+ format_t10_id(cur_id_str, cur_id_size, tmp_str, sizeof(tmp_str));
+ id_size = snprintf(id, ID_BUFSIZE, "t10.%s", tmp_str);
+ if (id_size < 0)
+ break;
+ if (id_size >= ID_BUFSIZE)
+ id_size = ID_BUFSIZE - 1;
+ add_wwid(id, 1, ids);
+ break;
+ case 0x2:
+ /* EUI-64 */
+ cur_id_size = d[3];
+ cur_id_str = d + 4;
+ switch (cur_id_size) {
+ case 8:
+ _to_hex(cur_id_str, 8, tmp_str, sizeof(tmp_str));
+ id_size = snprintf(id, ID_BUFSIZE, "eui.%s", tmp_str);
+ break;
+ case 12:
+ _to_hex(cur_id_str, 12, tmp_str, sizeof(tmp_str));
+ id_size = snprintf(id, ID_BUFSIZE, "eui.%s", tmp_str);
+ break;
+ case 16:
+ _to_hex(cur_id_str, 16, tmp_str, sizeof(tmp_str));
+ id_size = snprintf(id, ID_BUFSIZE, "eui.%s", tmp_str);
+ break;
+ default:
+ break;
+ }
+ if (id_size < 0)
+ break;
+ if (id_size >= ID_BUFSIZE)
+ id_size = ID_BUFSIZE - 1;
+ add_wwid(id, 2, ids);
+ break;
+ case 0x3:
+ /* NAA */
+ cur_id_size = d[3];
+ cur_id_str = d + 4;
+ switch (cur_id_size) {
+ case 8:
+ _to_hex(cur_id_str, 8, tmp_str, sizeof(tmp_str));
+ id_size = snprintf(id, ID_BUFSIZE, "naa.%s", tmp_str);
+ break;
+ case 16:
+ _to_hex(cur_id_str, 16, tmp_str, sizeof(tmp_str));
+ id_size = snprintf(id, ID_BUFSIZE, "naa.%s", tmp_str);
+ break;
+ default:
+ break;
+ }
+ if (id_size < 0)
+ break;
+ if (id_size >= ID_BUFSIZE)
+ id_size = ID_BUFSIZE - 1;
+ add_wwid(id, 3, ids);
+ break;
+ case 0x8:
+ /* SCSI name string */
+ cur_id_size = d[3];
+ cur_id_str = d + 4;
+ if (cur_id_size >= id_len)
+ cur_id_size = id_len - 1;
+ memcpy(id, cur_id_str, cur_id_size);
+ id_size = cur_id_size;
+
+ /*
+ * Not in the kernel version, copying multipath code,
+ * which checks if this string begins with naa or eui
+ * and if so does tolower() on the chars.
+ */
+ if (!strncmp(id, "naa.", 4) || !strncmp(id, "eui.", 4)) {
+ int i;
+ for (i = 0; i < id_size; i++)
+ id[i] = tolower(id[i]);
+ }
+ add_wwid(id, 8, ids);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return id_size;
+}
--
2.34.3

View File

@ -0,0 +1,36 @@
From 3cfb00e5f7c720549100c5297be18600c9abf530 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Fri, 24 Jun 2022 10:40:54 -0500
Subject: [PATCH 5/7] pvdisplay: restore --reportformat option
Fixes commit b8f4ec846 "display: ignore --reportformat"
by restoring the --reportformat option to pvdisplay.
Adding -C to pvdisplay turns the command into a reporting
command (like pvs, vgs, lvs) in which --reportformat can
be useful.
(cherry picked from commit db5277c97155632ce83e1125e348eda97c871968)
---
tools/command-lines.in | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/command-lines.in b/tools/command-lines.in
index b64fd0dda..b6a03d158 100644
--- a/tools/command-lines.in
+++ b/tools/command-lines.in
@@ -1593,10 +1593,10 @@ pvdisplay
OO: --aligned, --all, --binary, --colon, --columns, --configreport ConfigReport,
--foreign, --ignorelockingfailure,
--logonly, --maps, --noheadings, --nosuffix, --options String,
---readonly, --select String, --separator String, --shared,
+--readonly, --reportformat ReportFmt, --select String, --separator String, --shared,
--short, --sort String, --unbuffered, --units Units
OP: PV|Tag ...
-IO: --ignoreskippedcluster, --reportformat ReportFmt
+IO: --ignoreskippedcluster
ID: pvdisplay_general
---
--
2.34.3

View File

@ -0,0 +1,247 @@
From a369a7fd1fccf3c50103dd294b79055cc7c9d005 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Tue, 5 Jul 2022 17:08:00 -0500
Subject: [PATCH 6/7] exit with error when --devicesfile name doesn't exist
(cherry picked from commit 92b4fcf57f3c6d212d06b72b097e1a06e6efb84b)
---
lib/cache/lvmcache.c | 3 ++-
lib/label/label.c | 4 ++--
test/shell/devicesfile-basic.sh | 1 +
tools/pvcreate.c | 3 ++-
tools/pvremove.c | 3 ++-
tools/pvscan.c | 3 ++-
tools/toollib.c | 27 +++++++++++++++++++++------
tools/vgcfgrestore.c | 5 ++++-
tools/vgcreate.c | 5 ++++-
tools/vgextend.c | 3 ++-
tools/vgmerge.c | 3 ++-
tools/vgsplit.c | 3 ++-
12 files changed, 46 insertions(+), 17 deletions(-)
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 22edcfd84..a1c4a61c8 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -1612,7 +1612,8 @@ int lvmcache_label_scan(struct cmd_context *cmd)
* with infos/vginfos based on reading headers from
* each device, and a vg summary from each mda.
*/
- label_scan(cmd);
+ if (!label_scan(cmd))
+ return_0;
/*
* When devnames are used as device ids (which is dispreferred),
diff --git a/lib/label/label.c b/lib/label/label.c
index 711edb6f4..f845abb96 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -801,7 +801,7 @@ static int _setup_bcache(void)
}
if (!(scan_bcache = bcache_create(BCACHE_BLOCK_SIZE_IN_SECTORS, cache_blocks, ioe))) {
- log_error("Failed to create bcache with %d cache blocks.", cache_blocks);
+ log_error("Failed to set up io layer with %d blocks.", cache_blocks);
return 0;
}
@@ -1292,7 +1292,7 @@ int label_scan(struct cmd_context *cmd)
* data to invalidate.)
*/
if (!(iter = dev_iter_create(NULL, 0))) {
- log_error("Scanning failed to get devices.");
+ log_error("Failed to get device list.");
return 0;
}
while ((dev = dev_iter_get(cmd, iter))) {
diff --git a/test/shell/devicesfile-basic.sh b/test/shell/devicesfile-basic.sh
index 77fe265a0..715c579b3 100644
--- a/test/shell/devicesfile-basic.sh
+++ b/test/shell/devicesfile-basic.sh
@@ -107,6 +107,7 @@ not vgs --devicesfile test.devices $vg2
# misspelled override name fails
not vgs --devicesfile doesnotexist $vg1
not vgs --devicesfile doesnotexist $vg2
+not vgs --devicesfile doesnotexist
# devicesfile and devices cannot be used together
not vgs --devicesfile test.devices --devices "$dev1","$dev1" $vg1
diff --git a/tools/pvcreate.c b/tools/pvcreate.c
index 71eb060a3..a1ef0e9e1 100644
--- a/tools/pvcreate.c
+++ b/tools/pvcreate.c
@@ -144,7 +144,8 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv)
cmd->create_edit_devices_file = 1;
- lvmcache_label_scan(cmd);
+ if (!lvmcache_label_scan(cmd))
+ return_ECMD_FAILED;
if (!(handle = init_processing_handle(cmd, NULL))) {
log_error("Failed to initialize processing handle.");
diff --git a/tools/pvremove.c b/tools/pvremove.c
index 2dfdbd016..5c39ee0c7 100644
--- a/tools/pvremove.c
+++ b/tools/pvremove.c
@@ -45,7 +45,8 @@ int pvremove(struct cmd_context *cmd, int argc, char **argv)
clear_hint_file(cmd);
- lvmcache_label_scan(cmd);
+ if (!lvmcache_label_scan(cmd))
+ return_ECMD_FAILED;
/* When forcibly clearing a PV we don't care about a VG lock. */
if (pp.force == DONT_PROMPT_OVERRIDE)
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 1e47d754a..72c3279c3 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -1407,7 +1407,8 @@ static int _pvscan_cache_all(struct cmd_context *cmd, int argc, char **argv,
* which we want 'pvscan --cache' to do, and that uses
* info from lvmcache, e.g. duplicate pv info.
*/
- lvmcache_label_scan(cmd);
+ if (!lvmcache_label_scan(cmd))
+ return_0;
cmd->pvscan_recreate_hints = 0;
cmd->use_hints = 0;
diff --git a/tools/toollib.c b/tools/toollib.c
index d77092d89..544791808 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1655,7 +1655,10 @@ int process_each_label(struct cmd_context *cmd, int argc, char **argv,
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_LABEL);
- lvmcache_label_scan(cmd);
+ if (!lvmcache_label_scan(cmd)) {
+ ret_max = ECMD_FAILED;
+ goto_out;
+ }
if (argc) {
for (; opt < argc; opt++) {
@@ -2435,8 +2438,13 @@ int process_each_vg(struct cmd_context *cmd,
* Scan all devices to populate lvmcache with initial
* list of PVs and VGs.
*/
- if (!(read_flags & PROCESS_SKIP_SCAN))
- lvmcache_label_scan(cmd);
+ if (!(read_flags & PROCESS_SKIP_SCAN)) {
+ if (!lvmcache_label_scan(cmd)) {
+ ret_max = ECMD_FAILED;
+ goto_out;
+ }
+ }
+
/*
* A list of all VGs on the system is needed when:
@@ -3987,7 +3995,10 @@ int process_each_lv(struct cmd_context *cmd,
* Scan all devices to populate lvmcache with initial
* list of PVs and VGs.
*/
- lvmcache_label_scan(cmd);
+ if (!lvmcache_label_scan(cmd)) {
+ ret_max = ECMD_FAILED;
+ goto_out;
+ }
/*
* A list of all VGs on the system is needed when:
@@ -4623,8 +4634,12 @@ int process_each_pv(struct cmd_context *cmd,
goto_out;
}
- if (!(read_flags & PROCESS_SKIP_SCAN))
- lvmcache_label_scan(cmd);
+ if (!(read_flags & PROCESS_SKIP_SCAN)) {
+ if (!lvmcache_label_scan(cmd)) {
+ ret_max = ECMD_FAILED;
+ goto_out;
+ }
+ }
if (!lvmcache_get_vgnameids(cmd, &all_vgnameids, only_this_vgname, 1)) {
ret_max = ret;
diff --git a/tools/vgcfgrestore.c b/tools/vgcfgrestore.c
index e49313d14..9fcba89d4 100644
--- a/tools/vgcfgrestore.c
+++ b/tools/vgcfgrestore.c
@@ -132,7 +132,10 @@ int vgcfgrestore(struct cmd_context *cmd, int argc, char **argv)
clear_hint_file(cmd);
- lvmcache_label_scan(cmd);
+ if (!lvmcache_label_scan(cmd)) {
+ unlock_vg(cmd, NULL, vg_name);
+ return_ECMD_FAILED;
+ }
cmd->handles_unknown_segments = 1;
diff --git a/tools/vgcreate.c b/tools/vgcreate.c
index dde3f1eac..14608777f 100644
--- a/tools/vgcreate.c
+++ b/tools/vgcreate.c
@@ -84,7 +84,10 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
cmd->create_edit_devices_file = 1;
- lvmcache_label_scan(cmd);
+ if (!lvmcache_label_scan(cmd)) {
+ unlock_vg(cmd, NULL, vp_new.vg_name);
+ return_ECMD_FAILED;
+ }
if (lvmcache_vginfo_from_vgname(vp_new.vg_name, NULL)) {
unlock_vg(cmd, NULL, vp_new.vg_name);
diff --git a/tools/vgextend.c b/tools/vgextend.c
index 0856b4c78..fecd6bdd5 100644
--- a/tools/vgextend.c
+++ b/tools/vgextend.c
@@ -160,7 +160,8 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
cmd->edit_devices_file = 1;
- lvmcache_label_scan(cmd);
+ if (!lvmcache_label_scan(cmd))
+ return_ECMD_FAILED;
if (!(handle = init_processing_handle(cmd, NULL))) {
log_error("Failed to initialize processing handle.");
diff --git a/tools/vgmerge.c b/tools/vgmerge.c
index 08615cd62..4ed4a8f0b 100644
--- a/tools/vgmerge.c
+++ b/tools/vgmerge.c
@@ -72,7 +72,8 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
return ECMD_FAILED;
}
- lvmcache_label_scan(cmd);
+ if (!lvmcache_label_scan(cmd))
+ return_ECMD_FAILED;
if (strcmp(vg_name_to, vg_name_from) > 0)
lock_vg_from_first = 1;
diff --git a/tools/vgsplit.c b/tools/vgsplit.c
index 5f113b363..c7f4b8af4 100644
--- a/tools/vgsplit.c
+++ b/tools/vgsplit.c
@@ -559,7 +559,8 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- lvmcache_label_scan(cmd);
+ if (!lvmcache_label_scan(cmd))
+ return_ECMD_FAILED;
if (!(vginfo_to = lvmcache_vginfo_from_vgname(vg_name_to, NULL))) {
if (!validate_name(vg_name_to)) {
--
2.34.3

View File

@ -0,0 +1,43 @@
From a8588f39219a2794fad562b38e6dc63aee791f82 Mon Sep 17 00:00:00 2001
From: Zdenek Kabelac <zkabelac@redhat.com>
Date: Mon, 11 Jul 2022 01:02:22 +0200
Subject: [PATCH 7/7] make: generate
(cherry picked from commit c0f8e6675c62332263acdc7c3c2f61eca20bd60f)
---
man/pvdisplay.8_pregen | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/man/pvdisplay.8_pregen b/man/pvdisplay.8_pregen
index 23d41b29b..e7767d0c4 100644
--- a/man/pvdisplay.8_pregen
+++ b/man/pvdisplay.8_pregen
@@ -61,6 +61,8 @@ 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,6 +322,16 @@ 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.34.3

View File

@ -0,0 +1,55 @@
From 2a31250c445911eb07057f077a17e3a281ac0049 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Mon, 25 Jul 2022 13:50:43 -0500
Subject: [PATCH] apply multipath_component_detection=0 to duplicate PV
handling
multipath_component_detection=0 has always applied to the filter-based
component detection. Also apply this setting to the duplicate-PV
handling which also eliminates multipath components (based on duplicate
PVs having the same wwid.)
(cherry picked from commit 99ce09ae778c2cc4aa2611e425bba5287b8b9513)
---
lib/cache/lvmcache.c | 3 +++
test/shell/duplicate-pvs-multipath.sh | 10 +++++++---
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index a1c4a61c8..00916885c 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -652,6 +652,9 @@ static int _all_multipath_components(struct cmd_context *cmd, struct lvmcache_in
*dev_mpath = NULL;
+ if (!find_config_tree_bool(cmd, devices_multipath_component_detection_CFG, NULL))
+ return 0;
+
/* This function only makes sense with more than one dev. */
if ((info && dm_list_empty(altdevs)) || (!info && (dm_list_size(altdevs) == 1))) {
log_debug("Skip multipath component checks with single device for PVID %s", pvid);
diff --git a/test/shell/duplicate-pvs-multipath.sh b/test/shell/duplicate-pvs-multipath.sh
index 59c15b0d4..bc98d2d5a 100644
--- a/test/shell/duplicate-pvs-multipath.sh
+++ b/test/shell/duplicate-pvs-multipath.sh
@@ -24,9 +24,13 @@ modprobe --dry-run scsi_debug || skip
multipath -l || skip
multipath -l | grep scsi_debug && skip
-# Turn off multipath_component_detection so that the duplicate
-# resolution of mpath components is used.
-aux lvmconf 'devices/multipath_component_detection = 0'
+# FIXME: setting multipath_component_detection=0 now also disables
+# the wwid-based mpath component detection, so this test will need
+# to find another way to disable only the filter-mpath code (using
+# sysfs and multipath/wwids) while keeping the code enabled that
+# eliminates duplicates based on their matching wwids which this
+# tries to test.
+
# Prevent wwids from being used for filtering.
aux lvmconf 'devices/multipath_wwids_file = "/dev/null"'
# Need to use /dev/mapper/mpath
--
2.37.1

View File

@ -0,0 +1,30 @@
From f7277061859740712b67ef6b229c2fc07482ef16 Mon Sep 17 00:00:00 2001
From: Tony Asleson <tasleson@redhat.com>
Date: Wed, 25 May 2022 15:51:14 -0500
Subject: [PATCH 1/9] lvmdbusd: Correct conditional for lvm child process
running
Poll returns None when process is running, else exit value. If poll returns
0 we will fail to exit the select loop.
(cherry picked from commit 37733cd4eb5116db371ac1ae6e971e3c336c3ddb)
---
daemons/lvmdbusd/lvm_shell_proxy.py.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/daemons/lvmdbusd/lvm_shell_proxy.py.in b/daemons/lvmdbusd/lvm_shell_proxy.py.in
index 7816daa8b..78fe1e422 100644
--- a/daemons/lvmdbusd/lvm_shell_proxy.py.in
+++ b/daemons/lvmdbusd/lvm_shell_proxy.py.in
@@ -75,7 +75,7 @@ class LVMShellProxy(object):
stderr += read_decoded(self.lvm_shell.stderr)
# Check to see if the lvm process died on us
- if self.lvm_shell.poll():
+ if self.lvm_shell.poll() is not None:
raise Exception(self.lvm_shell.returncode, "%s" % stderr)
if stdout.endswith(SHELL_PROMPT):
--
2.37.1

View File

@ -0,0 +1,30 @@
From ece4c18a42af8fde41f55fd43e8cc0ca34ab2f7d Mon Sep 17 00:00:00 2001
From: Tony Asleson <tasleson@redhat.com>
Date: Wed, 25 May 2022 15:52:20 -0500
Subject: [PATCH 2/9] lvmdbusd: Simplify child process env
We don't need to duplicate the entire env from the parent, supply only what
is needed.
(cherry picked from commit 58c6c9e9aa8d6aa6d3be14a04ec0f4257b61495e)
---
daemons/lvmdbusd/lvm_shell_proxy.py.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/daemons/lvmdbusd/lvm_shell_proxy.py.in b/daemons/lvmdbusd/lvm_shell_proxy.py.in
index 78fe1e422..10719c67e 100644
--- a/daemons/lvmdbusd/lvm_shell_proxy.py.in
+++ b/daemons/lvmdbusd/lvm_shell_proxy.py.in
@@ -135,7 +135,8 @@ class LVMShellProxy(object):
self.report_stream = os.fdopen(self.report_fd, 'rb', 0)
# Setup the environment for using our own socket for reporting
- local_env = copy.deepcopy(os.environ)
+ local_env = {}
+ local_env["LC_ALL"] = "C"
local_env["LVM_REPORT_FD"] = "32"
local_env["LVM_COMMAND_PROFILE"] = "lvmdbusd"
--
2.37.1

View File

@ -0,0 +1,73 @@
From 6d0ad276260c902dba66df73beac1bafc3f4c254 Mon Sep 17 00:00:00 2001
From: Tony Asleson <tasleson@redhat.com>
Date: Wed, 25 May 2022 15:58:15 -0500
Subject: [PATCH 3/9] lvmdbusd: re-work lvm shell main
Add an optional single argument "bisect" to use with git bisect for
automation. Normal case is no arguments when running stand-alone.
(cherry picked from commit b3407b16c1c7b5bff01e3bde4e0f62a2608682f8)
---
daemons/lvmdbusd/lvm_shell_proxy.py.in | 46 ++++++++++++++++----------
1 file changed, 28 insertions(+), 18 deletions(-)
diff --git a/daemons/lvmdbusd/lvm_shell_proxy.py.in b/daemons/lvmdbusd/lvm_shell_proxy.py.in
index 10719c67e..40639442c 100644
--- a/daemons/lvmdbusd/lvm_shell_proxy.py.in
+++ b/daemons/lvmdbusd/lvm_shell_proxy.py.in
@@ -238,24 +238,34 @@ class LVMShellProxy(object):
if __name__ == "__main__":
- shell = LVMShellProxy()
- in_line = "start"
+ print("USING LVM BINARY: %s " % LVM_CMD)
+
try:
- while in_line:
- in_line = input("lvm> ")
- if in_line:
- start = time.time()
- ret, out, err = shell.call_lvm(in_line.split())
- end = time.time()
-
- print(("RC: %d" % ret))
- print(("OUT:\n%s" % out))
- print(("ERR:\n%s" % err))
-
- print("Command = %f seconds" % (end - start))
- except KeyboardInterrupt:
- pass
- except EOFError:
- pass
+ if len(sys.argv) > 1 and sys.argv[1] == "bisect":
+ shell = LVMShellProxy()
+ shell.exit_shell()
+ else:
+ shell = LVMShellProxy()
+ in_line = "start"
+ try:
+ while in_line:
+ in_line = input("lvm> ")
+ if in_line:
+ start = time.time()
+ ret, out, err = shell.call_lvm(in_line.split())
+ end = time.time()
+
+ print(("RC: %d" % ret))
+ print(("OUT:\n%s" % out))
+ print(("ERR:\n%s" % err))
+
+ print("Command = %f seconds" % (end - start))
+ except KeyboardInterrupt:
+ pass
+ except EOFError:
+ pass
except Exception:
traceback.print_exc(file=sys.stdout)
+ sys.exit(1)
+
+ sys.exit(0)
--
2.37.1

View File

@ -0,0 +1,26 @@
From a9ca83b880c19a72d6e00e13b6a638fb11630819 Mon Sep 17 00:00:00 2001
From: Tony Asleson <tasleson@redhat.com>
Date: Wed, 25 May 2022 15:59:11 -0500
Subject: [PATCH 4/9] lvmdbusd: Add debug output for which lvm binary is used
(cherry picked from commit 51d9b686c08d963c61898d407d15abf39f129d72)
---
daemons/lvmdbusd/main.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/daemons/lvmdbusd/main.py b/daemons/lvmdbusd/main.py
index b0a82d492..1e717ef69 100644
--- a/daemons/lvmdbusd/main.py
+++ b/daemons/lvmdbusd/main.py
@@ -127,6 +127,8 @@ def main():
log_error("You cannot specify --lvmshell and --nojson")
sys.exit(1)
+ log_debug("Using lvm binary: %s" % cfg.LVM_CMD)
+
# We will dynamically add interfaces which support vdo if it
# exists.
cfg.vdo_support = supports_vdo()
--
2.37.1

View File

@ -0,0 +1,73 @@
From aa5ec0804d151e5951c4516c3bc08d37e2494349 Mon Sep 17 00:00:00 2001
From: Tony Asleson <tasleson@redhat.com>
Date: Wed, 25 May 2022 16:03:27 -0500
Subject: [PATCH 5/9] lvmdbusd: Change unit test vdo minimum size
(cherry picked from commit 47c61907b4adbdead50f5bb5ac95c0f5d0fe263e)
---
test/dbus/lvmdbustest.py | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/test/dbus/lvmdbustest.py b/test/dbus/lvmdbustest.py
index 6d692223f..3eef77fd7 100755
--- a/test/dbus/lvmdbustest.py
+++ b/test/dbus/lvmdbustest.py
@@ -23,6 +23,9 @@ import os
g_tmo = 0
+# Approx. min size
+VDO_MIN_SIZE = mib(8192)
+
# Prefix on created objects to enable easier clean-up
g_prefix = os.getenv('PREFIX', '')
@@ -1155,7 +1158,7 @@ class TestDbusService(unittest.TestCase):
return
# This may not pass
- for i in [48, 64, 128]:
+ for i in [64, 128]:
yes = self._test_expired_timer(i)
if yes:
break
@@ -1907,8 +1910,8 @@ class TestDbusService(unittest.TestCase):
vdo_pool_object_path = self.handle_return(
vg_proxy.VgVdo.CreateVdoPoolandLv(
pool_name, lv_name,
- dbus.UInt64(mib(4096)), # Appears to be minimum size
- dbus.UInt64(mib(8192)),
+ dbus.UInt64(VDO_MIN_SIZE),
+ dbus.UInt64(VDO_MIN_SIZE * 2),
dbus.Int32(g_tmo),
EOD))
@@ -1950,7 +1953,7 @@ class TestDbusService(unittest.TestCase):
vg_proxy = self._vg_create(vg_prefix="vdo_conv_")
lv = self._test_lv_create(
vg_proxy.Vg.LvCreate,
- (dbus.String(pool_name), dbus.UInt64(mib(4096)),
+ (dbus.String(pool_name), dbus.UInt64(VDO_MIN_SIZE),
dbus.Array([], signature='(ott)'), dbus.Int32(g_tmo),
EOD), vg_proxy.Vg, LV_BASE_INT)
lv_obj_path = self._lookup("%s/%s" % (vg_proxy.Vg.Name, pool_name))
@@ -1959,7 +1962,7 @@ class TestDbusService(unittest.TestCase):
vdo_pool_path = self.handle_return(
vg_proxy.VgVdo.CreateVdoPool(
dbus.ObjectPath(lv.object_path), lv_name,
- dbus.UInt64(mib(8192)),
+ dbus.UInt64(VDO_MIN_SIZE),
dbus.Int32(g_tmo),
EOD))
@@ -2083,6 +2086,7 @@ if __name__ == '__main__':
std_err_print('\n*** Testing only lvm shell mode ***\n')
for g_tmo in [0, 15]:
+ std_err_print('Testing TMO=%d\n' % g_tmo)
if mode == 0:
if set_execution(False, r):
r.register_result(unittest.main(exit=False))
--
2.37.1

View File

@ -0,0 +1,54 @@
From d978fe593b3c75d4b5b66d743b4f5c3632861559 Mon Sep 17 00:00:00 2001
From: Tony Asleson <tasleson@redhat.com>
Date: Wed, 25 May 2022 16:21:14 -0500
Subject: [PATCH 6/9] lvmdbusd: Fix env variable LVM_DBUSD_TEST_MODE
Make it more logical.
(cherry picked from commit b3d7aff6a3a8fd55790f61b9b0b33d599841030b)
---
test/dbus/lvmdbustest.py | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/test/dbus/lvmdbustest.py b/test/dbus/lvmdbustest.py
index 3eef77fd7..d876a1748 100755
--- a/test/dbus/lvmdbustest.py
+++ b/test/dbus/lvmdbustest.py
@@ -40,9 +40,10 @@ pv_device_list = os.getenv('LVM_DBUSD_PV_DEVICE_LIST', None)
# Default is to test all modes
# 0 == Only test fork & exec mode
-# 1 == Test both fork & exec & lvm shell mode (default)
+# 1 == Only test lvm shell mode
+# 2 == Test both fork & exec & lvm shell mode (default)
# Other == Test just lvm shell mode
-test_shell = os.getenv('LVM_DBUSD_TEST_MODE', 1)
+test_shell = os.getenv('LVM_DBUSD_TEST_MODE', 2)
# LVM binary to use
LVM_EXECUTABLE = os.getenv('LVM_BINARY', '/usr/sbin/lvm')
@@ -2081,16 +2082,19 @@ if __name__ == '__main__':
if mode == 0:
std_err_print('\n*** Testing only lvm fork & exec test mode ***\n')
elif mode == 1:
+ std_err_print('\n*** Testing only lvm shell mode ***\n')
+ elif mode == 2:
std_err_print('\n*** Testing fork & exec & lvm shell mode ***\n')
else:
- std_err_print('\n*** Testing only lvm shell mode ***\n')
+ std_err_print("Unsupported \"LVM_DBUSD_TEST_MODE\"=%d, [0-2] valid" % mode)
+ sys.exit(1)
for g_tmo in [0, 15]:
std_err_print('Testing TMO=%d\n' % g_tmo)
if mode == 0:
if set_execution(False, r):
r.register_result(unittest.main(exit=False))
- elif mode == 2:
+ elif mode == 1:
if set_execution(True, r):
r.register_result(unittest.main(exit=False))
else:
--
2.37.1

View File

@ -0,0 +1,62 @@
From 8e724393079784edbf779678df6937dd838c4149 Mon Sep 17 00:00:00 2001
From: Tony Asleson <tasleson@redhat.com>
Date: Thu, 26 May 2022 10:44:02 -0500
Subject: [PATCH 7/9] lvmdbusd: Remove the use of sub shell for lvm shell
This reduces the number of processes and improves security.
(cherry picked from commit 7a2090655d3ab5abde83b981594ed527e2a7f1f7)
---
daemons/lvmdbusd/lvm_shell_proxy.py.in | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)
diff --git a/daemons/lvmdbusd/lvm_shell_proxy.py.in b/daemons/lvmdbusd/lvm_shell_proxy.py.in
index 40639442c..1a5051a92 100644
--- a/daemons/lvmdbusd/lvm_shell_proxy.py.in
+++ b/daemons/lvmdbusd/lvm_shell_proxy.py.in
@@ -129,31 +129,29 @@ class LVMShellProxy(object):
except FileExistsError:
pass
- # We have to open non-blocking as the other side isn't open until
- # we actually fork the process.
+ # Open the fifo for use to read and for lvm child process to write to.
self.report_fd = os.open(tmp_file, os.O_NONBLOCK)
self.report_stream = os.fdopen(self.report_fd, 'rb', 0)
+ lvm_fd = os.open(tmp_file, os.O_WRONLY)
- # Setup the environment for using our own socket for reporting
- local_env = {}
- local_env["LC_ALL"] = "C"
- local_env["LVM_REPORT_FD"] = "32"
- local_env["LVM_COMMAND_PROFILE"] = "lvmdbusd"
-
- # Disable the abort logic if lvm logs too much, which easily happens
- # when utilizing the lvm shell.
- local_env["LVM_LOG_FILE_MAX_LINES"] = "0"
+ # Set up the environment for using our own socket for reporting and disable the abort
+ # logic if lvm logs too much, which easily happens when utilizing the lvm shell.
+ local_env = {"LC_ALL": "C", "LVM_REPORT_FD": "%s" % lvm_fd, "LVM_COMMAND_PROFILE": "lvmdbusd",
+ "LVM_LOG_FILE_MAX_LINES": "0"}
# run the lvm shell
self.lvm_shell = subprocess.Popen(
- [LVM_CMD + " 32>%s" % tmp_file],
+ [LVM_CMD],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, env=local_env,
- stderr=subprocess.PIPE, close_fds=True, shell=True)
+ stderr=subprocess.PIPE, close_fds=True, pass_fds=(lvm_fd,), shell=False)
try:
make_non_block(self.lvm_shell.stdout)
make_non_block(self.lvm_shell.stderr)
+ # Close our copy of the lvm_fd, child process is open in its process space
+ os.close(lvm_fd)
+
# wait for the first prompt
errors = self._read_until_prompt(no_output=True)[2]
if errors and len(errors):
--
2.37.1

View File

@ -0,0 +1,42 @@
From 70714b7fbe4d6f1ee943614cc26a990f20e35450 Mon Sep 17 00:00:00 2001
From: Tony Asleson <tasleson@redhat.com>
Date: Mon, 6 Jun 2022 09:51:54 -0500
Subject: [PATCH 8/9] lvmdbusd: Job prop. Get/GetAll exec. immediately
This allows API user the ability to check on the status of a long running
job without blocking in the request queue.
(cherry picked from commit eee89a941eb4e63865356cfe9e513c24cfa8e0f9)
---
daemons/lvmdbusd/job.py | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/daemons/lvmdbusd/job.py b/daemons/lvmdbusd/job.py
index 988b1147a..7629cafc7 100644
--- a/daemons/lvmdbusd/job.py
+++ b/daemons/lvmdbusd/job.py
@@ -226,3 +226,21 @@ class Job(AutomatedProperties):
def Uuid(self):
import uuid
return uuid.uuid1()
+
+ # Override the property "getters" implementation for the job interface, so a user can query a job while the queue
+ # is processing items. Originally all the property get methods were this way, but we changed this in
+ # e53454d6de07de56736303dd2157c3859f6fa848
+
+ # Properties
+ # noinspection PyUnusedLocal
+ @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
+ in_signature='ss', out_signature='v')
+ def Get(self, interface_name, property_name):
+ # Note: If we get an exception in this handler we won't know about it,
+ # only the side effect of no returned value!
+ return AutomatedProperties._get_prop(self, interface_name, property_name)
+
+ @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
+ in_signature='s', out_signature='a{sv}')
+ def GetAll(self, interface_name):
+ return AutomatedProperties._get_all_prop(self, interface_name)
--
2.37.1

View File

@ -0,0 +1,174 @@
From a3c2dcc3726261d6463ea35102d86863d698021b Mon Sep 17 00:00:00 2001
From: Tony Asleson <tasleson@redhat.com>
Date: Mon, 6 Jun 2022 09:56:32 -0500
Subject: [PATCH 9/9] lvmdbusd: Don't require "lvm> " prompt for shell
Depending on how lvm is compiled, it may not present the "lvm> " prompt
when using the lvm shell. Don't require it to be present.
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2090391
(cherry picked from commit 691494268502ddb20da2a14568984c0fa4f29f50)
---
daemons/lvmdbusd/lvm_shell_proxy.py.in | 83 +++++++++++++-------------
1 file changed, 43 insertions(+), 40 deletions(-)
diff --git a/daemons/lvmdbusd/lvm_shell_proxy.py.in b/daemons/lvmdbusd/lvm_shell_proxy.py.in
index 1a5051a92..e106ca36f 100644
--- a/daemons/lvmdbusd/lvm_shell_proxy.py.in
+++ b/daemons/lvmdbusd/lvm_shell_proxy.py.in
@@ -19,7 +19,6 @@ import sys
import tempfile
import time
import select
-import copy
try:
import simplejson as json
@@ -31,8 +30,6 @@ from lvmdbusd.cfg import LVM_CMD
from lvmdbusd.utils import log_debug, log_error, add_no_notify, make_non_block,\
read_decoded
-SHELL_PROMPT = "lvm> "
-
def _quote_arg(arg):
if len(shlex.split(arg)) > 1:
@@ -43,10 +40,11 @@ def _quote_arg(arg):
class LVMShellProxy(object):
- # Read until we get prompt back and a result
- # @param: no_output Caller expects no output to report FD
- # Returns stdout, report, stderr (report is JSON!)
- def _read_until_prompt(self, no_output=False):
+ # Read REPORT FD until we have a complete and valid JSON record or give
+ # up trying to get one.
+ #
+ # Returns stdout, report (JSON), stderr
+ def _read_response(self):
stdout = ""
report = ""
stderr = ""
@@ -58,6 +56,7 @@ class LVMShellProxy(object):
# Try reading from all FDs to prevent one from filling up and causing
# a hang. Keep reading until we get the prompt back and the report
# FD does not contain valid JSON
+
while keep_reading:
try:
rd_fd = [
@@ -78,32 +77,33 @@ class LVMShellProxy(object):
if self.lvm_shell.poll() is not None:
raise Exception(self.lvm_shell.returncode, "%s" % stderr)
- if stdout.endswith(SHELL_PROMPT):
- if no_output:
- keep_reading = False
- else:
- cur_report_len = len(report)
- if cur_report_len != 0:
- # Only bother to parse if we have more data
- if prev_report_len != cur_report_len:
- prev_report_len = cur_report_len
- # Parse the JSON if it's good we are done,
- # if not we will try to read some more.
- try:
- report_json = json.loads(report)
- keep_reading = False
- except ValueError:
- pass
-
- if keep_reading:
- extra_passes -= 1
- if extra_passes <= 0:
- if len(report):
- raise ValueError("Invalid json: %s" %
- report)
- else:
- raise ValueError(
- "lvm returned no JSON output!")
+ cur_report_len = len(report)
+ if cur_report_len != 0:
+ # Only bother to parse if we have more data and the last 2 characters match expected
+ # complete JSON, prevents excessive JSON parsing attempts
+ if prev_report_len != cur_report_len and report[-2:] == "}\n":
+ prev_report_len = cur_report_len
+
+ # Parse the JSON if it's good we are done,
+ # if not we will try to read some more.
+ try:
+ report_json = json.loads(report)
+ keep_reading = False
+ except ValueError:
+ pass
+
+ # As long as lvm is spewing something on one of the FDs we will
+ # keep trying. If we get a few timeouts with no activity, and
+ # we don't have valid JSON, we will raise an error.
+ if len(ready) == 0 and keep_reading:
+ extra_passes -= 1
+ if extra_passes <= 0:
+ if len(report):
+ raise ValueError("Invalid json: %s" %
+ report)
+ else:
+ raise ValueError(
+ "lvm returned no JSON output!")
except IOError as ioe:
log_debug(str(ioe))
@@ -118,7 +118,6 @@ class LVMShellProxy(object):
self.lvm_shell.stdin.flush()
def __init__(self):
-
# Create a temp directory
tmp_dir = tempfile.mkdtemp(prefix="lvmdbus_")
tmp_file = "%s/lvmdbus_report" % (tmp_dir)
@@ -139,6 +138,11 @@ class LVMShellProxy(object):
local_env = {"LC_ALL": "C", "LVM_REPORT_FD": "%s" % lvm_fd, "LVM_COMMAND_PROFILE": "lvmdbusd",
"LVM_LOG_FILE_MAX_LINES": "0"}
+ # If any env variables contain LVM we will propagate them too
+ for k, v in os.environ.items():
+ if "LVM" in k:
+ local_env[k] = v
+
# run the lvm shell
self.lvm_shell = subprocess.Popen(
[LVM_CMD],
@@ -152,10 +156,9 @@ class LVMShellProxy(object):
# Close our copy of the lvm_fd, child process is open in its process space
os.close(lvm_fd)
- # wait for the first prompt
- errors = self._read_until_prompt(no_output=True)[2]
- if errors and len(errors):
- raise RuntimeError(errors)
+ # Assume we are ready as we may not get the lvm prompt message depending on
+ # if we are using readline or editline.
+
except:
raise
finally:
@@ -169,7 +172,7 @@ class LVMShellProxy(object):
self._write_cmd('lastlog\n')
# read everything from the STDOUT to the next prompt
- stdout, report_json, stderr = self._read_until_prompt()
+ stdout, report_json, stderr = self._read_response()
if 'log' in report_json:
error_msg = ""
# Walk the entire log array and build an error string
@@ -203,7 +206,7 @@ class LVMShellProxy(object):
self._write_cmd(cmd)
# read everything from the STDOUT to the next prompt
- stdout, report_json, stderr = self._read_until_prompt()
+ stdout, report_json, stderr = self._read_response()
# Parse the report to see what happened
if 'log' in report_json:
--
2.37.1

View File

@ -1,4 +1,4 @@
%global device_mapper_version 1.02.183
%global device_mapper_version 1.02.185
%global enable_cache 1
%global enable_cluster 1
@ -44,7 +44,7 @@
%global configure_cluster --with-cluster=internal
%endif
%global from_snapshot 1
%global from_snapshot 0
%if 0%{?from_snapshot}
%global commit 4a1f6173d29a7d7ecab14a9313000aa5f81170d0
%global shortcommit %(c=%{commit}; echo ${c:0:7})
@ -58,12 +58,12 @@ Name: lvm2
%if 0%{?rhel}
Epoch: %{rhel}
%endif
Version: 2.03.14
Version: 2.03.16
%if 0%{?from_snapshot}
#Release: 0.1.20211115git%{shortcommit}%{?dist}%{?rel_suffix}
Release: 4%{?dist}
%else
Release: 1%{?dist}
Release: 3%{?dist}
%endif
License: GPLv2
URL: http://sourceware.org/lvm2
@ -72,7 +72,25 @@ Source0: lvm2-%{shortcommit}.tgz
%else
Source0: ftp://sourceware.org/pub/lvm2/releases/LVM2.%{version}.tgz
%endif
Patch1: 0001-devices-file-do-not-clear-PVID-of-unread-devices.patch
Patch1: 0001-devices-file-move-clean-up-after-command-is-run.patch
Patch2: 0002-devices-file-fail-if-devicesfile-filename-doesn-t-ex.patch
Patch3: 0003-filter-mpath-handle-other-wwid-types-in-blacklist.patch
Patch4: 0004-filter-mpath-get-wwids-from-sysfs-vpd_pg83.patch
Patch5: 0005-pvdisplay-restore-reportformat-option.patch
Patch6: 0006-exit-with-error-when-devicesfile-name-doesn-t-exist.patch
Patch7: 0007-make-generate.patch
# BZ 2109351:
Patch8: 0008-apply-multipath_component_detection-0-to-duplicate-P.patch
# BZ 2090391:
Patch9: 0009-lvmdbusd-Correct-conditional-for-lvm-child-process-r.patch
Patch10: 0010-lvmdbusd-Simplify-child-process-env.patch
Patch11: 0011-lvmdbusd-re-work-lvm-shell-main.patch
Patch12: 0012-lvmdbusd-Add-debug-output-for-which-lvm-binary-is-us.patch
Patch13: 0013-lvmdbusd-Change-unit-test-vdo-minimum-size.patch
Patch14: 0014-lvmdbusd-Fix-env-variable-LVM_DBUSD_TEST_MODE.patch
Patch15: 0015-lvmdbusd-Remove-the-use-of-sub-shell-for-lvm-shell.patch
Patch16: 0016-lvmdbusd-Job-prop.-Get-GetAll-exec.-immediately.patch
Patch17: 0017-lvmdbusd-Don-t-require-lvm-prompt-for-shell.patch
BuildRequires: make
BuildRequires: gcc
@ -134,6 +152,22 @@ or more physical volumes and creating one or more logical volumes
%setup -q -n LVM2.%{version}
%endif
%patch1 -p1 -b .backup1
%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
%build
%global _default_pid_dir /run
@ -704,6 +738,19 @@ An extensive functional testsuite for LVM2.
%endif
%changelog
* Fri Jul 29 2022 Marian Csontos <mcsontos@redhat.com> - 2.03.16-3
- Fix effect of setting multipath_component_detection to 0.
- Fix lvmdbusd using lvm shell with editline.
* Thu Jul 14 2022 Marian Csontos <mcsontos@redhat.com> - 2.03.16-2
- Exit with error when --devicesfile used does not exist.
- Restore --reportformat option in pvdisplay.
- Improve multipath backlist option handling.
* Wed May 18 2022 Marian Csontos <mcsontos@redhat.com> - 2.03.16-1
- Update to upstream version 2.03.16.
- See WHATS_NEW and WHATS_NEW_DM for more information.
* Tue Feb 15 2022 Marian Csontos <mcsontos@redhat.com> - 2.03.14-4
- Remove service based autoactivation.
- New lvmautoactivation(7) man page.