summaryrefslogtreecommitdiff
path: root/lib/label
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2021-06-28 18:10:47 -0500
committerDavid Teigland <teigland@redhat.com>2021-07-06 10:10:23 -0500
commite035e323508383fdcd9df0ef036d276a9c9909ab (patch)
treee5eb5558f63e2468b457452c6fc48e676e739c7a /lib/label
parentd89942d157e49168d069a65f77a6ecb2c155b3fb (diff)
downloadlvm2-e035e323508383fdcd9df0ef036d276a9c9909ab.tar.gz
scan: retry reading metadata on error
If label_scan encounters bad vg metadata, invalidate bcache data for the device and reread the mda_header and metadata text back to back. With concurrent commands modifying large metadata, it's possible that the entire metadata area can be rewritten in the time between a command reading the mda_header and reading the metadata text that the header points to. Since the label_scan is just assembling an initial overview of devices, it doesn't use locking to serialize with other commands that may be modifying the vg metadata at the same time.
Diffstat (limited to 'lib/label')
-rw-r--r--lib/label/label.c5
-rw-r--r--lib/label/label.h1
2 files changed, 6 insertions, 0 deletions
diff --git a/lib/label/label.c b/lib/label/label.c
index 50107edc8..ac84b6293 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -1704,6 +1704,11 @@ bool dev_invalidate_bytes(struct device *dev, uint64_t start, size_t len)
return bcache_invalidate_bytes(scan_bcache, dev->bcache_di, start, len);
}
+void dev_invalidate(struct device *dev)
+{
+ bcache_invalidate_di(scan_bcache, dev->bcache_di);
+}
+
bool dev_write_zeros(struct device *dev, uint64_t start, size_t len)
{
return dev_set_bytes(dev, start, len, 0);
diff --git a/lib/label/label.h b/lib/label/label.h
index fcdc309ac..32ceebc34 100644
--- a/lib/label/label.h
+++ b/lib/label/label.h
@@ -130,6 +130,7 @@ bool dev_write_bytes(struct device *dev, uint64_t start, size_t len, void *data)
bool dev_write_zeros(struct device *dev, uint64_t start, size_t len);
bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val);
bool dev_invalidate_bytes(struct device *dev, uint64_t start, size_t len);
+void dev_invalidate(struct device *dev);
void dev_set_last_byte(struct device *dev, uint64_t offset);
void dev_unset_last_byte(struct device *dev);