Accepting request 725505 from home:ganghe:branches:openSUSE:Factory

Fix the bug 1145231

OBS-URL: https://build.opensuse.org/request/show/725505
OBS-URL: https://build.opensuse.org/package/show/Base:System/lvm2?expand=0&rev=246
This commit is contained in:
Gang He 2019-08-23 08:35:57 +00:00 committed by Git OBS Bridge
parent 600377c40b
commit 554da53f00
12 changed files with 1004 additions and 12 deletions

View File

@ -0,0 +1,220 @@
From c527a0cbfc391645d30407d2dc4a30275c6472f1 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Mon, 27 Aug 2018 11:15:35 -0500
Subject: [PATCH] lvmetad: improve scan for pvscan all
For 'pvscan --cache' avoid using dev_iter in the loop
after the label_scan by passing the necessary devs back
from the label_scan for the continued pvscan.
The dev_iter functions reapply the filters which will
trigger more io when we don't need or want it. With
many devs, incidental opens from the filters (not controlled
by the label scan) can lead to too many open files.
---
lib/cache/lvmetad.c | 34 ++++++++++++-------------
lib/label/label.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/label/label.h | 1 +
3 files changed, 91 insertions(+), 17 deletions(-)
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index a1ab41aab..acbb52e54 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -2322,8 +2322,8 @@ bad:
int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
{
- struct dev_iter *iter;
- struct device *dev;
+ struct device_list *devl, *devl2;
+ struct dm_list scan_devs;
daemon_reply reply;
char *future_token;
const char *reason;
@@ -2339,6 +2339,8 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
}
retry:
+ dm_list_init(&scan_devs);
+
/*
* If another update is in progress, delay to allow it to finish,
* rather than interrupting it with our own update.
@@ -2348,7 +2350,7 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
replacing_other_update = 1;
}
- label_scan(cmd);
+ label_scan_pvscan_all(cmd, &scan_devs);
lvmcache_pvscan_duplicate_check(cmd);
@@ -2357,19 +2359,14 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
return 0;
}
- log_verbose("Scanning all devices to update lvmetad.");
-
- if (!(iter = dev_iter_create(cmd->lvmetad_filter, 1))) {
- log_error("dev_iter creation failed");
- return 0;
- }
+ log_verbose("Scanning metadata from %d devices to update lvmetad.",
+ dm_list_size(&scan_devs));
future_token = _lvmetad_token;
_lvmetad_token = (char *) LVMETAD_TOKEN_UPDATE_IN_PROGRESS;
if (!_token_update(&replaced_update)) {
log_error("Failed to update lvmetad which had an update in progress.");
- dev_iter_destroy(iter);
_lvmetad_token = future_token;
return 0;
}
@@ -2385,12 +2382,10 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
if (do_wait && !retries) {
retries = 1;
log_warn("WARNING: lvmetad update in progress, retrying update.");
- dev_iter_destroy(iter);
_lvmetad_token = future_token;
goto retry;
}
log_warn("WARNING: lvmetad update in progress, skipping update.");
- dev_iter_destroy(iter);
_lvmetad_token = future_token;
return 0;
}
@@ -2404,15 +2399,22 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
was_silent = silent_mode();
init_silent(1);
- while ((dev = dev_iter_get(iter))) {
+ dm_list_iterate_items_safe(devl, devl2, &scan_devs) {
if (sigint_caught()) {
ret = 0;
stack;
break;
}
- if (!lvmetad_pvscan_single(cmd, dev, NULL, NULL)) {
- ret = 0;
+ dm_list_del(&devl->list);
+
+ ret = lvmetad_pvscan_single(cmd, devl->dev, NULL, NULL);
+
+ label_scan_invalidate(devl->dev);
+
+ dm_free(devl);
+
+ if (!ret) {
stack;
break;
}
@@ -2420,8 +2422,6 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
init_silent(was_silent);
- dev_iter_destroy(iter);
-
_lvmetad_token = future_token;
/*
diff --git a/lib/label/label.c b/lib/label/label.c
index bafa54366..837033c4b 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -876,6 +876,79 @@ int label_scan(struct cmd_context *cmd)
return 1;
}
+int label_scan_pvscan_all(struct cmd_context *cmd, struct dm_list *scan_devs)
+{
+ struct dm_list all_devs;
+ struct dev_iter *iter;
+ struct device_list *devl, *devl2;
+ struct device *dev;
+
+ log_debug_devs("Finding devices to scan");
+
+ dm_list_init(&all_devs);
+
+ /*
+ * Iterate through all the devices in dev-cache (block devs that appear
+ * under /dev that could possibly hold a PV and are not excluded by
+ * filters). Read each to see if it's an lvm device, and if so
+ * populate lvmcache with some basic info about the device and the VG
+ * on it. This info will be used by the vg_read() phase of the
+ * command.
+ */
+ dev_cache_scan();
+
+ if (!(iter = dev_iter_create(cmd->lvmetad_filter, 0))) {
+ log_error("Scanning failed to get devices.");
+ return 0;
+ }
+
+ while ((dev = dev_iter_get(iter))) {
+ if (!(devl = dm_zalloc(sizeof(*devl))))
+ return 0;
+ devl->dev = dev;
+ dm_list_add(&all_devs, &devl->list);
+
+ /*
+ * label_scan should not generally be called a second time,
+ * so this will usually not be true.
+ */
+ if (_in_bcache(dev)) {
+ bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
+ _scan_dev_close(dev);
+ }
+ };
+ dev_iter_destroy(iter);
+
+ log_debug_devs("Found %d devices to scan", dm_list_size(&all_devs));
+
+ if (!scan_bcache) {
+ if (!_setup_bcache(dm_list_size(&all_devs)))
+ return 0;
+ }
+
+ _scan_list(cmd, cmd->lvmetad_filter, &all_devs, NULL);
+
+ dm_list_iterate_items_safe(devl, devl2, &all_devs) {
+ dm_list_del(&devl->list);
+
+ /*
+ * If this device is lvm's then, return it to pvscan
+ * to do the further pvscan. (We could have _scan_list
+ * just set a result in devl indicating the result, but
+ * instead we're just checking indirectly if _scan_list
+ * saved lvmcache info for the dev which also means it's
+ * an lvm device.)
+ */
+
+ if (lvmcache_has_dev_info(devl->dev))
+ dm_list_add(scan_devs, &devl->list);
+ else
+ dm_free(devl);
+ }
+
+ return 1;
+}
+
/*
* Scan and cache lvm data from the listed devices. If a device is already
* scanned and cached, this replaces the previously cached lvm data for the
diff --git a/lib/label/label.h b/lib/label/label.h
index 5ed8bc86b..5b83bc734 100644
--- a/lib/label/label.h
+++ b/lib/label/label.h
@@ -116,6 +116,7 @@ void label_scan_confirm(struct device *dev);
int label_scan_setup_bcache(void);
int label_scan_open(struct device *dev);
int label_scan_open_excl(struct device *dev);
+int label_scan_pvscan_all(struct cmd_context *cmd, struct dm_list *scan_devs);
/*
* Wrappers around bcache equivalents.
--
2.12.3

View File

@ -0,0 +1,65 @@
From a01e1fec0fe7c2fa61577c0e636e907cde7279ea Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Thu, 29 Nov 2018 14:06:20 -0600
Subject: [PATCH] pvscan lvmetad: use full md filter when md 1.0 devices are
present
Apply the same logic to pvscan/lvmetad that was added to
the non-lvmetad label_scan in commit 3fd75d1b:
scan: use full md filter when md 1.0 devices are present
Before scanning, check if any of the devs on the system are
md 0.90/1.0, and if so make the scan read both the start and
the end of the device so that the components of those md
versions can be ignored.
---
tools/pvscan.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 2915db599..3755684d2 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -18,6 +18,8 @@
#include "lvmetad.h"
#include "lvmcache.h"
+extern int use_full_md_check;
+
struct pvscan_params {
int new_pvs_found;
int pvs_found;
@@ -302,6 +304,7 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
struct dm_list found_vgnames;
struct device *dev;
struct device_list *devl;
+ struct dev_iter *iter;
const char *pv_name;
const char *reason = NULL;
int32_t major = -1;
@@ -443,6 +446,22 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
/* Creates a list of dev names from /dev, sysfs, etc; does not read any. */
dev_cache_scan();
+ /* See the same check in label_scan() to handle md 0.9/1.0 components. */
+ if (!(iter = dev_iter_create(cmd->full_filter, 0))) {
+ log_error("Scanning failed to get devices.");
+ return 0;
+ }
+ while ((dev = dev_iter_get(iter))) {
+ if (dev_is_md_with_end_superblock(cmd->dev_types, dev)) {
+ cmd->use_full_md_check = 1;
+ use_full_md_check = 1;
+ log_debug("Found md with end superblock %s", dev_name(dev));
+ }
+ }
+ dev_iter_destroy(iter);
+ if (!use_full_md_check)
+ log_debug("No md devs with end superblock");
+
dm_list_init(&single_devs);
while (argc--) {
--
2.12.3

View File

@ -0,0 +1,215 @@
From a188b1e513ed5ca0f5f3702c823490f5610d4495 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Fri, 30 Nov 2018 16:32:32 -0600
Subject: [PATCH] pvscan lvmetad: use udev info to improve md component
detection
When no md devs are started, pvscan will only scan the start of
an md component, and if it has a superblock at the end may not
exclude it. udev may already have info identifying it as an
md component, so use that.
---
lib/device/dev-md.c | 14 ++++++++++--
lib/device/dev-type.c | 62 +++++++++++++++++++++++++++++++++++++++++----------
lib/device/dev-type.h | 1 +
lib/label/label.c | 6 +++++
tools/pvscan.c | 3 ++-
5 files changed, 71 insertions(+), 15 deletions(-)
diff --git a/lib/device/dev-md.c b/lib/device/dev-md.c
index 185499baf..972850726 100644
--- a/lib/device/dev-md.c
+++ b/lib/device/dev-md.c
@@ -190,14 +190,24 @@ out:
int dev_is_md(struct device *dev, uint64_t *offset_found, int full)
{
+ int ret;
/*
* If non-native device status source is selected, use it
* only if offset_found is not requested as this
* information is not in udev db.
*/
- if ((dev->ext.src == DEV_EXT_NONE) || offset_found)
- return _native_dev_is_md(dev, offset_found, full);
+ if ((dev->ext.src == DEV_EXT_NONE) || offset_found) {
+ ret = _native_dev_is_md(dev, offset_found, full);
+
+ if (!full) {
+ if (!ret || (ret == -EAGAIN)) {
+ if (udev_dev_is_md_component(dev))
+ return 1;
+ }
+ }
+ return ret;
+ }
if (dev->ext.src == DEV_EXT_UDEV)
return _udev_dev_is_md(dev);
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index af4b40760..33ebb73b2 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -1004,25 +1004,23 @@ int dev_is_rotational(struct dev_types *dt, struct device *dev)
* failed already due to timeout in udev - in both cases the
* udev_device_get_is_initialized returns 0.
*/
-#define UDEV_DEV_IS_MPATH_COMPONENT_ITERATION_COUNT 100
-#define UDEV_DEV_IS_MPATH_COMPONENT_USLEEP 100000
+#define UDEV_DEV_IS_COMPONENT_ITERATION_COUNT 100
+#define UDEV_DEV_IS_COMPONENT_USLEEP 100000
-int udev_dev_is_mpath_component(struct device *dev)
+static struct udev_device *_udev_get_dev(struct device *dev)
{
struct udev *udev_context = udev_get_library_context();
struct udev_device *udev_device = NULL;
- const char *value;
int initialized = 0;
unsigned i = 0;
- int ret = 0;
if (!udev_context) {
log_warn("WARNING: No udev context available to check if device %s is multipath component.", dev_name(dev));
- return 0;
+ return NULL;
}
while (1) {
- if (i >= UDEV_DEV_IS_MPATH_COMPONENT_ITERATION_COUNT)
+ if (i >= UDEV_DEV_IS_COMPONENT_ITERATION_COUNT)
break;
if (udev_device)
@@ -1030,7 +1028,7 @@ int udev_dev_is_mpath_component(struct device *dev)
if (!(udev_device = udev_device_new_from_devnum(udev_context, 'b', dev->dev))) {
log_warn("WARNING: Failed to get udev device handler for device %s.", dev_name(dev));
- return 0;
+ return NULL;
}
#ifdef HAVE_LIBUDEV_UDEV_DEVICE_GET_IS_INITIALIZED
@@ -1042,19 +1040,32 @@ int udev_dev_is_mpath_component(struct device *dev)
#endif
log_debug("Device %s not initialized in udev database (%u/%u, %u microseconds).", dev_name(dev),
- i + 1, UDEV_DEV_IS_MPATH_COMPONENT_ITERATION_COUNT,
- i * UDEV_DEV_IS_MPATH_COMPONENT_USLEEP);
+ i + 1, UDEV_DEV_IS_COMPONENT_ITERATION_COUNT,
+ i * UDEV_DEV_IS_COMPONENT_USLEEP);
- usleep(UDEV_DEV_IS_MPATH_COMPONENT_USLEEP);
+ usleep(UDEV_DEV_IS_COMPONENT_USLEEP);
i++;
}
if (!initialized) {
log_warn("WARNING: Device %s not initialized in udev database even after waiting %u microseconds.",
- dev_name(dev), i * UDEV_DEV_IS_MPATH_COMPONENT_USLEEP);
+ dev_name(dev), i * UDEV_DEV_IS_COMPONENT_USLEEP);
goto out;
}
+out:
+ return udev_device;
+}
+
+int udev_dev_is_mpath_component(struct device *dev)
+{
+ struct udev_device *udev_device;
+ const char *value;
+ int ret = 0;
+
+ if (!(udev_device = _udev_get_dev(dev)))
+ return 0;
+
value = udev_device_get_property_value(udev_device, DEV_EXT_UDEV_BLKID_TYPE);
if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_MPATH)) {
log_debug("Device %s is multipath component based on blkid variable in udev db (%s=\"%s\").",
@@ -1074,6 +1085,28 @@ out:
udev_device_unref(udev_device);
return ret;
}
+
+int udev_dev_is_md_component(struct device *dev)
+{
+ struct udev_device *udev_device;
+ const char *value;
+ int ret = 0;
+
+ if (!(udev_device = _udev_get_dev(dev)))
+ return 0;
+
+ value = udev_device_get_property_value(udev_device, DEV_EXT_UDEV_BLKID_TYPE);
+ if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID)) {
+ log_debug("Device %s is md raid component based on blkid variable in udev db (%s=\"%s\").",
+ dev_name(dev), DEV_EXT_UDEV_BLKID_TYPE, value);
+ ret = 1;
+ goto out;
+ }
+out:
+ udev_device_unref(udev_device);
+ return ret;
+}
+
#else
int udev_dev_is_mpath_component(struct device *dev)
@@ -1081,4 +1114,9 @@ int udev_dev_is_mpath_component(struct device *dev)
return 0;
}
+int udev_dev_is_md_component(struct device *dev)
+{
+ return 0;
+}
+
#endif
diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h
index f629a0278..264438339 100644
--- a/lib/device/dev-type.h
+++ b/lib/device/dev-type.h
@@ -62,6 +62,7 @@ int dev_is_swap(struct device *dev, uint64_t *signature, int full);
int dev_is_luks(struct device *dev, uint64_t *signature, int full);
int dasd_is_cdl_formatted(struct device *dev);
int udev_dev_is_mpath_component(struct device *dev);
+int udev_dev_is_md_component(struct device *dev);
int dev_is_lvm1(struct device *dev, char *buf, int buflen);
int dev_is_pool(struct device *dev, char *buf, int buflen);
diff --git a/lib/label/label.c b/lib/label/label.c
index b26ff3370..e01608d2c 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -957,6 +957,12 @@ int label_scan_pvscan_all(struct cmd_context *cmd, struct dm_list *scan_devs)
bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
_scan_dev_close(dev);
}
+
+ if (dev_is_md_with_end_superblock(cmd->dev_types, dev)) {
+ cmd->use_full_md_check = 1;
+ use_full_md_check = 1;
+ log_debug("Found md component in sysfs with end superblock %s", dev_name(dev));
+ }
};
dev_iter_destroy(iter);
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 3755684d2..877b6b2db 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -455,7 +455,8 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
if (dev_is_md_with_end_superblock(cmd->dev_types, dev)) {
cmd->use_full_md_check = 1;
use_full_md_check = 1;
- log_debug("Found md with end superblock %s", dev_name(dev));
+ log_debug("Found md component in sysfs with end superblock %s", dev_name(dev));
+ break;
}
}
dev_iter_destroy(iter);
--
2.12.3

