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

lvmetad: Hide corrupt MDAs from the cache.

This is probably not optimal, but makes the lvmetad case mimic non-lvmetad code
more closely. It also fixes vgremove of a partially corrupt VG with lvmetad, as
_vg_write_raw (and consequently, entire vg_write) currently panics when it
encounters a corrupt MDA. Ideally, we'd be able to explicitly control when it is
safe to ignore them.
This commit is contained in:
Petr Rockai 2014-02-27 23:06:42 +01:00
parent 6b43db5804
commit a368698672
2 changed files with 70 additions and 37 deletions

View File

@ -316,6 +316,49 @@ static void _xlate_mdah(struct mda_header *mdah)
}
}
static int _raw_read_mda_header(struct mda_header *mdah, struct device_area *dev_area)
{
if (!dev_open(dev_area->dev))
return_0;
if (!dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah))
return_0;
if (mdah->checksum_xl != xlate32(calc_crc(INITIAL_CRC, (uint8_t *)mdah->magic,
MDA_HEADER_SIZE -
sizeof(mdah->checksum_xl)))) {
log_error("Incorrect metadata area header checksum on %s"
" at offset %"PRIu64, dev_name(dev_area->dev),
dev_area->start);
return 0;
}
_xlate_mdah(mdah);
if (strncmp((char *)mdah->magic, FMTT_MAGIC, sizeof(mdah->magic))) {
log_error("Wrong magic number in metadata area header on %s"
" at offset %"PRIu64, dev_name(dev_area->dev),
dev_area->start);
return 0;
}
if (mdah->version != FMTT_VERSION) {
log_error("Incompatible metadata area header version: %d on %s"
" at offset %"PRIu64, mdah->version,
dev_name(dev_area->dev), dev_area->start);
return 0;
}
if (mdah->start != dev_area->start) {
log_error("Incorrect start sector in metadata area header: %"
PRIu64" on %s at offset %"PRIu64, mdah->start,
dev_name(dev_area->dev), dev_area->start);
return 0;
}
return 1;
}
struct mda_header *raw_read_mda_header(const struct format_type *fmt,
struct device_area *dev_area)
{
@ -326,46 +369,12 @@ struct mda_header *raw_read_mda_header(const struct format_type *fmt,
return NULL;
}
if (!dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah))
goto_bad;
if (mdah->checksum_xl != xlate32(calc_crc(INITIAL_CRC, (uint8_t *)mdah->magic,
MDA_HEADER_SIZE -
sizeof(mdah->checksum_xl)))) {
log_error("Incorrect metadata area header checksum on %s"
" at offset %"PRIu64, dev_name(dev_area->dev),
dev_area->start);
goto bad;
}
_xlate_mdah(mdah);
if (strncmp((char *)mdah->magic, FMTT_MAGIC, sizeof(mdah->magic))) {
log_error("Wrong magic number in metadata area header on %s"
" at offset %"PRIu64, dev_name(dev_area->dev),
dev_area->start);
goto bad;
}
if (mdah->version != FMTT_VERSION) {
log_error("Incompatible metadata area header version: %d on %s"
" at offset %"PRIu64, mdah->version,
dev_name(dev_area->dev), dev_area->start);
goto bad;
}
if (mdah->start != dev_area->start) {
log_error("Incorrect start sector in metadata area header: %"
PRIu64" on %s at offset %"PRIu64, mdah->start,
dev_name(dev_area->dev), dev_area->start);
goto bad;
if (!_raw_read_mda_header(mdah, dev_area)) {
dm_pool_free(fmt->cmd->mem, mdah);
return NULL;
}
return mdah;
bad:
dm_pool_free(fmt->cmd->mem, mdah);
return NULL;
}
static int _raw_write_mda_header(const struct format_type *fmt,
@ -1670,6 +1679,10 @@ static int _mda_export_text_raw(struct metadata_area *mda,
struct dm_config_node *parent)
{
struct mda_context *mdc = (struct mda_context *) mda->metadata_locn;
char mdah[MDA_HEADER_SIZE]; /* temporary */
if (!mdc || !_raw_read_mda_header(mdah, &mdc->area))
return 1; /* pretend the MDA does not exist */
return config_make_nodes(cft, parent, NULL,
"ignore = %" PRId64, (int64_t) mda_is_ignored(mda),

View File

@ -0,0 +1,20 @@
#!/bin/sh
# Copyright (C) 2013 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
. lib/test
aux prepare_vg 3
lvcreate -n blabla -L 1 $vg -an --zero n
dd if=/dev/urandom bs=512 seek=2 count=32 of="$dev2"
aux notify_lvmetad "$dev2"
vgremove -f $vg