New upstream release v2.03.16

This commit is contained in:
Marian Csontos 2022-09-26 13:46:42 +02:00
parent baedfca644
commit 44a7aeaa64
37 changed files with 1283 additions and 3598 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

43
0007-make-generate.patch Normal file
View File

@ -0,0 +1,43 @@
From a8588f39219a2794fad562b38e6dc63aee791f82 Mon Sep 17 00:00:00 2001
From: Zdenek Kabelac <zkabelac@redhat.com>
Date: Mon, 11 Jul 2022 01:02:22 +0200
Subject: [PATCH 7/7] make: generate
(cherry picked from commit c0f8e6675c62332263acdc7c3c2f61eca20bd60f)
---
man/pvdisplay.8_pregen | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/man/pvdisplay.8_pregen b/man/pvdisplay.8_pregen
index 23d41b29b..e7767d0c4 100644
--- a/man/pvdisplay.8_pregen
+++ b/man/pvdisplay.8_pregen
@@ -61,6 +61,8 @@ and more, using a more compact and configurable output format.
.br
[ \fB--readonly\fP ]
.br
+[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ]
+.br
[ \fB--separator\fP \fIString\fP ]
.br
[ \fB--shared\fP ]
@@ -320,6 +322,16 @@ device-mapper kernel driver, so this option is unable to report whether
or not LVs are actually in use.
.
.HP
+\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
+.br
+Overrides current output format for reports which is defined globally by
+the report/output_format setting in \fBlvm.conf\fP(5).
+\fBbasic\fP is the original format with columns and rows.
+If there is more than one report per command, each report is prefixed
+with the report name for identification. \fBjson\fP produces report
+output in JSON format. See \fBlvmreport\fP(7) for more information.
+.
+.HP
\fB-S\fP|\fB--select\fP \fIString\fP
.br
Select objects for processing and reporting based on specified criteria.
--
2.34.3

View File

@ -1,17 +0,0 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)
iQIcBAABAgAGBQJf+CGBAAoJELkRJDHlCQOfbcAQAIky3+aEOxnpeT5T2XFRvsCJ
Uk71G70q24JupybEEYvhehf3RmeQkLP3c0TeNMFweqzUwpZBIhpbymglhaNG2AZc
3Bbnl1SAGZ5IzdqacrKfCIas1b/UZMbRAhjcCFQ3oD0SApl+dED2RUacJCnlZxkE
NX3+MG4S6po84uQdHwZGtAw2+HQ0G5GwIETjxJHcQ+q8SZdWJRhKU25Z7UC1LI5u
648SmSlsy2KoNIOSM/sWwgz1MXSWnN0y1mBxfBrR7bdnrPW+ExumzTqZrECIuiyl
bbD3Me/wEfyk4XZt2SoZF9k0Hf3QcSULeTeJlHOqUfLRGKm9E9ngkR/yfb2De/zP
tMzvFyu/tiCfFRXmQbS7K8dFzUzs6KQCHIPuJYnv+BjxOW9gjeyK5JPgBCsOLu//
mEf64ttDDKmCx1qOEnMhxTckvSH8YedmbQRov3g0ZXE3syG4OrhT1DHTyAnv69/f
fNVhOjd4POAoQx2UQzftgU7f4LiMPrQyRiUnQ0DRxHSEYXnIngpqokaVodfvpJp5
8YEuce9Xvq9JCplzKc1OXNtZQUHMybeyVzeenPVYvRV11ZbHzMAzwB6Byhwc9xgt
iKIuWpxMiPveKih3l/THoGOj19OUAN2XvWcGbOa6hTy6m/wsnoJQ0Xx5b5Ysfc1s
U60q2IDLJUS0H2R2raoc
=NE9u
-----END PGP SIGNATURE-----

16
LVM2.2.03.16.tgz.asc Normal file
View File

@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEE1QGkeEQK4v0TChvouREkMeUJA58FAmKFHcYACgkQuREkMeUJ
A58CdQ//UthHUyGSHS2LiNKPhpr4vKuxstwlOclxHjvardZ1QW7ry5Ype5Elrnfb
GVot/9oZPzoYzuHaMp6E8rRTfdsmiuSU9mQ3sTDAzPcuB9QbiZUW9oTCLfACTRqK
bP8XdKVE/sJgllUFz93kQke69GntBuvrvXFzUF4yMSSRwvWMtZ4jTs2KSfCdFJUB
3r4d9ynxTdcskexYQ0fnXubl5FRokKlmi7k5G0n2BnI/eqMMMsJg8lGYiw7kmkPc
7cqE9FJzVhzEv3rLYz0+gc7/6JymAJAJcUD5jaToI3eyA6KhqauH03HZhc5JDtxL
nthpURhCETDp/St/DsXWffVCKXBKq5TIa44Hh/n1TgFKVvgshEwOCWMmsh4P1MKI
ilvwkjmpzGbVOAgFUIJnMPOpg5aQ8jatFDbzcFwUXpIXdfSS+0ghMyc4Vihh1sa0
wAM7hYSvzjYAXPb+UjRrwRunmU36SgvUpg8ZI8ZxvFgLw57IAxqlx41MbQjtPg4B
3hI/ibtiWckVwROmga1daeLe696h4lrXjRCjj85EG8FsAuZpUikuSf1ym/3uF0aP
142Dd8lvWjfjl9nXDU8cl3Ke7JFfEtQUplswaaIpwKXv37dlwyfaCrgR/laLTs4V
xLh50C5Hxr1RPQwt1qPzM6tNYS+R3O8B56iWzcF8WIBiOOG5XWc=
=HIKn
-----END PGP SIGNATURE-----

View File

@ -1,15 +0,0 @@
WHATS_NEW | 2 ++
1 file changed, 2 insertions(+)
diff --git a/WHATS_NEW b/WHATS_NEW
index ffefc9d..3953c7e 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,7 @@
Version 2.03.12 -
===================================
+ Fix problem with wiping of converted LVs.
+ Fix memleak in scanning (2.03.11).
Fix corner case allocation for thin-pools.
Version 2.03.11 - 08th January 2021

View File

@ -1,47 +0,0 @@
WHATS_NEW | 10 ++++++++--
lib/metadata/lv_manip.c | 10 +++++++---
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 452a631..fe347f7 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,3 +1,7 @@
+Version 2.03.12 -
+===================================
+ Fix corner case allocation for thin-pools.
+
Version 2.03.11 - 08th January 2021
===================================
Fix pvck handling MDA at offset different from 4096.
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 7046436..443d32c 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1850,11 +1850,13 @@ static uint32_t _mirror_log_extents(uint32_t region_size, uint32_t pe_size, uint
/* Is there enough total space or should we give up immediately? */
static int _sufficient_pes_free(struct alloc_handle *ah, struct dm_list *pvms,
- uint32_t allocated, uint32_t extents_still_needed)
+ uint32_t allocated, uint32_t log_still_needed,
+ uint32_t extents_still_needed)
{
uint32_t area_extents_needed = (extents_still_needed - allocated) * ah->area_count / ah->area_multiple;
uint32_t parity_extents_needed = (extents_still_needed - allocated) * ah->parity_count / ah->area_multiple;
- uint32_t metadata_extents_needed = ah->alloc_and_split_meta ? 0 : ah->metadata_area_count * RAID_METADATA_AREA_LEN + ah->log_len; /* One each */
+ uint32_t metadata_extents_needed = (ah->alloc_and_split_meta ? 0 : ah->metadata_area_count * RAID_METADATA_AREA_LEN) +
+ (log_still_needed ? ah->log_len : 0); /* One each */
uint64_t total_extents_needed = (uint64_t)area_extents_needed + parity_extents_needed + metadata_extents_needed;
uint32_t free_pes = pv_maps_size(pvms);
@@ -3359,7 +3361,9 @@ static int _allocate(struct alloc_handle *ah,
old_allocated = alloc_state.allocated;
log_debug_alloc("Trying allocation using %s policy.", get_alloc_string(alloc));
- if (!ah->approx_alloc && !_sufficient_pes_free(ah, pvms, alloc_state.allocated, ah->new_extents))
+ if (!ah->approx_alloc && !_sufficient_pes_free(ah, pvms, alloc_state.allocated,
+ alloc_state.log_area_count_still_needed,
+ ah->new_extents))
goto_out;
_init_alloc_parms(ah, &alloc_parms, alloc, prev_lvseg,

View File

@ -1,107 +0,0 @@
lib/metadata/cache_manip.c | 40 ++++++++++++++--------------------------
lib/metadata/metadata-exported.h | 1 +
tools/lvconvert.c | 1 +
tools/lvcreate.c | 1 +
4 files changed, 17 insertions(+), 26 deletions(-)
diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c
index 2c4cc92..90ebd94 100644
--- a/lib/metadata/cache_manip.c
+++ b/lib/metadata/cache_manip.c
@@ -204,6 +204,7 @@ int update_cache_pool_params(struct cmd_context *cmd,
unsigned attr,
uint32_t pool_data_extents,
uint32_t *pool_metadata_extents,
+ struct logical_volume *metadata_lv,
int *chunk_size_calc_method, uint32_t *chunk_size)
{
uint64_t min_meta_size;
@@ -252,39 +253,26 @@ int update_cache_pool_params(struct cmd_context *cmd,
if (!validate_cache_chunk_size(cmd, *chunk_size))
return_0;
- min_meta_size = _cache_min_metadata_size((uint64_t) pool_data_extents * extent_size, *chunk_size);
+ if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
+ log_error("Size of %s data volume cannot be smaller than chunk size %s.",
+ segtype->name, display_size(cmd, *chunk_size));
+ return 0;
+ }
- /* Round up to extent size */
- if (min_meta_size % extent_size)
- min_meta_size += extent_size - min_meta_size % extent_size;
+ min_meta_size = _cache_min_metadata_size((uint64_t) pool_data_extents * extent_size, *chunk_size);
+ min_meta_size = dm_round_up(min_meta_size, extent_size);
if (!pool_metadata_size)
pool_metadata_size = min_meta_size;
- if (pool_metadata_size > (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE)) {
- pool_metadata_size = 2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE;
- if (*pool_metadata_extents)
- log_warn("WARNING: Maximum supported pool metadata size is %s.",
- display_size(cmd, pool_metadata_size));
- } else if (pool_metadata_size < min_meta_size) {
- if (*pool_metadata_extents)
- log_warn("WARNING: Minimum required pool metadata size is %s "
- "(needs extra %s).",
- display_size(cmd, min_meta_size),
- display_size(cmd, min_meta_size - pool_metadata_size));
- pool_metadata_size = min_meta_size;
- }
-
- if (!(*pool_metadata_extents =
- extents_from_size(cmd, pool_metadata_size, extent_size)))
+ if (!update_pool_metadata_min_max(cmd, extent_size,
+ min_meta_size,
+ (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE),
+ &pool_metadata_size,
+ metadata_lv,
+ pool_metadata_extents))
return_0;
- if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
- log_error("Size of %s data volume cannot be smaller than chunk size %s.",
- segtype->name, display_size(cmd, *chunk_size));
- return 0;
- }
-
log_verbose("Preferred pool metadata size %s.",
display_size(cmd, (uint64_t)*pool_metadata_extents * extent_size));
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 0e57722..c0fa564 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -1319,6 +1319,7 @@ int update_cache_pool_params(struct cmd_context *cmd,
unsigned attr,
uint32_t pool_data_extents,
uint32_t *pool_metadata_extents,
+ struct logical_volume *metadata_lv,
int *chunk_size_calc_method, uint32_t *chunk_size);
int validate_lv_cache_chunk_size(struct logical_volume *pool_lv, uint32_t chunk_size);
int validate_lv_cache_create_pool(const struct logical_volume *pool_lv);
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index ce90279..416e8a7 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -3189,6 +3189,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
pool_segtype, target_attr,
lv->le_count,
&meta_extents,
+ metadata_lv,
&chunk_calc,
&chunk_size))
goto_bad;
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 1ee9e14..1ce561f 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -403,6 +403,7 @@ static int _update_extents_params(struct volume_group *vg,
lp->segtype, lp->target_attr,
lp->extents,
&lp->pool_metadata_extents,
+ NULL,
&lp->thin_chunk_size_calc_policy,
&lp->chunk_size))
return_0;

View File