View File

@ -0,0 +1,136 @@
From e7bb50880901a4462e350ce0d272a63aa8440781 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Thu, 18 Oct 2018 11:32:32 -0500
Subject: [PATCH] scan: enable full md filter when md 1.0 devices are present
The previous commit de2863739f2ea17d89d0e442379109f967b5919d
scan: use full md filter when md 1.0 devices are present
needs the use_full_md_check flag in the md filter, but
the cmd struct is not available when the filter is run,
so that commit wasn't working. Fix this by setting the
flag in a global variable.
(This was fixed in the master branch with commit 8eab37593
in which the cmd struct was passed to the filters, but it
was an intrusive change, so this commit is using the less
intrusive global variable.)
---
lib/filters/filter-md.c | 33 +++++++--------------------------
lib/label/label.c | 13 ++++++++++++-
2 files changed, 19 insertions(+), 27 deletions(-)
diff --git a/lib/filters/filter-md.c b/lib/filters/filter-md.c
index ad5b8e4e8..e03ff5059 100644
--- a/lib/filters/filter-md.c
+++ b/lib/filters/filter-md.c
@@ -16,6 +16,9 @@
#include "lib.h"
#include "filter.h"
+/* See label.c comment about this hack. */
+extern int use_full_md_check;
+
#ifdef __linux__
#define MSG_SKIPPING "%s: Skipping md component device"
@@ -80,7 +83,7 @@
* that will not pass.
*/
-static int _passes_md_filter(struct device *dev, int full)
+static int _passes_md_filter(struct dev_filter *f, struct device *dev)
{
int ret;
@@ -91,7 +94,7 @@ static int _passes_md_filter(struct device *dev, int full)
if (!md_filtering())
return 1;
- ret = dev_is_md(dev, NULL, full);
+ ret = dev_is_md(dev, NULL, use_full_md_check);
if (ret == -EAGAIN) {
/* let pass, call again after scan */
@@ -104,6 +107,7 @@ static int _passes_md_filter(struct device *dev, int full)
return 1;
if (ret == 1) {
+ log_debug_devs("md filter full %d excluding md component %s", use_full_md_check, dev_name(dev));
if (dev->ext.src == DEV_EXT_NONE)
log_debug_devs(MSG_SKIPPING, dev_name(dev));
else
@@ -121,18 +125,6 @@ static int _passes_md_filter(struct device *dev, int full)
return 1;
}
-static int _passes_md_filter_lite(struct dev_filter *f __attribute__((unused)),
- struct device *dev)
-{
- return _passes_md_filter(dev, 0);
-}
-
-static int _passes_md_filter_full(struct dev_filter *f __attribute__((unused)),
- struct device *dev)
-{
- return _passes_md_filter(dev, 1);
-}
-
static void _destroy(struct dev_filter *f)
{
if (f->use_count)
@@ -150,18 +142,7 @@ struct dev_filter *md_filter_create(struct cmd_context *cmd, struct dev_types *d
return NULL;
}
- /*
- * FIXME: for commands that want a full md check (pvcreate, vgcreate,
- * vgextend), we do an extra read at the end of every device that the
- * filter looks at. This isn't necessary; we only need to do the full
- * md check on the PVs that these commands are trying to use.
- */
-
- if (cmd->use_full_md_check)
- f->passes_filter = _passes_md_filter_full;
- else
- f->passes_filter = _passes_md_filter_lite;
-
+ f->passes_filter = _passes_md_filter;
f->destroy = _destroy;
f->use_count = 0;
f->private = dt;
diff --git a/lib/label/label.c b/lib/label/label.c
index e76ddd4b2..e5aa2c129 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -27,6 +27,7 @@
#include <unistd.h>
#include <sys/time.h>
+int use_full_md_check;
/* FIXME Allow for larger labels? Restricted to single sector currently */
@@ -868,8 +869,18 @@ int label_scan(struct cmd_context *cmd)
* devs in 'pvs', which is a pretty harmless effect from a
* pretty uncommon situation.
*/
- if (dev_is_md_with_end_superblock(cmd->dev_types, dev))
+ if (dev_is_md_with_end_superblock(cmd->dev_types, dev)) {
cmd->use_full_md_check = 1;
+
+ /* This is a hack because 'cmd' is not passed
+ into the filters so we can't check the flag
+ in the cmd struct. The master branch has
+ changed the filters in commit 8eab37593eccb
+ to accept cmd, but it's a complex change
+ that I'm trying to avoid in the stable branch. */
+
+ use_full_md_check = 1;
+ }
};
dev_iter_destroy(iter);
--
2.12.3

View File

@ -0,0 +1,59 @@
From 0e42ebd6d4012d210084a9ccf8d76f853726de3c Mon Sep 17 00:00:00 2001
From: Peter Rajnoha <prajnoha@redhat.com>
Date: Thu, 29 Nov 2018 11:51:05 -0600
Subject: [PATCH] scan: md metadata version 0.90 is at the end of disk
commit de28637
scan: use full md filter when md 1.0 devices are present
missed the fact that md superblock version 0.90 also puts
metadata at the end of the device, so the full md filter
needs to be used when either 0.90 or 1.0 is present.
---
lib/device/dev-md.c | 2 +-
lib/filters/filter-md.c | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/lib/device/dev-md.c b/lib/device/dev-md.c
index 7196dc007..185499baf 100644
--- a/lib/device/dev-md.c
+++ b/lib/device/dev-md.c
@@ -422,7 +422,7 @@ int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev)
log_very_verbose("Device %s %s is %s.",
dev_name(dev), attribute, version_string);
- if (!strcmp(version_string, "1.0"))
+ if (!strcmp(version_string, "1.0") || !strcmp(version_string, "0.90"))
return 1;
return 0;
}
diff --git a/lib/filters/filter-md.c b/lib/filters/filter-md.c
index e03ff5059..2011e1d5a 100644
--- a/lib/filters/filter-md.c
+++ b/lib/filters/filter-md.c
@@ -47,7 +47,7 @@ extern int use_full_md_check;
* 3. use udev to detect components
*
* mode 1 will not detect and exclude components of md devices
- * that use superblock version 1.0 which is at the end of the device.
+ * that use superblock version 0.9 or 1.0 which is at the end of the device.
*
* mode 2 will detect these, but mode 2 doubles the i/o done by label
* scan, since there's a read at both the start and end of every device.
@@ -60,11 +60,11 @@ extern int use_full_md_check;
*
* - the command is pvcreate/vgcreate/vgextend, which format new
* devices, and if the user ran these commands on a component
- * device of an md device 1.0, then it would cause problems.
+ * device of an md device 0.9 or 1.0, then it would cause problems.
* FIXME: this would only really need to scan the end of the
* devices being formatted, not all devices.
*
- * - it sees an md device on the system using version 1.0.
+ * - it sees an md device on the system using version 0.9 or 1.0.
* The point of this is just to avoid displaying md components
* from the 'pvs' command.
* FIXME: the cost (double i/o) may not be worth the benefit
--
2.12.3

