summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2021-01-12 11:53:02 -0600
committerDavid Teigland <teigland@redhat.com>2021-02-02 14:31:23 -0600
commitcb54d0801d776205788f8f46b31dd9e487833343 (patch)
treea77012ab347d8e4b5875167353606d5ef3064fd2
parentae2af1d5eda8fa4e082e67429758f731ca6fcef6 (diff)
downloadlvm2-cb54d0801d776205788f8f46b31dd9e487833343.tar.gz
cachevol: allow forced detaching of damaged or invalid cachevol
A cachevol can be forcibly detached when it's missing devices. Also allow this if it's damaged/invalid and unrepairable. This would be needed to recover data from the origin LV after a cachevol is lost or damaged beyond repair.
-rw-r--r--test/shell/writecache-split.sh34
-rw-r--r--tools/lvconvert.c27
2 files changed, 54 insertions, 7 deletions
diff --git a/test/shell/writecache-split.sh b/test/shell/writecache-split.sh
index 5723f7aab..f6d2d9aec 100644
--- a/test/shell/writecache-split.sh
+++ b/test/shell/writecache-split.sh
@@ -154,6 +154,40 @@ vgextend --restoremissing $vg "$dev3"
vgremove -ff $vg
#
+# split while cachevol is damaged
+#
+
+vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4"
+
+lvcreate -n $lv1 -l 16 -an $vg "$dev1" "$dev4"
+lvcreate -n $lv2 -l 4 -an $vg "$dev2"
+
+lvchange -ay $vg/$lv1
+
+mkfs_mount_umount $lv1
+
+lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1
+
+mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir"
+diff pattern1 "$mount_dir/pattern1"
+cp pattern1 "$mount_dir/pattern2"
+umount "$mount_dir"
+lvchange -an $vg/$lv1
+
+dd if=/dev/zero of="$dev2" seek=1 bs=1M count=16
+
+lvconvert --splitcache --force --yes $vg/$lv1
+
+lvchange -ay $vg/$lv1
+
+mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir"
+diff pattern1 "$mount_dir/pattern1"
+umount "$mount_dir"
+lvchange -an $vg/$lv1
+
+vgremove -ff $vg
+
+#
# splitcache when origin is raid
#
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 3457cd08a..a72126bf4 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -1882,6 +1882,7 @@ static int _lvconvert_split_and_keep_cachevol(struct cmd_context *cmd,
char cvol_name[NAME_LEN];
struct lv_segment *cache_seg = first_seg(lv);
int cache_mode = cache_seg->cache_mode;
+ int direct_detach = 0;
if (!archive(lv->vg))
return_0;
@@ -1889,6 +1890,15 @@ static int _lvconvert_split_and_keep_cachevol(struct cmd_context *cmd,
log_debug("Detaching cachevol %s from LV %s.", display_lvname(lv_fast), display_lvname(lv));
/*
+ * Allow forcible detach without activating or flushing
+ * in case the cache is corrupt/damaged/invalid.
+ * This would generally be done to rescue data from
+ * the origin if the cache could not be repaired.
+ */
+ if (!lv_is_active(lv) && arg_count(cmd, force_ARG))
+ direct_detach = 1;
+
+ /*
* Detaching a writeback cache generally requires flushing;
* doing otherwise can mean data loss/corruption.
* If the cache devices are missing, the cache can't be
@@ -1902,7 +1912,10 @@ static int _lvconvert_split_and_keep_cachevol(struct cmd_context *cmd,
log_error("Conversion aborted.");
return 0;
}
+ direct_detach = 1;
+ }
+ if (direct_detach) {
log_warn("WARNING: Data may be lost by detaching writeback cache without flushing.");
if (!arg_count(cmd, yes_ARG) &&
@@ -5554,7 +5567,13 @@ static int _lvconvert_detach_writecache(struct cmd_context *cmd,
if (!archive(lv->vg))
return_0;
- if (lv_is_partial(lv_fast)) {
+ /*
+ * If the LV is inactive when we begin, then we want to
+ * deactivate the LV at the end.
+ */
+ active_begin = lv_is_active(lv);
+
+ if (lv_is_partial(lv_fast) || (!active_begin && arg_count(cmd, force_ARG))) {
if (!arg_count(cmd, force_ARG)) {
log_warn("WARNING: writecache on %s is not complete and cannot be flushed.", display_lvname(lv_fast));
log_warn("WARNING: cannot detach writecache from %s without --force.", display_lvname(lv));
@@ -5574,12 +5593,6 @@ static int _lvconvert_detach_writecache(struct cmd_context *cmd,
noflush = 1;
}
- /*
- * If the LV is inactive when we begin, then we want to
- * deactivate the LV at the end.
- */
- active_begin = lv_is_active(lv);
-
if (!noflush) {
/*
* --cachesettings cleaner=0 means to skip the use of the cleaner