diff options
author | David Teigland <teigland@redhat.com> | 2017-08-02 16:40:00 -0500 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2017-10-18 14:09:12 -0500 |
commit | fc0153fdc824790c3036b7124bd84a4c195f5dac (patch) | |
tree | a35f262904ce1368e46facbcf8e3cffeeb209a82 | |
parent | ec4c4d40a45df4c77dd3f21694ef8a1fb3b10496 (diff) | |
download | lvm2-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.c | 26 | ||||
-rw-r--r-- | lib/cache/lvmcache.h | 2 | ||||
-rw-r--r-- | lib/cache/lvmetad.c | 2 | ||||
-rw-r--r-- | lib/format1/format1.c | 1 | ||||
-rw-r--r-- | lib/format_pool/format_pool.c | 1 | ||||
-rw-r--r-- | lib/format_text/archiver.c | 2 | ||||
-rw-r--r-- | lib/format_text/format-text.c | 15 | ||||
-rw-r--r-- | lib/format_text/import-export.h | 3 | ||||
-rw-r--r-- | lib/format_text/import.c | 34 | ||||
-rw-r--r-- | lib/label/label.c | 241 | ||||
-rw-r--r-- | lib/label/label.h | 3 | ||||
-rw-r--r-- | lib/metadata/metadata.c | 18 | ||||
-rw-r--r-- | lib/metadata/metadata.h | 4 |
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); /* |