View File

@ -0,0 +1,228 @@
From de2863739f2ea17d89d0e442379109f967b5919d Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Fri, 15 Jun 2018 11:42:10 -0500
Subject: [PATCH] scan: use full md filter when md 1.0 devices are present
The md filter can operate in two native modes:
- normal: reads only the start of each device
- full: reads both the start and end of each device
md 1.0 devices place the superblock at the end of the device,
so components of this version will only be identified and
excluded when lvm uses the full md filter.
Previously, the full md filter was only used in commands
that could write to the device. Now, the full md filter
is also applied when there is an md 1.0 device present
on the system. This means the 'pvs' command can avoid
displaying md 1.0 components (at the cost of doubling
the i/o to every device on the system.)
(The md filter can operate in a third mode, using udev,
but this is disabled by default because there have been
problems with reliability of the info returned from udev.)
---
lib/cache/lvmcache.c | 2 +-
lib/device/dev-md.c | 27 ++++++++++----
lib/device/dev-type.h | 1 +
lib/filters/filter-md.c | 74 +++++++++++++++++++-------------------
lib/label/label.c | 14 ++++++++
test/shell/pvcreate-md-fake-hdr.sh | 3 +-
6 files changed, 75 insertions(+), 46 deletions(-)
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 3e681a2ba..a2ee0cd43 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -998,7 +998,7 @@ int lvmcache_dev_is_unchosen_duplicate(struct device *dev)
* unused_duplicate_devs list, and restrict what we allow done with it.
*
* In the case of md components, we usually filter these out in filter-md,
- * but in the special case of md superblocks <= 1.0 where the superblock
+ * but in the special case of md superblock version 1.0 where the superblock
* is at the end of the device, filter-md doesn't always eliminate them
* first, so we eliminate them here.
*
diff --git a/lib/device/dev-md.c b/lib/device/dev-md.c
index f5a736fc2..7196dc007 100644
--- a/lib/device/dev-md.c
+++ b/lib/device/dev-md.c
@@ -142,13 +142,6 @@ static int _native_dev_is_md(struct device *dev, uint64_t *offset_found, int ful
* command if it should do a full check (cmd->use_full_md_check),
* and set it for commands that could possibly write to an md dev
* (pvcreate/vgcreate/vgextend).
- *
- * For old md versions with magic numbers at the end of devices,
- * the md dev components won't be filtered out here when full is 0,
- * so they will be scanned, and appear as duplicate PVs in lvmcache.
- * The md device itself will be chosen as the primary duplicate,
- * and the components are dropped from the list of duplicates in,
- * i.e. a kind of post-scan filtering.
*/
if (!full) {
sb_offset = 0;
@@ -414,6 +407,26 @@ unsigned long dev_md_stripe_width(struct dev_types *dt, struct device *dev)
return stripe_width_sectors;
}
+int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev)
+{
+ char version_string[MD_MAX_SYSFS_SIZE];
+ const char *attribute = "metadata_version";
+
+ if (MAJOR(dev->dev) != dt->md_major)
+ return 0;
+
+ if (_md_sysfs_attribute_scanf(dt, dev, attribute,
+ "%s", &version_string) != 1)
+ return -1;
+
+ log_very_verbose("Device %s %s is %s.",
+ dev_name(dev), attribute, version_string);
+
+ if (!strcmp(version_string, "1.0"))
+ return 1;
+ return 0;
+}
+
#else
int dev_is_md(struct device *dev __attribute__((unused)),
diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h
index 843e2545b..f629a0278 100644
--- a/lib/device/dev-type.h
+++ b/lib/device/dev-type.h
@@ -76,6 +76,7 @@ int wipe_known_signatures(struct cmd_context *cmd, struct device *dev, const cha
/* Type-specific device properties */
unsigned long dev_md_stripe_width(struct dev_types *dt, struct device *dev);
+int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev);
/* Partitioning */
int major_max_partitions(struct dev_types *dt, int major);
diff --git a/lib/filters/filter-md.c b/lib/filters/filter-md.c
index ab97b5946..ad5b8e4e8 100644
--- a/lib/filters/filter-md.c
+++ b/lib/filters/filter-md.c
@@ -29,43 +29,43 @@
*
* (This is assuming lvm.conf md_component_detection=1.)
*
- * If lvm does *not* ignore the components, then lvm will read lvm
- * labels from the md dev and from the component devs, and will see
- * them all as duplicates of each other. LVM duplicate resolution
- * will then kick in and keep the md dev around to use and ignore
- * the components.
- *
- * It is better to exclude the components as early as possible during
- * lvm processing, ideally before lvm even looks for labels on the
- * components, so that duplicate resolution can be avoided. There are
- * a number of ways that md components can be excluded earlier than
- * the duplicate resolution phase:
- *
- * - When external_device_info_source="udev", lvm discovers a device is
- * an md component by asking udev during the initial filtering phase.
- * However, lvm's default is to not use udev for this. The
- * alternative is "native" detection in which lvm tries to detect
- * md components itself.
- *
- * - When using native detection, lvm's md filter looks for the md
- * superblock at the start of devices. It will see the md superblock
- * on the components, exclude them in the md filter, and avoid
- * handling them later in duplicate resolution.
- *
- * - When using native detection, lvm's md filter will not detect
- * components when the md device has an older superblock version that
- * places the superblock at the end of the device. This case will
- * fall back to duplicate resolution to exclude components.
- *
- * A variation of the description above occurs for lvm commands that
- * intend to create new PVs on devices (pvcreate, vgcreate, vgextend).
- * For these commands, the native md filter also reads the end of all
- * devices to check for the odd md superblocks.
- *
- * (The reason that external_device_info_source is not set to udev by
- * default is that there have be issues with udev not being promptly
- * or reliably updated about md state changes, causing the udev info
- * that lvm uses to be occasionally wrong.)
+ * If lvm does *not* ignore the components, then lvm may read lvm
+ * labels from the component devs and potentially the md dev,
+ * which can trigger duplicate detection, and/or cause lvm to display
+ * md components as PVs rather than ignoring them.
+ *
+ * If scanning md componenents causes duplicates to be seen, then
+ * the lvm duplicate resolution will exclude the components.
+ *
+ * The lvm md filter has three modes:
+ *
+ * 1. look for md superblock at the start of the device
+ * 2. look for md superblock at the start and end of the device
+ * 3. use udev to detect components
+ *
+ * mode 1 will not detect and exclude components of md devices
+ * that use superblock version 1.0 which is at the end of the device.
+ *
+ * mode 2 will detect these, but mode 2 doubles the i/o done by label
+ * scan, since there's a read at both the start and end of every device.
+ *
+ * mode 3 is used when external_device_info_source="udev". It does
+ * not require any io from lvm, but this mode is not used by default
+ * because there have been problems getting reliable info from udev.
+ *
+ * lvm uses mode 2 when:
+ *
+ * - the command is pvcreate/vgcreate/vgextend, which format new
+ * devices, and if the user ran these commands on a component
+ * device of an md device 1.0, then it would cause problems.
+ * FIXME: this would only really need to scan the end of the
+ * devices being formatted, not all devices.
+ *
+ * - it sees an md device on the system using version 1.0.
+ * The point of this is just to avoid displaying md components
+ * from the 'pvs' command.
+ * FIXME: the cost (double i/o) may not be worth the benefit
+ * (not showing md components).
*/
/*
diff --git a/lib/label/label.c b/lib/label/label.c
index 837033c4b..e76ddd4b2 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -856,6 +856,20 @@ int label_scan(struct cmd_context *cmd)
bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
_scan_dev_close(dev);
}
+
+ /*
+ * When md devices exist that use the old superblock at the
+ * end of the device, then in order to detect and filter out
+ * the component devices of those md devs, we need to enable
+ * the full md filter which scans both the start and the end
+ * of every device. This doubles the amount of scanning i/o,
+ * which we want to avoid. FIXME: it may not be worth the
+ * cost of double i/o just to avoid displaying md component
+ * devs in 'pvs', which is a pretty harmless effect from a
+ * pretty uncommon situation.
+ */
+ if (dev_is_md_with_end_superblock(cmd->dev_types, dev))
+ cmd->use_full_md_check = 1;
};
dev_iter_destroy(iter);
diff --git a/test/shell/pvcreate-md-fake-hdr.sh b/test/shell/pvcreate-md-fake-hdr.sh
index b89fe4377..4c9ac7cbc 100644
--- a/test/shell/pvcreate-md-fake-hdr.sh
+++ b/test/shell/pvcreate-md-fake-hdr.sh
@@ -89,6 +89,7 @@ sleep 1
# (when mdadm supports repair)
if mdadm --action=repair "$mddev" ; then
sleep 1
+ pvscan -vvvv
# should be showing correctly PV3 & PV4
- pvs
+ pvs -vvvv "$dev3" "$dev4"
fi
--
2.12.3

