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

handle bad metadata text in vg_read path

Corrupt metadata text (with good mda header) was being handled
in the label_scan phase, but not in the vg_read phase.  This
was sufficient because metadata areas would always be read and
checksummed during label_scan (metadata parsing was skipped
previously as an optimization.)

This changed with the optimization in
commit 61a6f9905e
"metadata: optimize reading metadata copies in scan"

Now, some metadata areas will not be read and checksummed
at all during the label_scan phase, only during the vg_read
phase.  This means that bad metadata text may first be detected
in the vg_read phase.  So, add equivalent bad metadata handling
to the vg_read path to match the label_scan path.
This commit is contained in:
David Teigland 2021-09-28 14:58:03 -05:00
parent e3b4c365a4
commit 939b4bc587
6 changed files with 49 additions and 15 deletions

14
lib/cache/lvmcache.c vendored
View File

@ -237,6 +237,20 @@ void lvmcache_save_bad_mda(struct lvmcache_info *info, struct metadata_area *mda
dm_list_add(&info->bad_mdas, &mda->list); dm_list_add(&info->bad_mdas, &mda->list);
} }
void lvmcache_del_save_bad_mda(struct lvmcache_info *info, int mda_num, int bad_mda_flag)
{
struct metadata_area *mda, *mda_safe;
dm_list_iterate_items_safe(mda, mda_safe, &info->mdas) {
if (mda->mda_num == mda_num) {
dm_list_del(&mda->list);
mda->bad_fields |= bad_mda_flag;
lvmcache_save_bad_mda(info, mda);
break;
}
}
}
void lvmcache_get_bad_mdas(struct cmd_context *cmd, void lvmcache_get_bad_mdas(struct cmd_context *cmd,
const char *vgname, const char *vgid, const char *vgname, const char *vgid,
struct dm_list *bad_mda_list) struct dm_list *bad_mda_list)

View File

@ -210,6 +210,8 @@ void lvmcache_del_outdated_devs(struct cmd_context *cmd,
void lvmcache_save_bad_mda(struct lvmcache_info *info, struct metadata_area *mda); void lvmcache_save_bad_mda(struct lvmcache_info *info, struct metadata_area *mda);
void lvmcache_del_save_bad_mda(struct lvmcache_info *info, int mda_num, int bad_mda_flag);
void lvmcache_get_bad_mdas(struct cmd_context *cmd, void lvmcache_get_bad_mdas(struct cmd_context *cmd,
const char *vgname, const char *vgid, const char *vgname, const char *vgid,
struct dm_list *bad_mda_list); struct dm_list *bad_mda_list);

View File

@ -465,6 +465,24 @@ static struct volume_group *_vg_read_raw(struct cmd_context *cmd,
vg = _vg_read_raw_area(cmd, fid, vgname, &mdac->area, vg_fmtdata, use_previous_vg, 0, mda_is_primary(mda)); vg = _vg_read_raw_area(cmd, fid, vgname, &mdac->area, vg_fmtdata, use_previous_vg, 0, mda_is_primary(mda));
if (!vg && !*use_previous_vg) {
/*
* This condition (corrupt metadata text) is often seen in the
* label_scan()/_text_read() phase, where this code corresponds to
* the lvmcache_save_bad_mda() in _text_read(). In this case we
* have two mda structs to deal with, one in lvmcache from label scan,
* and the mda copy on fid->metadata_areas_in_use.
*/
struct device *dev = mdac->area.dev;
struct lvmcache_info *info = lvmcache_info_from_pvid(dev->pvid, dev, 0);
log_warn("WARNING: reading %s mda%d failed to read metadata.", dev_name(dev), mda_is_primary(mda)?1:2);
log_warn("WARNING: repair VG metadata on %s with vgck --updatemetadata.", dev_name(dev));
/* remove mda from lvmcache, saving it in info->bad_mdas for possible repair with updatemetadata */
lvmcache_del_save_bad_mda(info, mda->mda_num, BAD_MDA_TEXT);
/* remove mda from fid */
fid_remove_mda(fid, mda, NULL, 0, 0);
}
return vg; return vg;
} }

View File

@ -157,13 +157,12 @@ struct volume_group *text_read_metadata(struct format_instance *fid,
if (!config_file_read_fd(cft, dev, MDA_CONTENT_REASON(primary_mda), offset, size, if (!config_file_read_fd(cft, dev, MDA_CONTENT_REASON(primary_mda), offset, size,
offset2, size2, checksum_fn, checksum, offset2, size2, checksum_fn, checksum,
skip_parse, 1)) { skip_parse, 1)) {
/* FIXME: handle errors */ log_warn("WARNING: couldn't read volume group metadata from %s.", dev_name(dev));
log_error("Couldn't read volume group metadata from %s.", dev_name(dev));
goto out; goto out;
} }
} else { } else {
if (!config_file_read(cft)) { if (!config_file_read(cft)) {
log_error("Couldn't read volume group metadata from file."); log_warn("WARNING: couldn't read volume group metadata from file.");
goto out; goto out;
} }
} }

View File

