summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2019-02-05 12:39:08 -0600
committerDavid Teigland <teigland@redhat.com>2019-04-11 12:03:04 -0500
commit838ba5930c4cf97cbe55efb163a33856c066eb61 (patch)
tree6a972c4361ba74e004e1b8d93f47c199731ad380
parent990c824c21871018b6b21cc79d4832932caa9a3e (diff)
downloadlvm2-838ba5930c4cf97cbe55efb163a33856c066eb61.tar.gz
ability to keep track of bad mdas in lvmcache
mda's that cannot be processed by lvm because of some corruption can be kept on a separate list. These will be used for more advanced repair in a subsequent commit.
-rw-r--r--lib/cache/lvmcache.c52
-rw-r--r--lib/cache/lvmcache.h9
-rw-r--r--lib/metadata/metadata.h1
3 files changed, 62 insertions, 0 deletions
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 8aed59ba9..8a8a2c867 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -31,6 +31,7 @@ struct lvmcache_info {
struct dm_list mdas; /* list head for metadata areas */
struct dm_list das; /* list head for data areas */
struct dm_list bas; /* list head for bootloader areas */
+ struct dm_list bad_mdas;/* list head for bad metadata areas */
struct lvmcache_vginfo *vginfo; /* NULL == unknown */
struct label *label;
const struct format_type *fmt;
@@ -39,6 +40,8 @@ struct lvmcache_info {
uint32_t ext_version; /* Extension version */
uint32_t ext_flags; /* Extension flags */
uint32_t status;
+ unsigned mda1_bad:1; /* label scan found bad metadata in mda1 */
+ unsigned mda2_bad:1; /* label scan found bad metadata in mda2 */
};
/* One per VG */
@@ -175,6 +178,51 @@ static void _destroy_duplicate_device_list(struct dm_list *head)
dm_list_init(head);
}
+int lvmcache_has_bad_metadata(struct device *dev)
+{
+ struct lvmcache_info *info;
+
+ if (!(info = lvmcache_info_from_pvid(dev->pvid, dev, 0))) {
+ /* shouldn't happen */
+ log_error("No lvmcache info for checking bad metadata on %s", dev_name(dev));
+ return 0;
+ }
+
+ if (info->mda1_bad || info->mda2_bad)
+ return 1;
+ return 0;
+}
+
+void lvmcache_save_bad_mda(struct lvmcache_info *info, struct metadata_area *mda)
+{
+ if (mda->mda_num == 1)
+ info->mda1_bad = 1;
+ else if (mda->mda_num == 2)
+ info->mda2_bad = 1;
+ dm_list_add(&info->bad_mdas, &mda->list);
+}
+
+void lvmcache_get_bad_mdas(struct cmd_context *cmd,
+ const char *vgname, const char *vgid,
+ struct dm_list *bad_mdas)
+{
+ struct lvmcache_vginfo *vginfo;
+ struct lvmcache_info *info;
+ struct metadata_area *mda, *mda2;
+
+ if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) {
+ log_error(INTERNAL_ERROR "lvmcache_get_bad_mdas no vginfo %s", vgname);
+ return;
+ }
+
+ dm_list_iterate_items(info, &vginfo->infos) {
+ dm_list_iterate_items_safe(mda, mda2, &info->bad_mdas) {
+ dm_list_del(&mda->list);
+ dm_list_add(bad_mdas, &mda->list);
+ }
+ }
+}
+
static void _vginfo_attach_info(struct lvmcache_vginfo *vginfo,
struct lvmcache_info *info)
{
@@ -1950,6 +1998,10 @@ void lvmcache_del_mdas(struct lvmcache_info *info)
if (info->mdas.n)
del_mdas(&info->mdas);
dm_list_init(&info->mdas);
+
+ if (info->bad_mdas.n)
+ del_mdas(&info->bad_mdas);
+ dm_list_init(&info->bad_mdas);
}
void lvmcache_del_das(struct lvmcache_info *info)
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index 26e09535e..fe91159ff 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -215,4 +215,13 @@ void lvmcache_save_metadata_size(uint64_t val);
int dev_in_device_list(struct device *dev, struct dm_list *head);
+int lvmcache_has_bad_metadata(struct device *dev);
+
+void lvmcache_save_bad_mda(struct lvmcache_info *info, struct metadata_area *mda);
+
+void lvmcache_get_bad_mdas(struct cmd_context *cmd,
+ const char *vgname, const char *vgid,
+ struct dm_list *bad_mdas);
+
+
#endif
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index d904aa642..07ae29f8b 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -185,6 +185,7 @@ struct metadata_area {
struct metadata_area_ops *ops;
void *metadata_locn;
uint32_t status;
+ int mda_num;
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 */
};