diff options
Diffstat (limited to 'lib/format_text/import.c')
-rw-r--r-- | lib/format_text/import.c | 116 |
1 files changed, 98 insertions, 18 deletions
diff --git a/lib/format_text/import.c b/lib/format_text/import.c index 62dee8faf..bbb2eb208 100644 --- a/lib/format_text/import.c +++ b/lib/format_text/import.c @@ -35,8 +35,9 @@ static void _init_text_import(void) /* * Find out vgname on a given device. */ -int text_vgsummary_import(const struct format_type *fmt, +int text_read_metadata_summary(const struct format_type *fmt, struct device *dev, + struct label_read_data *ld, off_t offset, uint32_t size, off_t offset2, uint32_t size2, checksum_fn_t checksum_fn, @@ -45,20 +46,52 @@ int text_vgsummary_import(const struct format_type *fmt, { struct dm_config_tree *cft; struct text_vg_version_ops **vsn; + char *buf = NULL; int r = 0; + if (ld) { + if (ld->buf_len >= (offset + size)) + buf = ld->buf; + else { + /* + * Needs data beyond the end of the ld buffer. + * Will do a new synchronous read to get the data. + * (scan_size could also be made larger.) + */ + log_debug_metadata("label scan buffer for %s too small %u for metadata offset %llu size %u", + dev_name(dev), ld->buf_len, (unsigned long long)offset, size); + buf = NULL; + } + } + _init_text_import(); if (!(cft = config_open(CONFIG_FILE_SPECIAL, NULL, 0))) return_0; - if ((!dev && !config_file_read(cft)) || - (dev && !config_file_read_fd(cft, dev, offset, size, + if (dev) { + if (buf) + log_debug_metadata("Copying metadata summary for %s at %llu size %d (+%d)", + dev_name(dev), (unsigned long long)offset, + size, size2); + else + log_debug_metadata("Reading metadata summary from %s at %llu size %d (+%d)", + dev_name(dev), (unsigned long long)offset, + size, size2); + + if (!config_file_read_fd(cft, dev, buf, offset, size, offset2, size2, checksum_fn, vgsummary->mda_checksum, - checksum_only, 1))) { - log_error("Couldn't read volume group metadata."); - goto out; + checksum_only, 1)) { + /* FIXME: handle errors */ + log_error("Couldn't read volume group metadata from %s.", dev_name(dev)); + goto out; + } + } else { + if (!config_file_read(cft)) { + log_error("Couldn't read volume group metadata from file."); + goto out; + } } if (checksum_only) { @@ -91,12 +124,12 @@ struct cached_vg_fmtdata { size_t cached_mda_size; }; -struct volume_group *text_vg_import_fd(struct format_instance *fid, +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, - int single_device, - struct device *dev, off_t offset, uint32_t size, off_t offset2, uint32_t size2, checksum_fn_t checksum_fn, @@ -106,8 +139,18 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid, struct volume_group *vg = NULL; struct dm_config_tree *cft; struct text_vg_version_ops **vsn; + char *buf = NULL; int skip_parse; + /* + * This struct holds the checksum and size of the VG metadata + * that was read from a previous device. When we read the VG + * metadata from this device, we can skip parsing it into a + * cft (saving time) if the checksum of the metadata buffer + * we read from this device matches the size/checksum saved in + * the mda_header/rlocn struct on this device, and matches the + * size/checksum from the previous device. + */ if (vg_fmtdata && !*vg_fmtdata && !(*vg_fmtdata = dm_pool_zalloc(fid->mem, sizeof(**vg_fmtdata)))) { log_error("Failed to allocate VG fmtdata for text format."); @@ -127,15 +170,49 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid, ((*vg_fmtdata)->cached_mda_checksum == checksum) && ((*vg_fmtdata)->cached_mda_size == (size + size2)); - if ((!dev && !config_file_read(cft)) || - (dev && !config_file_read_fd(cft, dev, offset, size, + if (ld) { + if (ld->buf_len >= (offset + size)) + buf = ld->buf; + else { + /* + * Needs data beyond the end of the ld buffer. + * Will do a new synchronous read to get the data. + * (scan_size could also be made larger.) + */ + log_debug_metadata("label scan buffer for %s too small %u for metadata offset %llu size %u", + dev_name(dev), ld->buf_len, (unsigned long long)offset, size); + buf = NULL; + } + } + + if (dev) { + if (buf) + 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, buf, offset, size, offset2, size2, checksum_fn, checksum, - skip_parse, 1))) - goto_out; + skip_parse, 1)) { + /* FIXME: handle errors */ + log_error("Couldn't read volume group metadata from %s.", dev_name(dev)); + goto out; + } + } else { + if (!config_file_read(cft)) { + log_error("Couldn't read volume group metadata from file."); + goto out; + } + } if (skip_parse) { if (use_previous_vg) *use_previous_vg = 1; + log_debug_metadata("Skipped parsing metadata on %s", dev_name(dev)); goto out; } @@ -146,7 +223,7 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid, if (!(*vsn)->check_version(cft)) continue; - if (!(vg = (*vsn)->read_vg(fid, cft, single_device, 0))) + if (!(vg = (*vsn)->read_vg(fid, cft, 0))) goto_out; (*vsn)->read_desc(vg->vgmem, cft, when, desc); @@ -166,17 +243,20 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid, return vg; } -struct volume_group *text_vg_import_file(struct format_instance *fid, +struct volume_group *text_read_metadata_file(struct format_instance *fid, const char *file, time_t *when, char **desc) { - return text_vg_import_fd(fid, file, NULL, NULL, 0, NULL, (off_t)0, 0, (off_t)0, 0, NULL, 0, + return text_read_metadata(fid, NULL, file, NULL, NULL, NULL, + (off_t)0, 0, (off_t)0, 0, + NULL, + 0, when, desc); } static struct volume_group *_import_vg_from_config_tree(const struct dm_config_tree *cft, struct format_instance *fid, - unsigned allow_lvmetad_extensions) + unsigned for_lvmetad) { struct volume_group *vg = NULL; struct text_vg_version_ops **vsn; @@ -191,7 +271,7 @@ static struct volume_group *_import_vg_from_config_tree(const struct dm_config_t * The only path to this point uses cached vgmetadata, * so it can use cached PV state too. */ - if (!(vg = (*vsn)->read_vg(fid, cft, 1, allow_lvmetad_extensions))) + if (!(vg = (*vsn)->read_vg(fid, cft, for_lvmetad))) stack; else if ((vg_missing = vg_missing_pv_count(vg))) { log_verbose("There are %d physical volumes missing.", |