summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--WHATS_NEW1
-rw-r--r--lib/metadata/metadata-exported.h1
-rw-r--r--lib/metadata/raid_manip.c8
-rw-r--r--test/shell/lvchange-raid1-writemostly.sh41
-rw-r--r--tools/lvchange.c15
5 files changed, 65 insertions, 1 deletions
diff --git a/WHATS_NEW b/WHATS_NEW
index 722b6f66a..14109fb5e 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.169 -
=====================================
+ Reject writemostly/writebehind in lvchange during resynchronization.
Deactivate active origin first before removal for improved workflow.
Fix regression of accepting options --type and -m with lvresize (2.02.158).
Add lvconvert --swapmetadata, new specific way to swap pool metadata LVs.
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 573c09d90..e4d2267d0 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -1232,6 +1232,7 @@ uint32_t raid_rimage_extents(const struct segment_type *segtype,
uint32_t raid_ensure_min_region_size(const struct logical_volume *lv, uint64_t raid_size, uint32_t region_size);
int lv_raid_change_region_size(struct logical_volume *lv,
int yes, int force, uint32_t new_region_size);
+int lv_raid_in_sync(const struct logical_volume *lv);
/* -- metadata/raid_manip.c */
/* ++ metadata/cache_manip.c */
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index cdd7af8d6..b6215a2dd 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -238,7 +238,7 @@ static int _deactivate_and_remove_lvs(struct volume_group *vg, struct dm_list *r
* Returns: 1 if in-sync, 0 otherwise.
*/
#define _RAID_IN_SYNC_RETRIES 6
-static int _raid_in_sync(struct logical_volume *lv)
+static int _raid_in_sync(const struct logical_volume *lv)
{
int retries = _RAID_IN_SYNC_RETRIES;
dm_percent_t sync_percent;
@@ -269,6 +269,12 @@ static int _raid_in_sync(struct logical_volume *lv)
return (sync_percent == DM_PERCENT_100) ? 1 : 0;
}
+/* External interface to raid in-sync check */
+int lv_raid_in_sync(const struct logical_volume *lv)
+{
+ return _raid_in_sync(lv);
+}
+
/* Check if RaidLV @lv is synced or any raid legs of @lv are not synced */
static int _raid_devs_sync_healthy(struct logical_volume *lv)
{
diff --git a/test/shell/lvchange-raid1-writemostly.sh b/test/shell/lvchange-raid1-writemostly.sh
new file mode 100644
index 000000000..edf11bd4e
--- /dev/null
+++ b/test/shell/lvchange-raid1-writemostly.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA
+
+SKIP_WITH_LVMLOCKD=1
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+which mkfs.ext4 || skip
+aux have_raid 1 3 5 || skip
+
+aux prepare_vg 4
+
+for d in $dev1 $dev2 $dev3 $dev4
+do
+ aux delay_dev $d 1
+done
+
+#
+# Test writemostly prohibited on resyncrhonizing raid1
+#
+
+# Create 4-way striped LV
+lvcreate -aey --ty raid1 -m 3 -L 32M -n $lv1 $vg
+not lvchange -y --writemostly $dev1 $vg/$lv1
+check lv_field $vg/$lv1 segtype "raid1"
+check lv_field $vg/$lv1 stripes 4
+check lv_attr_bit health $vg/${lv1}_rimage_0 "-"
+aux wait_for_sync $vg $lv1
+lvchange -y --writemostly $dev1 $vg/$lv1
+check lv_attr_bit health $vg/${lv1}_rimage_0 "w"
+
+vgremove -ff $vg
diff --git a/tools/lvchange.c b/tools/lvchange.c
index 1c00b76f1..cba0496f3 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -739,6 +739,21 @@ static int _lvchange_writemostly(struct logical_volume *lv)
struct cmd_context *cmd = lv->vg->cmd;
struct lv_segment *raid_seg = first_seg(lv);
+ /*
+ * Prohibit writebehind and writebehind during synchronization.
+ *
+ * FIXME: we can do better once we can distingush between
+ * an initial sync after a linear -> raid1 upconversion
+ * and any later additions of legs, requested resyncs
+ * via lvchange or leg repairs/replacements.
+ */
+ if (!lv_raid_in_sync(lv)) {
+ log_error("Unable to change write%s on %s while it is not in-sync.",
+ arg_is_set(cmd, writemostly_ARG) ? "mostly" : "behind",
+ display_lvname(lv));
+ return 0;
+ }
+
if (arg_is_set(cmd, writebehind_ARG))
raid_seg->writebehind = arg_uint_value(cmd, writebehind_ARG, 0);