1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

vgchange: allow changing system ID with majority of PVs

when used with --majoritypvs.  This allows the fail-over
of a VG between systems by changing the VG system ID when
a PV is missing.
This commit is contained in:
David Teigland 2022-07-07 16:06:01 -05:00
parent da44f2b6fe
commit aa85ed1784
4 changed files with 94 additions and 2 deletions

View File

@ -22,7 +22,7 @@ print_lvmlocal() {
. lib/inittest
aux prepare_devs 1
aux prepare_devs 5
SIDFILE="etc/lvm_test.conf"
LVMLOCAL="etc/lvmlocal.conf"
@ -541,6 +541,73 @@ echo "$SID1" > "$SIDFILE"
clear_df_systemid
vgremove $vg1
# vgchange --systemid --majoritypvs
SID1=sidfoofile1
SID2=sidfoofile2
rm -f "$LVMLOCAL"
echo "$SID1" > "$SIDFILE"
clear_df_systemid
aux lvmconf "global/system_id_source = file" \
"global/system_id_file = \"$SIDFILE\""
# create a vg
vgcreate $vg1 "$dev1" "$dev2" "$dev3"
vgcreate $vg2 "$dev4" "$dev5"
# normal vgs sees the vg
# change the local system_id, making the vg foreign
echo "$SID2" > "$SIDFILE"
clear_df_systemid
# normal vgs doesn't see the vg
vgs >err
not grep $vg1 err
not grep $vg2 err
# using --foreign we can see the vg
vgs --foreign >err
grep $vg1 err
grep $vg2 err
# cannot clear the system_id of the foreign vg
not vgchange --yes --systemid "" $vg1
not vgchange --yes --systemid "" $vg2
# cannot set the system_id of the foreign vg
not vgchange --yes --systemid foo $vg1
not vgchange --yes --systemid foo $vg2
# we are local node SID2, foreign node is SID1
# use extra_system_ids to take over the foreign vg, making it local
vgchange --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg1
vgs $vg1
# make it foreign again
vgchange --yes --systemid sidfoofile1 $vg1
not vgs $vg1
# both vgs are foreign, drop dev1/dev4 so both vgs are missing a device
aux hide_dev "$dev1"
aux hide_dev "$dev4"
not pvs "$dev1"
not pvs "$dev4"
# neither VG can be changed because both are missing a dev
not vgchange --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg1
not vgchange --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg2
# using majoritypvs, vg1 can be changed because 2 of 3 PVs exist
vgchange --majoritypvs --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg1
vgs $vg1
# using majoritypvs, vg2 cannot be changed because 1 of 2 PVs exist
not vgchange --majoritypvs --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg2
not vgs $vg2
vgs --foreign $vg2
# dev1/dev4 return so we can take over vg2 now
# vg1 will complain about stale metadata on dev1
aux unhide_dev "$dev1"
aux unhide_dev "$dev4"
vgs
pvs
vgchange --majoritypvs --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg2
vgs $vg2
# update metadata on dev1
vgck --updatemetadata $vg1
vgs $vg1
clear_df_systemid
vgremove $vg1
vgremove $vg2
# vgcfgbackup backs up foreign vg with --foreign
SID1=sidfoofile1
SID2=sidfoofile2

View File

@ -416,6 +416,10 @@ arg(logonly_ARG, '\0', "logonly", 0, 0, 0,
arg(longhelp_ARG, '\0', "longhelp", 0, 0, 0,
"Display long help text.\n")
arg(majoritypvs_ARG, '\0', "majoritypvs", 0, 0, 0,
"Change the VG system ID if the majority of PVs in the VG\n"
"are present (one more than half).\n")
arg(maxrecoveryrate_ARG, '\0', "maxrecoveryrate", sizekb_VAL, 0, 0,
"Sets the maximum recovery rate for a RAID LV. The rate value\n"
"is an amount of data per second for each device in the array.\n"

View File

@ -1767,7 +1767,7 @@ ID: vgchange_refresh
DESC: Reactivate LVs using the latest metadata.
vgchange --systemid String VG|Tag|Select
OO: --select String
OO: --select String, --majoritypvs
ID: vgchange_systemid
DESC: Change the system ID of a VG.

View File

@ -1383,6 +1383,24 @@ static int _vgchange_systemid_single(struct cmd_context *cmd, const char *vg_nam
struct volume_group *vg,
struct processing_handle *handle)
{
if (arg_is_set(cmd, majoritypvs_ARG)) {
struct pv_list *pvl;
int missing_pvs = 0;
int found_pvs = 0;
dm_list_iterate_items(pvl, &vg->pvs) {
if (!pvl->pv->dev)
missing_pvs++;
else
found_pvs++;
}
if (found_pvs <= missing_pvs) {
log_error("Cannot change system ID without the majority of PVs (found %d of %d)",
found_pvs, found_pvs+missing_pvs);
return ECMD_FAILED;
}
}
if (!_vgchange_system_id(cmd, vg))
return_ECMD_FAILED;
@ -1415,6 +1433,9 @@ int vgchange_systemid_cmd(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
if (arg_is_set(cmd, majoritypvs_ARG))
cmd->handles_missing_pvs = 1;
ret = process_each_vg(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, 0, handle, &_vgchange_systemid_single);
destroy_processing_handle(cmd, handle);