View File

@ -1,3 +1,14 @@
-------------------------------------------------------------------
Wed Aug 21 10:10:30 UTC 2019 - ghe@suse.com
- MD devices should be detected by LVM2 with metadata=1.0/0.9 (bsc#1145231)
+ bug-1145231_lvmetad-improve-scan-for-pvscan-all.patch
+ bug-1145231_scan-use-full-md-filter-when-md-1.0-devices-are-pres.patch
+ bug-1145231_scan-enable-full-md-filter-when-md-1.0-devices-are-p.patch
+ bug-1145231_scan-md-metadata-version-0.90-is-at-the-end-of-disk.patch
+ bug-1145231_pvscan-lvmetad-use-full-md-filter-when-md-1.0-device.patch
+ bug-1145231_pvscan-lvmetad-use-udev-info-to-improve-md-component.patch
-------------------------------------------------------------------
Tue Jul 9 10:00:05 UTC 2019 - ghe@suse.com

View File

@ -50,10 +50,16 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-build
%{?systemd_requires}
### COMMON-PATCH-BEGIN ###
# Upstream patches
Patch0001: bug-1114113_metadata-prevent-writing-beyond-metadata-area.patch
Patch0002: bug-1122666_devices-drop-open-error-message.patch
Patch0003: bug-1137296_pvremove-vgextend-fix-using-device-aliases-with-lvmetad.patch
Patch0004: bug-1135984_cache-support-no_discard_passdown.patch
Patch0001: bug-1145231_lvmetad-improve-scan-for-pvscan-all.patch
Patch0002: bug-1145231_scan-use-full-md-filter-when-md-1.0-devices-are-pres.patch
Patch0003: bug-1145231_scan-enable-full-md-filter-when-md-1.0-devices-are-p.patch
Patch0004: bug-1114113_metadata-prevent-writing-beyond-metadata-area.patch
Patch0005: bug-1145231_scan-md-metadata-version-0.90-is-at-the-end-of-disk.patch
Patch0006: bug-1145231_pvscan-lvmetad-use-full-md-filter-when-md-1.0-device.patch
Patch0007: bug-1145231_pvscan-lvmetad-use-udev-info-to-improve-md-component.patch
Patch0008: bug-1122666_devices-drop-open-error-message.patch
Patch0009: bug-1137296_pvremove-vgextend-fix-using-device-aliases-with-lvmetad.patch
Patch0010: bug-1135984_cache-support-no_discard_passdown.patch
# SUSE patches: 1000+ for LVM
# Never upstream
@ -78,6 +84,12 @@ Programs and man pages for configuring and using the device mapper.
%patch0002 -p1
%patch0003 -p1
%patch0004 -p1
%patch0005 -p1
%patch0006 -p1
%patch0007 -p1
%patch0008 -p1
%patch0009 -p1
%patch0010 -p1
%patch1001 -p1
%patch1002 -p1
%patch1003 -p1

View File

@ -1,3 +1,14 @@
-------------------------------------------------------------------
Wed Aug 21 10:10:30 UTC 2019 - ghe@suse.com
- MD devices should be detected by LVM2 with metadata=1.0/0.9 (bsc#1145231)
+ bug-1145231_lvmetad-improve-scan-for-pvscan-all.patch
+ bug-1145231_scan-use-full-md-filter-when-md-1.0-devices-are-pres.patch
+ bug-1145231_scan-enable-full-md-filter-when-md-1.0-devices-are-p.patch
+ bug-1145231_scan-md-metadata-version-0.90-is-at-the-end-of-disk.patch
+ bug-1145231_pvscan-lvmetad-use-full-md-filter-when-md-1.0-device.patch
+ bug-1145231_pvscan-lvmetad-use-udev-info-to-improve-md-component.patch
-------------------------------------------------------------------
Tue Jul 9 10:00:05 UTC 2019 - ghe@suse.com

View File

@ -58,10 +58,16 @@ Obsoletes: cmirrord < %{version}
Provides: cmirrord = %{version}
### COMMON-PATCH-BEGIN ###
# Upstream patches
Patch0001: bug-1114113_metadata-prevent-writing-beyond-metadata-area.patch
Patch0002: bug-1122666_devices-drop-open-error-message.patch
Patch0003: bug-1137296_pvremove-vgextend-fix-using-device-aliases-with-lvmetad.patch
Patch0004: bug-1135984_cache-support-no_discard_passdown.patch
Patch0001: bug-1145231_lvmetad-improve-scan-for-pvscan-all.patch
Patch0002: bug-1145231_scan-use-full-md-filter-when-md-1.0-devices-are-pres.patch
Patch0003: bug-1145231_scan-enable-full-md-filter-when-md-1.0-devices-are-p.patch
Patch0004: bug-1114113_metadata-prevent-writing-beyond-metadata-area.patch
Patch0005: bug-1145231_scan-md-metadata-version-0.90-is-at-the-end-of-disk.patch
Patch0006: bug-1145231_pvscan-lvmetad-use-full-md-filter-when-md-1.0-device.patch
Patch0007: bug-1145231_pvscan-lvmetad-use-udev-info-to-improve-md-component.patch
Patch0008: bug-1122666_devices-drop-open-error-message.patch
Patch0009: bug-1137296_pvremove-vgextend-fix-using-device-aliases-with-lvmetad.patch
Patch0010: bug-1135984_cache-support-no_discard_passdown.patch
# SUSE patches: 1000+ for LVM
# Never upstream
@ -90,6 +96,12 @@ A daemon for using LVM2 Logival Volumes in a clustered environment.
%patch0002 -p1
%patch0003 -p1
%patch0004 -p1
%patch0005 -p1
%patch0006 -p1
%patch0007 -p1
%patch0008 -p1
%patch0009 -p1
%patch0010 -p1
%patch1001 -p1
%patch1002 -p1
%patch1003 -p1

View File

@ -1,3 +1,14 @@
-------------------------------------------------------------------
Wed Aug 21 10:10:30 UTC 2019 - ghe@suse.com
- MD devices should be detected by LVM2 with metadata=1.0/0.9 (bsc#1145231)
+ bug-1145231_lvmetad-improve-scan-for-pvscan-all.patch
+ bug-1145231_scan-use-full-md-filter-when-md-1.0-devices-are-pres.patch
+ bug-1145231_scan-enable-full-md-filter-when-md-1.0-devices-are-p.patch
+ bug-1145231_scan-md-metadata-version-0.90-is-at-the-end-of-disk.patch
+ bug-1145231_pvscan-lvmetad-use-full-md-filter-when-md-1.0-device.patch
+ bug-1145231_pvscan-lvmetad-use-udev-info-to-improve-md-component.patch
-------------------------------------------------------------------
Tue Jul 9 10:00:05 UTC 2019 - ghe@suse.com

View File

@ -60,10 +60,16 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-build
### COMMON-PATCH-BEGIN ###
# Upstream patches
Patch0001: bug-1114113_metadata-prevent-writing-beyond-metadata-area.patch
Patch0002: bug-1122666_devices-drop-open-error-message.patch
Patch0003: bug-1137296_pvremove-vgextend-fix-using-device-aliases-with-lvmetad.patch
Patch0004: bug-1135984_cache-support-no_discard_passdown.patch
Patch0001: bug-1145231_lvmetad-improve-scan-for-pvscan-all.patch
Patch0002: bug-1145231_scan-use-full-md-filter-when-md-1.0-devices-are-pres.patch
Patch0003: bug-1145231_scan-enable-full-md-filter-when-md-1.0-devices-are-p.patch
Patch0004: bug-1114113_metadata-prevent-writing-beyond-metadata-area.patch
Patch0005: bug-1145231_scan-md-metadata-version-0.90-is-at-the-end-of-disk.patch
Patch0006: bug-1145231_pvscan-lvmetad-use-full-md-filter-when-md-1.0-device.patch
Patch0007: bug-1145231_pvscan-lvmetad-use-udev-info-to-improve-md-component.patch
Patch0008: bug-1122666_devices-drop-open-error-message.patch
Patch0009: bug-1137296_pvremove-vgextend-fix-using-device-aliases-with-lvmetad.patch
Patch0010: bug-1135984_cache-support-no_discard_passdown.patch
# SUSE patches: 1000+ for LVM
# Never upstream
@ -98,6 +104,12 @@ Volume Manager.
%patch0002 -p1
%patch0003 -p1
%patch0004 -p1
%patch0005 -p1
%patch0006 -p1
%patch0007 -p1
%patch0008 -p1
%patch0009 -p1
%patch0010 -p1
%patch1001 -p1
%patch1002 -p1
%patch1003 -p1