1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

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
This commit is contained in:
David Teigland 2019-02-06 12:32:26 -06:00
parent 45b164f62c
commit ab61a6d85d
5 changed files with 109 additions and 53 deletions

View File

@ -179,6 +179,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.

View File

@ -2463,3 +2463,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;
}

View File

@ -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

View File

@ -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);

View File

@ -99,6 +99,8 @@ int vgremove(struct cmd_context *cmd, int argc, char **argv)
clear_hint_file(cmd);
cmd->wipe_outdated_pvs = 1;
cmd->handles_missing_pvs = 1;
ret = process_each_vg(cmd, argc, argv, NULL, NULL,
READ_FOR_UPDATE, 0,