diff options
author | David Teigland <teigland@redhat.com> | 2016-09-13 16:50:47 -0500 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2016-09-14 10:43:33 -0500 |
commit | d455300d7baff341f1c7fe5776d975369dd3a23a (patch) | |
tree | e8d9b60cf2e0094796bedd681a72713db16c9dce | |
parent | 629059ee84e83b9d013d80e0b382a3474b30c7a4 (diff) | |
download | lvm2-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.c | 31 |
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); } |