summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2019-02-06 12:32:26 -0600
committerDavid Teigland <teigland@redhat.com>2019-04-11 12:03:04 -0500
commit4de9e82b75a9ef31889345665e514c74e8347e1d (patch)
tree6af4e85ec6fb99c1d230a961fa216713eb65c00e
parenta3601b40048927eb80f6de22678a117321034c9e (diff)
downloadlvm2-4de9e82b75a9ef31889345665e514c74e8347e1d.tar.gz
move wipe_outdated_pvs to vg_write
and implement it based on a device, not based on a pv struct (which is not available when the device is not a part of the vg.) currently only the vgremove command wipes outdated pvs until more advanced recovery is added in a subsequent commit
-rw-r--r--lib/commands/toolcontext.h1
-rw-r--r--lib/format_text/format-text.c33
-rw-r--r--lib/format_text/format-text.h3
-rw-r--r--lib/metadata/metadata.c123
-rw-r--r--tools/vgremove.c2
5 files changed, 109 insertions, 53 deletions
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index fea0e5142..31cda2bdb 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -175,6 +175,7 @@ struct cmd_context {
unsigned use_hints:1; /* if hints are enabled this cmd can use them */
unsigned pvscan_recreate_hints:1; /* enable special case hint handling for pvscan --cache */
unsigned scan_lvs:1;
+ unsigned wipe_outdated_pvs:1;
/*
* Devices and filtering.
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index 9423712c4..f8756a882 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -2633,3 +2633,36 @@ bad:
return NULL;
}
+
+int text_wipe_outdated_pv_mda(struct cmd_context *cmd, struct device *dev,
+ struct metadata_area *mda)
+{
+ struct mda_context *mdac = mda->metadata_locn;
+ uint64_t start_byte = mdac->area.start;
+ struct mda_header *mdab;
+ struct raw_locn *rlocn_slot0;
+ struct raw_locn *rlocn_slot1;
+ uint32_t bad_fields = 0;
+
+ if (!(mdab = raw_read_mda_header(cmd->fmt, &mdac->area, mda_is_primary(mda), 0, &bad_fields))) {
+ log_error("Failed to read outdated pv mda header on %s", dev_name(dev));
+ return 0;
+ }
+
+ rlocn_slot0 = &mdab->raw_locns[0];
+ rlocn_slot1 = &mdab->raw_locns[1];
+
+ rlocn_slot0->offset = 0;
+ rlocn_slot0->size = 0;
+ rlocn_slot0->checksum = 0;
+ rlocn_slot1->offset = 0;
+ rlocn_slot1->size = 0;
+ rlocn_slot1->checksum = 0;
+
+ if (!_raw_write_mda_header(cmd->fmt, dev, mda_is_primary(mda), start_byte, mdab)) {
+ log_error("Failed to write outdated pv mda header on %s", dev_name(dev));
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/lib/format_text/format-text.h b/lib/format_text/format-text.h
index c42d5c0f7..2345d52a9 100644
--- a/lib/format_text/format-text.h
+++ b/lib/format_text/format-text.h
@@ -77,4 +77,7 @@ struct data_area_list {
struct disk_locn disk_locn;
};
+int text_wipe_outdated_pv_mda(struct cmd_context *cmd, struct device *dev,
+ struct metadata_area *mda);
+
#endif
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 1e92a1084..2d6364688 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -28,11 +28,14 @@
#include "lib/display/display.h"
#include "lib/locking/locking.h"
#include "lib/format_text/archiver.h"
+#include "lib/format_text/format-text.h"
+#include "lib/format_text/layout.h"
+#include "lib/format_text/import-export.h"
#include "lib/config/defaults.h"
#include "lib/locking/lvmlockd.h"
-#include "time.h"
#include "lib/notify/lvmnotify.h"
+#include <time.h>
#include <math.h>
static struct physical_volume *_pv_read(struct cmd_context *cmd,
@@ -2922,6 +2925,69 @@ static int _handle_historical_lvs(struct volume_group *vg)
return 1;
}
+static void _wipe_outdated_pvs(struct cmd_context *cmd, struct volume_group *vg)
+{
+ struct dm_list devs;
+ struct dm_list *mdas = NULL;
+ struct device_list *devl;
+ struct device *dev;
+ struct metadata_area *mda;
+ struct label *label;
+ struct lvmcache_info *info;
+ uint32_t ext_flags;
+
+ dm_list_init(&devs);
+
+ /*
+ * When vg_read selected a good copy of the metadata, it used it to
+ * update the lvmcache representation of the VG (lvmcache_update_vg).
+ * At that point outdated PVs were recognized and moved into the
+ * vginfo->outdated_infos list. Here we clear the PVs on that list.
+ */
+
+ lvmcache_get_outdated_devs(cmd, vg->name, (const char *)&vg->id, &devs);
+
+ dm_list_iterate_items(devl, &devs) {
+ dev = devl->dev;
+
+ lvmcache_get_outdated_mdas(cmd, vg->name, (const char *)&vg->id, dev, &mdas);
+
+ if (mdas) {
+ dm_list_iterate_items(mda, mdas) {
+ log_warn("WARNING: wiping mda on outdated PV %s", dev_name(dev));
+
+ if (!text_wipe_outdated_pv_mda(cmd, dev, mda))
+ log_warn("WARNING: failed to wipe mda on outdated PV %s", dev_name(dev));
+ }
+ }
+
+ if (!(label = lvmcache_get_dev_label(dev))) {
+ log_error("_wipe_outdated_pvs no label for %s", dev_name(dev));
+ continue;
+ }
+
+ info = label->info;
+ ext_flags = lvmcache_ext_flags(info);
+ ext_flags &= ~PV_EXT_USED;
+ lvmcache_set_ext_version(info, PV_HEADER_EXTENSION_VSN);
+ lvmcache_set_ext_flags(info, ext_flags);
+
+ log_warn("WARNING: wiping header on outdated PV %s", dev_name(dev));
+
+ if (!label_write(dev, label))
+ log_warn("WARNING: failed to wipe header on outdated PV %s", dev_name(dev));
+
+ lvmcache_del(info);
+ }
+
+ /*
+ * A vgremove will involve many vg_write() calls (one for each lv
+ * removed) but we only need to wipe pvs once, so clear the outdated
+ * list so it won't be wiped again.
+ */
+ lvmcache_del_outdated_devs(cmd, vg->name, (const char *)&vg->id);
+}
+
/*
* After vg_write() returns success,
* caller MUST call either vg_commit() or vg_revert()
@@ -2986,6 +3052,9 @@ int vg_write(struct volume_group *vg)
return 0;
}
+ if (vg->cmd->wipe_outdated_pvs)
+ _wipe_outdated_pvs(vg->cmd, vg);
+
if (critical_section())
log_error(INTERNAL_ERROR
"Writing metadata in critical section.");
@@ -3538,52 +3607,6 @@ static int _repair_inconsistent_vg(struct volume_group *vg, uint32_t lockd_state
return 1;
}
-static int _wipe_outdated_pvs(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *to_check, uint32_t lockd_state)
-{
- struct pv_list *pvl, *pvl2;
- char uuid[64] __attribute__((aligned(8)));
-
- if (lvmcache_found_duplicate_pvs()) {
- log_debug_metadata("Skip wiping outdated PVs with duplicates.");
- return 0;
- }
-
- /*
- * Cannot write foreign VGs, the owner will repair it.
- * Also, if another host is updating its VG, we may read
- * the PVs while some are written but not others, making
- * some PVs look outdated to us just because we're reading
- * the VG while it's only partially written out.
- */
- if (_is_foreign_vg(vg)) {
- log_debug_metadata("Skip wiping outdated PVs for foreign VG.");
- return 0;
- }
-
- if (vg_is_shared(vg) && !(lockd_state & LDST_EX)) {
- log_verbose("Skip wiping outdated PVs for shared VG without exclusive lock.");
- return 0;
- }
-
- dm_list_iterate_items(pvl, to_check) {
- dm_list_iterate_items(pvl2, &vg->pvs) {
- if (pvl->pv->dev == pvl2->pv->dev)
- goto next_pv;
- }
-
-
- if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid)))
- return_0;
- log_warn("WARNING: Removing PV %s (%s) that no longer belongs to VG %s",
- pv_dev_name(pvl->pv), uuid, vg->name);
- if (!pv_write_orphan(cmd, pvl->pv))
- return_0;
-next_pv:
- ;
- }
- return 1;
-}
-
static int _check_or_repair_pv_ext(struct cmd_context *cmd,
struct volume_group *vg,
uint32_t lockd_state,
@@ -4217,12 +4240,6 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
release_vg(correct_vg);
return NULL;
}
-
- if (!_wipe_outdated_pvs(cmd, correct_vg, &all_pvs, lockd_state)) {
- _free_pv_list(&all_pvs);
- release_vg(correct_vg);
- return_NULL;
- }
}
_free_pv_list(&all_pvs);
diff --git a/tools/vgremove.c b/tools/vgremove.c
index 212085869..3b6b2610a 100644
--- a/tools/vgremove.c
+++ b/tools/vgremove.c
@@ -115,6 +115,8 @@ int vgremove(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
+ cmd->wipe_outdated_pvs = 1;
+
cmd->handles_missing_pvs = 1;
ret = process_each_vg(cmd, argc, argv, NULL, NULL,
READ_FOR_UPDATE, 0,