@ -4798,7 +4798,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
* fid->metadata_areas_in_use by create_instance above, and here we * fid->metadata_areas_in_use by create_instance above, and here we
* read VG metadata from each of those mdas. * read VG metadata from each of those mdas.
*/ */
dm_list_iterate_items(mda, &fid->metadata_areas_in_use) { dm_list_iterate_items_safe(mda, mda2, &fid->metadata_areas_in_use) {
mda_dev = mda_get_device(mda); mda_dev = mda_get_device(mda);
/* I don't think this can happen */ /* I don't think this can happen */

View File

@ -44,7 +44,7 @@ sed 's/flags =/flagx =/' meta1 > meta1.bad
dd if=meta1.bad of="$dev1" dd if=meta1.bad of="$dev1"
pvs 2>&1 | tee out pvs 2>&1 | tee out
grep "bad metadata text" out grep "Checksum error" out
pvs "$dev1" pvs "$dev1"
pvs "$dev2" pvs "$dev2"
@ -58,7 +58,7 @@ lvcreate -l1 $vg
vgck --updatemetadata $vg vgck --updatemetadata $vg
pvs 2>&1 | tee out pvs 2>&1 | tee out
not grep "bad metadata text" out not grep "Checksum error" out
pvs "$dev1" pvs "$dev1"
pvs "$dev2" pvs "$dev2"
@ -92,7 +92,8 @@ dd if=meta1.bad of="$dev1"
dd if=meta2.bad of="$dev2" dd if=meta2.bad of="$dev2"
pvs 2>&1 | tee out pvs 2>&1 | tee out
grep "bad metadata text" out > out2 # FIXME: find a better test than looking for a specific message
grep "Checksum error" out > out2
grep "$dev1" out2 grep "$dev1" out2
grep "$dev2" out2 grep "$dev2" out2
@ -108,7 +109,7 @@ lvcreate -l1 $vg
vgck --updatemetadata $vg vgck --updatemetadata $vg
pvs 2>&1 | tee out pvs 2>&1 | tee out
not grep "bad metadata text" out not grep "Checksum error" out
pvs "$dev1" pvs "$dev1"
pvs "$dev2" pvs "$dev2"
@ -149,7 +150,7 @@ dd if=meta2.bad of="$dev2"
dd if=meta3.bad of="$dev3" dd if=meta3.bad of="$dev3"
pvs 2>&1 | tee out pvs 2>&1 | tee out
grep "bad metadata text" out > out2 grep "Checksum error" out > out2
grep "$dev1" out2 grep "$dev1" out2
grep "$dev2" out2 grep "$dev2" out2
grep "$dev3" out2 grep "$dev3" out2
@ -166,7 +167,7 @@ lvcreate -l1 $vg
vgck --updatemetadata $vg vgck --updatemetadata $vg
pvs 2>&1 | tee out pvs 2>&1 | tee out
not grep "bad metadata text" out not grep "Checksum error" out
pvs "$dev1" pvs "$dev1"
pvs "$dev2" pvs "$dev2"
@ -197,7 +198,7 @@ sed 's/READ/RRRR/' meta1 > meta1.bad
dd if=meta1.bad of="$dev1" dd if=meta1.bad of="$dev1"
pvs 2>&1 | tee out pvs 2>&1 | tee out
grep "bad metadata text" out > out2 grep "Checksum error" out > out2
grep "$dev1" out2 grep "$dev1" out2
# We can still use the VG with other available # We can still use the VG with other available
@ -224,7 +225,7 @@ aux enable_dev "$dev2"
# Both old and bad metadata are reported. # Both old and bad metadata are reported.
pvs 2>&1 | tee out pvs 2>&1 | tee out
grep "ignoring metadata seqno" out grep "ignoring metadata seqno" out
grep "bad metadata text" out grep "Checksum error" out
pvs "$dev1" pvs "$dev1"
pvs "$dev2" pvs "$dev2"
pvs "$dev3" pvs "$dev3"
@ -238,7 +239,7 @@ vgck --updatemetadata $vg
pvs 2>&1 | tee out pvs 2>&1 | tee out
not grep "ignoring metadata seqno" out not grep "ignoring metadata seqno" out
not grep "bad metadata text" out not grep "Checksum error" out
pvs "$dev1" pvs "$dev1"
pvs "$dev2" pvs "$dev2"
pvs "$dev3" pvs "$dev3"
@ -282,7 +283,7 @@ dd if=meta1.bad of="$dev1"
dd if=meta2.bad of="$dev2" dd if=meta2.bad of="$dev2"
pvs 2>&1 | tee out pvs 2>&1 | tee out
grep "bad metadata text" out > out2 grep "Checksum error" out > out2
grep "$dev1" out2 grep "$dev1" out2
grep "$dev2" out2 grep "$dev2" out2
@ -319,7 +320,7 @@ not ls "$RUNDIR/lvm/vgs_online/$vg"
vgck --updatemetadata $vg vgck --updatemetadata $vg
pvs 2>&1 | tee out pvs 2>&1 | tee out
not grep "bad metadata text" out not grep "Checksum error" out
pvs "$dev1" pvs "$dev1"
pvs "$dev2" pvs "$dev2"