summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2016-09-13 16:50:47 -0500
committerDavid Teigland <teigland@redhat.com>2016-09-14 10:43:33 -0500
commitd455300d7baff341f1c7fe5776d975369dd3a23a (patch)
treee8d9b60cf2e0094796bedd681a72713db16c9dce
parent629059ee84e83b9d013d80e0b382a3474b30c7a4 (diff)
downloadlvm2-d455300d7baff341f1c7fe5776d975369dd3a23a.tar.gz
lvmlockd: fix metadata validation when rescanning VG
When rescanning a VG from disk, the metadata read from each PV was compared as a sanity check. The comparison is done by exporting the vg metadata from each dev to a config tree, and then comparing the config trees. The function to create the config tree inserts extraneous information along with the actual VG metadata. This extra info includes creation_time. The config trees for two devs can easily be created one second apart in which case the different creation_times would cause the metadata comparison to fail. The fix is to exclude the extraneous info from the metadata comparison.
-rw-r--r--lib/cache/lvmetad.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index b3cd1bf22..727d3d399 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -1918,15 +1918,44 @@ scan_more:
vgmeta_ret = vgmeta;
save_dev = devl->dev;
} else {
- if (compare_config(vgmeta_ret->root, vgmeta->root)) {
+ struct dm_config_node *meta1 = vgmeta_ret->root;
+ struct dm_config_node *meta2 = vgmeta->root;
+ struct dm_config_node *sib1 = meta1->sib;
+ struct dm_config_node *sib2 = meta2->sib;
+
+ /*
+ * Do not compare the extraneous data that
+ * export_vg_to_config_tree() inserts next to the
+ * actual VG metadata. This includes creation_time
+ * which may not match since it is generated separately
+ * for each call to create the config tree.
+ *
+ * We're saving the sibling pointer and restoring it
+ * after the compare because we're unsure if anything
+ * later might want it.
+ *
+ * FIXME: make it clearer what we're doing here, e.g.
+ * pass a parameter to export_vg_to_config_tree()
+ * telling it to skip the extraneous data, or something.
+ * It's very non-obvious that setting sib=NULL does that.
+ */
+ meta1->sib = NULL;
+ meta2->sib = NULL;
+
+ if (compare_config(meta1, meta2)) {
log_error("VG %s metadata comparison failed for device %s vs %s",
vg->name, dev_name(devl->dev), save_dev ? dev_name(save_dev) : "none");
_log_debug_inequality(vg->name, vgmeta_ret->root, vgmeta->root);
+
+ meta1->sib = sib1;
+ meta2->sib = sib2;
dm_config_destroy(vgmeta);
dm_config_destroy(vgmeta_ret);
release_vg(baton.vg);
return NULL;
}
+ meta1->sib = sib1;
+ meta2->sib = sib2;
dm_config_destroy(vgmeta);
}