[lvm-devel] master - separate code for setting devices from metadata parsing

David Teigland teigland at sourceware.org
Thu May 23 18:09:22 UTC 2019


Gitweb:        https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=645dd276049e8dbab37b169b27cf6af29a8bd8e5
Commit:        645dd276049e8dbab37b169b27cf6af29a8bd8e5
Parent:        ef2d61fea81dbae3d1a32d20ee22d2afae7701af
Author:        David Teigland <teigland at redhat.com>
AuthorDate:    Tue Feb 5 11:32:54 2019 -0600
Committer:     David Teigland <teigland at redhat.com>
CommitterDate: Thu May 23 11:57:38 2019 -0500

separate code for setting devices from metadata parsing

Pull the code that sets devs for PVs out of the metadata
parsing code and call it separately.
---
 lib/format_text/archiver.c    |    3 ++
 lib/format_text/import.c      |    8 +++--
 lib/format_text/import_vsn1.c |   51 ----------------------------
 lib/metadata/metadata.c       |   75 +++++++++++++++++++++++++++++++++++++++++
 lib/metadata/metadata.h       |    2 +
 tools/pvscan.c                |    2 +
 6 files changed, 87 insertions(+), 54 deletions(-)

diff --git a/lib/format_text/archiver.c b/lib/format_text/archiver.c
index 34eff55..052c2bd 100644
--- a/lib/format_text/archiver.c
+++ b/lib/format_text/archiver.c
@@ -320,6 +320,9 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd,
 		break;
 	}
 
+	if (vg)
+		set_pv_devices(tf, vg);
+
 	if (!vg)
 		tf->fmt->ops->destroy_instance(tf);
 
