summaryrefslogtreecommitdiff
path: root/lib/format_text/import.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/format_text/import.c')
-rw-r--r--lib/format_text/import.c116
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.",