summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2019-02-05 12:08:00 -0600
committerDavid Teigland <teigland@redhat.com>2019-04-11 12:03:04 -0500
commit990c824c21871018b6b21cc79d4832932caa9a3e (patch)
tree0b8adb14014668afe4c62c7cd3c7f6d6671dbd38
parent4eff1da46f80eba498e4cf16e6a84046068a42da (diff)
downloadlvm2-990c824c21871018b6b21cc79d4832932caa9a3e.tar.gz
add flags to keep track of bad metadata
When reading metadata headers and text, use a new set of flags to identify specific errors that are seen. These will be used for more advanced repair in a subsequent commit.
-rw-r--r--lib/format_text/format-text.c64
-rw-r--r--lib/format_text/layout.h4
-rw-r--r--lib/format_text/text_label.c3
-rw-r--r--lib/metadata/metadata.h14
4 files changed, 67 insertions, 18 deletions
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index d97617753..3a015f371 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -166,6 +166,7 @@ static int _pv_analyze_mda_raw (const struct format_type * fmt,
char *buf=NULL;
struct device_area *area;
struct mda_context *mdac;
+ uint32_t bad_fields = 0;
int r=0;
mdac = (struct mda_context *) mda->metadata_locn;
@@ -174,7 +175,7 @@ static int _pv_analyze_mda_raw (const struct format_type * fmt,
FMTu64, mdac->area.start, mdac->area.size);
area = &mdac->area;
- if (!(mdah = raw_read_mda_header(fmt, area, mda_is_primary(mda))))
+ if (!(mdah = raw_read_mda_header(fmt, area, mda_is_primary(mda), 0, &bad_fields)))
goto_out;
rlocn = mdah->raw_locns;
@@ -312,61 +313,88 @@ static void _xlate_mdah(struct mda_header *mdah)
}
}
-static int _raw_read_mda_header(struct mda_header *mdah, struct device_area *dev_area, int primary_mda)
+static int _raw_read_mda_header(struct mda_header *mdah, struct device_area *dev_area,
+ int primary_mda, uint32_t ignore_bad_fields, uint32_t *bad_fields)
{
+ int bad = 0;
+
log_debug_metadata("Reading mda header sector from %s at %llu",
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
if (!dev_read_bytes(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah)) {
log_error("Failed to read metadata area header on %s at %llu",
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
+ *bad_fields |= BAD_MDA_READ;
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 checksum in metadata area header on %s at %llu",
+ log_warn("WARNING: wrong checksum %x in mda header on %s at %llu",
+ mdah->checksum_xl,
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
- return 0;
+
+ if (!(ignore_bad_fields & BAD_MDA_CHECKSUM)) {
+ *bad_fields |= BAD_MDA_CHECKSUM;
+ bad = 1;
+ }
}
_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 %llu",
+ log_warn("WARNING: wrong magic number %.8s in mda header on %s at %llu",
+ mdah->magic,
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
- return 0;
+
+ if (!(ignore_bad_fields & BAD_MDA_MAGIC)) {
+ *bad_fields |= BAD_MDA_MAGIC;
+ bad = 1;
+ }
}
if (mdah->version != FMTT_VERSION) {
- log_error("Incompatible version %u metadata area header on %s at %llu",
+ log_warn("WARNING: wrong version %u in mda header on %s at %llu",
mdah->version,
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
- return 0;
+
+ if (!(ignore_bad_fields & BAD_MDA_VERSION)) {
+ *bad_fields |= BAD_MDA_VERSION;
+ bad = 1;
+ }
}
if (mdah->start != dev_area->start) {
- log_error("Incorrect start sector %llu in metadata area header on %s at %llu",
+ log_warn("WARNING: wrong start sector %llu in mda header on %s at %llu",
(unsigned long long)mdah->start,
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
- return 0;
+
+ if (!(ignore_bad_fields & BAD_MDA_START)) {
+ *bad_fields |= BAD_MDA_START;
+ bad = 1;
+ }
}
+ if (bad)
+ return 0;
+
return 1;
}
struct mda_header *raw_read_mda_header(const struct format_type *fmt,
- struct device_area *dev_area, int primary_mda)
+ struct device_area *dev_area,
+ int primary_mda, uint32_t ignore_bad_fields, uint32_t *bad_fields)
{
struct mda_header *mdah;
if (!(mdah = dm_pool_alloc(fmt->cmd->mem, MDA_HEADER_SIZE))) {
log_error("struct mda_header allocation failed");
+ *bad_fields |= BAD_MDA_INTERNAL;
return NULL;
}
- if (!_raw_read_mda_header(mdah, dev_area, primary_mda)) {
+ if (!_raw_read_mda_header(mdah, dev_area, primary_mda, ignore_bad_fields, bad_fields)) {
dm_pool_free(fmt->cmd->mem, mdah);
return NULL;
}
@@ -564,8 +592,9 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
time_t when;
char *desc;
uint32_t wrap = 0;
+ uint32_t bad_fields = 0;
- if (!(mdah = raw_read_mda_header(fid->fmt, area, primary_mda))) {
+ if (!(mdah = raw_read_mda_header(fid->fmt, area, primary_mda, 0, &bad_fields))) {
log_error("Failed to read vg %s from %s", vgname, dev_name(area->dev));
goto out;
}
@@ -686,6 +715,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
uint64_t old_start = 0, old_last = 0, old_size = 0, old_wrap = 0;
uint64_t new_start = 0, new_last = 0, new_size = 0, new_wrap = 0;
uint64_t max_size;
+ uint32_t bad_fields = 0;
char *new_buf = NULL;
int overlap;
int found = 0;
@@ -701,7 +731,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
if (!found)
return 1;
- if (!(mdah = raw_read_mda_header(fid->fmt, &mdac->area, mda_is_primary(mda))))
+ if (!(mdah = raw_read_mda_header(fid->fmt, &mdac->area, mda_is_primary(mda), mda->ignore_bad_fields, &bad_fields)))
goto_out;
/*
@@ -972,6 +1002,7 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
struct raw_locn *rlocn_slot1;
struct raw_locn *rlocn_new;
struct pv_list *pvl;
+ uint32_t bad_fields = 0;
int r = 0;
int found = 0;
@@ -992,7 +1023,7 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
* mdah buffer, but the mdah buffer is not modified and mdac->rlocn is
* modified.
*/
- if (!(mdab = raw_read_mda_header(fid->fmt, &mdac->area, mda_is_primary(mda))))
+ if (!(mdab = raw_read_mda_header(fid->fmt, &mdac->area, mda_is_primary(mda), mda->ignore_bad_fields, &bad_fields)))
goto_out;
/*
@@ -1184,6 +1215,7 @@ static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
struct mda_header *mdah;
struct raw_locn *rlocn_slot0;
struct raw_locn *rlocn_slot1;
+ uint32_t bad_fields = 0;
int r = 0;
if (!(mdah = dm_pool_alloc(fid->fmt->cmd->mem, MDA_HEADER_SIZE))) {
@@ -1197,7 +1229,7 @@ static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
* Just to print the warning?
*/
- if (!_raw_read_mda_header(mdah, &mdac->area, mda_is_primary(mda)))
+ if (!_raw_read_mda_header(mdah, &mdac->area, mda_is_primary(mda), 0, &bad_fields))
log_warn("WARNING: Removing metadata location on %s with bad mda header.",
dev_name(mdac->area.dev));
diff --git a/lib/format_text/layout.h b/lib/format_text/layout.h
index e1462f172..7320d9c2f 100644
--- a/lib/format_text/layout.h
+++ b/lib/format_text/layout.h
@@ -81,7 +81,9 @@ struct mda_header {
} __attribute__ ((packed));
struct mda_header *raw_read_mda_header(const struct format_type *fmt,
- struct device_area *dev_area, int primary_mda);
+ struct device_area *dev_area, int primary_mda,
+ uint32_t ignore_bad_fields,
+ uint32_t *bad_fields);
struct mda_lists {
struct metadata_area_ops *file_ops;
diff --git a/lib/format_text/text_label.c b/lib/format_text/text_label.c
index 1157b98aa..72c153e75 100644
--- a/lib/format_text/text_label.c
+++ b/lib/format_text/text_label.c
@@ -331,8 +331,9 @@ static int _read_mda_header_and_metadata(struct metadata_area *mda, void *baton)
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct mda_header *mdah;
struct lvmcache_vgsummary vgsummary = { 0 };
+ uint32_t bad_fields = 0;
- if (!(mdah = raw_read_mda_header(fmt, &mdac->area, mda_is_primary(mda)))) {
+ if (!(mdah = raw_read_mda_header(fmt, &mdac->area, mda_is_primary(mda), 0, &bad_fields))) {
log_error("Failed to read mda header from %s", dev_name(mdac->area.dev));
goto fail;
}
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index a140c29f3..d904aa642 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -168,11 +168,25 @@ struct metadata_area_ops {
#define MDA_CONTENT_REASON(primary_mda) ((primary_mda) ? DEV_IO_MDA_CONTENT : DEV_IO_MDA_EXTRA_CONTENT)
#define MDA_HEADER_REASON(primary_mda) ((primary_mda) ? DEV_IO_MDA_HEADER : DEV_IO_MDA_EXTRA_HEADER)
+/*
+ * Flags describing errors found while reading.
+ */
+#define BAD_MDA_INTERNAL 0x00000001 /* internal lvm error */
+#define BAD_MDA_READ 0x00000002 /* read io failed */
+#define BAD_MDA_HEADER 0x00000004 /* general problem with header */
+#define BAD_MDA_TEXT 0x00000008 /* general problem with text */
+#define BAD_MDA_CHECKSUM 0x00000010
+#define BAD_MDA_MAGIC 0x00000020
+#define BAD_MDA_VERSION 0x00000040
+#define BAD_MDA_START 0x00000080
+
struct metadata_area {
struct dm_list list;
struct metadata_area_ops *ops;
void *metadata_locn;
uint32_t status;
+ uint32_t bad_fields; /* BAD_MDA_ flags are set to indicate errors found when reading */
+ uint32_t ignore_bad_fields; /* BAD_MDA_ flags are set to indicate errors to ignore */
};
struct metadata_area *mda_copy(struct dm_pool *mem,
struct metadata_area *mda);