diff --git a/lib/format_text/import.c b/lib/format_text/import.c
index d487100..64fbb08 100644
--- a/lib/format_text/import.c
+++ b/lib/format_text/import.c
@@ -229,9 +229,11 @@ static struct volume_group *_import_vg_from_config_tree(const struct dm_config_t
 		 */
 		if (!(vg = (*vsn)->read_vg(fid, cft, allow_lvmetad_extensions)))
 			stack;
-		else if ((vg_missing = vg_missing_pv_count(vg))) {
-			log_verbose("There are %d physical volumes missing.",
-				    vg_missing);
+		else {
+			set_pv_devices(fid, vg);
+
+			if ((vg_missing = vg_missing_pv_count(vg)))
+				log_verbose("There are %d physical volumes missing.", vg_missing);
 			vg_mark_partial_lvs(vg, 1);
 			/* FIXME: move this code inside read_vg() */
 		}
diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
index 8dad8e9..43ec10b 100644
--- a/lib/format_text/import_vsn1.c
+++ b/lib/format_text/import_vsn1.c
@@ -206,21 +206,6 @@ static int _read_pv(struct format_instance *fid,
 
         pv->is_labelled = 1; /* All format_text PVs are labelled. */
 
-	/*
-	 * Convert the uuid into a device.
-	 */
-	if (!(pv->dev = lvmcache_device_from_pvid(fid->fmt->cmd, &pv->id, &pv->label_sector))) {
-		char buffer[64] __attribute__((aligned(8)));
-
-		if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
-			buffer[0] = '\0';
-
-		if (fid->fmt->cmd && !fid->fmt->cmd->pvscan_cache_single)
-			log_error_once("Couldn't find device with uuid %s.", buffer);
-		else
-			log_debug_metadata("Couldn't find device with uuid %s.", buffer);
-	}
-
 	if (!(pv->vg_name = dm_pool_strdup(mem, vg->name)))
 		return_0;
 
@@ -231,15 +216,6 @@ static int _read_pv(struct format_instance *fid,
 		return 0;
 	}
 
-	if (!pv->dev)
-		pv->status |= MISSING_PV;
-
-	if ((pv->status & MISSING_PV) && pv->dev && pv_mda_used_count(pv) == 0) {
-		pv->status &= ~MISSING_PV;
-		log_info("Recovering a previously MISSING PV %s with no MDAs.",
-			 pv_dev_name(pv));
-	}
-
 	/* Late addition */
 	if (dm_config_has_node(pvn, "dev_size") &&
 	    !_read_uint64(pvn, "dev_size", &pv->size)) {
@@ -292,33 +268,6 @@ static int _read_pv(struct format_instance *fid,
 	pv->pe_align = 0;
 	pv->fmt = fid->fmt;
 
-	/*
-	 * It would be nice to check this earlier, e.g. in or after label scan,
-	 * but this is first time we get far enough through the vg metadata to
-	 * see the PV size, and can finally compare it with the device size.
-	 */
-	if (pv->dev && (pv->size != pv->dev->size)) {
-		if (dev_is_md_component(pv->dev, NULL, 1)) {
-			log_warn("WARNING: device %s is an md component, ignoring PV.", dev_name(pv->dev));
-			return_0;
-		}
-	}
-
-	/* Fix up pv size if missing or impossibly large */
-	if ((!pv->size || pv->size > (1ULL << 62)) && pv->dev) {
-		if (!dev_get_size(pv->dev, &pv->size)) {
-			log_error("%s: Couldn't get size.", pv_dev_name(pv));
-			return 0;
-		}
-		log_verbose("Fixing up missing size (%s) "
-			    "for PV %s", display_size(fid->fmt->cmd, pv->size),
-			    pv_dev_name(pv));
-		size = pv->pe_count * (uint64_t) vg->extent_size + pv->pe_start;
-		if (size > pv->size)
-			log_warn("WARNING: Physical Volume %s is too large "
-				 "for underlying device", pv_dev_name(pv));
-	}
-
 	if (!alloc_pv_segment_whole_pv(mem, pv))
 		return_0;
 
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index e9d4fa2..8f6de26 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -3866,6 +3866,9 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
 			continue;
 		}
 
+		if (vg)
+			set_pv_devices(fid, vg);
+
 		/* Use previous VG because checksum matches */
 		if (!vg) {
 			vg = correct_vg;
@@ -4073,6 +4076,9 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
 				continue;
 			}
 
+			if (vg)
+				set_pv_devices(fid, vg);
+
 			/* Use previous VG because checksum matches */
 			if (!vg) {
 				vg = correct_vg;
@@ -4498,6 +4504,75 @@ bad:
 	return NULL;
 }
 
+/*
+ * FIXME: we only want to print the warnings when this is called from
+ * vg_read, not from import_vg_from_metadata, so do the warnings elsewhere
+ * or avoid calling this from import_vg_from.
+ */
+static void _set_pv_device(struct format_instance *fid,
+			   struct volume_group *vg,
+			   struct physical_volume *pv)
+{
+	char buffer[64] __attribute__((aligned(8)));
+	uint64_t size;
+
+	if (!(pv->dev = lvmcache_device_from_pvid(fid->fmt->cmd, &pv->id, &pv->label_sector))) {
+		if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
+			buffer[0] = '\0';
+
+		if (fid->fmt->cmd && !fid->fmt->cmd->pvscan_cache_single)
+			log_error_once("Couldn't find device with uuid %s.", buffer);
+		else
+			log_debug_metadata("Couldn't find device with uuid %s.", buffer);
+	}
+
+	/*
+	 * A previous command wrote the VG while this dev was missing, so
+	 * the MISSING flag was included in the PV.
+	 */
+	if ((pv->status & MISSING_PV) && pv->dev)
+		log_warn("WARNING: VG %s was previously updated while PV %s was missing.", vg->name, dev_name(pv->dev));
+
+	/*
+	 * If this command writes the VG, we want the MISSING flag to be
+	 * written for this PV with no device.
+	 */
+	if (!pv->dev)
+		pv->status |= MISSING_PV;
+
+	/* is this correct? */
+	if ((pv->status & MISSING_PV) && pv->dev && (pv_mda_used_count(pv) == 0)) {
+		pv->status &= ~MISSING_PV;
+		log_info("Found a previously MISSING PV %s with no MDAs.", pv_dev_name(pv));
+	}
+
+	/* Fix up pv size if missing or impossibly large */
+	if ((!pv->size || pv->size > (1ULL << 62)) && pv->dev) {
+		if (!dev_get_size(pv->dev, &pv->size)) {
+			log_error("%s: Couldn't get size.", pv_dev_name(pv));
+			return;
+		}
+		log_verbose("Fixing up missing size (%s) for PV %s", display_size(fid->fmt->cmd, pv->size),
+			    pv_dev_name(pv));
+		size = pv->pe_count * (uint64_t) vg->extent_size + pv->pe_start;
+		if (size > pv->size)
+			log_warn("WARNING: Physical Volume %s is too large "
+				 "for underlying device", pv_dev_name(pv));
+	}
+}
+
+/*
+ * Finds the 'struct device' that correponds to each PV in the metadata,
+ * and may make some adjustments to vg fields based on the dev properties.
+ */
+void set_pv_devices(struct format_instance *fid, struct volume_group *vg)
+{
+	struct pv_list *pvl;
+
+	dm_list_iterate_items(pvl, &vg->pvs)
+		_set_pv_device(fid, vg, pvl->pv);
+}
+
 int get_vgnameids(struct cmd_context *cmd, struct dm_list *vgnameids,
 		  const char *only_this_vgname, int include_internal)
 {
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 8e9c18a..a140c29 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -502,4 +502,6 @@ struct id pv_vgid(const struct physical_volume *pv);
 uint64_t find_min_mda_size(struct dm_list *mdas);
 char *tags_format_and_copy(struct dm_pool *mem, const struct dm_list *tagsl);
 
+void set_pv_devices(struct format_instance *fid, struct volume_group *vg);
+
 #endif
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 6d89426..d41345f 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -617,6 +617,8 @@ static int _online_pvscan_one(struct cmd_context *cmd, struct device *dev,
 		if (pvid_without_metadata)
 			*pvid_without_metadata = dm_pool_strdup(cmd->mem, dev->pvid);
 		fmt->ops->destroy_instance(baton.fid);
+	} else {
+		set_pv_devices(baton.fid, baton.vg);
 	}
 
 	if (baton.vg && vg_is_shared(baton.vg)) {




More information about the lvm-devel mailing list