import lvm2-2.03.17-7.el9

c9 imports/c9/lvm2-2.03.17-7.el9
CentOS Sources 2023-05-09 05:39:35 +00:00 committed by Stepan Oksanichenko
parent 923f8f3abf
commit 21958a66ff
31 changed files with 946 additions and 1884 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/LVM2.2.03.16.tgz
SOURCES/LVM2.2.03.17.tgz

View File

@ -1 +1 @@
a99cfcbcb2cf665824acde03775dccc9ef54a836 SOURCES/LVM2.2.03.16.tgz
8a0043a552c17be61234989c02ef501eda971fd1 SOURCES/LVM2.2.03.17.tgz

View File

@ -0,0 +1,133 @@
From b01433cdc841133500a0ed4041b9b35838d45e87 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Fri, 2 Dec 2022 11:59:09 -0600
Subject: [PATCH] device_id: fix segfault verifying serial for non-pv
The recent change that verifies sys_serial system.devices entries
using the PVID did not exclude non-PV devices from being checked.
The verification code would attempt to use du->pvid which was null
for the non-PVs causing a segfault.
(cherry picked from commit 6613a61d3b5ce4d12a6fef79195eac34f30ef4da)
---
lib/device/device_id.c | 6 ++-
test/shell/devicesfile-serial.sh | 79 ++++++++++++++++++++++++++++++++
2 files changed, 83 insertions(+), 2 deletions(-)
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index aae875776..96726a448 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -2237,8 +2237,8 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
* number is correct, since serial numbers may not be unique.
* Search for the PVID on other devs in device_ids_check_serial.
*/
- if ((du->idtype == DEV_ID_TYPE_SYS_SERIAL) &&
- (!du->pvid || memcmp(dev->pvid, du->pvid, ID_LEN))) {
+ if ((du->idtype == DEV_ID_TYPE_SYS_SERIAL) && du->pvid &&
+ memcmp(dev->pvid, du->pvid, ID_LEN)) {
log_debug("suspect device id serial %s for %s", du->idname, dev_name(dev));
str_list_add(cmd->mem, &cmd->device_ids_check_serial, dm_pool_strdup(cmd->mem, du->idname));
*device_ids_invalid = 1;
@@ -2570,6 +2570,8 @@ void device_ids_check_serial(struct cmd_context *cmd, struct dm_list *scan_devs,
dm_list_iterate_items(dul, &dus_check) {
if (!dul->du->dev)
continue;
+ if (!dul->du->pvid)
+ continue;
/* save previously matched devs so they can be dropped from
lvmcache at the end if they are no longer used */
if (!(dil = dm_pool_zalloc(cmd->mem, sizeof(*dil))))
diff --git a/test/shell/devicesfile-serial.sh b/test/shell/devicesfile-serial.sh
index b7bfce29e..a88c1906a 100644
--- a/test/shell/devicesfile-serial.sh
+++ b/test/shell/devicesfile-serial.sh
@@ -772,6 +772,85 @@ grep $SERIAL1 out2
grep $dev3 out3
grep $SERIAL3 out3
+# non-PV devices
+
+aux wipefs_a $dev1
+aux wipefs_a $dev2
+aux wipefs_a $dev3
+aux wipefs_a $dev4
+
+echo $SERIAL1 > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial
+echo $SERIAL2 > $SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/serial
+echo $SERIAL2 > $SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/serial
+echo $SERIAL4 > $SYS_DIR/dev/block/$MAJOR4:$MINOR4/device/serial
+
+rm $DF
+touch $DF
+vgcreate $vg4 $dev4
+lvmdevices --adddev "$dev1"
+lvmdevices --adddev "$dev2"
+lvmdevices --adddev "$dev3"
+cat $DF
+
+grep $dev1 $DF |tee out1
+grep $dev2 $DF |tee out2
+grep $dev3 $DF |tee out3
+grep $dev4 $DF |tee out4
+
+grep $SERIAL1 out1
+grep $SERIAL2 out2
+grep $SERIAL2 out3
+grep $SERIAL4 out4
+
+pvs |tee out
+grep $dev4 out
+not grep $dev1 out
+not grep $dev2 out
+not grep $dev3 out
+
+pvcreate $dev1
+pvs |tee out
+grep $dev1 out
+grep $dev4 out
+not grep $dev2 out
+not grep $dev3 out
+
+pvcreate $dev2
+pvs |tee out
+grep $dev1 out
+grep $dev4 out
+grep $dev2 out
+not grep $dev3 out
+
+pvcreate $dev3
+pvs |tee out
+grep $dev1 out
+grep $dev4 out
+grep $dev2 out
+grep $dev3 out
+
+PVID1=`pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}'`
+PVID2=`pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}'`
+PVID3=`pvs "$dev3" --noheading -o uuid | tr -d - | awk '{print $1}'`
+PVID4=`pvs "$dev4" --noheading -o uuid | tr -d - | awk '{print $1}'`
+OPVID1=`pvs "$dev1" --noheading -o uuid | awk '{print $1}'`
+OPVID2=`pvs "$dev2" --noheading -o uuid | awk '{print $1}'`
+OPVID3=`pvs "$dev3" --noheading -o uuid | awk '{print $1}'`
+OPVID4=`pvs "$dev4" --noheading -o uuid | awk '{print $1}'`
+
+grep $dev1 $DF |tee out1
+grep $dev2 $DF |tee out2
+grep $dev3 $DF |tee out3
+grep $dev4 $DF |tee out4
+
+grep $PVID1 out1
+grep $PVID2 out2
+grep $PVID3 out3
+grep $PVID4 out4
+
+vgcreate $vg2 $dev2 $dev3
+vgs | grep $vg2
+
remove_base
rmmod brd
--
2.38.1

View File

@ -1,49 +0,0 @@
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

@ -1,55 +0,0 @@
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,36 @@
From 20c6961e37bf6f5010f9d2035dbc1ce03f9b0223 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Thu, 15 Dec 2022 09:57:04 -0600
Subject: [PATCH] lvextend: fix overprovisioning check for thin lvs
18722dfdf4d3 lvresize: restructure code
mistakenly changed the overprovisioning check from applying
to all lv_is_thin_type lvs to only lv_is_thin_pool lvs, so
it no longer applied when extending thin lvs. The result
was missing warning messages when extending thin lvs.
(cherry picked from commit 4baef0f93f608403b6f2db445e7bf1e80f8f3ee6)
---
lib/metadata/lv_manip.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 4cdbc19a0..f8eae0447 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -7007,9 +7007,10 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
if (lv_is_thin_pool(lv_top)) {
if (!update_thin_pool_lv(lv_top, 1))
goto_out;
- if (is_extend)
- thin_pool_check_overprovisioning(lv_top);
}
+ if (lv_is_thin_type(lv_top) && is_extend)
+ thin_pool_check_overprovisioning(lv_top);
+
if (lv_main && lv_is_cow_covering_origin(lv_main)) {
if (!monitor_dev_for_events(cmd, lv_main, 0, 0))
stack;
--
2.38.1

View File

@ -1,54 +0,0 @@
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,32 @@
From db067b9054d87ada6aa133394e65e3af9d75fc08 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Tue, 3 Jan 2023 11:38:33 -0600
Subject: [PATCH] lvresize: fix cryptsetup resize in helper
typo used "cryptresize" as command name
this affects cases where the file system is resized
independently, and then the lvresize command is used
which only needs to resize the crypt device and the LV.
(cherry picked from commit 81acde7ffdf9fbe522ada16f89e429d9f729dc0c)
---
scripts/lvresize_fs_helper.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/lvresize_fs_helper.sh b/scripts/lvresize_fs_helper.sh
index 031b8453b..f531dd447 100755
--- a/scripts/lvresize_fs_helper.sh
+++ b/scripts/lvresize_fs_helper.sh
@@ -224,7 +224,7 @@ fsreduce() {
cryptresize() {
NEWSIZESECTORS=$(($NEWSIZEBYTES/512))
logmsg "cryptsetup resize ${NEWSIZESECTORS} sectors ${DEVPATH}"
- cryptresize resize --size "$NEWSIZESECTORS" "$DEVPATH"
+ cryptsetup resize --size "$NEWSIZESECTORS" "$DEVPATH"
if [ $? -eq 0 ]; then
logmsg "cryptsetup done"
else
--
2.39.0

View File

@ -1,743 +0,0 @@
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,48 @@
From 8f7b4456ad93c3907a82fd03d0feceb9785e3bfc Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Thu, 5 Jan 2023 14:28:31 -0600
Subject: [PATCH 1/3] vgimportclone: fix importing PV without metadata
If one of the PVs in the VG does not hold metadata, then the
command would fail, thinking that PV was from a different VG.
Also add missing free on that error path.
(cherry picked from commit c4b898a53eec39bc28b5451e7fde87945303a644)
---
tools/vgimportclone.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/tools/vgimportclone.c b/tools/vgimportclone.c
index 60ef20762..93fa3b18d 100644
--- a/tools/vgimportclone.c
+++ b/tools/vgimportclone.c
@@ -203,7 +203,7 @@ int vgimportclone(struct cmd_context *cmd, int argc, char **argv)
struct device *dev;
struct device_list *devl;
struct dm_list other_devs;
- struct volume_group *vg, *error_vg;
+ struct volume_group *vg, *error_vg = NULL;
const char *vgname;
char base_vgname[NAME_LEN] = { 0 };
char tmp_vgname[NAME_LEN] = { 0 };
@@ -322,7 +322,7 @@ int vgimportclone(struct cmd_context *cmd, int argc, char **argv)
goto out;
}
- if (!(vgname = lvmcache_vgname_from_info(info))) {
+ if (!(vgname = lvmcache_vgname_from_info(info)) || is_orphan_vg(vgname)) {
/* The PV may not have metadata, this will be resolved in
the process_each_vg/vg_read at the end. */
continue;
@@ -503,6 +503,8 @@ retry_name:
}
ret = ECMD_PROCESSED;
out:
+ if (error_vg)
+ release_vg(error_vg);
unlock_devices_file(cmd);
return ret;
}
--
2.39.1

View File

@ -0,0 +1,89 @@
From 4e34edd6e4e52328dd77b6a55aeadd9b0454c743 Mon Sep 17 00:00:00 2001
From: Tony Asleson <tasleson@redhat.com>
Date: Tue, 29 Nov 2022 10:00:39 -0600
Subject: [PATCH 2/3] lvmdbusd: Move get_error_msg to utils
Moving this so we can re-use outside of lvm_shell_proxy.
(cherry picked from commit 8f60c494515ddccb20e4afb804edb6b9599e65c0)
---
daemons/lvmdbusd/lvm_shell_proxy.py.in | 23 +++--------------------
daemons/lvmdbusd/utils.py | 17 +++++++++++++++++
2 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/daemons/lvmdbusd/lvm_shell_proxy.py.in b/daemons/lvmdbusd/lvm_shell_proxy.py.in
index ac6d51e65..37d73218b 100755
--- a/daemons/lvmdbusd/lvm_shell_proxy.py.in
+++ b/daemons/lvmdbusd/lvm_shell_proxy.py.in
@@ -28,7 +28,7 @@ except ImportError:
import lvmdbusd.cfg as cfg
from lvmdbusd.utils import log_debug, log_error, add_no_notify, make_non_block,\
- read_decoded, extract_stack_trace, LvmBug
+ read_decoded, extract_stack_trace, LvmBug, get_error_msg
SHELL_PROMPT = "lvm> "
@@ -191,24 +191,7 @@ class LVMShellProxy(object):
def get_last_log(self):
self._write_cmd('lastlog\n')
report_json = self._read_response()[1]
- return LVMShellProxy.get_error_msg(report_json)
-
- @staticmethod
- def get_error_msg(report_json):
- # Get the error message from the returned JSON
- if 'log' in report_json:
- error_msg = ""
- # Walk the entire log array and build an error string
- for log_entry in report_json['log']:
- if log_entry['log_type'] == "error":
- if error_msg:
- error_msg += ', ' + log_entry['log_message']
- else:
- error_msg = log_entry['log_message']
-
- return error_msg
-
- return None
+ return get_error_msg(report_json)
def call_lvm(self, argv, debug=False):
rc = 1
@@ -245,7 +228,7 @@ class LVMShellProxy(object):
# report json too.
error_msg = self.get_last_log()
if error_msg is None:
- error_msg = LVMShellProxy.get_error_msg(report_json)
+ error_msg = get_error_msg(report_json)
if error_msg is None:
error_msg = 'No error reason provided! (missing "log" section)'
diff --git a/daemons/lvmdbusd/utils.py b/daemons/lvmdbusd/utils.py
index 5aecb1fff..0b81591b2 100644
--- a/daemons/lvmdbusd/utils.py
+++ b/daemons/lvmdbusd/utils.py
@@ -859,3 +859,20 @@ class LvmDebugData:
self._close_fd()
# In case lvm_complete doesn't get called.
self._remove_file()
+
+
+def get_error_msg(report_json):
+ # Get the error message from the returned JSON
+ if 'log' in report_json:
+ error_msg = ""
+ # Walk the entire log array and build an error string
+ for log_entry in report_json['log']:
+ if log_entry['log_type'] == "error":
+ if error_msg:
+ error_msg += ', ' + log_entry['log_message']
+ else:
+ error_msg = log_entry['log_message']
+
+ return error_msg
+
+ return None
--
2.39.1

View File

@ -1,36 +0,0 @@
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

@ -1,247 +0,0 @@
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,79 @@
From 0441d340e752427d0d355a85e5e5e465e911a102 Mon Sep 17 00:00:00 2001
From: Tony Asleson <tasleson@redhat.com>
Date: Tue, 29 Nov 2022 10:04:17 -0600
Subject: [PATCH 3/3] lvmdbusd: Add command_log_selection to command line
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2145114
(cherry picked from commit e63b0c7262f50ab43fcde1c50b6d880acab68407)
---
daemons/lvmdbusd/cmdhandler.py | 33 +++++++++++++++++----------------
1 file changed, 17 insertions(+), 16 deletions(-)
diff --git a/daemons/lvmdbusd/cmdhandler.py b/daemons/lvmdbusd/cmdhandler.py
index 0c7bd8528..9a76db4c9 100644
--- a/daemons/lvmdbusd/cmdhandler.py
+++ b/daemons/lvmdbusd/cmdhandler.py
@@ -17,7 +17,7 @@ import os
from lvmdbusd import cfg
from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error, add_no_notify,\
- make_non_block, read_decoded, extract_stack_trace, LvmBug, add_config_option
+ make_non_block, read_decoded, extract_stack_trace, LvmBug, add_config_option, get_error_msg
from lvmdbusd.lvm_shell_proxy import LVMShellProxy
try:
@@ -121,6 +121,9 @@ def call_lvm(command, debug=False, line_cb=None,
command.insert(0, cfg.LVM_CMD)
command = add_no_notify(command)
+ # Ensure we get an error message when we fork & exec the lvm command line
+ command = add_config_option(command, "--config", 'log/command_log_selection="log_context!=''"')
+
process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True,
env=os.environ)
@@ -167,7 +170,17 @@ def call_lvm(command, debug=False, line_cb=None,
if debug or (process.returncode != 0 and (process.returncode != 5 and "fullreport" in command)):
_debug_c(command, process.returncode, (stdout_text, stderr_text))
- return process.returncode, stdout_text, stderr_text
+ try:
+ report_json = json.loads(stdout_text)
+ except json.decoder.JSONDecodeError:
+ # Some lvm commands don't return json even though we are asking for it to do so.
+ return process.returncode, stdout_text, stderr_text
+
+ error_msg = get_error_msg(report_json)
+ if error_msg:
+ stderr_text += error_msg
+
+ return process.returncode, report_json, stderr_text
else:
if cfg.run.value == 0:
raise SystemExit
@@ -619,20 +632,8 @@ def lvm_full_report_json():
rc, out, err = call(cmd)
# When we have an exported vg the exit code of lvs or fullreport will be 5
if rc == 0 or rc == 5:
- # If the 'call' implementation is lvmshell, the out is a dictionary as lvmshell has to
- # parse the output to get the exit value. When doing fork & exec, out is a string
- # representing the JSON. TODO: Make this consistent between implementations.
- if cfg.SHELL_IN_USE:
- assert(type(out) == dict)
- return out
- else:
- try:
- return json.loads(out)
- except json.decoder.JSONDecodeError as joe:
- log_error("JSONDecodeError %s, \n JSON=\n%s\n" %
- (str(joe), out))
- raise LvmBug("'fullreport' returned invalid JSON")
-
+ assert(type(out) == dict)
+ return out
raise LvmBug("'fullreport' exited with code '%d'" % rc)
--
2.39.1

View File

@ -1,43 +0,0 @@
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,49 @@
From 380e3855fbc661eed490665cf1e3d05e985da189 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Tue, 3 Jan 2023 14:35:26 -0600
Subject: [PATCH 1/4] tests: lvresize-fs-crypt using helper only for crypt dev
(cherry picked from commit 2580f007f0aaa3bf22c43295caa2c60c6142494f)
---
test/shell/lvresize-fs-crypt.sh | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/test/shell/lvresize-fs-crypt.sh b/test/shell/lvresize-fs-crypt.sh
index e7b8b9426..61a6de022 100644
--- a/test/shell/lvresize-fs-crypt.sh
+++ b/test/shell/lvresize-fs-crypt.sh
@@ -135,6 +135,31 @@ cryptsetup close $cr
lvchange -an $vg/$lv
lvremove $vg/$lv
+# lvresize uses helper only for crypt dev resize
+# because the fs was resized separately beforehand
+lvcreate -n $lv -L 456M $vg
+echo 93R4P4pIqAH8 | cryptsetup luksFormat -i1 --type luks1 "$DM_DEV_DIR/$vg/$lv"
+echo 93R4P4pIqAH8 | cryptsetup luksOpen "$DM_DEV_DIR/$vg/$lv" $cr
+mkfs.ext4 /dev/mapper/$cr
+mount /dev/mapper/$cr "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# resize only the fs (to 256M), not the crypt dev or LV
+umount "$mount_dir"
+resize2fs /dev/mapper/$cr 262144k
+mount /dev/mapper/$cr "$mount_dir"
+# this lvresize will not resize the fs (which is already reduced
+# to smaller than the requested LV size), but lvresize will use
+# the helper to resize the crypt dev before resizing the LV.
+lvresize -L-100M $vg/$lv
+check lv_field $vg/$lv lv_size "356.00m"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+umount "$mount_dir"
+cryptsetup close $cr
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
# test with LUKS2?
vgremove -ff $vg
--
2.39.1

View File

@ -1,55 +0,0 @@
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 +++++++---