Toshaan Bharvani
1 year ago
20 changed files with 1898 additions and 5 deletions
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
Loading…
Reference in new issue