@ -1,613 +0,0 @@
conf/example.conf.in | 146 +++++++++++++++++++++++++-------------------------
conf/lvmlocal.conf.in | 4 +-
lib/config/config.c | 2 +-
3 files changed, 76 insertions(+), 76 deletions(-)
diff --git a/conf/example.conf.in b/conf/example.conf.in
index d149ed9..cd53147 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -78,14 +78,14 @@ devices {
# routines to acquire this information. For example, this information
# is used to drive LVM filtering like MD component detection, multipath
# component detection, partition detection and others.
- #
+ #
# Accepted values:
# none
# No external device information source is used.
# udev
# Reuse existing udev database records. Applicable only if LVM is
# compiled with udev support.
- #
+ #
external_device_info_source = "none"
# Configuration option devices/hints.
@@ -94,13 +94,13 @@ devices {
# scanning, and will only scan the listed PVs. Removing the hint file
# will cause lvm to generate a new one. Disable hints if PVs will
# be copied onto devices using non-lvm commands, like dd.
- #
+ #
# Accepted values:
# all
# Use all hints.
# none
# Use no hints.
- #
+ #
# This configuration option has an automatic default value.
# hints = "all"
@@ -118,11 +118,11 @@ devices {
# Prefer the name with the least number of slashes.
# Prefer a name that is a symlink.
# Prefer the path with least value in lexicographical order.
- #
+ #
# Example
# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
- #
- # This configuration option has an automatic default value.
+ #
+ # This configuration option does not have a default value defined.
# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
# Configuration option devices/filter.
@@ -140,7 +140,7 @@ devices {
# then the device is accepted. Be careful mixing 'a' and 'r' patterns,
# as the combination might produce unexpected results (test changes.)
# Run vgscan after changing the filter to regenerate the cache.
- #
+ #
# Example
# Accept every block device:
# filter = [ "a|.*|" ]
@@ -152,7 +152,7 @@ devices {
# filter = [ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ]
# Use anchors to be very specific:
# filter = [ "a|^/dev/hda8$|", "r|.*|" ]
- #
+ #
# This configuration option has an automatic default value.
# filter = [ "a|.*|" ]
@@ -170,10 +170,10 @@ devices {
# List of additional acceptable block device types.
# These are of device type names from /proc/devices, followed by the
# maximum number of partitions.
- #
+ #
# Example
# types = [ "fd", 16 ]
- #
+ #
# This configuration option is advanced.
# This configuration option does not have a default value defined.
@@ -215,7 +215,7 @@ devices {
# Configuration option devices/md_component_checks.
# The checks LVM should use to detect MD component devices.
# MD component devices are block devices used by MD software RAID.
- #
+ #
# Accepted values:
# auto
# LVM will skip scanning the end of devices when it has other
@@ -226,7 +226,7 @@ devices {
# full
# LVM will scan the start and end of devices for MD superblocks.
# This requires an extra read at the end of devices.
- #
+ #
# This configuration option has an automatic default value.
# md_component_checks = "auto"
@@ -368,7 +368,7 @@ allocation {
# defined here, it will check whether any of them are attached to the
# PVs concerned and then seek to match those PV tags between existing
# extents and new extents.
- #
+ #
# Example
# Use the special tag "@*" as a wildcard to match any PV tag:
# cling_tag_list = [ "@*" ]
@@ -376,7 +376,7 @@ allocation {
# PVs are tagged with either @site1 or @site2 to indicate where
# they are situated:
# cling_tag_list = [ "@site1", "@site2" ]
- #
+ #
# This configuration option does not have a default value defined.
# Configuration option allocation/maximise_cling.
@@ -435,25 +435,25 @@ allocation {
# Configuration option allocation/cache_metadata_format.
# Sets default metadata format for new cache.
- #
+ #
# Accepted values:
# 0 Automatically detected best available format
# 1 Original format
# 2 Improved 2nd. generation format
- #
+ #
# This configuration option has an automatic default value.
# cache_metadata_format = 0
# Configuration option allocation/cache_mode.
# The default cache mode used for new cache.
- #
+ #
# Accepted values:
# writethrough
# Data blocks are immediately written from the cache to disk.
# writeback
# Data blocks are written from the cache back to disk after some
# delay to improve performance.
- #
+ #
# This setting replaces allocation/cache_pool_cachemode.
# This configuration option has an automatic default value.
# cache_mode = "writethrough"
@@ -502,18 +502,18 @@ allocation {
# Configuration option allocation/thin_pool_discards.
# The discards behaviour of thin pool volumes.
- #
+ #
# Accepted values:
# ignore
# nopassdown
# passdown
- #
+ #
# This configuration option has an automatic default value.
# thin_pool_discards = "passdown"
# Configuration option allocation/thin_pool_chunk_size_policy.
# The chunk size calculation policy for thin pool volumes.
- #
+ #
# Accepted values:
# generic
# If thin_pool_chunk_size is defined, use it. Otherwise, calculate
@@ -525,7 +525,7 @@ allocation {
# the chunk size for performance based on device hints exposed in
# sysfs - the optimal_io_size. The chunk size is always at least
# 512KiB.
- #
+ #
# This configuration option has an automatic default value.
# thin_pool_chunk_size_policy = "generic"
@@ -962,7 +962,7 @@ global {
# Configuration option global/mirror_segtype_default.
# The segment type used by the short mirroring option -m.
# The --type mirror|raid1 option overrides this setting.
- #
+ #
# Accepted values:
# mirror
# The original RAID1 implementation from LVM/DM. It is
@@ -982,16 +982,16 @@ global {
# handling a failure. This mirror implementation is not
# cluster-aware and cannot be used in a shared (active/active)
# fashion in a cluster.
- #
+ #
mirror_segtype_default = "@DEFAULT_MIRROR_SEGTYPE@"
# Configuration option global/support_mirrored_mirror_log.
# Enable mirrored 'mirror' log type for testing.
- #
+ #
# This type is deprecated to create or convert to but can
# be enabled to test that activation of existing mirrored
# logs and conversion to disk/core works.
- #
+ #
# Not supported for regular operation!
# This configuration option has an automatic default value.
# support_mirrored_mirror_log = 0
@@ -1002,7 +1002,7 @@ global {
# The --stripes/-i and --mirrors/-m options can both be specified
# during the creation of a logical volume to use both striping and
# mirroring for the LV. There are two different implementations.
- #
+ #
# Accepted values:
# raid10
# LVM uses MD's RAID10 personality through DM. This is the
@@ -1012,7 +1012,7 @@ global {
# is done by creating a mirror LV on top of striped sub-LVs,
# effectively creating a RAID 0+1 array. The layering is suboptimal
# in terms of providing redundancy and performance.
- #
+ #
raid10_segtype_default = "@DEFAULT_RAID10_SEGTYPE@"
# Configuration option global/sparse_segtype_default.
@@ -1020,7 +1020,7 @@ global {
# The --type snapshot|thin option overrides this setting.
# The combination of -V and -L options creates a sparse LV. There are
# two different implementations.
- #
+ #
# Accepted values:
# snapshot
# The original snapshot implementation from LVM/DM. It uses an old
@@ -1032,7 +1032,7 @@ global {
# bigger minimal chunk size (64KiB) and uses a separate volume for
# metadata. It has better performance, especially when more data
# is used. It also supports full snapshots.
- #
+ #
sparse_segtype_default = "@DEFAULT_SPARSE_SEGTYPE@"
# Configuration option global/lvdisplay_shows_full_device_path.
@@ -1130,20 +1130,20 @@ global {
# causing problems. Features include: block_size, discards,
# discards_non_power_2, external_origin, metadata_resize,
# external_origin_extend, error_if_no_space.
- #
+ #
# Example
# thin_disabled_features = [ "discards", "block_size" ]
- #
+ #
# This configuration option does not have a default value defined.
# Configuration option global/cache_disabled_features.
# Features to not use in the cache driver.
# This can be helpful for testing, or to avoid using a feature that is
# causing problems. Features include: policy_mq, policy_smq, metadata2.
- #
+ #
# Example
# cache_disabled_features = [ "policy_smq" ]
- #
+ #
# This configuration option does not have a default value defined.
# Configuration option global/cache_check_executable.
@@ -1207,7 +1207,7 @@ global {
# or vgimport.) A VG on shared storage devices is accessible only to
# the host with a matching system ID. See 'man lvmsystemid' for
# information on limitations and correct usage.
- #
+ #
# Accepted values:
# none
# The host has no system ID.
@@ -1224,7 +1224,7 @@ global {
# file
# Use the contents of another file (system_id_file) to set the
# system ID.
- #
+ #
system_id_source = "none"
# Configuration option global/system_id_file.
@@ -1350,7 +1350,7 @@ activation {
# If this list is defined, an LV is only activated if it matches an
# entry in this list. If this list is undefined, it imposes no limits
# on LV activation (all are allowed).
- #
+ #
# Accepted values:
# vgname
# The VG name is matched exactly and selects all LVs in the VG.
@@ -1364,10 +1364,10 @@ activation {
# or VG. See tags/hosttags. If any host tags exist but volume_list
# is not defined, a default single-entry list containing '@*'
# is assumed.
- #
+ #
# Example
# volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
- #
+ #
# This configuration option does not have a default value defined.
# Configuration option activation/auto_activation_volume_list.
@@ -1387,7 +1387,7 @@ activation {
# commands run directly by a user. A user may also use the 'a' flag
# directly to perform auto-activation. Also see pvscan(8) for more
# information about auto-activation.
- #
+ #
# Accepted values:
# vgname
# The VG name is matched exactly and selects all LVs in the VG.
@@ -1401,10 +1401,10 @@ activation {
# or VG. See tags/hosttags. If any host tags exist but volume_list
# is not defined, a default single-entry list containing '@*'
# is assumed.
- #
+ #
# Example
# auto_activation_volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
- #
+ #
# This configuration option does not have a default value defined.
# Configuration option activation/read_only_volume_list.
@@ -1413,7 +1413,7 @@ activation {
# against this list, and if it matches, it is activated in read-only
# mode. This overrides the permission setting stored in the metadata,
# e.g. from --permission rw.
- #
+ #
# Accepted values:
# vgname
# The VG name is matched exactly and selects all LVs in the VG.
@@ -1427,10 +1427,10 @@ activation {
# or VG. See tags/hosttags. If any host tags exist but volume_list
# is not defined, a default single-entry list containing '@*'
# is assumed.
- #
+ #
# Example
# read_only_volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
- #
+ #
# This configuration option does not have a default value defined.
# Configuration option activation/raid_region_size.
@@ -1453,13 +1453,13 @@ activation {
# Configuration option activation/readahead.
# Setting to use when there is no readahead setting in metadata.
- #
+ #
# Accepted values:
# none
# Disable readahead.
# auto
# Use default value chosen by kernel.
- #
+ #
# This configuration option has an automatic default value.
# readahead = "auto"
@@ -1471,7 +1471,7 @@ activation {
# performed by dmeventd automatically, and the steps perfomed by the
# manual command lvconvert --repair --use-policies.
# Automatic handling requires dmeventd to be monitoring the LV.
- #
+ #
# Accepted values:
# warn
# Use the system log to warn the user that a device in the RAID LV
@@ -1482,7 +1482,7 @@ activation {
# allocate
# Attempt to use any extra physical volumes in the VG as spares and
# replace faulty devices.
- #
+ #
raid_fault_policy = "warn"
# Configuration option activation/mirror_image_fault_policy.
@@ -1494,7 +1494,7 @@ activation {
# determines the steps perfomed by dmeventd automatically, and the steps
# performed by the manual command lvconvert --repair --use-policies.
# Automatic handling requires dmeventd to be monitoring the LV.
- #
+ #
# Accepted values:
# remove
# Simply remove the faulty device and run without it. If the log
@@ -1519,7 +1519,7 @@ activation {
# the redundant nature of the mirror. This policy acts like
# 'remove' if no suitable device and space can be allocated for the
# replacement.
- #
+ #
mirror_image_fault_policy = "remove"
# Configuration option activation/mirror_log_fault_policy.
@@ -1534,26 +1534,26 @@ activation {
# The minimum value is 50 (a smaller value is treated as 50.)
# Also see snapshot_autoextend_percent.
# Automatic extension requires dmeventd to be monitoring the LV.
- #
+ #
# Example
# Using 70% autoextend threshold and 20% autoextend size, when a 1G
# snapshot exceeds 700M, it is extended to 1.2G, and when it exceeds
# 840M, it is extended to 1.44G:
# snapshot_autoextend_threshold = 70
- #
+ #
snapshot_autoextend_threshold = 100
# Configuration option activation/snapshot_autoextend_percent.
# Auto-extending a snapshot adds this percent extra space.
# The amount of additional space added to a snapshot is this
# percent of its current size.
- #
+ #
# Example
# Using 70% autoextend threshold and 20% autoextend size, when a 1G
# snapshot exceeds 700M, it is extended to 1.2G, and when it exceeds
# 840M, it is extended to 1.44G:
# snapshot_autoextend_percent = 20
- #
+ #
snapshot_autoextend_percent = 20
# Configuration option activation/thin_pool_autoextend_threshold.
@@ -1562,26 +1562,26 @@ activation {
# The minimum value is 50 (a smaller value is treated as 50.)
# Also see thin_pool_autoextend_percent.
# Automatic extension requires dmeventd to be monitoring the LV.
- #
+ #
# Example
# Using 70% autoextend threshold and 20% autoextend size, when a 1G
# thin pool exceeds 700M, it is extended to 1.2G, and when it exceeds
# 840M, it is extended to 1.44G:
# thin_pool_autoextend_threshold = 70
- #
+ #
thin_pool_autoextend_threshold = 100
# Configuration option activation/thin_pool_autoextend_percent.
# Auto-extending a thin pool adds this percent extra space.
# The amount of additional space added to a thin pool is this
# percent of its current size.
- #
+ #
# Example
# Using 70% autoextend threshold and 20% autoextend size, when a 1G
# thin pool exceeds 700M, it is extended to 1.2G, and when it exceeds
# 840M, it is extended to 1.44G:
# thin_pool_autoextend_percent = 20
- #
+ #
thin_pool_autoextend_percent = 20
# Configuration option activation/vdo_pool_autoextend_threshold.
@@ -1590,13 +1590,13 @@ activation {
# The minimum value is 50 (a smaller value is treated as 50.)
# Also see vdo_pool_autoextend_percent.
# Automatic extension requires dmeventd to be monitoring the LV.
- #
+ #
# Example
# Using 70% autoextend threshold and 20% autoextend size, when a 10G
# VDO pool exceeds 7G, it is extended to 12G, and when it exceeds
# 8.4G, it is extended to 14.4G:
# vdo_pool_autoextend_threshold = 70
- #
+ #
# This configuration option has an automatic default value.
# vdo_pool_autoextend_threshold = 100
@@ -1604,7 +1604,7 @@ activation {
# Auto-extending a VDO pool adds this percent extra space.
# The amount of additional space added to a VDO pool is this
# percent of its current size.
- #
+ #
# Example
# Using 70% autoextend threshold and 20% autoextend size, when a 10G
# VDO pool exceeds 7G, it is extended to 12G, and when it exceeds
@@ -1623,10 +1623,10 @@ activation {
# pages corresponding to lines that match are not pinned. On some
# systems, locale-archive was found to make up over 80% of the memory
# used by the process.
- #
+ #
# Example
# mlock_filter = [ "locale/locale-archive", "gconv/gconv-modules.cache" ]
- #
+ #
# This configuration option is advanced.
# This configuration option does not have a default value defined.
@@ -1667,7 +1667,7 @@ activation {
# Configuration option activation/activation_mode.
# How LVs with missing devices are activated.
# The --activationmode option overrides this setting.
- #
+ #
# Accepted values:
# complete
# Only allow activation of an LV if all of the Physical Volumes it
@@ -1682,7 +1682,7 @@ activation {
# could cause data loss with a portion of the LV inaccessible.
# This setting should not normally be used, but may sometimes
# assist with data recovery.
- #
+ #
activation_mode = "degraded"
# Configuration option activation/lock_start_list.
@@ -1730,7 +1730,7 @@ activation {
# Configuration option metadata/pvmetadatacopies.
# Number of copies of metadata to store on each PV.
# The --pvmetadatacopies option overrides this setting.
- #
+ #
# Accepted values:
# 2
# Two copies of the VG metadata are stored on the PV, one at the
@@ -1740,7 +1740,7 @@ activation {
# 0
# No copies of VG metadata are stored on the PV. This may be
# useful for VGs containing large numbers of PVs.
- #
+ #
# This configuration option is advanced.
# This configuration option has an automatic default value.
# pvmetadatacopies = 1
@@ -1890,7 +1890,7 @@ activation {
# sequences are copied verbatim. Each special character sequence is
# introduced by the '%' character and such sequence is then
# substituted with a value as described below.
- #
+ #
# Accepted values:
# %a
# The abbreviated name of the day of the week according to the
@@ -2013,7 +2013,7 @@ activation {
# The timezone name or abbreviation.
# %%
# A literal '%' character.
- #
+ #
# This configuration option has an automatic default value.
# time_format = "%Y-%m-%d %T %z"
@@ -2282,12 +2282,12 @@ dmeventd {
# applied to the local machine as a 'host tag'. If this subsection is
# empty (has no host_list), then the subsection name is always applied
# as a 'host tag'.
- #
+ #
# Example
# The host tag foo is given to all hosts, and the host tag
# bar is given to the hosts named machine1 and machine2.
# tags { foo { } bar { host_list = [ "machine1", "machine2" ] } }
- #
+ #
# This configuration section has variable name.
# This configuration section has an automatic default value.
# tag {
diff --git a/conf/lvmlocal.conf.in b/conf/lvmlocal.conf.in
index 04414bf..12214ea 100644
--- a/conf/lvmlocal.conf.in
+++ b/conf/lvmlocal.conf.in
@@ -28,13 +28,13 @@ local {
# main configuration file, e.g. lvm.conf. When used, it must be set to
# a unique value among all hosts sharing access to the storage,
# e.g. a host name.
- #
+ #
# Example
# Set no system ID:
# system_id = ""
# Set the system_id to a specific name:
# system_id = "host1"
- #
+ #
# This configuration option has an automatic default value.
# system_id = ""
diff --git a/lib/config/config.c b/lib/config/config.c
index a25b7db..f9ca566 100644
--- a/lib/config/config.c
+++ b/lib/config/config.c
@@ -1738,7 +1738,7 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
continue;
commentline[0] = '\0';
}
- fprintf(out->fp, "%s# %s\n", line, commentline);
+ fprintf(out->fp, "%s#%s%s\n", line, commentline[0] ? " " : "", commentline);
/* withsummary prints only the first comment line. */
if (!out->tree_spec->withcomments)
break;

View File

@ -1,48 +0,0 @@
From b3719266bd5e3a9e6737d6bda60e543121ddf343 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Tue, 9 Feb 2021 09:47:08 -0600
Subject: [PATCH] dev_get_primary_dev: fix invalid path check
Fix commit bee9f4efdd81 "filter-mpath: work with nvme devices"
which removed setting the path for readlink.
(cherry picked from commit f74f94c2ddb1d33d75d325c959344a566a621fd5)
Conflicts:
lib/device/dev-type.c
---
lib/device/dev-type.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index 379afa8..1342e97 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -434,7 +434,7 @@ static int _has_sys_partition(struct device *dev)
int minor = (int) MINOR(dev->dev);
/* check if dev is a partition */
- if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
+ if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/partition",
dm_sysfs_dir(), major, minor) < 0) {
log_error("dm_snprintf partition failed");
return 0;
@@ -660,8 +660,13 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
* - basename ../../block/md0/md0 = md0
* Parent's 'dev' sysfs attribute = /sys/block/md0/dev
*/
- if ((size = readlink(dirname(path), temp_path, sizeof(temp_path) - 1)) < 0) {
- log_sys_error("readlink", path);
+ if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d",
+ dm_sysfs_dir(), major, minor) < 0) {
+ log_warn("WARNING: %s: major:minor sysfs path is too long.", dev_name(dev));
+ return 0;
+ }
+ if ((size = readlink(path, temp_path, sizeof(temp_path) - 1)) < 0) {
+ log_warn("WARNING: Readlink of %s failed.", path);
goto out;
}
--
1.8.3.1

View File

@ -1,255 +0,0 @@
lib/device/dev-cache.c | 161 ++++++++++++++++++++++++++++++++++++----------
test/shell/dev-aliases.sh | 53 +++++++++++++++
2 files changed, 179 insertions(+), 35 deletions(-)
create mode 100644 test/shell/dev-aliases.sh
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index d5f18ff..8082efa 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -1428,60 +1428,151 @@ struct device *dev_hash_get(const char *name)
return (struct device *) dm_hash_lookup(_cache.names, name);
}
+static void _remove_alias(struct device *dev, const char *name)
+{
+ struct dm_str_list *strl;
+
+ dm_list_iterate_items(strl, &dev->aliases) {
+ if (!strcmp(strl->str, name)) {
+ dm_list_del(&strl->list);
+ return;
+ }
+ }
+}
+
+/*
+ * Check that paths for this dev still refer to the same dev_t. This is known
+ * to drop invalid paths in the case where lvm deactivates an LV, which causes
+ * that LV path to go away, but that LV path is not removed from dev-cache (it
+ * probably should be). Later a new path to a different LV is added to
+ * dev-cache, where the new LV has the same major:minor as the previously
+ * deactivated LV. The new LV will find the existing struct dev, and that
+ * struct dev will have dev->aliases entries that refer to the name of the old
+ * deactivated LV. Those old paths are all invalid and are dropped here.
+ */
+
+static void _verify_aliases(struct device *dev, const char *newname)
+{
+ struct dm_str_list *strl, *strl2;
+ struct stat st;
+
+ dm_list_iterate_items_safe(strl, strl2, &dev->aliases) {
+ /* newname was just stat'd and added by caller */
+ if (newname && !strcmp(strl->str, newname))
+ continue;
+
+ if (stat(strl->str, &st) || (st.st_rdev != dev->dev)) {
+ log_debug("Drop invalid path %s for %d:%d (new path %s).",
+ strl->str, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), newname ?: "");
+ dm_hash_remove(_cache.names, strl->str);
+ dm_list_del(&strl->list);
+ }
+ }
+}
+
struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f)
{
- struct stat buf;
- struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
- int info_available = 0;
- int ret = 1;
+ struct device *dev = (struct device *) dm_hash_lookup(_cache.names, name);
+ struct stat st;
+ int ret;
- if (d && (d->flags & DEV_REGULAR))
- return d;
+ /*
+ * DEV_REGULAR means that is "dev" is actually a file, not a device.
+ * FIXME: I don't think dev-cache is used for files any more and this
+ * can be dropped?
+ */
+ if (dev && (dev->flags & DEV_REGULAR))
+ return dev;
+
+ /*
+ * The requested path is invalid, remove any dev-cache
+ * info for it.
+ */
+ if (stat(name, &st)) {
+ if (dev) {
+ log_print("Device path %s is invalid for %d:%d %s.",
+ name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev));
- /* If the entry's wrong, remove it */
- if (stat(name, &buf) < 0) {
- if (d)
dm_hash_remove(_cache.names, name);
- log_sys_very_verbose("stat", name);
- d = NULL;
- } else
- info_available = 1;
- if (d && (buf.st_rdev != d->dev)) {
- dm_hash_remove(_cache.names, name);
- d = NULL;
- }
+ _remove_alias(dev, name);
- if (!d) {
- _insert(name, info_available ? &buf : NULL, 0, obtain_device_list_from_udev());
- d = (struct device *) dm_hash_lookup(_cache.names, name);
- if (!d) {
- log_debug_devs("Device name not found in dev_cache repeat dev_cache_scan for %s", name);
- dev_cache_scan();
- d = (struct device *) dm_hash_lookup(_cache.names, name);
+ /* Remove any other names in dev->aliases that are incorrect. */
+ _verify_aliases(dev, NULL);
}
+ return NULL;
}
- if (!d)
+ if (!S_ISBLK(st.st_mode)) {
+ log_debug("Not a block device %s.", name);
return NULL;
+ }
- if (d && (d->flags & DEV_REGULAR))
- return d;
+ /*
+ * dev-cache has incorrect info for the requested path.
+ * Remove incorrect info and then add new dev-cache entry.
+ */
+ if (dev && (st.st_rdev != dev->dev)) {
+ log_print("Device path %s does not match %d:%d %s.",
+ name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev));
+
+ dm_hash_remove(_cache.names, name);
+
+ _remove_alias(dev, name);
+
+ /* Remove any other names in dev->aliases that are incorrect. */
+ _verify_aliases(dev, NULL);
+
+ /* Add new dev-cache entry next. */
+ dev = NULL;
+ }
+
+ /*
+ * Either add a new struct dev for st_rdev and name,
+ * or add name as a new alias for an existing struct dev
+ * for st_rdev.
+ */
+ if (!dev) {
+ _insert_dev(name, st.st_rdev);
- if (f && !(d->flags & DEV_REGULAR)) {
- ret = f->passes_filter(cmd, f, d, NULL);
+ /* Get the struct dev that was just added. */
+ dev = (struct device *) dm_hash_lookup(_cache.names, name);
- if (ret == -EAGAIN) {
- log_debug_devs("get device by name defer filter %s", dev_name(d));
- d->flags |= DEV_FILTER_AFTER_SCAN;
- ret = 1;
+ if (!dev) {
+ log_error("Failed to get device %s", name);
+ return NULL;
}
+
+ _verify_aliases(dev, name);
}
- if (f && !(d->flags & DEV_REGULAR) && !ret)
+ /*
+ * The caller passed a filter if they only want the dev if it
+ * passes filters.
+ */
+
+ if (!f)
+ return dev;
+
+ ret = f->passes_filter(cmd, f, dev, NULL);
+
+ /*
+ * This might happen if this function is called before
+ * filters can do i/o. I don't think this will happen
+ * any longer and this EAGAIN case can be removed.
+ */
+ if (ret == -EAGAIN) {
+ log_debug_devs("dev_cache_get filter deferred %s", dev_name(dev));
+ dev->flags |= DEV_FILTER_AFTER_SCAN;
+ ret = 1;
+ }
+
+ if (!ret) {
+ log_debug_devs("dev_cache_get filter excludes %s", dev_name(dev));
return NULL;
+ }
- return d;
+ return dev;
}
static struct device *_dev_cache_seek_devt(dev_t dev)
diff --git a/test/shell/dev-aliases.sh b/test/shell/dev-aliases.sh
new file mode 100644
index 0000000..c97cd5d
--- /dev/null
+++ b/test/shell/dev-aliases.sh
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2012 Red Hat, Inc. All rights reserved.
+#
+# 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 General Public License v.2.
+#
+# You should have received a copy of the GNU 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
+
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+aux prepare_devs 3
+
+vgcreate $vg $dev1 $dev2 $dev3
+
+#
+# This lvconvert command will deactivate LV1, then internally create a new
+# lv, lvol0, as a poolmetadataspare, then activate lvol0 to zero it.
+# lvol0 will get the same major:minor that LV1 had. When the code gets
+# the struct dev for lvol0, the new path to lvol0 is added to the
+# dev-cache with it's major:minor. That major:minor already exists in
+# dev-cache and has the stale LV1 as an alias. So the path to lvol0 is
+# added as an alias to the existing struct dev (with the correct
+# major:minor), but that struct dev has the stale LV1 path on its aliases
+# list. The code will now validate all the aliases before returning the
+# dev for lvol0, and will find that the LV1 path is stale and remove it
+# from the aliases. That will prevent the stale path from being used for
+# the dev in place of the new path.
+#
+# The preferred_name is set to /dev/mapper so that if the stale path still
+# exists, that stale path would be used as the name for the dev, and the
+# wiping code would fail to open that stale name.
+#
+
+lvcreate -n $lv1 -L32M $vg $dev1
+lvcreate -n $lv2 -L16M $vg $dev2
+lvconvert -y --type cache-pool --poolmetadata $lv2 --cachemode writeback $vg/$lv1 --config='devices { preferred_names=["/dev/mapper/"] }'
+lvremove -y $vg/$lv1
+
+lvcreate -n $lv1 -L32M $vg $dev1
+lvcreate -n $lv2 -L16M $vg $dev2
+lvconvert -y --type cache-pool --poolmetadata $lv2 $vg/$lv1
+lvremove -y $vg/$lv1
+
+# TODO: add more validation of dev aliases being specified as command
+# args in combination with various preferred_names settings.
+
+vgremove -ff $vg

View File

@ -1,494 +0,0 @@
lib/device/dev-type.c | 81 +++++++++++++++++++----
lib/device/dev-type.h | 2 +
lib/device/device.h | 1 +
lib/filters/filter-mpath.c | 156 ++++++++++++++++++++++++++++++---------------
4 files changed, 177 insertions(+), 63 deletions(-)
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index 896821d..379afa8 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -21,6 +21,7 @@
#include "lib/metadata/metadata.h"
#include "lib/device/bcache.h"
#include "lib/label/label.h"
+#include "lib/commands/toolcontext.h"
#ifdef BLKID_WIPING_SUPPORT
#include <blkid.h>
@@ -67,6 +68,31 @@ int dev_is_pmem(struct device *dev)
return is_pmem ? 1 : 0;
}
+/*
+ * An nvme device has major number 259 (BLKEXT), minor number <minor>,
+ * and reading /sys/dev/block/259:<minor>/device/dev shows a character
+ * device cmajor:cminor where cmajor matches the major number of the
+ * nvme character device entry in /proc/devices. Checking all of that
+ * is excessive and unnecessary compared to just comparing /dev/name*.
+ */
+
+int dev_is_nvme(struct dev_types *dt, struct device *dev)
+{
+ struct dm_str_list *strl;
+
+ if (dev->flags & DEV_IS_NVME)
+ return 1;
+
+ dm_list_iterate_items(strl, &dev->aliases) {
+ if (!strncmp(strl->str, "/dev/nvme", 9)) {
+ log_debug("Found nvme device %s", dev_name(dev));
+ dev->flags |= DEV_IS_NVME;
+ return 1;
+ }
+ }
+ return 0;
+}
+
int dev_is_lv(struct device *dev)
{
FILE *fp;
@@ -302,6 +328,9 @@ int dev_subsystem_part_major(struct dev_types *dt, struct device *dev)
const char *dev_subsystem_name(struct dev_types *dt, struct device *dev)
{
+ if (dev->flags & DEV_IS_NVME)
+ return "NVME";
+
if (MAJOR(dev->dev) == dt->device_mapper_major)
return "DM";
@@ -348,7 +377,6 @@ int major_is_scsi_device(struct dev_types *dt, int major)
return (dt->dev_type_array[major].flags & PARTITION_SCSI_DEVICE) ? 1 : 0;
}
-
static int _loop_is_with_partscan(struct device *dev)
{
FILE *fp;
@@ -398,6 +426,28 @@ struct partition {
uint32_t nr_sects;
} __attribute__((packed));
+static int _has_sys_partition(struct device *dev)
+{
+ char path[PATH_MAX];
+ struct stat info;
+ int major = (int) MAJOR(dev->dev);
+ int minor = (int) MINOR(dev->dev);
+
+ /* check if dev is a partition */
+ if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
+ dm_sysfs_dir(), major, minor) < 0) {
+ log_error("dm_snprintf partition failed");
+ return 0;
+ }
+
+ if (stat(path, &info) == -1) {
+ if (errno != ENOENT)
+ log_sys_error("stat", path);
+ return 0;
+ }
+ return 1;
+}
+
static int _is_partitionable(struct dev_types *dt, struct device *dev)
{
int parts = major_max_partitions(dt, MAJOR(dev->dev));
@@ -414,6 +464,13 @@ static int _is_partitionable(struct dev_types *dt, struct device *dev)
_loop_is_with_partscan(dev))
return 1;
+ if (dev_is_nvme(dt, dev)) {
+ /* If this dev is already a partition then it's not partitionable. */
+ if (_has_sys_partition(dev))
+ return 0;
+ return 1;
+ }
+
if ((parts <= 1) || (MINOR(dev->dev) % parts))
return 0;
@@ -557,11 +614,18 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
char path[PATH_MAX];
char temp_path[PATH_MAX];
char buffer[64];
- struct stat info;
FILE *fp = NULL;
int parts, residue, size, ret = 0;
/*
+ * /dev/nvme devs don't use the major:minor numbering like
+ * block dev types that have their own major number, so
+ * the calculation based on minor number doesn't work.
+ */
+ if (dev_is_nvme(dt, dev))
+ goto sys_partition;
+
+ /*
* Try to get the primary dev out of the
* list of known device types first.
*/
@@ -576,23 +640,14 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
goto out;
}
+ sys_partition:
/*
* If we can't get the primary dev out of the list of known device
* types, try to look at sysfs directly then. This is more complex
* way and it also requires certain sysfs layout to be present
* which might not be there in old kernels!
*/
-
- /* check if dev is a partition */
- if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
- sysfs_dir, major, minor) < 0) {
- log_error("dm_snprintf partition failed");
- goto out;
- }
-
- if (stat(path, &info) == -1) {
- if (errno != ENOENT)
- log_sys_error("stat", path);
+ if (!_has_sys_partition(dev)) {
*result = dev->dev;
ret = 1;
goto out; /* dev is not a partition! */
diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h
index fdf7791..8b94b79 100644
--- a/lib/device/dev-type.h
+++ b/lib/device/dev-type.h
@@ -95,6 +95,8 @@ int dev_is_rotational(struct dev_types *dt, struct device *dev);
int dev_is_pmem(struct device *dev);
+int dev_is_nvme(struct dev_types *dt, struct device *dev);
+
int dev_is_lv(struct device *dev);
int get_fs_block_size(struct device *dev, uint32_t *fs_block_size);
diff --git a/lib/device/device.h b/lib/device/device.h
index a58bff8..816db31 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -38,6 +38,7 @@
#define DEV_SCAN_FOUND_LABEL 0x00010000 /* label scan read dev and found label */
#define DEV_IS_MD_COMPONENT 0x00020000 /* device is an md component */
#define DEV_UDEV_INFO_MISSING 0x00040000 /* we have no udev info for this device */
+#define DEV_IS_NVME 0x00080000 /* set if dev is nvme */
/*
* Support for external device info.
diff --git a/lib/filters/filter-mpath.c b/lib/filters/filter-mpath.c
index 85d1625..40e7df6 100644
--- a/lib/filters/filter-mpath.c
+++ b/lib/filters/filter-mpath.c
@@ -16,6 +16,7 @@
#include "lib/misc/lib.h"
#include "lib/filters/filter.h"
#include "lib/activate/activate.h"
+#include "lib/commands/toolcontext.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h>
#include "lib/device/dev-ext-udev-constants.h"
@@ -27,7 +28,6 @@
#define MPATH_PREFIX "mpath-"
-
struct mpath_priv {
struct dm_pool *mem;
struct dev_filter f;
@@ -35,6 +35,9 @@ struct mpath_priv {
struct dm_hash_table *hash;
};
+/*
+ * given "/dev/foo" return "foo"
+ */
static const char *_get_sysfs_name(struct device *dev)
{
const char *name;
@@ -53,6 +56,11 @@ static const char *_get_sysfs_name(struct device *dev)
return name;
}
+/*
+ * given major:minor
+ * readlink translates /sys/dev/block/major:minor to /sys/.../foo
+ * from /sys/.../foo return "foo"
+ */
static const char *_get_sysfs_name_by_devt(const char *sysfs_dir, dev_t devno,
char *buf, size_t buf_size)
{
@@ -102,27 +110,28 @@ static int _get_sysfs_string(const char *path, char *buffer, int max_size)
return r;
}
-static int _get_sysfs_get_major_minor(const char *sysfs_dir, const char *kname, int *major, int *minor)
+static int _get_sysfs_dm_mpath(struct dev_types *dt, const char *sysfs_dir, const char *holder_name)
{
- char path[PATH_MAX], buffer[64];
+ char path[PATH_MAX];
+ char buffer[128];
- if (dm_snprintf(path, sizeof(path), "%s/block/%s/dev", sysfs_dir, kname) < 0) {
+ if (dm_snprintf(path, sizeof(path), "%sblock/%s/dm/uuid", sysfs_dir, holder_name) < 0) {
log_error("Sysfs path string is too long.");
return 0;
}
+ buffer[0] = '\0';
+
if (!_get_sysfs_string(path, buffer, sizeof(buffer)))
return_0;
- if (sscanf(buffer, "%d:%d", major, minor) != 2) {
- log_error("Failed to parse major minor from %s", buffer);
- return 0;
- }
+ if (!strncmp(buffer, MPATH_PREFIX, 6))
+ return 1;
- return 1;
+ return 0;
}
-static int _get_parent_mpath(const char *dir, char *name, int max_size)
+static int _get_holder_name(const char *dir, char *name, int max_size)
{
struct dirent *d;
DIR *dr;
@@ -155,7 +164,7 @@ static int _get_parent_mpath(const char *dir, char *name, int max_size)
}
#ifdef UDEV_SYNC_SUPPORT
-static int _udev_dev_is_mpath(struct device *dev)
+static int _udev_dev_is_mpath_component(struct device *dev)
{
const char *value;
struct dev_ext *ext;
@@ -174,95 +183,148 @@ static int _udev_dev_is_mpath(struct device *dev)
return 0;
}
#else
-static int _udev_dev_is_mpath(struct device *dev)
+static int _udev_dev_is_mpath_component(struct device *dev)
{
return 0;
}
#endif
-static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
+static int _native_dev_is_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
{
struct mpath_priv *mp = (struct mpath_priv *) f->private;
struct dev_types *dt = mp->dt;
- const char *part_name, *name;
- struct stat info;
- char path[PATH_MAX], parent_name[PATH_MAX];
+ 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/" */
+ char dm_dev_path[PATH_MAX]; /* e.g. "/dev/dm-1" */
+ char holder_name[128] = { 0 }; /* e.g. "dm-1" */
const char *sysfs_dir = dm_sysfs_dir();
- int major = MAJOR(dev->dev);
- int minor = MINOR(dev->dev);
+ int dev_major = MAJOR(dev->dev);
+ int dev_minor = MINOR(dev->dev);
+ int dm_dev_major;
+ int dm_dev_minor;
+ struct stat info;
dev_t primary_dev;
long look;
- /* Limit this filter only to SCSI devices */
- if (!major_is_scsi_device(dt, MAJOR(dev->dev)))
+ /* Limit this filter to 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)) {
+
case 2: /* The dev is partition. */
part_name = dev_name(dev); /* name of original dev for log_debug msg */
- if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, parent_name, sizeof(parent_name))))
+
+ /* 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. */
+
+ /* gets "foo" for "/dev/foo" */
if (!(name = _get_sysfs_name(dev)))
return_0;
break;
+
default: /* 0, error. */
- log_warn("Failed to get primary device for %d:%d.", major, minor);
+ log_warn("Failed to get primary device for %d:%d.", dev_major, dev_minor);
return 0;
}
- if (dm_snprintf(path, sizeof(path), "%s/block/%s/holders", sysfs_dir, name) < 0) {
+ if (dm_snprintf(holders_path, sizeof(holders_path), "%sblock/%s/holders", sysfs_dir, name) < 0) {
log_warn("Sysfs path to check mpath is too long.");
return 0;
}
/* also will filter out partitions */
- if (stat(path, &info))
+ if (stat(holders_path, &info))
return 0;
if (!S_ISDIR(info.st_mode)) {
- log_warn("Path %s is not a directory.", path);
+ log_warn("Path %s is not a directory.", holders_path);
return 0;
}
- if (!_get_parent_mpath(path, parent_name, sizeof(parent_name)))
+ /*
+ * If holders dir contains an entry such as "dm-1", then this sets
+ * holder_name to "dm-1".
+ *
+ * If holders dir is empty, return 0 (this is generally where
+ * devs that are not mpath components return.)
+ */
+ if (!_get_holder_name(holders_path, holder_name, sizeof(holder_name)))
return 0;
- if (!_get_sysfs_get_major_minor(sysfs_dir, parent_name, &major, &minor))
- return_0;
+ if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s/%s", cmd->dev_dir, holder_name) < 0) {
+ log_warn("dm device path to check mpath is too long.");
+ return 0;
+ }
- if (major != dt->device_mapper_major)
+ /*
+ * stat "/dev/dm-1" which is the holder of the dev we're checking
+ * dm_dev_major:dm_dev_minor come from stat("/dev/dm-1")
+ */
+ if (stat(dm_dev_path, &info)) {
+ log_debug("filter-mpath %s holder %s stat result %d",
+ dev_name(dev), dm_dev_path, errno);
return 0;
+ }
+ dm_dev_major = (int)MAJOR(info.st_rdev);
+ dm_dev_minor = (int)MINOR(info.st_rdev);
+
+ if (dm_dev_major != dt->device_mapper_major) {
+ log_debug_devs("filter-mpath %s holder %s %d:%d does not have dm major",
+ dev_name(dev), dm_dev_path, dm_dev_major, dm_dev_minor);
+ return 0;
+ }
- /* Avoid repeated detection of multipath device and use first checked result */
- look = (long) dm_hash_lookup_binary(mp->hash, &minor, sizeof(minor));
+ /*
+ * Save the result of checking that "/dev/dm-1" is an mpath device
+ * to avoid repeating it for each path component.
+ * The minor number of "/dev/dm-1" is added to the hash table with
+ * const value 2 meaning that dm minor 1 (for /dev/dm-1) is a multipath dev
+ * and const value 1 meaning that dm minor 1 is not a multipath dev.
+ */
+ look = (long) dm_hash_lookup_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor));
if (look > 0) {
- log_debug_devs("%s(%u:%u): already checked as %sbeing mpath.",
- parent_name, major, minor, (look > 1) ? "" : "not ");
+ log_debug_devs("filter-mpath %s holder %s %u:%u already checked as %sbeing mpath.",
+ dev_name(dev), holder_name, dm_dev_major, dm_dev_minor, (look > 1) ? "" : "not ");
return (look > 1) ? 1 : 0;
}
- if (lvm_dm_prefix_check(major, minor, MPATH_PREFIX)) {
- (void) dm_hash_insert_binary(mp->hash, &minor, sizeof(minor), (void*)2);
+ /*
+ * Returns 1 if /sys/block/<holder_name>/dm/uuid indicates that
+ * <holder_name> is a dm device with dm uuid prefix mpath-.
+ * When true, <holder_name> will be something like "dm-1".
+ *
+ * (Is a hash table worth it to avoid reading one sysfs file?)
+ */
+ if (_get_sysfs_dm_mpath(dt, sysfs_dir, holder_name)) {
+ log_debug_devs("filter-mpath %s holder %s %u:%u ignore mpath component",
+ dev_name(dev), holder_name, dm_dev_major, dm_dev_minor);
+ (void) dm_hash_insert_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor), (void*)2);
return 1;
}
- (void) dm_hash_insert_binary(mp->hash, &minor, sizeof(minor), (void*)1);
+ (void) dm_hash_insert_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor), (void*)1);
return 0;
}
-static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
+static int _dev_is_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
{
if (dev->ext.src == DEV_EXT_NONE)
- return _native_dev_is_mpath(f, dev);
+ return _native_dev_is_mpath_component(cmd, f, dev);
if (dev->ext.src == DEV_EXT_UDEV)
- return _udev_dev_is_mpath(dev);
+ return _udev_dev_is_mpath_component(dev);
log_error(INTERNAL_ERROR "Missing hook for mpath recognition "
"using external device info source %s", dev_ext_name(dev));
@@ -272,11 +334,11 @@ static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
#define MSG_SKIPPING "%s: Skipping mpath component device"
-static int _ignore_mpath(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
+static int _ignore_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
{
dev->filtered_flags &= ~DEV_FILTERED_MPATH_COMPONENT;
- if (_dev_is_mpath(f, dev) == 1) {
+ if (_dev_is_mpath_component(cmd, f, dev) == 1) {
if (dev->ext.src == DEV_EXT_NONE)
log_debug_devs(MSG_SKIPPING, dev_name(dev));
else
@@ -303,8 +365,8 @@ static void _destroy(struct dev_filter *f)
struct dev_filter *mpath_filter_create(struct dev_types *dt)
{
const char *sysfs_dir = dm_sysfs_dir();
- struct dm_pool *mem;
struct mpath_priv *mp;
+ struct dm_pool *mem;
struct dm_hash_table *hash;
if (!*sysfs_dir) {
@@ -328,19 +390,13 @@ struct dev_filter *mpath_filter_create(struct dev_types *dt)
goto bad;
}
- if (!(mp = dm_pool_zalloc(mem, sizeof(*mp)))) {
- log_error("mpath filter allocation failed.");
- goto bad;
- }
-
- mp->f.passes_filter = _ignore_mpath;
+ mp->f.passes_filter = _ignore_mpath_component;
mp->f.destroy = _destroy;
mp->f.use_count = 0;
mp->f.private = mp;
mp->f.name = "mpath";
-
- mp->mem = mem;
mp->dt = dt;
+ mp->mem = mem;
mp->hash = hash;
log_debug_devs("mpath filter initialised.");

View File

@ -1,24 +0,0 @@
lib/metadata/integrity_manip.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/lib/metadata/integrity_manip.c b/lib/metadata/integrity_manip.c
index 53ab1b3..abf90d8 100644
--- a/lib/metadata/integrity_manip.c
+++ b/lib/metadata/integrity_manip.c
@@ -773,9 +773,13 @@ int lv_add_integrity_to_raid(struct logical_volume *lv, struct integrity_setting
bad:
log_error("Failed to add integrity.");
- for (s = 0; s < revert_meta_lvs; s++) {
- if (!lv_remove(imeta_lvs[s]))
- log_error("New integrity metadata LV may require manual removal.");
+ if (revert_meta_lvs) {
+ for (s = 0; s < DEFAULT_RAID_MAX_IMAGES; s++) {
+ if (!imeta_lvs[s])
+ continue;
+ if (!lv_remove(imeta_lvs[s]))
+ log_error("New integrity metadata LV may require manual removal.");
+ }
}
if (!vg_write(vg) || !vg_commit(vg))

View File

@ -1,19 +0,0 @@
lib/label/label.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lib/label/label.c b/lib/label/label.c
index e067a6b..e6dd4a1 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -1243,6 +1243,11 @@ int label_scan(struct cmd_context *cmd)
free(devl);
}
+ dm_list_iterate_items_safe(devl, devl2, &filtered_devs) {
+ dm_list_del(&devl->list);
+ free(devl);
+ }
+
/*
* If hints were not available/usable, then we scanned all devs,
* and we now know which are PVs. Save this list of PVs we've

View File

@ -1,66 +0,0 @@
WHATS_NEW | 4 ++++
lib/activate/activate.c | 5 +++++
lib/activate/activate.h | 2 ++
lib/metadata/lv_manip.c | 6 ++++++
4 files changed, 17 insertions(+)
diff --git a/WHATS_NEW b/WHATS_NEW
index 3953c7e..c8f869c 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,9 @@
Version 2.03.12 -
===================================
+ Check if lvcreate passes read_only_volume_list with tags and skips zeroing.
+ Limit pool metadata spare to 16GiB.
+ Improves conversion and allocation of pool metadata.
+ Support thin pool metadata 15.88GiB, adds 64MiB, thin_pool_crop_metadata=0.
Fix problem with wiping of converted LVs.
Fix memleak in scanning (2.03.11).
Fix corner case allocation for thin-pools.
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 7ed6441..de866fb 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -466,6 +466,11 @@ static int _passes_readonly_filter(struct cmd_context *cmd,
return _lv_passes_volumes_filter(cmd, lv, cn, activation_read_only_volume_list_CFG);
}
+int lv_passes_readonly_filter(const struct logical_volume *lv)
+{
+ return _passes_readonly_filter(lv->vg->cmd, lv);
+}
+
int library_version(char *version, size_t size)
{
if (!activation())
diff --git a/lib/activate/activate.h b/lib/activate/activate.h
index 3f4d128..53c8631 100644
--- a/lib/activate/activate.h
+++ b/lib/activate/activate.h
@@ -208,6 +208,8 @@ int lvs_in_vg_opened(const struct volume_group *vg);
int lv_is_active(const struct logical_volume *lv);
+int lv_passes_readonly_filter(const struct logical_volume *lv);
+
/* Check is any component LV is active */
const struct logical_volume *lv_component_is_active(const struct logical_volume *lv);
const struct logical_volume *lv_holder_is_active(const struct logical_volume *lv);
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 445c4ad..5ff64a3 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -7976,6 +7976,12 @@ static int _should_wipe_lv(struct lvcreate_params *lp,
first_seg(first_seg(lv)->pool_lv)->zero_new_blocks))
return 0;
+ if (warn && (lv_passes_readonly_filter(lv))) {
+ log_warn("WARNING: Read-only activated logical volume %s not zeroed.",
+ display_lvname(lv));
+ return 0;
+ }
+
/* Cannot zero read-only volume */
if ((lv->status & LVM_WRITE) &&
(lp->zero || lp->wipe_signatures))

View File

@ -1,61 +0,0 @@
From 51d4b6069e5767467b4264b7182943a0c73b4c92 Mon Sep 17 00:00:00 2001
From: Marian Csontos <mcsontos@redhat.com>
Date: Mon, 22 Mar 2021 10:50:42 +0100
Subject: [PATCH] lvm: Fix editline compilation
---
configure | 2 +-
configure.ac | 4 ++--
tools/lvm.c | 1 -
3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/configure b/configure
index 4c38cbe..0be9f13 100755
--- a/configure
+++ b/configure
@@ -13404,7 +13404,7 @@ $as_echo_n "checking whether to enable readline... " >&6; }
$as_echo "$READLINE" >&6; }
if test "$EDITLINE" = yes; then
- for ac_header in editline/readline.h editline/history.h
+ for ac_header in editline/readline.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
diff --git a/configure.ac b/configure.ac
index ee21b87..b92be0d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1420,7 +1420,7 @@ if test "$EDITLINE" == yes; then
PKG_CHECK_MODULES([EDITLINE], [libedit], [
AC_DEFINE([EDITLINE_SUPPORT], 1,
[Define to 1 to include the LVM editline shell.])], AC_MSG_ERROR(
-[libedit could not be found which is required for the --enable-readline option.])
+[libedit could not be found which is required for the --enable-editline option.])
)
fi
@@ -1557,7 +1557,7 @@ AC_MSG_CHECKING(whether to enable readline)
AC_MSG_RESULT($READLINE)
if test "$EDITLINE" = yes; then
- AC_CHECK_HEADERS(editline/readline.h editline/history.h,,hard_bailout)
+ AC_CHECK_HEADERS(editline/readline.h,,hard_bailout)
fi
AC_MSG_CHECKING(whether to enable editline)
AC_MSG_RESULT($EDITLINE)
diff --git a/tools/lvm.c b/tools/lvm.c
index 79b1210..cc67e92 100644
--- a/tools/lvm.c
+++ b/tools/lvm.c
@@ -33,7 +33,6 @@ int main(int argc, char **argv)
# endif
# elif defined(EDITLINE_SUPPORT)
# include <editline/readline.h>
-# include <editline/history.h>
# endif
static struct cmdline_context *_cmdline;
--
1.8.3.1

View File

@ -1,29 +0,0 @@
daemons/lvmlockd/lvmlockd-core.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/daemons/lvmlockd/lvmlockd-core.c b/daemons/lvmlockd/lvmlockd-core.c
index fea8ee6..c4abf66 100644
--- a/daemons/lvmlockd/lvmlockd-core.c
+++ b/daemons/lvmlockd/lvmlockd-core.c
@@ -896,8 +896,9 @@ static int read_adopt_file(struct list_head *vg_lockd)
goto fail;
memset(vg_uuid, 0, sizeof(vg_uuid));
+ memset(lm_type_str, 0, sizeof(lm_type_str));
- if (sscanf(adopt_line, "VG: %63s %64s %16s %64s",
+ if (sscanf(adopt_line, "VG: %63s %64s %15s %64s",
vg_uuid, ls->vg_name, lm_type_str, ls->vg_args) != 4) {
goto fail;
}
@@ -916,8 +917,9 @@ static int read_adopt_file(struct list_head *vg_lockd)
r->type = LD_RT_LV;
memset(vg_uuid, 0, sizeof(vg_uuid));
+ memset(mode, 0, sizeof(mode));
- if (sscanf(adopt_line, "LV: %64s %64s %s %8s %u",
+ if (sscanf(adopt_line, "LV: %64s %64s %s %7s %u",
vg_uuid, r->name, r->lv_args, mode, &r->version) != 5) {
goto fail;
}

View File

@ -1,18 +0,0 @@
man/lvconvert.8_pregen | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/man/lvconvert.8_pregen b/man/lvconvert.8_pregen
index a47ccac..170eec8 100644
--- a/man/lvconvert.8_pregen
+++ b/man/lvconvert.8_pregen
@@ -772,6 +772,10 @@ Add a cache to an LV, using a specified cache device.
.br
.RS 4
.ad l
+[ \fB-c\fP|\fB--chunksize\fP \fISize\fP[k|UNIT] ]
+.ad b
+.br
+.ad l
[ \fB--cachesize\fP \fISize\fP[m|UNIT] ]
.ad b
.br

View File

@ -1,86 +0,0 @@
man/lvmthin.7_main | 37 +++++++++++++++++++++++++------------
1 file changed, 25 insertions(+), 12 deletions(-)
diff --git a/man/lvmthin.7_main b/man/lvmthin.7_main
index ce23431..e6f1d63 100644
--- a/man/lvmthin.7_main
+++ b/man/lvmthin.7_main
@@ -394,7 +394,7 @@ the pmspare LV.
\&
If thin pool metadata is damaged, it may be repairable.
-Checking and repairing thin pool metadata is analagous to
+Checking and repairing thin pool metadata is analogous to
running fsck/repair on a file system.
When a thin pool LV is activated, lvm runs the thin_check command
@@ -437,14 +437,24 @@ copy to the VG's pmspare LV.
If step 1 is successful, the thin pool metadata LV is replaced
with the pmspare LV containing the corrected metadata.
The previous thin pool metadata LV, containing the damaged metadata,
-becomes visible with the new name ThinPoolLV_tmetaN (where N is 0,1,...).
-
-If the repair works, the thin pool LV and its thin LVs can be activated,
-and the LV containing the damaged thin pool metadata can be removed.
-It may be useful to move the new metadata LV (previously pmspare) to a
-better PV.
-
-If the repair does not work, the thin pool LV and its thin LVs are lost.
+becomes visible with the new name ThinPoolLV_metaN (where N is 0,1,...).
+
+If the repair works, the thin pool LV and its thin LVs can be activated.
+User should manually check if repaired thin pool kernel metadata
+has all data for all lvm2 known LVs by individual activation of
+every thin LV. When all works, user should continue with fsck of
+all filesystems present these such volumes.
+Once the thin pool is considered fully functional user may remove ThinPoolLV_metaN
+(the LV containing the damaged thin pool metadata) for possible
+space reuse.
+For a better performance it may be useful to pvmove the new repaired metadata LV
+(written to previous pmspare volume) to a better PV (i.e. SSD)
+
+If the repair operation fails, the thin pool LV and its thin LVs
+are not accessible and it may be necessary to restore their content
+from a backup. In such case the content of unmodified original damaged
+ThinPoolLV_metaN volume can be used by your support for more
+advanced recovery methods.
If metadata is manually restored with thin_repair directly,
the pool metadata LV can be manually swapped with another LV
@@ -452,6 +462,9 @@ containing new metadata:
.B lvconvert --thinpool VG/ThinPoolLV --poolmetadata VG/NewThinMetaLV
+Note: Thin pool metadata is compact so even small corruptions
+in them may result in significant portions of mappings to be lost.
+It is recommended to use fast resilient storage for them.
.SS Activation of thin snapshots
@@ -549,7 +562,7 @@ Command to extend thin pool data space:
.fi
Other methods of increasing free data space in a thin pool LV
-include removing a thin LV and its related snapsots, or running
+include removing a thin LV and its related snapshots, or running
fstrim on the file system using a thin LV.
@@ -689,7 +702,7 @@ with two configuration settings:
.B thin_pool_autoextend_threshold
.br
is a percentage full value that defines when the thin pool LV should be
-extended. Setting this to 100 disables automatic extention. The minimum
+extended. Setting this to 100 disables automatic extension. The minimum
value is 50.
.BR lvm.conf (5)
@@ -716,7 +729,7 @@ the --ignoremonitoring option can be used. With this option, the command
will not ask dmeventd to monitor the thin pool LV.
.IP \[bu]
-Setting thin_pool_autoextend_threshould to 100 disables automatic
+Setting thin_pool_autoextend_threshold to 100 disables automatic
extension of thin pool LVs, even if they are being monitored by dmeventd.
.P

View File

@ -1,39 +0,0 @@
lib/metadata/pool_manip.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
index b67882e..1975cb4 100644
--- a/lib/metadata/pool_manip.c
+++ b/lib/metadata/pool_manip.c
@@ -697,6 +697,8 @@ static struct logical_volume *_alloc_pool_metadata_spare(struct volume_group *vg
int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
struct dm_list *pvh, int poolmetadataspare)
{
+ /* Max usable size of any spare volume is currently 16GiB rouned to extent size */
+ const uint64_t MAX_SIZE = (UINT64_C(2 * 16) * 1024 * 1024 + vg->extent_size - 1) / vg->extent_size;
struct logical_volume *lv = vg->pool_metadata_spare_lv;
uint32_t seg_mirrors;
struct lv_segment *seg;
@@ -706,8 +708,11 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
/* Find maximal size of metadata LV */
dm_list_iterate_items(lvl, &vg->lvs)
if (lv_is_pool_metadata(lvl->lv) &&
- (lvl->lv->le_count > extents))
+ (lvl->lv->le_count > extents)) {
extents = lvl->lv->le_count;
+ if (extents >= MAX_SIZE)
+ break;
+ }
if (!poolmetadataspare) {
/* TODO: Not showing when lvm.conf would define 'n' ? */
@@ -718,6 +723,9 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
return 1;
}
+ if (extents > MAX_SIZE)
+ extents = MAX_SIZE;
+
if (!lv) {
if (!_alloc_pool_metadata_spare(vg, extents, pvh))
return_0;

View File

@ -1,92 +0,0 @@
lib/metadata/lv_manip.c | 48 ++++++++++++++++++++++++------------------------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 443d32c..c740ba2 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1470,6 +1470,8 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
struct logical_volume *external_lv = NULL;
int is_raid10 = 0;
uint32_t data_copies = 0;
+ struct lv_list *lvl;
+ int is_last_pool = lv_is_pool(lv);
if (!dm_list_empty(&lv->segments)) {
seg = first_seg(lv);
@@ -1581,6 +1583,28 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
!lv_update_and_reload(external_lv))
return_0;
+ /* When removing last pool, automatically drop the spare volume */
+ if (is_last_pool && lv->vg->pool_metadata_spare_lv) {
+ /* TODO: maybe use a list of pools or a counter to avoid linear search through VG */
+ dm_list_iterate_items(lvl, &lv->vg->lvs)
+ if (lv_is_thin_type(lvl->lv) ||
+ lv_is_cache_type(lvl->lv)) {
+ is_last_pool = 0;
+ break;
+ }
+
+ if (is_last_pool) {
+ /* This is purely internal LV volume, no question */
+ if (!deactivate_lv(lv->vg->cmd, lv->vg->pool_metadata_spare_lv)) {
+ log_error("Unable to deactivate spare logical volume %s.",
+ display_lvname(lv->vg->pool_metadata_spare_lv));
+ return 0;
+ }
+ if (!lv_remove(lv->vg->pool_metadata_spare_lv))
+ return_0;
+ }
+ }
+
return 1;
}
@@ -6433,10 +6457,8 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
struct logical_volume *lock_lv = lv;
struct lv_segment *cache_seg = NULL;
int ask_discard;
- struct lv_list *lvl;
struct seg_list *sl;
struct lv_segment *seg = first_seg(lv);
- int is_last_pool = lv_is_pool(lv);
vg = lv->vg;
@@ -6558,9 +6580,6 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
*/
struct logical_volume *cachevol_lv = first_seg(lv)->pool_lv;
- if (lv_is_cache_pool(cachevol_lv))
- is_last_pool = 1;
-
if (!archive(vg))
return_0;
@@ -6667,25 +6686,6 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
return 0;
}
- if (is_last_pool && vg->pool_metadata_spare_lv) {
- /* When removed last pool, also remove the spare */
- dm_list_iterate_items(lvl, &vg->lvs)
- if (lv_is_pool_metadata(lvl->lv)) {
- is_last_pool = 0;
- break;
- }
- if (is_last_pool) {
- /* This is purely internal LV volume, no question */
- if (!deactivate_lv(cmd, vg->pool_metadata_spare_lv)) {
- log_error("Unable to deactivate spare logical volume %s.",
- display_lvname(vg->pool_metadata_spare_lv));
- return 0;
- }
- if (!lv_remove(vg->pool_metadata_spare_lv))
- return_0;
- }
- }
-
/* store it on disks */
if (!vg_write(vg) || !vg_commit(vg))
return_0;

View File

@ -1,24 +0,0 @@
tools/pvck.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/tools/pvck.c b/tools/pvck.c
index c36e182..88350de 100644
--- a/tools/pvck.c
+++ b/tools/pvck.c
@@ -1140,9 +1140,13 @@ static int _dump_label_and_pv_header(struct cmd_context *cmd, uint64_t labelsect
*mda1_offset = xlate64(dlocn->offset);
*mda1_size = xlate64(dlocn->size);
- if (*mda1_offset != 4096) {
- log_print("CHECK: pv_header.disk_locn[%d].offset expected 4096 # for first mda", di);
- bad++;
+ /*
+ * mda1 offset is page size from machine that created it,
+ * warn if it's not one of the expected page sizes.
+ */
+ if ((*mda1_offset != 4096) && (*mda1_offset != 8192) && (*mda1_offset != 65536)) {
+ log_print("WARNING: pv_header.disk_locn[%d].offset %llu is unexpected # for first mda",
+ di, (unsigned long long)*mda1_offset);
}
} else {
*mda2_offset = xlate64(dlocn->offset);

View File

@ -1,19 +0,0 @@
test/shell/tags.sh | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/test/shell/tags.sh b/test/shell/tags.sh
index fd1b332..5b636a8 100644
--- a/test/shell/tags.sh
+++ b/test/shell/tags.sh
@@ -52,6 +52,11 @@ check lv_field @firstlvtag1 tags "firstlvtag1"
not check lv_field @secondlvtag1 tags "firstlvtag1"
check lv_field $vg1/$lv2 tags "secondlvtag1"
not check lv_field $vg1/$lv1 tags "secondlvtag1"
+
+# LV is not zeroed when tag matches read only volume list
+lvcreate -l1 $vg1 --addtag "RO" --config "activation/read_only_volume_list = [ \"@RO\" ]" 2>&1 | tee out
+grep "not zeroed" out
+
vgremove -f $vg1
# lvchange with --addtag and --deltag

View File

@ -1,98 +0,0 @@
test/shell/thin-16g.sh | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
create mode 100644 test/shell/thin-16g.sh
diff --git a/test/shell/thin-16g.sh b/test/shell/thin-16g.sh
new file mode 100644
index 0000000..ee7e22e
--- /dev/null
+++ b/test/shell/thin-16g.sh
@@ -0,0 +1,88 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
+#
+# 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 General Public License v.2.
+#
+# You should have received a copy of the GNU 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
+
+# Test usability of 16g thin pool metadata LV
+
+
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+aux have_thin 1 0 0 || skip
+
+aux prepare_vg 1 50000
+
+lvcreate -T -L10 --poolmetadatasize 16g $vg/pool
+check lv_field $vg/pool_tmeta size "<15.88g"
+lvremove -f $vg
+
+# Cropped way
+lvcreate -T -L10 --poolmetadatasize 16g --config 'allocation/thin_pool_crop_metadata=1' $vg/pool
+check lv_field $vg/pool_tmeta size "15.81g"
+lvremove -f $vg
+
+lvcreate -L16G -n meta $vg
+lvcreate -L10 -n pool $vg
+lvconvert --yes --thinpool $vg/pool --poolmetadata meta
+# Uncropped size 33554432 sectors - 16GiB
+dmsetup table ${vg}-pool_tmeta | grep 33554432
+lvremove -f $vg
+
+# Uses 20G metadata volume, but crops the size in DM table
+lvcreate -L20G -n meta $vg
+lvcreate -L10 -n pool $vg
+lvconvert --yes --thinpool $vg/pool --poolmetadata meta --config 'allocation/thin_pool_crop_metadata=1'
+check lv_field $vg/lvol0_pmspare size "16.00g"
+# Size should be cropped to 33161216 sectors ~15.81GiB
+dmsetup table ${vg}-pool_tmeta | grep 33161216
+
+# Also size remains unchanged with activation has no cropping,
+# but metadata have no CROP_METADATA flag set
+lvchange -an $vg
+lvchange -ay $vg
+# Size still stays cropped to 33161216 sectors ~15.81GiB
+dmsetup table ${vg}-pool_tmeta | grep 33161216
+lvremove -f $vg
+
+# Minimal size is 2M
+lvcreate -L1M -n meta $vg
+lvcreate -L10 -n pool $vg
+not lvconvert --yes --thinpool $vg/pool --poolmetadata meta
+lvremove -f $vg
+
+# Uses 20G metadata volume, but crops the size in DM table
+lvcreate -L1 --poolmetadatasize 10G -T $vg/pool
+lvresize -L+10G $vg/pool_tmeta --config 'allocation/thin_pool_crop_metadata=1'
+check lv_field $vg/lvol0_pmspare size "15.81g"
+# Size should be cropped to 33161216 sectors ~15.81GiB
+dmsetup table ${vg}-pool_tmeta | grep 33161216
+
+# Without cropping we can grop to ~15.88GiB
+lvresize -L+10G $vg/pool_tmeta
+check lv_field $vg/lvol0_pmspare size "<15.88g"
+lvremove -f $vg
+
+# User has already 'bigger' metadata and wants them uncropped
+lvcreate -L16G -n meta $vg
+lvcreate -L10 -n pool $vg
+lvconvert --yes --thinpool $vg/pool --poolmetadata meta --config 'allocation/thin_pool_crop_metadata=1'
+
+# No change with cropping
+lvresize -l+1 $vg/pool_tmeta --config 'allocation/thin_pool_crop_metadata=1'
+dmsetup table ${vg}-pool_tmeta | grep 33161216
+
+# Resizes to 'uncropped' size 16GiB with ANY size
+lvresize -l+1 $vg/pool_tmeta
+dmsetup table ${vg}-pool_tmeta | grep 33554432
+check lv_field $vg/pool_tmeta size "16.00g"
+
+vgremove -ff $vg

View File

@ -1,78 +0,0 @@
test/shell/thin-zero-meta.sh | 68 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
create mode 100644 test/shell/thin-zero-meta.sh
diff --git a/test/shell/thin-zero-meta.sh b/test/shell/thin-zero-meta.sh
new file mode 100644
index 0000000..6a15a73
--- /dev/null
+++ b/test/shell/thin-zero-meta.sh
@@ -0,0 +1,68 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
+#
+# 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 General Public License v.2.
+#
+# You should have received a copy of the GNU 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
+
+# Test how zeroing of thin-pool metadata works
+
+SKIP_WITH_LVMLOCKD=1
+SKIP_WITH_LVMPOLLD=1
+
+export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false}
+
+. lib/inittest
+
+#
+# Main
+#
+aux have_thin 1 3 0 || skip
+aux have_cache 1 3 0 || skip
+
+aux prepare_vg 3 40000
+
+# Create mostly-zero devs only front of it has some 'real' back-end
+aux zero_dev "$dev1" "$(( $(get first_extent_sector "$dev1") + 8192 )):"
+aux zero_dev "$dev2" "$(( $(get first_extent_sector "$dev2") + 8192 )):"
+aux zero_dev "$dev3" "$(( $(get first_extent_sector "$dev3") + 8192 )):"
+
+# Prepare randomly filled 4M LV on dev2
+lvcreate -L16G -n $lv1 $vg "$dev2"
+dd if=/dev/urandom of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=4 oflag=direct || true
+lvremove -f $vg
+
+for i in 0 1
+do
+ aux lvmconf "allocation/zero_metadata = $i"
+
+ # Lvm2 should allocate metadata on dev2
+ lvcreate -T -L10G --poolmetadatasize 16G $vg/pool "$dev1" "$dev2"
+ lvchange -an $vg
+
+ lvs -ao+seg_pe_ranges $vg
+ lvchange -ay $vg/pool_tmeta --yes
+
+ # Skip past 1.2M which is 'created' by thin-pool initialization
+ hexdump -C -n 200 -s 2000000 "$DM_DEV_DIR/$vg/pool_tmeta" | tee out
+
+ # When fully zeroed, it should be zero - so almost no output from hexdump
+ case "$i" in
+ 0) test $(wc -l < out) -ge 10 ;; # should not be zeroed
+ 1) test $(wc -l < out) -le 10 ;; # should be zeroed
+ esac
+
+ lvremove -f $vg/pool
+done
+
+# Check lvm2 spots error during full zeroing of metadata device
+aux error_dev "$dev2" "$(( $(get first_extent_sector "$dev2") + 32 )):"
+not lvcreate -T -L10G --poolmetadatasize 16G $vg/pool "$dev1" "$dev2" |& tee err
+grep "Failed to initialize logical volume" err
+
+vgremove -ff $vg

View File

@ -1,128 +0,0 @@
test/shell/lvcreate-vdo-cache.sh | 17 +-------
test/shell/lvrename-vdo.sh | 88 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 90 insertions(+), 15 deletions(-)
create mode 100644 test/shell/lvrename-vdo.sh
diff --git a/test/shell/lvcreate-vdo-cache.sh b/test/shell/lvcreate-vdo-cache.sh
index c31cccc..6cf8437 100644
--- a/test/shell/lvcreate-vdo-cache.sh
+++ b/test/shell/lvcreate-vdo-cache.sh
@@ -32,22 +32,9 @@ export MKE2FS_CONFIG="$TESTDIR/lib/mke2fs.conf"
aux prepare_vg 1 9000
-lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1
-
+lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool
# Test caching VDOPoolLV
-lvcreate -H -L10 $vg/vpool1
-
-# Current VDO target driver cannot handle online rename
-# once this will be supported - update this test
-not lvrename $vg/vpool1 $vg/vpool 2>&1 | tee out
-grep "Cannot rename" out
-
-lvchange -an $vg
-
-# Ofline should work
-lvrename $vg/vpool1 $vg/vpool
-
-lvchange -ay $vg
+lvcreate -H -L10 $vg/vpool
mkfs.ext4 -E nodiscard "$DM_DEV_DIR/$vg/$lv1"
diff --git a/test/shell/lvrename-vdo.sh b/test/shell/lvrename-vdo.sh
new file mode 100644
index 0000000..1417d9f
--- /dev/null
+++ b/test/shell/lvrename-vdo.sh
@@ -0,0 +1,88 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
+#
+# 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 General Public License v.2.
+#
+# You should have received a copy of the GNU 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
+
+# Check online renaming of VDO devices works
+
+
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+#
+# Main
+#
+
+aux have_vdo 6 2 1 || skip
+aux have_cache 1 3 0 || skip
+aux have_raid 1 3 0 || skip
+
+aux prepare_vg 2 5000
+
+lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1
+lvrename $vg/vpool1 vpool2
+check lv_exists $vg $lv1 vpool2 vpool2_vdata
+
+lvremove -ff $vg
+
+# With version >= 6.2.3 online rename should work
+if aux have_vdo 6 2 3 ; then
+
+### CACHE ####
+lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1
+lvcreate -H -L10 $vg/vpool1
+lvrename $vg/vpool1 $vg/vpool2
+check lv_exists $vg vpool2 vpool2_vdata
+lvremove -ff $vg
+
+### RAID ####
+lvcreate --type raid1 -L4G --nosync --name vpool1 $vg
+lvconvert --yes --type vdo-pool $vg/vpool1
+lvrename $vg/vpool1 $vg/vpool2
+check lv_exists $vg vpool2 vpool2_vdata vpool2_vdata_rimage_0
+lvremove -ff $vg
+
+fi # >= 6.2.3
+
+# Check when VDO target does not support online resize
+aux lvmconf "global/vdo_disabled_features = [ \"online_rename\" ]"
+
+
+### CACHE ####
+lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1
+lvcreate -H -L10 $vg/vpool1
+
+# VDO target driver cannot handle online rename
+not lvrename $vg/vpool1 $vg/vpool2 2>&1 | tee out
+grep "Cannot rename" out
+
+# Ofline should work
+lvchange -an $vg
+lvrename $vg/vpool1 $vg/vpool2
+lvchange -ay $vg
+check lv_exists $vg $lv1 vpool2 vpool2_vdata
+lvremove -ff $vg
+
+
+### RAID ####
+lvcreate --type raid1 -L4G --nosync --name vpool1 $vg
+lvconvert --yes --type vdo-pool $vg/vpool1
+not lvrename $vg/vpool1 $vg/vpool2 2>&1 | tee out
+grep "Cannot rename" out
+
+# Ofline should work
+lvchange -an $vg
+lvrename $vg/vpool1 $vg/vpool2
+lvchange -ay $vg
+check lv_exists $vg vpool2 vpool2_vdata vpool2_vdata_rimage_0
+lvremove -ff $vg
+
+vgremove -ff $vg

View File

@ -1,47 +0,0 @@
test/shell/lvcreate-thin-limits.sh | 30 ++++++++++++++++++++++++++----
1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/test/shell/lvcreate-thin-limits.sh b/test/shell/lvcreate-thin-limits.sh
index 6a9c33d..5dcc160 100644
--- a/test/shell/lvcreate-thin-limits.sh
+++ b/test/shell/lvcreate-thin-limits.sh
@@ -27,13 +27,35 @@ aux can_use_16T || skip
aux have_thin 1 0 0 || skip
which mkfs.ext4 || skip
-aux prepare_pvs 1 16777216
+# 16T device
+aux prepare_pvs 2 8388608
get_devs
-vgcreate $SHARED -s 4K "$vg" "${DEVICES[@]}"
+# gives 16777215M device
+vgcreate $SHARED -s 4M "$vg" "${DEVICES[@]}"
-not lvcreate -T -L15.995T --poolmetadatasize 5G $vg/pool
+# For 1st. pass only single PV
+lvcreate -l100%PV --name $lv1 $vg "$dev2"
-lvs -ao+seg_pe_ranges $vg
+for i in 1 0
+do
+ SIZE=$(get vg_field "$vg" vg_free --units m)
+ SIZE=${SIZE%%\.*}
+
+ # ~16T - 2 * 5G + something -> should not fit
+ not lvcreate -Zn -T -L$(( SIZE - 2 * 5 * 1024 + 1 )) --poolmetadatasize 5G $vg/pool
+
+ check vg_field "$vg" lv_count "$i"
+
+ # Should fit data + metadata + pmspare
+ lvcreate -Zn -T -L$(( SIZE - 2 * 5 * 1024 )) --poolmetadatasize 5G $vg/pool
+
+ check vg_field "$vg" vg_free "0"
+
+ lvs -ao+seg_pe_ranges $vg
+
+ # Remove everything for 2nd. pass
+ lvremove -ff $vg
+done
vgremove -ff $vg

View File

@ -1,77 +0,0 @@
test/shell/lvconvert-thin.sh | 2 +-
test/shell/lvcreate-cache.sh | 12 +++++-------
test/shell/lvcreate-thin-big.sh | 10 +++++-----
3 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/test/shell/lvconvert-thin.sh b/test/shell/lvconvert-thin.sh
index 1319655..ee85691 100644
--- a/test/shell/lvconvert-thin.sh
+++ b/test/shell/lvconvert-thin.sh
@@ -128,7 +128,7 @@ lvcreate -L1T -n $lv1 $vg
lvcreate -L32G -n $lv2 $vg
# Warning about bigger then needed
lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 2>&1 | tee err
-grep "WARNING: Maximum" err
+grep -i "maximum" err
lvremove -f $vg
diff --git a/test/shell/lvcreate-cache.sh b/test/shell/lvcreate-cache.sh
index 2c46e21..4d9d75e 100644
--- a/test/shell/lvcreate-cache.sh
+++ b/test/shell/lvcreate-cache.sh
@@ -27,7 +27,6 @@ aux prepare_vg 5 80000
aux lvmconf 'global/cache_disabled_features = [ "policy_smq" ]'
-
#######################
# Cache_Pool creation #
#######################
@@ -173,17 +172,16 @@ dmsetup table ${vg}-$lv1 | grep cache # ensure it is loaded in kernel
lvremove -f $vg
-
# Check minimum cache pool metadata size
-lvcreate -l 1 --type cache-pool --poolmetadatasize 1 $vg 2>out
-grep "WARNING: Minimum" out
+lvcreate -l 1 --type cache-pool --poolmetadatasize 1 $vg 2>&1 | tee out
+grep -i "minimal" out
+
# FIXME: This test is failing in allocator with smaller VG sizes
-lvcreate -l 1 --type cache-pool --poolmetadatasize 17G $vg 2>out
-grep "WARNING: Maximum" out
+lvcreate -l 1 --type cache-pool --poolmetadatasize 17G $vg 2>&1 | tee out
+grep -i "maximum" out
lvremove -f $vg
-
########################################
# Cache conversion and r/w permissions #
########################################
diff --git a/test/shell/lvcreate-thin-big.sh b/test/shell/lvcreate-thin-big.sh
index 0b622b7..2549035 100644
--- a/test/shell/lvcreate-thin-big.sh
+++ b/test/shell/lvcreate-thin-big.sh
@@ -31,14 +31,14 @@ vgcreate $SHARED -s 64K "$vg" "${DEVICES[@]}"
# Size 0 is not valid
invalid lvcreate -L4M --chunksize 128 --poolmetadatasize 0 -T $vg/pool1 2>out
-lvcreate -Zn -L4M --chunksize 128 --poolmetadatasize 16k -T $vg/pool1 2>out
-grep "WARNING: Minimum" out
+lvcreate -Zn -L4M --chunksize 128 --poolmetadatasize 16k -T $vg/pool1 2>&1 >out
+grep -i "minimal" out
# FIXME: metadata allocation fails, if PV doesn't have at least 16GB
# i.e. pool metadata device cannot be multisegment
-lvcreate -Zn -L4M --chunksize 64k --poolmetadatasize 17G -T $vg/pool2 2>out
-grep "WARNING: Maximum" out
+lvcreate -Zn -L4M --chunksize 64k --poolmetadatasize 17G -T $vg/pool2 2>&1 >out
+grep "maximum" out
check lv_field $vg/pool1_tmeta size "2.00m"
-check lv_field $vg/pool2_tmeta size "15.81g"
+check lv_field $vg/pool2_tmeta size "<15.88g"
# Check we do report correct percent values.
lvcreate --type zero -L3G $vg -n pool3

View File

@ -1,694 +0,0 @@
conf/example.conf.in | 7 +++
device_mapper/all.h | 16 +++++--
device_mapper/libdm-deptree.c | 39 ++++++++++++-----
lib/activate/dev_manager.c | 8 ++--
lib/config/config_settings.h | 5 +++
lib/config/defaults.h | 2 +
lib/format_text/flags.c | 1 +
lib/metadata/lv_manip.c | 31 ++++++++++++++
lib/metadata/merge.c | 2 +
lib/metadata/metadata-exported.h | 11 +++++
lib/metadata/metadata.h | 13 ++++++
lib/metadata/pool_manip.c | 46 ++++++++++++++++++++
lib/metadata/thin_manip.c | 92 ++++++++++++++++++++++++++--------------
lib/thin/thin.c | 22 +++++++---
man/lvmthin.7_main | 10 ++++-
tools/lvconvert.c | 4 ++
tools/lvcreate.c | 2 +
17 files changed, 256 insertions(+), 55 deletions(-)
diff --git a/conf/example.conf.in b/conf/example.conf.in
index d149ed9..107a071 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -494,6 +494,13 @@ allocation {
# This configuration option has an automatic default value.
# thin_pool_metadata_require_separate_pvs = 0
+ # Configuration option allocation/thin_pool_crop_metadata.
+ # Older version of lvm2 cropped pool's metadata size to 15.81 GiB.
+ # This is slightly less then the actual maximum 15.88 GiB.
+ # For compatibility with older version and use of cropped size set to 1.
+ # This configuration option has an automatic default value.
+ # thin_pool_crop_metadata = 0
+
# Configuration option allocation/thin_pool_zero.
# Thin pool data chunks are zeroed before they are first used.
# Zeroing with a larger thin pool chunk size reduces performance.
diff --git a/device_mapper/all.h b/device_mapper/all.h
index 1080d25..489ca1c 100644
--- a/device_mapper/all.h
+++ b/device_mapper/all.h
@@ -1072,10 +1072,10 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
#define DM_THIN_MIN_DATA_BLOCK_SIZE (UINT32_C(128))
#define DM_THIN_MAX_DATA_BLOCK_SIZE (UINT32_C(2097152))
/*
- * Max supported size for thin pool metadata device (17112760320 bytes)
- * Limitation is hardcoded into the kernel and bigger device size
- * is not accepted.
+ * Max supported size for thin pool metadata device (17045913600 bytes)
* drivers/md/dm-thin-metadata.h THIN_METADATA_MAX_SECTORS
+ * But here DM_THIN_MAX_METADATA_SIZE got defined incorrectly
+ * Correct size is (UINT64_C(255) * ((1 << 14) - 64) * (4096 / (1 << 9)))
*/
#define DM_THIN_MAX_METADATA_SIZE (UINT64_C(255) * (1 << 14) * (4096 / (1 << 9)) - 256 * 1024)
@@ -1088,6 +1088,16 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
uint64_t low_water_mark,
unsigned skip_block_zeroing);
+int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
+ uint64_t size,
+ uint64_t transaction_id,
+ const char *metadata_uuid,
+ const char *pool_uuid,
+ uint32_t data_block_size,
+ uint64_t low_water_mark,
+ unsigned skip_block_zeroing,
+ unsigned crop_metadata);
+
/* Supported messages for thin provision target */
typedef enum {
DM_THIN_MESSAGE_CREATE_SNAP, /* device_id, origin_id */
diff --git a/device_mapper/libdm-deptree.c b/device_mapper/libdm-deptree.c
index 6ce956f..5b60dc9 100644
--- a/device_mapper/libdm-deptree.c
+++ b/device_mapper/libdm-deptree.c
@@ -3979,6 +3979,24 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
uint64_t low_water_mark,
unsigned skip_block_zeroing)
{
+ return dm_tree_node_add_thin_pool_target_v1(node, size, transaction_id,
+ metadata_uuid, pool_uuid,
+ data_block_size,
+ low_water_mark,
+ skip_block_zeroing,
+ 1);
+}
+
+int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
+ uint64_t size,
+ uint64_t transaction_id,
+ const char *metadata_uuid,
+ const char *pool_uuid,
+ uint32_t data_block_size,
+ uint64_t low_water_mark,
+ unsigned skip_block_zeroing,
+ unsigned crop_metadata)
+{
struct load_segment *seg, *mseg;
uint64_t devsize = 0;
@@ -4005,17 +4023,18 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
if (!_link_tree_nodes(node, seg->metadata))
return_0;
- /* FIXME: more complex target may need more tweaks */
- dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
- devsize += mseg->size;
- if (devsize > DM_THIN_MAX_METADATA_SIZE) {
- log_debug_activation("Ignoring %" PRIu64 " of device.",
- devsize - DM_THIN_MAX_METADATA_SIZE);
- mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
- devsize = DM_THIN_MAX_METADATA_SIZE;
- /* FIXME: drop remaining segs */
+ if (crop_metadata)
+ /* FIXME: more complex target may need more tweaks */
+ dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
+ devsize += mseg->size;
+ if (devsize > DM_THIN_MAX_METADATA_SIZE) {
+ log_debug_activation("Ignoring %" PRIu64 " of device.",
+ devsize - DM_THIN_MAX_METADATA_SIZE);
+ mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
+ devsize = DM_THIN_MAX_METADATA_SIZE;
+ /* FIXME: drop remaining segs */
+ }
}
- }
if (!(seg->pool = dm_tree_find_node_by_uuid(node->dtree, pool_uuid))) {
log_error("Missing pool uuid %s.", pool_uuid);
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 8d27bd3..9a25482 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -261,7 +261,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
int dmtask;
int with_flush; /* TODO: arg for _info_run */
void *target = NULL;
- uint64_t target_start, target_length, start, length;
+ uint64_t target_start, target_length, start, length, length_crop = 0;
char *target_name, *target_params;
const char *devname;
@@ -297,7 +297,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
/* Uses max DM_THIN_MAX_METADATA_SIZE sectors for metadata device */
if (lv_is_thin_pool_metadata(seg_status->seg->lv) &&
(length > DM_THIN_MAX_METADATA_SIZE))
- length = DM_THIN_MAX_METADATA_SIZE;
+ length_crop = DM_THIN_MAX_METADATA_SIZE;
/* Uses virtual size with headers for VDO pool device */
if (lv_is_vdo_pool(seg_status->seg->lv))
@@ -310,7 +310,9 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
target = dm_get_next_target(dmt, target, &target_start,
&target_length, &target_name, &target_params);
- if ((start == target_start) && (length == target_length))
+ if ((start == target_start) &&
+ ((length == target_length) ||
+ (length_crop && (length_crop == target_length))))
break; /* Keep target_params when matching segment is found */
target_params = NULL; /* Marking this target_params unusable */
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index 3c4032e..cb4e23a 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -628,6 +628,11 @@ cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CF
cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL,
"Thin pool metadata and data will always use different PVs.\n")
+cfg(allocation_thin_pool_crop_metadata_CFG, "thin_pool_crop_metadata", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_CROP_METADATA, vsn(2, 3, 12), NULL, 0, NULL,
+ "Older version of lvm2 cropped pool's metadata size to 15.81 GiB.\n"
+ "This is slightly less then the actual maximum 15.88 GiB.\n"
+ "For compatibility with older version and use of cropped size set to 1.\n")
+
cfg(allocation_thin_pool_zero_CFG, "thin_pool_zero", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_ZERO, vsn(2, 2, 99), NULL, 0, NULL,
"Thin pool data chunks are zeroed before they are first used.\n"
"Zeroing with a larger thin pool chunk size reduces performance.\n")
diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index 708a575..bcc20cc 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -118,6 +118,8 @@
#define DEFAULT_THIN_REPAIR_OPTION1 ""
#define DEFAULT_THIN_REPAIR_OPTIONS_CONFIG "#S" DEFAULT_THIN_REPAIR_OPTION1
#define DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS 0
+#define DEFAULT_THIN_POOL_CROP_METADATA 0
+#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE_V1_KB (UINT64_C(255) * ((1 << 14) - 64) * 4) /* KB */ /* 0x3f8040 blocks */
#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE (DM_THIN_MAX_METADATA_SIZE / 2) /* KB */
#define DEFAULT_THIN_POOL_MIN_METADATA_SIZE 2048 /* KB */
#define DEFAULT_THIN_POOL_OPTIMAL_METADATA_SIZE (128 * 1024) /* KB */
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index bc93a5d..4cee14a 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -72,6 +72,7 @@ static const struct flag _lv_flags[] = {
{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
{LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG},
{LV_METADATA_FORMAT, "METADATA_FORMAT", SEGTYPE_FLAG},
+ {LV_CROP_METADATA, "CROP_METADATA", SEGTYPE_FLAG},
{LV_CACHE_VOL, "CACHE_VOL", COMPATIBLE_FLAG},
{LV_CACHE_USES_CACHEVOL, "CACHE_USES_CACHEVOL", SEGTYPE_FLAG},
{LV_NOSCAN, NULL, 0},
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 443d32c..445c4ad 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -5384,6 +5384,8 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
uint32_t existing_extents;
uint32_t seg_size = 0;
uint32_t new_extents;
+ uint64_t max_metadata_size;
+ thin_crop_metadata_t crop;
int reducing = 0;
seg_last = last_seg(lv);
@@ -5544,6 +5546,33 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
return 1;
}
}
+ } else if (lv_is_thin_pool_metadata(lv)) {
+ if (!(seg = get_only_segment_using_this_lv(lv)))
+ return_0;
+
+ max_metadata_size = get_thin_pool_max_metadata_size(cmd, vg->profile, &crop);
+
+ if (((uint64_t)lp->extents * vg->extent_size) > max_metadata_size) {
+ lp->extents = (max_metadata_size + vg->extent_size - 1) / vg->extent_size;
+ log_print_unless_silent("Reached maximum pool metadata size %s (%" PRIu32 " extents).",
+ display_size(vg->cmd, max_metadata_size), lp->extents);
+ }
+
+ if (existing_logical_extents >= lp->extents)
+ lp->extents = existing_logical_extents;
+
+ crop = get_thin_pool_crop_metadata(cmd, crop, (uint64_t)lp->extents * vg->extent_size);
+
+ if (seg->crop_metadata != crop) {
+ seg->crop_metadata = crop;
+ seg->lv->status |= LV_CROP_METADATA;
+ /* Crop change require reload even if there no size change */
+ lp->size_changed = 1;
+ log_print_unless_silent("Thin pool will use metadata without cropping.");
+ }
+
+ if (!(seg_size = lp->extents - existing_logical_extents))
+ return 1; /* No change in metadata size */
}
} else { /* If reducing, find stripes, stripesize & size of last segment */
if (lp->stripes || lp->stripe_size || lp->mirrors)
@@ -8388,6 +8417,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
first_seg(lv)->chunk_size = lp->chunk_size;
first_seg(lv)->zero_new_blocks = lp->zero_new_blocks;
first_seg(lv)->discards = lp->discards;
+ if ((first_seg(lv)->crop_metadata = lp->crop_metadata) == THIN_CROP_METADATA_NO)
+ lv->status |= LV_CROP_METADATA;
if (!recalculate_pool_chunk_size_with_dev_hints(lv, lp->thin_chunk_size_calc_policy)) {
stack;
goto revert_new_lv;
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 0aa2293..eff59ae 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -495,6 +495,8 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
seg_error("sets discards");
if (!dm_list_empty(&seg->thin_messages))
seg_error("sets thin_messages list");
+ if (seg->lv->status & LV_CROP_METADATA)
+ seg_error("sets CROP_METADATA flag");
}
if (seg_is_thin_volume(seg)) {
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 54dc29f..0e57722 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -143,6 +143,7 @@
#define LV_REMOVE_AFTER_RESHAPE UINT64_C(0x0400000000000000) /* LV needs to be removed after a shrinking reshape */
#define LV_METADATA_FORMAT UINT64_C(0x0800000000000000) /* LV has segments with metadata format */
+#define LV_CROP_METADATA UINT64_C(0x0000000000000400) /* LV - also VG CLUSTERED */
#define LV_RESHAPE UINT64_C(0x1000000000000000) /* Ongoing reshape (number of stripes, stripesize or raid algorithm change):
used as SEGTYPE_FLAG to prevent activation on old runtime */
@@ -326,6 +327,12 @@ typedef enum {
} thin_discards_t;
typedef enum {
+ THIN_CROP_METADATA_UNSELECTED = 0, /* 'auto' selects */
+ THIN_CROP_METADATA_NO,
+ THIN_CROP_METADATA_YES,
+} thin_crop_metadata_t;
+
+typedef enum {
CACHE_MODE_UNSELECTED = 0,
CACHE_MODE_WRITETHROUGH,
CACHE_MODE_WRITEBACK,
@@ -502,6 +509,7 @@ struct lv_segment {
uint64_t transaction_id; /* For thin_pool, thin */
thin_zero_t zero_new_blocks; /* For thin_pool */
thin_discards_t discards; /* For thin_pool */
+ thin_crop_metadata_t crop_metadata; /* For thin_pool */
struct dm_list thin_messages; /* For thin_pool */
struct logical_volume *external_lv; /* For thin */
struct logical_volume *pool_lv; /* For thin, cache */
@@ -885,6 +893,8 @@ int update_thin_pool_params(struct cmd_context *cmd,
unsigned attr,
uint32_t pool_data_extents,
uint32_t *pool_metadata_extents,
+ struct logical_volume *metadata_lv,
+ unsigned *crop_metadata,
int *chunk_size_calc_method, uint32_t *chunk_size,
thin_discards_t *discards, thin_zero_t *zero_new_blocks);
@@ -1011,6 +1021,7 @@ struct lvcreate_params {
uint64_t permission; /* all */
unsigned error_when_full; /* when segment supports it */
+ thin_crop_metadata_t crop_metadata;
uint32_t read_ahead; /* all */
int approx_alloc; /* all */
alloc_policy_t alloc; /* all */
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 2c22450..0f230e4 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -512,8 +512,21 @@ int pool_below_threshold(const struct lv_segment *pool_seg);
int pool_check_overprovisioning(const struct logical_volume *lv);
int create_pool(struct logical_volume *pool_lv, const struct segment_type *segtype,
struct alloc_handle *ah, uint32_t stripes, uint32_t stripe_size);
+uint64_t get_thin_pool_max_metadata_size(struct cmd_context *cmd, struct profile *profile,
+ thin_crop_metadata_t *crop);
+thin_crop_metadata_t get_thin_pool_crop_metadata(struct cmd_context *cmd,
+ thin_crop_metadata_t crop,
+ uint64_t metadata_size);
uint64_t estimate_thin_pool_metadata_size(uint32_t data_extents, uint32_t extent_size, uint32_t chunk_size);
+int update_pool_metadata_min_max(struct cmd_context *cmd,
+ uint32_t extent_size,
+ uint64_t min_metadata_size, /* required min */
+ uint64_t max_metadata_size, /* writable max */
+ uint64_t *metadata_size, /* current calculated */
+ struct logical_volume *metadata_lv, /* name of converted LV or NULL */
+ uint32_t *metadata_extents); /* resulting extent count */
+
/*
* Begin skeleton for external LVM library
*/
diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
index a9dc611..b67882e 100644
--- a/lib/metadata/pool_manip.c
+++ b/lib/metadata/pool_manip.c
@@ -742,6 +742,52 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
return 1;
}
+int update_pool_metadata_min_max(struct cmd_context *cmd,
+ uint32_t extent_size,
+ uint64_t min_metadata_size, /* required min */
+ uint64_t max_metadata_size, /* writable max */
+ uint64_t *metadata_size, /* current calculated */
+ struct logical_volume *metadata_lv, /* name of converted LV or NULL */
+ uint32_t *metadata_extents) /* resulting extent count */
+{
+ max_metadata_size = dm_round_up(max_metadata_size, extent_size);
+ min_metadata_size = dm_round_up(min_metadata_size, extent_size);
+
+ if (*metadata_size > max_metadata_size) {
+ if (metadata_lv) {
+ log_print_unless_silent("Size %s of pool metadata volume %s is bigger then maximum usable size %s.",
+ display_size(cmd, *metadata_size),
+ display_lvname(metadata_lv),
+ display_size(cmd, max_metadata_size));
+ } else {
+ if (*metadata_extents)
+ log_print_unless_silent("Reducing pool metadata size %s to maximum usable size %s.",
+ display_size(cmd, *metadata_size),
+ display_size(cmd, max_metadata_size));
+ *metadata_size = max_metadata_size;
+ }
+ } else if (*metadata_size < min_metadata_size) {
+ if (metadata_lv) {
+ log_error("Can't use volume %s with size %s as pool metadata. Minimal required size is %s.",
+ display_lvname(metadata_lv),
+ display_size(cmd, *metadata_size),
+ display_size(cmd, min_metadata_size));
+ return 0;
+ } else {
+ if (*metadata_extents)
+ log_print_unless_silent("Extending pool metadata size %s to required minimal size %s.",
+ display_size(cmd, *metadata_size),
+ display_size(cmd, min_metadata_size));
+ *metadata_size = min_metadata_size;
+ }
+ }
+
+ if (!(*metadata_extents = extents_from_size(cmd, *metadata_size, extent_size)))
+ return_0;
+
+ return 1;
+}
+
int vg_set_pool_metadata_spare(struct logical_volume *lv)
{
char new_name[NAME_LEN];
diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
index 4591dd7..451c382 100644
--- a/lib/metadata/thin_manip.c
+++ b/lib/metadata/thin_manip.c
@@ -610,9 +610,9 @@ static uint64_t _estimate_metadata_size(uint32_t data_extents, uint32_t extent_s
}
/* Estimate maximal supportable thin pool data size for given chunk_size */
-static uint64_t _estimate_max_data_size(uint32_t chunk_size)
+static uint64_t _estimate_max_data_size(uint64_t max_metadata_size, uint32_t chunk_size)
{
- return chunk_size * (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2) * SECTOR_SIZE / UINT64_C(64);
+ return max_metadata_size * chunk_size * SECTOR_SIZE / UINT64_C(64);
}
/* Estimate thin pool chunk size from data and metadata size (in sector units) */
@@ -662,6 +662,38 @@ int get_default_allocation_thin_pool_chunk_size(struct cmd_context *cmd, struct
return 1;
}
+/* Return max supported metadata size with selected cropping */
+uint64_t get_thin_pool_max_metadata_size(struct cmd_context *cmd, struct profile *profile,
+ thin_crop_metadata_t *crop)
+{
+ *crop = find_config_tree_bool(cmd, allocation_thin_pool_crop_metadata_CFG, profile) ?
+ THIN_CROP_METADATA_YES : THIN_CROP_METADATA_NO;
+
+ return (*crop == THIN_CROP_METADATA_NO) ?
+ (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE_V1_KB) : (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE);
+}
+
+/*
+ * With existing crop method, check if the metadata_size would need cropping.
+ * If not, set UNSELECTED, otherwise print some verbose info about selected cropping
+ */
+thin_crop_metadata_t get_thin_pool_crop_metadata(struct cmd_context *cmd,
+ thin_crop_metadata_t crop,
+ uint64_t metadata_size)
+{
+ const uint64_t crop_size = (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE);
+
+ if (metadata_size > crop_size) {
+ if (crop == THIN_CROP_METADATA_NO)
+ log_verbose("Using metadata size without cropping.");
+ else
+ log_verbose("Cropping metadata size to %s.", display_size(cmd, crop_size));
+ } else
+ crop = THIN_CROP_METADATA_UNSELECTED;
+
+ return crop;
+}
+
int update_thin_pool_params(struct cmd_context *cmd,
struct profile *profile,
uint32_t extent_size,
@@ -669,10 +701,13 @@ int update_thin_pool_params(struct cmd_context *cmd,
unsigned attr,
uint32_t pool_data_extents,
uint32_t *pool_metadata_extents,
+ struct logical_volume *metadata_lv,
+ thin_crop_metadata_t *crop_metadata,
int *chunk_size_calc_method, uint32_t *chunk_size,
thin_discards_t *discards, thin_zero_t *zero_new_blocks)
{
- uint64_t pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
+ uint64_t pool_metadata_size;
+ uint64_t max_metadata_size;
uint32_t estimate_chunk_size;
uint64_t max_pool_data_size;
const char *str;
@@ -702,7 +737,9 @@ int update_thin_pool_params(struct cmd_context *cmd,
*zero_new_blocks = find_config_tree_bool(cmd, allocation_thin_pool_zero_CFG, profile)
? THIN_ZERO_YES : THIN_ZERO_NO;
- if (!pool_metadata_size) {
+ max_metadata_size = get_thin_pool_max_metadata_size(cmd, profile, crop_metadata);
+
+ if (!*pool_metadata_extents) {
if (!*chunk_size) {
if (!get_default_allocation_thin_pool_chunk_size(cmd, profile,
chunk_size,
@@ -723,20 +760,20 @@ int update_thin_pool_params(struct cmd_context *cmd,
} else {
pool_metadata_size = _estimate_metadata_size(pool_data_extents, extent_size, *chunk_size);
- if (pool_metadata_size > (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2)) {
+ if (pool_metadata_size > max_metadata_size) {
/* Suggest bigger chunk size */
estimate_chunk_size =
_estimate_chunk_size(pool_data_extents, extent_size,
- (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2), attr);
+ max_metadata_size, attr);
log_warn("WARNING: Chunk size is too small for pool, suggested minimum is %s.",
display_size(cmd, estimate_chunk_size));
}
}
/* Round up to extent size silently */
- if (pool_metadata_size % extent_size)
- pool_metadata_size += extent_size - pool_metadata_size % extent_size;
+ pool_metadata_size = dm_round_up(pool_metadata_size, extent_size);
} else {
+ pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
estimate_chunk_size = _estimate_chunk_size(pool_data_extents, extent_size,
pool_metadata_size, attr);
@@ -751,7 +788,19 @@ int update_thin_pool_params(struct cmd_context *cmd,
}
}
- max_pool_data_size = _estimate_max_data_size(*chunk_size);
+ /* Use not rounded max for data size */
+ max_pool_data_size = _estimate_max_data_size(max_metadata_size, *chunk_size);
+
+ if (!update_pool_metadata_min_max(cmd, extent_size,
+ 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE,
+ max_metadata_size,
+ &pool_metadata_size,
+ metadata_lv,
+ pool_metadata_extents))
+ return_0;
+
+ *crop_metadata = get_thin_pool_crop_metadata(cmd, *crop_metadata, pool_metadata_size);
+
if ((max_pool_data_size / extent_size) < pool_data_extents) {
log_error("Selected chunk size %s cannot address more then %s of thin pool data space.",
display_size(cmd, *chunk_size), display_size(cmd, max_pool_data_size));
@@ -764,22 +813,6 @@ int update_thin_pool_params(struct cmd_context *cmd,
if (!validate_thin_pool_chunk_size(cmd, *chunk_size))
return_0;
- if (pool_metadata_size > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE)) {
- pool_metadata_size = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
- if (*pool_metadata_extents)
- log_warn("WARNING: Maximum supported pool metadata size is %s.",
- display_size(cmd, pool_metadata_size));
- } else if (pool_metadata_size < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE)) {
- pool_metadata_size = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE;
- if (*pool_metadata_extents)
- log_warn("WARNING: Minimum supported pool metadata size is %s.",
- display_size(cmd, pool_metadata_size));
- }
-
- if (!(*pool_metadata_extents =
- extents_from_size(cmd, pool_metadata_size, extent_size)))
- return_0;
-
if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
log_error("Size of %s data volume cannot be smaller than chunk size %s.",
segtype->name, display_size(cmd, *chunk_size));
@@ -958,12 +991,5 @@ int validate_thin_pool_chunk_size(struct cmd_context *cmd, uint32_t chunk_size)
uint64_t estimate_thin_pool_metadata_size(uint32_t data_extents, uint32_t extent_size, uint32_t chunk_size)
{
- uint64_t sz = _estimate_metadata_size(data_extents, extent_size, chunk_size);
-
- if (sz > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE))
- sz = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
- else if (sz < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE))
- sz = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE;
-
- return sz;
+ return _estimate_metadata_size(data_extents, extent_size, chunk_size);
}
diff --git a/lib/thin/thin.c b/lib/thin/thin.c
index ba0da71..51bc269 100644
--- a/lib/thin/thin.c
+++ b/lib/thin/thin.c
@@ -86,6 +86,7 @@ static int _thin_pool_text_import(struct lv_segment *seg,
struct logical_volume *pool_data_lv, *pool_metadata_lv;
const char *discards_str = NULL;
uint32_t zero = 0;
+ uint32_t crop = 0;
if (!dm_config_get_str(sn, "metadata", &lv_name))
return SEG_LOG_ERROR("Metadata must be a string in");
@@ -131,6 +132,13 @@ static int _thin_pool_text_import(struct lv_segment *seg,
seg->zero_new_blocks = (zero) ? THIN_ZERO_YES : THIN_ZERO_NO;
+ if (dm_config_has_node(sn, "crop_metadata")) {
+ if (!dm_config_get_uint32(sn, "crop_metadata", &crop))
+ return SEG_LOG_ERROR("Could not read crop_metadata for");
+ seg->crop_metadata = (crop) ? THIN_CROP_METADATA_YES : THIN_CROP_METADATA_NO;
+ seg->lv->status |= LV_CROP_METADATA;
+ }
+
/* Read messages */
for (; sn; sn = sn->sib)
if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child))
@@ -177,6 +185,9 @@ static int _thin_pool_text_export(const struct lv_segment *seg, struct formatter
return 0;
}
+ if (seg->crop_metadata != THIN_CROP_METADATA_UNSELECTED)
+ outf(f, "crop_metadata = %u", (seg->crop_metadata == THIN_CROP_METADATA_YES) ? 1 : 0);
+
dm_list_iterate_items(tmsg, &seg->thin_messages) {
/* Extra validation */
switch (tmsg->type) {
@@ -307,11 +318,12 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
else
low_water_mark = 0;
- if (!dm_tree_node_add_thin_pool_target(node, len,
- seg->transaction_id,
- metadata_dlid, pool_dlid,
- seg->chunk_size, low_water_mark,
- (seg->zero_new_blocks == THIN_ZERO_YES) ? 0 : 1))
+ if (!dm_tree_node_add_thin_pool_target_v1(node, len,
+ seg->transaction_id,
+ metadata_dlid, pool_dlid,
+ seg->chunk_size, low_water_mark,
+ (seg->zero_new_blocks == THIN_ZERO_YES) ? 0 : 1,
+ (seg->crop_metadata == THIN_CROP_METADATA_YES) ? 1 : 0))
return_0;
if (attr & THIN_FEATURE_DISCARDS) {
diff --git a/man/lvmthin.7_main b/man/lvmthin.7_main
index e6f1d63..3ce34a5 100644
--- a/man/lvmthin.7_main
+++ b/man/lvmthin.7_main
@@ -1104,7 +1104,7 @@ The default value is shown by:
The amount of thin metadata depends on how many blocks are shared between
thin LVs (i.e. through snapshots). A thin pool with many snapshots may
need a larger metadata LV. Thin pool metadata LV sizes can be from 2MiB
-to 16GiB.
+to approximately 16GiB.
When using lvcreate to create what will become a thin metadata LV, the
size is specified with the -L|--size option.
@@ -1119,6 +1119,14 @@ needed, so it is recommended to start with a size of 1GiB which should be
enough for all practical purposes. A thin pool metadata LV can later be
manually or automatically extended if needed.
+Configurable setting
+.BR lvm.conf (5)
+.BR allocation / thin_pool_crop_metadata
+gives control over cropping to 15.81GiB to stay backward compatible with older
+versions of lvm2. With enabled cropping there can be observed some problems when
+using volumes above this size with thin tools (i.e. thin_repair).
+Cropping should be enabled only when compatibility is required.
+
.SS Create a thin snapshot of an external, read only LV
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 7b74afb..ce90279 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -3032,6 +3032,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
const char *policy_name;
struct dm_config_tree *policy_settings = NULL;
int pool_metadata_spare;
+ thin_crop_metadata_t crop_metadata;
thin_discards_t discards;
thin_zero_t zero_new_blocks;
int r = 0;
@@ -3196,6 +3197,8 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
pool_segtype, target_attr,
lv->le_count,
&meta_extents,
+ metadata_lv,
+ &crop_metadata,
&chunk_calc,
&chunk_size,
&discards, &zero_new_blocks))
@@ -3401,6 +3404,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
goto_bad;
} else {
seg->transaction_id = 0;
+ seg->crop_metadata = crop_metadata;
seg->chunk_size = chunk_size;
seg->discards = discards;
seg->zero_new_blocks = zero_new_blocks;
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index e384291..1ee9e14 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -391,6 +391,8 @@ static int _update_extents_params(struct volume_group *vg,
lp->segtype, lp->target_attr,
lp->extents,
&lp->pool_metadata_extents,
+ NULL,
+ &lp->crop_metadata,
&lp->thin_chunk_size_calc_policy,
&lp->chunk_size,
&lp->discards,

View File

@ -1,194 +0,0 @@
conf/example.conf.in | 10 ++++++++++
lib/config/config_settings.h | 9 +++++++++
lib/metadata/lv_manip.c | 14 +++++++++++---
lib/metadata/segtype.h | 2 ++
lib/vdo/vdo.c | 46 ++++++++++++++++++++++++++++++++++++--------
5 files changed, 70 insertions(+), 11 deletions(-)
diff --git a/conf/example.conf.in b/conf/example.conf.in
index cd53147..d02965e 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -1195,6 +1195,16 @@ global {
# This configuration option has an automatic default value.
# vdo_format_options = [ "" ]
+ # Configuration option global/vdo_disabled_features.
+ # Features to not use in the vdo driver.
+ # This can be helpful for testing, or to avoid using a feature that is
+ # causing problems. Features include: online_rename
+ #
+ # Example
+ # vdo_disabled_features = [ "online_rename" ]
+ #
+ # This configuration option does not have a default value defined.
+
# Configuration option global/fsadm_executable.
# The full path to the fsadm command.
# LVM uses this command to help with lvresize -r operations.
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index 3c4032e..f844594 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -1206,6 +1206,15 @@ cfg(global_vdo_format_executable_CFG, "vdo_format_executable", global_CFG_SECTIO
cfg_array(global_vdo_format_options_CFG, "vdo_format_options", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VDO_FORMAT_OPTIONS_CONFIG, VDO_1ST_VSN, NULL, 0, NULL,
"List of options passed added to standard vdoformat command.\n")
+cfg_array(global_vdo_disabled_features_CFG, "vdo_disabled_features", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 3, 11), NULL, 0, NULL,
+ "Features to not use in the vdo driver.\n"
+ "This can be helpful for testing, or to avoid using a feature that is\n"
+ "causing problems. Features include: online_rename\n"
+ "#\n"
+ "Example\n"
+ "vdo_disabled_features = [ \"online_rename\" ]\n"
+ "#\n")
+
cfg(global_fsadm_executable_CFG, "fsadm_executable", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FSADM_PATH, vsn(2, 2, 170), "@FSADM_PATH@", 0, NULL,
"The full path to the fsadm command.\n"
"LVM uses this command to help with lvresize -r operations.\n")
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index c740ba2..6c71263 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -4738,6 +4738,8 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv,
struct lv_names lv_names = { .old = lv->name };
int old_lv_is_historical = lv_is_historical(lv);
int historical;
+ unsigned attrs;
+ const struct segment_type *segtype;
/*
* rename is not allowed on sub LVs except for pools
@@ -4763,9 +4765,15 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv,
}
if (lv_is_vdo_pool(lv) && lv_is_active(lv_lock_holder(lv))) {
- log_error("Cannot rename active VDOPOOL volume %s.",
- display_lvname(lv));
- return 0;
+ segtype = first_seg(lv)->segtype;
+ if (!segtype->ops->target_present ||
+ !segtype->ops->target_present(lv->vg->cmd, NULL, &attrs) ||
+ !(attrs & VDO_FEATURE_ONLINE_RENAME)) {
+ log_error("Cannot rename active VDOPOOL volume %s, "
+ "VDO target feature support is missing.",
+ display_lvname(lv));
+ return 0;
+ }
}
if (update_mda && !archive(vg))
diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
index 08ddc35..2714a6b 100644
--- a/lib/metadata/segtype.h
+++ b/lib/metadata/segtype.h
@@ -349,6 +349,8 @@ int init_cache_segtypes(struct cmd_context *cmd, struct segtype_library *seglib)
int init_vdo_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
#endif
+#define VDO_FEATURE_ONLINE_RENAME (1U << 0) /* version 6.2.3 */
+
int init_writecache_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
int init_integrity_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
diff --git a/lib/vdo/vdo.c b/lib/vdo/vdo.c
index c43a5dc..bb7c784 100644
--- a/lib/vdo/vdo.c
+++ b/lib/vdo/vdo.c
@@ -25,6 +25,7 @@
#include "lib/metadata/segtype.h"
#include "base/memory/zalloc.h"
+static const char _vdo_module[] = MODULE_NAME_VDO;
static unsigned _feature_mask;
static int _bad_field(const char *field)
@@ -391,18 +392,21 @@ static int _vdo_target_present(struct cmd_context *cmd,
static const struct feature {
uint32_t maj;
uint32_t min;
+ uint32_t patchlevel;
unsigned vdo_feature;
const char *feature;
} _features[] = {
- { 1, 1, 0, "" },
- //{ 9, 9, VDO_FEATURE_RESIZE, "resize" },
+ { 6, 2, 3, VDO_FEATURE_ONLINE_RENAME, "online_rename" },
};
- //static const char _lvmconf[] = "global/vdo_disabled_features";
+ static const char _lvmconf[] = "global/vdo_disabled_features";
static int _vdo_checked = 0;
static int _vdo_present = 0;
static unsigned _vdo_attrs = 0;
uint32_t i, maj, min, patchlevel;
const struct segment_type *segtype;
+ const struct dm_config_node *cn;
+ const struct dm_config_value *cv;
+ const char *str;
if (!activation())
return 0;
@@ -419,8 +423,8 @@ static int _vdo_target_present(struct cmd_context *cmd,
}
if (maj < 6 || (maj == 6 && min < 2)) {
- log_warn("WARNING: VDO target version %u.%u.%u is too old.",
- maj, min, patchlevel);
+ log_warn("WARNING: Target %s version %u.%u.%u is too old.",
+ _vdo_module, maj, min, patchlevel);
return 0;
}
@@ -437,15 +441,41 @@ static int _vdo_target_present(struct cmd_context *cmd,
/* Prepare for adding supported features */
for (i = 0; i < DM_ARRAY_SIZE(_features); ++i)
if ((maj > _features[i].maj) ||
- (maj == _features[i].maj && min >= _features[i].min))
+ ((maj == _features[i].maj) && (min > _features[i].min)) ||
+ ((maj == _features[i].maj) && (min == _features[i].min) && (patchlevel >= _features[i].patchlevel)))
_vdo_attrs |= _features[i].vdo_feature;
else
log_very_verbose("Target %s does not support %s.",
- TARGET_NAME_VDO,
+ _vdo_module,
_features[i].feature);
}
if (attributes) {
+ if (!_feature_mask) {
+ /* Support runtime lvm.conf changes, N.B. avoid 32 feature */
+ if ((cn = find_config_tree_array(cmd, global_vdo_disabled_features_CFG, NULL))) {
+ for (cv = cn->v; cv; cv = cv->next) {
+ if (cv->type != DM_CFG_STRING) {
+ log_warn("WARNING: Ignoring invalid string in config file %s.",
+ _lvmconf);
+ continue;
+ }
+ str = cv->v.str;
+ if (!*str)
+ continue;
+ for (i = 0; i < DM_ARRAY_SIZE(_features); ++i)
+ if (strcasecmp(str, _features[i].feature) == 0)
+ _feature_mask |= _features[i].vdo_feature;
+ }
+ }
+ _feature_mask = ~_feature_mask;
+ for (i = 0; i < DM_ARRAY_SIZE(_features); ++i)
+ if ((_vdo_attrs & _features[i].vdo_feature) &&
+ !(_feature_mask & _features[i].vdo_feature))
+ log_very_verbose("Target %s %s support disabled by %s.",
+ _vdo_module,
+ _features[i].feature, _lvmconf);
+ }
*attributes = _vdo_attrs & _feature_mask;
}
@@ -456,7 +486,7 @@ static int _vdo_modules_needed(struct dm_pool *mem,
const struct lv_segment *seg __attribute__((unused)),
struct dm_list *modules)
{
- if (!str_list_add(mem, modules, MODULE_NAME_VDO)) {
+ if (!str_list_add(mem, modules, _vdo_module)) {
log_error("String list allocation failed for VDO module.");
return 0;
}

View File

@ -1,45 +0,0 @@
lib/metadata/writecache_manip.c | 10 +++++++---
tools/lvconvert.c | 2 ++
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/lib/metadata/writecache_manip.c b/lib/metadata/writecache_manip.c
index 5004aa9..8150d07 100644
--- a/lib/metadata/writecache_manip.c
+++ b/lib/metadata/writecache_manip.c
@@ -75,7 +75,7 @@ static int _get_writecache_kernel_status(struct cmd_context *cmd,
return 0;
}
- if (!lv_info_with_seg_status(cmd, first_seg(lv), &status, 1, 1)) {
+ if (!lv_info_with_seg_status(cmd, first_seg(lv), &status, 0, 0)) {
log_error("Failed to get device mapper status for %s", display_lvname(lv));
goto fail;
}
@@ -434,8 +434,12 @@ int lv_writecache_set_cleaner(struct logical_volume *lv)
seg->writecache_settings.cleaner_set = 1;
if (lv_is_active(lv)) {
- if (!lv_update_and_reload(lv)) {
- log_error("Failed to update VG and reload LV.");
+ if (!vg_write(lv->vg) || !vg_commit(lv->vg)) {
+ log_error("Failed to update VG.");
+ return 0;
+ }
+ if (!lv_writecache_message(lv, "cleaner")) {
+ log_error("Failed to set writecache cleaner for %s.", display_lvname(lv));
return 0;
}
} else {
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 4323965..7b74afb 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -5720,6 +5720,8 @@ static int _lvconvert_detach_writecache_when_clean(struct cmd_context *cmd,
return 0;
}
+ log_debug("detach writecache check clean reading vg %s", id->vg_name);
+
vg = vg_read(cmd, id->vg_name, NULL, READ_FOR_UPDATE, lockd_state, &error_flags, NULL);
if (!vg) {

View File

@ -1,37 +0,0 @@
conf/example.conf.in | 7 ++++---
lib/config/config_settings.h | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/conf/example.conf.in b/conf/example.conf.in
index a5eba01..8fa126b 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -118,11 +118,12 @@ devices {
# Prefer the name with the least number of slashes.
# Prefer a name that is a symlink.
# Prefer the path with least value in lexicographical order.
- #
- # Example
+ #
+ # Example:
# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
#
- # This configuration option does not have a default value defined.
+ # This configuration option has an automatic default value.
+ # preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
# Configuration option devices/filter.
# Limit the block devices that are used by LVM commands.
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index efa86e7..b3b6c77 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -269,7 +269,7 @@ cfg(devices_hints_CFG, "hints", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_
" Use no hints.\n"
"#\n")
-cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED , CFG_TYPE_STRING, NULL, vsn(1, 2, 19), NULL, 0, NULL,
+cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#S^/dev/mpath/#S^/dev/mapper/mpath#S^/dev/[hs]d", vsn(1, 2, 19), NULL, 0, NULL,
"Select which path name to display for a block device.\n"
"If multiple path names exist for a block device, and LVM needs to\n"
"display a name for the device, the path names are matched against\n"

167
lvm2.spec
View File

@ -1,8 +1,6 @@
%global device_mapper_version 1.02.175
%global device_mapper_version 1.02.185
%global enable_cache 1
%global enable_cluster 1
%global enable_cmirror 1
%global enable_lvmdbusd 1
%global enable_lvmlockd 1
%global enable_lvmpolld 1
@ -14,7 +12,7 @@
%global enable_integrity 1
%global system_release_version 23
%global systemd_version 189-3
%global systemd_version 247-1
%global dracut_version 002-18
%global util_linux_version 2.24
%global bash_version 4.0
@ -30,8 +28,6 @@
%if 0%{?rhel} && 0%{?rhel} <= 8
%ifnarch i686 x86_64 ppc64le s390x
%global enable_cluster 0
%global enable_cmirror 0
%global enable_lockd_dlm 0
%endif
@ -48,44 +44,18 @@ Name: lvm2
%if 0%{?rhel}
Epoch: %{rhel}
%endif
Version: 2.03.11
Release: 9%{?dist}
Version: 2.03.16
Release: 1%{?dist}
License: GPLv2
URL: https://sourceware.org/lvm2/
Source0: https://sourceware.org/pub/lvm2/releases/LVM2.%{version}.tgz
Patch0: lvm2-set-default-preferred_names.patch
Patch3: lvm2-2_03_12-lvmlockd-sscanf-buffer-size-warnings.patch
# BZ 1915497:
Patch4: lvm2-2_03_12-alloc-enhance-estimation-of-sufficient_pes_free.patch
Patch5: lvm2-2_03_12-tests-check-thin-pool-corner-case-allocs.patch
Patch6: lvm2-2_03_12-tests-check-full-zeroing-of-thin-pool-metadata.patch
# BZ 1915580:
Patch7: lvm2-2_03_12-integrity-fix-segfault-on-error-path-when-replacing-.patch
# BZ 1872695:
Patch8: lvm2-2_03_12-devs-remove-invalid-path-name-aliases.patch
Patch9: lvm2-2_03_12-make-generate.patch
Patch10: lvm2-2_03_12-label_scan-fix-missing-free-of-filtered_devs.patch
# BZ 1917920:
Patch11: lvm2-2_03_12-pvck-fix-warning-and-exit-code-for-non-4k-mda1-offse.patch
Patch12: lvm2-2_03_12-WHATS_NEW-update.patch
# BZ 1921214:
Patch13: lvm2-2_03_12-writecache-use-cleaner-message-instead-of-table-relo.patch
# BZ 1909699:
Patch14: lvm2-2_03_12-man-update-lvmthin.patch
Patch15: lvm2-2_03_12-thin-improve-16g-support-for-thin-pool-metadata.patch
Patch16: lvm2-2_03_12-pool-limit-pmspare-to-16GiB.patch
Patch17: lvm2-2_03_12-cache-reuse-code-for-metadata-min_max.patch
Patch18: lvm2-2_03_12-tests-check-16G-thin-pool-metadata-size.patch
Patch19: lvm2-2_03_12-tests-update-thin-and-cache-checked-messages.patch
# BZ 1914389:
Patch20: lvm2-2_03_12-lvcreate-use-lv_passes_readonly_filter.patch
Patch21: lvm2-2_03_12-test-check-read_only_volume_list-tagging-works.patch
# BZ 1859659:
Patch22: lvm2-2_03_12-filter-mpath-work-with-nvme-devices.patch
# BZ 1925871:
Patch23: lvm2-2_03_12-dev_get_primary_dev-fix-invalid-path-check.patch
# Fix editline compilation:
Patch24: lvm2-2_03_12-lvm-Fix-editline-compilation.patch
Patch1: 0001-devices-file-move-clean-up-after-command-is-run.patch
Patch2: 0002-devices-file-fail-if-devicesfile-filename-doesn-t-ex.patch
Patch3: 0003-filter-mpath-handle-other-wwid-types-in-blacklist.patch
Patch4: 0004-filter-mpath-get-wwids-from-sysfs-vpd_pg83.patch
Patch5: 0005-pvdisplay-restore-reportformat-option.patch
Patch6: 0006-exit-with-error-when-devicesfile-name-doesn-t-exist.patch
Patch7: 0007-make-generate.patch
BuildRequires: make
BuildRequires: gcc
@ -97,10 +67,7 @@ BuildRequires: libblkid-devel >= %{util_linux_version}
BuildRequires: ncurses-devel
BuildRequires: libedit-devel
BuildRequires: libaio-devel
%if %{enable_cluster}
BuildRequires: corosynclib-devel >= %{corosync_version}
%endif
%if %{enable_cluster} || %{enable_lockd_dlm}
%if %{enable_lockd_dlm}
BuildRequires: dlm-devel >= %{dlm_version}
%endif
BuildRequires: module-init-tools
@ -142,29 +109,13 @@ or more physical volumes and creating one or more logical volumes
%prep
%setup -q -n LVM2.%{version}
%patch0 -p1 -b .backup0
%patch1 -p1 -b .backup1
%patch2 -p1 -b .backup2
%patch3 -p1 -b .backup3
%patch4 -p1 -b .backup4
%patch5 -p1 -b .backup5
%patch6 -p1 -b .backup6
%patch7 -p1 -b .backup7
%patch8 -p1 -b .backup8
%patch9 -p1 -b .backup9
%patch10 -p1 -b .backup10
%patch11 -p1 -b .backup11
%patch12 -p1 -b .backup12
%patch13 -p1 -b .backup13
%patch14 -p1 -b .backup14
%patch15 -p1 -b .backup15
%patch16 -p1 -b .backup16
%patch17 -p1 -b .backup17
%patch18 -p1 -b .backup18
%patch19 -p1 -b .backup19
%patch20 -p1 -b .backup20
%patch21 -p1 -b .backup21
%patch22 -p1 -b .backup22
%patch23 -p1 -b .backup23
%patch24 -p1 -b .backup24
%build
%global _default_pid_dir /run
@ -191,16 +142,6 @@ or more physical volumes and creating one or more logical volumes
--enable-cmdlib \
--enable-dmeventd \
--enable-blkid_wiping \
--disable-readline \
--enable-editline \
%if %{enable_cluster}
--with-cluster=internal \
%if %{enable_cmirror}
--enable-cmirrord \
%endif
%else
--with-cluster=internal \
%endif
--with-udevdir=%{_udevdir} --enable-udev_sync \
%if %{enable_thin}
--with-thin=internal \
@ -232,7 +173,11 @@ or more physical volumes and creating one or more logical volumes
%if %{enable_integrity}
--with-integrity=internal \
%endif
--disable-silent-rules
--with-default-use-devices-file=1 \
--disable-silent-rules \
--enable-app-machineid \
--enable-editline \
--disable-readline
%make_build
@ -293,10 +238,12 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || :
%{_sbindir}/fsadm
%{_sbindir}/lvm
%{_sbindir}/lvmconfig
%{_sbindir}/lvmdevices
%{_sbindir}/lvmdump
%if %{enable_lvmpolld}
%{_sbindir}/lvmpolld
%endif
%{_sbindir}/lvm_import_vdo
# Other files
%{_sbindir}/lvchange
@ -333,6 +280,7 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || :
%{_sbindir}/vgextend
%{_sbindir}/vgimport
%{_sbindir}/vgimportclone
%{_sbindir}/vgimportdevices
%{_sbindir}/vgmerge
%{_sbindir}/vgmknodes
%{_sbindir}/vgreduce
@ -342,6 +290,7 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || :
%{_sbindir}/vgscan
%{_sbindir}/vgsplit
%{_mandir}/man5/lvm.conf.5.gz
%{_mandir}/man7/lvmautoactivation.7.gz
%{_mandir}/man7/lvmcache.7.gz
%{_mandir}/man7/lvmraid.7.gz
%{_mandir}/man7/lvmreport.7.gz
@ -355,9 +304,9 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || :
%{_mandir}/man8/lvdisplay.8.gz
%{_mandir}/man8/lvextend.8.gz
%{_mandir}/man8/lvm.8.gz
%{_mandir}/man8/lvm2-activation-generator.8.gz
%{_mandir}/man8/lvm-config.8.gz
%{_mandir}/man8/lvmconfig.8.gz
%{_mandir}/man8/lvmdevices.8.gz
%{_mandir}/man8/lvm-dumpconfig.8.gz
%{_mandir}/man8/lvmdiskscan.8.gz
%{_mandir}/man8/lvmdump.8.gz
@ -379,6 +328,7 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || :
%{_mandir}/man8/pvresize.8.gz
%{_mandir}/man8/pvs.8.gz
%{_mandir}/man8/pvscan.8.gz
%{_mandir}/man8/lvm_import_vdo.8.gz
%{_mandir}/man8/vgcfgbackup.8.gz
%{_mandir}/man8/vgcfgrestore.8.gz
%{_mandir}/man8/vgchange.8.gz
@ -390,6 +340,7 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || :
%{_mandir}/man8/vgextend.8.gz
%{_mandir}/man8/vgimport.8.gz
%{_mandir}/man8/vgimportclone.8.gz
%{_mandir}/man8/vgimportdevices.8.gz
%{_mandir}/man8/vgmerge.8.gz
%{_mandir}/man8/vgmknodes.8.gz
%{_mandir}/man8/vgreduce.8.gz
@ -399,7 +350,7 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || :
%{_mandir}/man8/vgscan.8.gz
%{_mandir}/man8/vgsplit.8.gz
%{_udevdir}/11-dm-lvm.rules
%{_udevdir}/69-dm-lvm-metad.rules
%{_udevdir}/69-dm-lvm.rules
%if %{enable_lvmpolld}
%{_mandir}/man8/lvmpolld.8.gz
%{_mandir}/man8/lvm-lvpoll.8.gz
@ -427,8 +378,7 @@ systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || :
%{_tmpfilesdir}/%{name}.conf
%{_unitdir}/blk-availability.service
%{_unitdir}/lvm2-monitor.service
%{_unitdir}/lvm2-pvscan@.service
%{_prefix}/lib/systemd/system-generators/lvm2-activation-generator
#%%{_unitdir}/lvm-vgchange@.service # vgchange is now part of udev rule
%if %{enable_lvmpolld}
%{_unitdir}/lvm2-lvmpolld.socket
%{_unitdir}/lvm2-lvmpolld.service
@ -524,55 +474,6 @@ LVM commands use lvmlockd to coordinate access to shared storage.
%endif
###############################################################################
# Cluster mirror subpackage
# The 'clvm' OCF script to manage cmirrord instance is part of resource-agents.
###############################################################################
%if %{enable_cluster}
%if %{enable_cmirror}
%package -n cmirror
Summary: Daemon for device-mapper-based clustered mirrors
Requires: corosync >= %{corosync_version}
Requires: device-mapper = %{?epoch}:%{device_mapper_version}-%{release}
Requires: resource-agents >= %{resource_agents_version}
%description -n cmirror
Daemon providing device-mapper-based mirrors in a shared-storage cluster.
%files -n cmirror
%{_sbindir}/cmirrord
%{_mandir}/man8/cmirrord.8.gz
##############################################################################
# Cmirror-standalone subpackage
##############################################################################
%package -n cmirror-standalone
Summary: Additional files to support device-mapper-based clustered mirrors in standalone mode
License: GPLv2
Requires: cmirror >= %{?epoch}:%{version}-%{release}
%description -n cmirror-standalone
Additional files needed to run daemon for device-mapper-based clustered
mirrors in standalone mode as a service without cluster resource manager
involvement (e.g. pacemaker).
%post -n cmirror-standalone
%systemd_post lvm2-cmirrord.service
%preun -n cmirror-standalone
%systemd_preun lvm2-cmirrord.service
%postun -n cmirror-standalone
%systemd_postun lvm2-cmirrord.service
%files -n cmirror-standalone
%{_unitdir}/lvm2-cmirrord.service
%endif
%endif
##############################################################################
# LVM D-Bus daemon
##############################################################################
@ -766,6 +667,18 @@ An extensive functional testsuite for LVM2.
%endif
%changelog
* Mon Sep 26 2022 Marian Csontos <mcsontos@redhat.com> - 2.03.16-1
- Update to upstream version 2.03.16.
- Devices file feature - see lvmdevices(8).
- Changes in udev support:
- obtain_device_list_from_udev defaults to 0.
- see devices/external_device_info_source,
devices/obtain_device_list_from_udev, and devices/multipath_wwids_file help
in lvm.conf
- Remove service based autoactivation. global/event_activation = 0 is NOOP.
- see lvmautoactivation(7).
- Many fixes and improvements, see WHATS_NEW and WHATS_NEW_DM for more.
* Thu Jul 21 2022 Fedora Release Engineering <releng@fedoraproject.org> - 2.03.11-9
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild