summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2017-08-02 16:40:00 -0500
committerDavid Teigland <teigland@redhat.com>2017-10-18 14:09:12 -0500
commitfc0153fdc824790c3036b7124bd84a4c195f5dac (patch)
treea35f262904ce1368e46facbcf8e3cffeeb209a82
parentec4c4d40a45df4c77dd3f21694ef8a1fb3b10496 (diff)
downloadlvm2-fc0153fdc824790c3036b7124bd84a4c195f5dac.tar.gz
vg_read: use the same async read code as label scan
Both for rescanning labels at the start of vg_read, and then passing and using that reread data through the vg_read() path to avoid rereading the same data from disk.
-rw-r--r--lib/cache/lvmcache.c26
-rw-r--r--lib/cache/lvmcache.h2
-rw-r--r--lib/cache/lvmetad.c2
-rw-r--r--lib/format1/format1.c1
-rw-r--r--lib/format_pool/format_pool.c1
-rw-r--r--lib/format_text/archiver.c2
-rw-r--r--lib/format_text/format-text.c15
-rw-r--r--lib/format_text/import-export.h3
-rw-r--r--lib/format_text/import.c34
-rw-r--r--lib/label/label.c241
-rw-r--r--lib/label/label.h3
-rw-r--r--lib/metadata/metadata.c18
-rw-r--r--lib/metadata/metadata.h4
13 files changed, 302 insertions, 50 deletions
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 0602d8e8f..e9a68f18f 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -1136,7 +1136,25 @@ next:
goto next;
}
-int lvmcache_label_refresh_for_vg(struct cmd_context *cmd, const char *vgname, const char *vgid)
+/*
+ * The initial label_scan at the start of the command is done without
+ * holding VG locks. Then for each VG identified during the label_scan,
+ * vg_read(vgname) is called while holding the VG lock. The labels
+ * and metadata on this VG's devices could have changed between the
+ * initial unlocked label_scan and the current vg_read(). So, we reread
+ * the labels/metadata for each device in the VG now that we hold the
+ * lock, and use this for processing the VG.
+ *
+ * FIXME: In some cases, the data read by label_scan may be fine, and not
+ * need to be reread here. e.g. a reporting command, possibly with a
+ * special option, could skip this second reread. Or, we could look
+ * at the VG seqno in each copy of the metadata read in the first label
+ * scan, and if they all match, consider it good enough to use for
+ * reporting without rereading it. (A command modifying the VG would
+ * always want to reread while the lock is held before modifying.)
+ */
+
+int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, const char *vgid)
{
struct dm_list devs;
struct device_list *devl;
@@ -1160,10 +1178,8 @@ int lvmcache_label_refresh_for_vg(struct cmd_context *cmd, const char *vgname, c
dm_list_add(&devs, &devl->list);
}
- dm_list_iterate_items(devl, &devs) {
- log_debug_cache("Reading label on %s for VG %s", dev_name(devl->dev), vgname);
- label_read(devl->dev, NULL, 0);
- }
+ if (!cmd->use_aio || !label_rescan_async(cmd, &devs))
+ label_rescan_sync(cmd, &devs);
/*
* TODO: grab vginfo again, and compare vginfo->infos
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index f46fdfd12..3a75d9ca3 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -74,7 +74,7 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset);
*/
void lvmcache_force_next_label_scan(void);
int lvmcache_label_scan(struct cmd_context *cmd);
-int lvmcache_label_refresh_for_vg(struct cmd_context *cmd, const char *vgname, const char *vgid);
+int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, const char *vgid);
/* Add/delete a device */
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index 51e813d31..86a2caced 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -1766,7 +1766,7 @@ static int _lvmetad_pvscan_single(struct metadata_area *mda, void *baton)
struct volume_group *vg;
if (mda_is_ignored(mda) ||
- !(vg = mda->ops->vg_read(b->fid, "", mda, NULL, NULL)))
+ !(vg = mda->ops->vg_read(b->fid, "", mda, NULL, NULL, NULL)))
return 1;
/* FIXME Also ensure contents match etc. */
diff --git a/lib/format1/format1.c b/lib/format1/format1.c
index 6e7e888ff..816e2580f 100644
--- a/lib/format1/format1.c
+++ b/lib/format1/format1.c
@@ -180,6 +180,7 @@ out:
static struct volume_group *_format1_vg_read(struct format_instance *fid,
const char *vg_name,
struct metadata_area *mda __attribute__((unused)),
+ struct label_read_data *ld __attribute__((unused)),
struct cached_vg_fmtdata **vg_fmtdata __attribute__((unused)),
unsigned *use_previous_vg __attribute__((unused)))
{
diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c
index f8223a392..93214a179 100644
--- a/lib/format_pool/format_pool.c
+++ b/lib/format_pool/format_pool.c
@@ -101,6 +101,7 @@ static int _check_usp(const char *vgname, struct user_subpool *usp, int sp_count
static struct volume_group *_pool_vg_read(struct format_instance *fid,
const char *vg_name,
struct metadata_area *mda __attribute__((unused)),
+ struct label_read_data *ld __attribute__((unused)),
struct cached_vg_fmtdata **vg_fmtdata __attribute__((unused)),
unsigned *use_previous_vg __attribute__((unused)))
{
diff --git a/lib/format_text/archiver.c b/lib/format_text/archiver.c
index c696ee832..aa448735e 100644
--- a/lib/format_text/archiver.c
+++ b/lib/format_text/archiver.c
@@ -320,7 +320,7 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd,
}
dm_list_iterate_items(mda, &tf->metadata_areas_in_use) {
- if (!(vg = mda->ops->vg_read(tf, vg_name, mda, NULL, NULL)))
+ if (!(vg = mda->ops->vg_read(tf, vg_name, mda, NULL, NULL, NULL)))
stack;
break;
}
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index 86ee888ac..3755169ba 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -515,6 +515,7 @@ static int _raw_holds_vgname(struct format_instance *fid,
static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
const char *vgname,
struct device_area *area,
+ struct label_read_data *ld,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg,
int precommitted)
@@ -526,7 +527,7 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
char *desc;
uint32_t wrap = 0;
- if (!(mdah = raw_read_mda_header(fid->fmt, area, NULL)))
+ if (!(mdah = raw_read_mda_header(fid->fmt, area, ld)))
goto_out;
if (!(rlocn = _find_vg_rlocn(area, mdah, vgname, &precommitted))) {
@@ -543,7 +544,7 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
goto out;
}
- vg = text_read_metadata(fid, NULL, vg_fmtdata, use_previous_vg, area->dev,
+ vg = text_read_metadata(fid, area->dev, NULL, ld, vg_fmtdata, use_previous_vg,
(off_t) (area->start + rlocn->offset),
(uint32_t) (rlocn->size - wrap),
(off_t) (area->start + MDA_HEADER_SIZE),
@@ -573,6 +574,7 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
static struct volume_group *_vg_read_raw(struct format_instance *fid,
const char *vgname,
struct metadata_area *mda,
+ struct label_read_data *ld,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg)
{
@@ -582,7 +584,7 @@ static struct volume_group *_vg_read_raw(struct format_instance *fid,
if (!dev_open_readonly(mdac->area.dev))
return_NULL;
- vg = _vg_read_raw_area(fid, vgname, &mdac->area, vg_fmtdata, use_previous_vg, 0);
+ vg = _vg_read_raw_area(fid, vgname, &mdac->area, ld, vg_fmtdata, use_previous_vg, 0);
if (!dev_close(mdac->area.dev))
stack;
@@ -593,6 +595,7 @@ static struct volume_group *_vg_read_raw(struct format_instance *fid,
static struct volume_group *_vg_read_precommit_raw(struct format_instance *fid,
const char *vgname,
struct metadata_area *mda,
+ struct label_read_data *ld,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg)
{
@@ -602,7 +605,7 @@ static struct volume_group *_vg_read_precommit_raw(struct format_instance *fid,
if (!dev_open_readonly(mdac->area.dev))
return_NULL;
- vg = _vg_read_raw_area(fid, vgname, &mdac->area, vg_fmtdata, use_previous_vg, 1);
+ vg = _vg_read_raw_area(fid, vgname, &mdac->area, ld, vg_fmtdata, use_previous_vg, 1);
if (!dev_close(mdac->area.dev))
stack;
@@ -917,6 +920,7 @@ static struct volume_group *_vg_read_file_name(struct format_instance *fid,
static struct volume_group *_vg_read_file(struct format_instance *fid,
const char *vgname,
struct metadata_area *mda,
+ struct label_read_data *ld,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg __attribute__((unused)))
{
@@ -928,6 +932,7 @@ static struct volume_group *_vg_read_file(struct format_instance *fid,
static struct volume_group *_vg_read_precommit_file(struct format_instance *fid,
const char *vgname,
struct metadata_area *mda,
+ struct label_read_data *ld,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg __attribute__((unused)))
{
@@ -1293,7 +1298,7 @@ static int _scan_raw(const struct format_type *fmt, const char *vgname __attribu
/* TODO: caching as in read_metadata_location() (trigger this code?) */
if (read_metadata_location(fmt, mdah, NULL, &rl->dev_area, &vgsummary, NULL)) {
- vg = _vg_read_raw_area(&fid, vgsummary.vgname, &rl->dev_area, NULL, NULL, 0);
+ vg = _vg_read_raw_area(&fid, vgsummary.vgname, &rl->dev_area, NULL, NULL, NULL, 0);
if (vg)
lvmcache_update_vg(vg, 0);
}
diff --git a/lib/format_text/import-export.h b/lib/format_text/import-export.h
index a23a15c8f..2610a39b5 100644
--- a/lib/format_text/import-export.h
+++ b/lib/format_text/import-export.h
@@ -71,10 +71,11 @@ struct volume_group *text_read_metadata_file(struct format_instance *fid,
const char *file,
time_t *when, char **desc);
struct volume_group *text_read_metadata(struct format_instance *fid,
+ struct device *dev,
const char *file,
+ struct label_read_data *ld,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg,
- struct device *dev,
off_t offset, uint32_t size,
off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn,
diff --git a/lib/format_text/import.c b/lib/format_text/import.c
index d7d707aa1..7dac1b86e 100644
--- a/lib/format_text/import.c
+++ b/lib/format_text/import.c
@@ -125,10 +125,11 @@ struct cached_vg_fmtdata {
};
struct volume_group *text_read_metadata(struct format_instance *fid,
+ struct device *dev,
const char *file,
+ struct label_read_data *ld,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg,
- struct device *dev,
off_t offset, uint32_t size,
off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn,
@@ -138,6 +139,7 @@ struct volume_group *text_read_metadata(struct format_instance *fid,
struct volume_group *vg = NULL;
struct dm_config_tree *cft;
struct text_vg_version_ops **vsn;
+ char *buf_async = NULL;
int skip_parse;
/*
@@ -168,12 +170,32 @@ struct volume_group *text_read_metadata(struct format_instance *fid,
((*vg_fmtdata)->cached_mda_checksum == checksum) &&
((*vg_fmtdata)->cached_mda_size == (size + size2));
+ if (ld) {
+ if (ld->buf_len >= (offset + size))
+ buf_async = ld->buf;
+ else {
+ /*
+ * Needs data beyond the end of the async read buffer.
+ * Will do a new synchronous read to get the data.
+ * (ASYNC_SCAN_SIZE could also be made larger.)
+ */
+ log_debug_metadata("async read buffer for %s too small %u for metadata offset %llu size %u",
+ dev_name(dev), ld->buf_len, (unsigned long long)offset, size);
+ buf_async = NULL;
+ }
+ }
+
if (dev) {
- log_debug_metadata("Reading metadata from %s at %llu size %d (+%d)",
- dev_name(dev), (unsigned long long)offset,
- size, size2);
+ if (buf_async)
+ log_debug_metadata("Copying metadata for %s at %llu size %d (+%d)",
+ dev_name(dev), (unsigned long long)offset,
+ size, size2);
+ else
+ log_debug_metadata("Reading metadata from %s at %llu size %d (+%d)",
+ dev_name(dev), (unsigned long long)offset,
+ size, size2);
- if (!config_file_read_fd(cft, dev, NULL, offset, size,
+ if (!config_file_read_fd(cft, dev, buf_async, offset, size,
offset2, size2, checksum_fn, checksum,
skip_parse, 1)) {
/* FIXME: handle errors */
@@ -225,7 +247,7 @@ struct volume_group *text_read_metadata_file(struct format_instance *fid,
const char *file,
time_t *when, char **desc)
{
- return text_read_metadata(fid, file, NULL, NULL, NULL,
+ return text_read_metadata(fid, NULL, file, NULL, NULL, NULL,
(off_t)0, 0, (off_t)0, 0,
NULL,
0,
diff --git a/lib/label/label.c b/lib/label/label.c
index f371c3588..77b498f3f 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -25,6 +25,8 @@
#include <fcntl.h>
#include <unistd.h>
+static DM_LIST_INIT(label_read_list);
+
/* FIXME Allow for larger labels? Restricted to single sector currently */
/*
@@ -447,6 +449,31 @@ struct label *label_create(struct labeller *labeller)
return label;
}
+static void _free_label_read_list(int do_close)
+{
+ struct label_read_data *ld, *ld2;
+
+ dm_list_iterate_items_safe(ld, ld2, &label_read_list) {
+ dm_list_del(&ld->list);
+ if (do_close)
+ dev_close(ld->dev);
+ if (ld->buf)
+ free(ld->buf);
+ free(ld);
+ }
+}
+
+struct label_read_data *get_label_read_data(struct cmd_context *cmd, struct device *dev)
+{
+ struct label_read_data *ld;
+
+ dm_list_iterate_items(ld, &label_read_list) {
+ if (ld->dev == dev)
+ return ld;
+ }
+ return NULL;
+}
+
/*
* Start label aio read on a device.
*/
@@ -582,22 +609,22 @@ static int _label_read_async_process(struct cmd_context *cmd, struct label_read_
#define MAX_ASYNC_EVENTS 1024
/*
- * label_scan iterates over all visible devices, looking
- * for any that belong to lvm, and fills lvmcache with
- * basic info about them. It's main job is to prepare
- * for subsequent vg_reads. vg_read(vgname) needs to
- * know which devices/locations to read metadata from
- * for the given vg name. The label_scan has scanned
- * all devices and saved info in lvmcache about:
- * the device, the mda locations on that device,
- * and the vgname referenced in those mdas. So,
- * vg_read(vgname) can map the vgname to a set of
- * mda locations it needs to read to get the metadata.
+ * label_scan run at the start of a command iterates over all visible devices,
+ * looking for any that belong to lvm, and fills lvmcache with basic info about
+ * them. It's main job is to prepare for subsequent vg_reads. vg_read(vgname)
+ * needs to know which devices/locations to read metadata from for the given vg
+ * name. The label_scan has scanned all devices and saved info in lvmcache
+ * about: the device, the mda locations on that device, and the vgname
+ * referenced in those mdas. So, vg_read(vgname) can map the vgname to a the
+ * subset of devices it needs to read for that VG.
+ */
+
+/*
+ * Scan labels/metadata for all devices (async)
*/
int label_scan_async(struct cmd_context *cmd)
{
- struct dm_list label_read_list;
struct label_read_data *ld, *ld2;
struct dev_iter *iter;
struct device *dev;
@@ -611,7 +638,7 @@ int label_scan_async(struct cmd_context *cmd)
int dev_count = 0;
int error;
- dm_list_init(&label_read_list);
+ _free_label_read_list(0);
/*
* "buf" is the buffer into which the first ASYNC_SCAN_SIZE bytes
@@ -652,7 +679,7 @@ int label_scan_async(struct cmd_context *cmd)
dev_cache_full_scan(cmd->full_filter);
- log_debug_devs("Scanning labels async");
+ log_debug_devs("Scanning all labels async");
if (!(iter = dev_iter_create(cmd->full_filter, 0))) {
log_error("Scanning labels failed to get devices.");
@@ -780,13 +807,8 @@ int label_scan_async(struct cmd_context *cmd)
io_destroy(aio_ctx);
- dm_list_iterate_items_safe(ld, ld2, &label_read_list) {
- dm_list_del(&ld->list);
+ dm_list_iterate_items(ld, &label_read_list)
dev_close(ld->dev);
- if (ld->buf)
- free(ld->buf);
- free(ld);
- }
log_debug_devs("Scanned %d labels async", dev_count);
return 1;
@@ -808,6 +830,148 @@ bad:
return 0;
}
+/*
+ * Rescan labels/metadata for select devices (async)
+ * (devs from a specific VG)
+ */
+
+int label_rescan_async(struct cmd_context *cmd, struct dm_list *devs)
+{
+ struct dm_list tmp_label_read_list;
+ struct label_read_data *ld, *ld2;
+ struct device_list *devl;
+ struct device *dev;
+ io_context_t aio_ctx;
+ int need_wait_count;
+ int need_process_count;
+ int dev_count = 0;
+ int error;
+
+ dm_list_init(&tmp_label_read_list);
+
+ memset(&aio_ctx, 0, sizeof(io_context_t));
+
+ error = io_setup(MAX_ASYNC_EVENTS, &aio_ctx);
+ if (error < 0) {
+ log_debug_devs("async io setup error %d, reverting to sync io.", error);
+ return_0;
+ }
+
+ log_debug_devs("Scanning labels for VG devs async");
+
+ dm_list_iterate_items(devl, devs) {
+ dev = devl->dev;
+
+ if (!(ld = get_label_read_data(cmd, dev))) {
+ log_warn("WARNING: label rescan cannot find dev %s", dev_name(dev));
+ continue;
+ }
+
+ /* Temporarily move structs being reread onto local list. */
+ dm_list_del(&ld->list);
+ dm_list_add(&tmp_label_read_list, &ld->list);
+
+ if (!dev_open_readonly(ld->dev)) {
+ log_debug_devs("Reading label skipped can't open %s", dev_name(dev));
+ continue;
+ }
+
+ ld->try_sync = 0;
+ ld->read_done = 0;
+ ld->process_done = 0;
+
+ if (!_label_read_async_start(cmd, aio_ctx, ld))
+ ld->try_sync = 1;
+ else
+ log_debug_devs("Reading sectors from device %s async", dev_name(ld->dev));
+
+ dev_count++;
+ }
+
+ /*
+ * Try a synchronous read for any dev where aio couldn't be submitted.
+ */
+ dm_list_iterate_items(ld, &tmp_label_read_list) {
+ if (ld->try_sync) {
+ log_debug_devs("Reading sectors from device %s trying sync", dev_name(ld->dev));
+
+ if (!dev_read(ld->dev, 0, ld->buf_len, ld->buf)) {
+ log_debug_devs("%s: Failed to read label area", dev_name(ld->dev));
+ ld->read_result = -1;
+ } else {
+ ld->read_result = ld->buf_len;
+ }
+ ld->read_done = 1;
+ }
+ }
+
+ /*
+ * Reap the aio and process the results.
+ */
+
+ check_aio:
+ need_wait_count = 0;
+ need_process_count = 0;
+
+ dm_list_iterate_items(ld, &tmp_label_read_list) {
+ if (!ld->read_done)
+ need_wait_count++;
+ else if (!ld->process_done)
+ need_process_count++;
+ }
+
+ /*
+ * Process devices that have finished reading label sectors.
+ * Processing includes sync i/o to read mda locations and vg metadata.
+ *
+ * FIXME: we shouldn't need to fully reprocess everything when rescanning.
+ * lvmcache is already populated from the previous scan, and if nothing
+ * has changed we don't need to repopulate it with the same data.
+ * Do something like check the metadata checksum from previous label scan
+ * and don't reprocess here if it's the same.
+ */
+ if (need_process_count) {
+ dm_list_iterate_items(ld, &tmp_label_read_list) {
+ if (!ld->read_done || ld->process_done)
+ continue;
+ log_debug_devs("Parsing label and data from device %s", dev_name(ld->dev));
+ _label_read_async_process(cmd, ld);
+ ld->process_done = 1;
+ }
+ }
+
+ /*
+ * Wait for more devices to finish reading label sectors.
+ */
+ if (need_wait_count) {
+ if (_label_read_async_wait(cmd, aio_ctx, need_wait_count))
+ goto check_aio;
+
+ /* TODO: handle this error */
+ /* an error getting aio events, should we fall back
+ to doing sync dev_read() on any that aren't done? */
+ log_error(INTERNAL_ERROR "aio getevents error");
+ }
+
+ io_destroy(aio_ctx);
+
+ dm_list_iterate_items(ld, &tmp_label_read_list)
+ dev_close(ld->dev);
+
+ /* Move structs being reread back to normal list */
+ dm_list_iterate_items_safe(ld, ld2, &tmp_label_read_list) {
+ dm_list_del(&ld->list);
+ dm_list_add(&label_read_list, &ld->list);
+ }
+
+ log_debug_devs("Scanned %d labels for VG devs async", dev_count);
+ return 1;
+}
+
+/*
+ * Read label/metadata for one dev (sync)
+ */
+
static int _label_read_sync(struct cmd_context *cmd, struct device *dev)
{
char scanbuf[LABEL_SCAN_SIZE] __attribute__((aligned(8)));
@@ -856,8 +1020,9 @@ static int _label_read_sync(struct cmd_context *cmd, struct device *dev)
}
/*
- * Read and process device labels/data without aio.
+ * Scan labels/metadata for all devices (sync)
*/
+
int label_scan_sync(struct cmd_context *cmd)
{
struct dev_iter *iter;
@@ -865,11 +1030,13 @@ int label_scan_sync(struct cmd_context *cmd)
int dev_count = 0;
struct lvmcache_info *info;
+ _free_label_read_list(0);
+
log_debug_devs("Finding devices to scan");
dev_cache_full_scan(cmd->full_filter);
- log_very_verbose("Scanning labels sync");
+ log_very_verbose("Scanning all labels sync");
if (!(iter = dev_iter_create(cmd->full_filter, 0))) {
log_error("Scanning labels failed to get devices.");
@@ -900,3 +1067,33 @@ int label_scan_sync(struct cmd_context *cmd)
return 1;
}
+/*
+ * Rescan labels/metadata for select devices (sync)
+ * (devs from a specific VG)
+ */
+
+int label_rescan_sync(struct cmd_context *cmd, struct dm_list *devs)
+{
+ struct device_list *devl;
+ int dev_count = 0;
+
+ log_debug_devs("Scanning labels for VG devs sync");
+
+ dm_list_iterate_items(devl, devs) {
+ if (!dev_open_readonly(devl->dev)) {
+ log_debug_devs("Reading label skipped can't open %s", dev_name(devl->dev));
+ continue;
+ }
+
+ _label_read_sync(cmd, devl->dev);
+
+ if (!dev_close(devl->dev))
+ stack;
+
+ dev_count++;
+ }
+
+ log_very_verbose("Scanned %d labels for VG devs sync", dev_count);
+ return 1;
+}
+
diff --git a/lib/label/label.h b/lib/label/label.h
index ebd0afb44..26424e5bd 100644
--- a/lib/label/label.h
+++ b/lib/label/label.h
@@ -131,5 +131,8 @@ void label_destroy(struct label *label);
int label_scan_async(struct cmd_context *cmd);
int label_scan_sync(struct cmd_context *cmd);
+int label_rescan_async(struct cmd_context *cmd, struct dm_list *devs);
+int label_rescan_sync(struct cmd_context *cmd, struct dm_list *devs);
+struct label_read_data *get_label_read_data(struct cmd_context *cmd, struct device *dev);
#endif
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 895519d89..4ea5aca27 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -34,6 +34,7 @@
#include "lvmlockd.h"
#include "time.h"
#include "lvmnotify.h"
+#include "label.h"
#include <math.h>
#include <sys/param.h>
@@ -3851,7 +3852,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
*/
log_debug_metadata("Reading VG rereading labels for %s", vgname);
- if (!lvmcache_label_refresh_for_vg(cmd, vgname, vgid)) {
+ if (!lvmcache_label_rescan_vg(cmd, vgname, vgid)) {
/* The VG wasn't found, so force a full label scan. */
lvmcache_force_next_label_scan();
lvmcache_label_scan(cmd);
@@ -3901,15 +3902,16 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
inconsistent_mda_count=0;
dm_list_iterate_items(mda, &fid->metadata_areas_in_use) {
struct device *mda_dev = mda_get_device(mda);
+ struct label_read_data *ld;
use_previous_vg = 0;
- log_debug_metadata("Reading VG %s from mda on %s", vgname, dev_name(mda_dev));
+ log_debug_metadata("Reading VG %s from %s", vgname, dev_name(mda_dev));
- if ((use_precommitted &&
- !(vg = mda->ops->vg_read_precommit(fid, vgname, mda, &vg_fmtdata, &use_previous_vg)) && !use_previous_vg) ||
- (!use_precommitted &&
- !(vg = mda->ops->vg_read(fid, vgname, mda, &vg_fmtdata, &use_previous_vg)) && !use_previous_vg)) {
+ ld = get_label_read_data(cmd, mda_dev);
+
+ if ((use_precommitted && !(vg = mda->ops->vg_read_precommit(fid, vgname, mda, ld, &vg_fmtdata, &use_previous_vg)) && !use_previous_vg) ||
+ (!use_precommitted && !(vg = mda->ops->vg_read(fid, vgname, mda, ld, &vg_fmtdata, &use_previous_vg)) && !use_previous_vg)) {
inconsistent = 1;
vg_fmtdata = NULL;
continue;
@@ -4099,9 +4101,9 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
use_previous_vg = 0;
if ((use_precommitted &&
- !(vg = mda->ops->vg_read_precommit(fid, vgname, mda, &vg_fmtdata, &use_previous_vg)) && !use_previous_vg) ||
+ !(vg = mda->ops->vg_read_precommit(fid, vgname, mda, NULL, &vg_fmtdata, &use_previous_vg)) && !use_previous_vg) ||
(!use_precommitted &&
- !(vg = mda->ops->vg_read(fid, vgname, mda, &vg_fmtdata, &use_previous_vg)) && !use_previous_vg)) {
+ !(vg = mda->ops->vg_read(fid, vgname, mda, NULL, &vg_fmtdata, &use_previous_vg)) && !use_previous_vg)) {
inconsistent = 1;
vg_fmtdata = NULL;
continue;
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index a60780ef7..937945607 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -25,6 +25,8 @@
#include "dev-cache.h"
#include "lvm-string.h"
#include "metadata-exported.h"
+#include "lvm-logging.h"
+#include "label.h"
//#define MAX_STRIPES 128U
//#define SECTOR_SHIFT 9L
@@ -79,11 +81,13 @@ struct metadata_area_ops {
struct volume_group *(*vg_read) (struct format_instance * fi,
const char *vg_name,
struct metadata_area * mda,
+ struct label_read_data *ld,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg);
struct volume_group *(*vg_read_precommit) (struct format_instance * fi,
const char *vg_name,
struct metadata_area * mda,
+ struct label_read_data *ld,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg);
/*