]> sourceware.org Git - lvm2.git/commitdiff
lvconvert: linear -> raid1 upconvert should cause "recover" not "resync"
authorJonathan Brassow <jbrassow@redhat.com>
Wed, 14 Jun 2017 13:33:42 +0000 (08:33 -0500)
committerJonathan Brassow <jbrassow@redhat.com>
Wed, 14 Jun 2017 13:35:22 +0000 (08:35 -0500)
Two of the sync actions performed by the kernel (aka MD runtime) are
"resync" and "recover".  The "resync" refers to when an entirely new array
is going through the process of initializing (or resynchronizing after an
unexpected shutdown).  The "recover" is the process of initializing a new
member device to the array.  So, a brand new array with all new devices
will undergo "resync".  An array with replaced or added sub-LVs will undergo
"recover".

These two states are treated very differently when failures happen.  If any
device is lost or replaced while "resync", there are no worries.  This is
because any writes created from the inception of the array have occurred to
all the devices and can be safely recovered.  Even though non-initialized
portions will still be resync'ed with uninitialized data, it is ok.  However,
if a pre-existing device is lost (aka, the original linear device in a
linear -> raid1 convert) during a "recover", data loss can be the result.
Thus, writes are errored by the kernel and recovery is halted.  The failed
device must be restored or removed.  This is the correct behavior.

Unfortunately, we were treating an up-convert from linear as a "resync"
when we should have been treating it as a "recover".  This patch
removes the special case for linear upconvert.  It allows each new image
sub-LV to be marked with a rebuild flag and treats the array as 'in-sync'.
This has the correct effect of causing the upconvert to be treated as a
"recover" rather than a "resync".  There is no need to flag these two states
differently in LVM metadata, because they are already considered differently
by the kernel RAID metadata.  (Any activation/deactivation will properly
resume the "recover" process and not a "resync" process.)

We make this behavior change based on the presense of dm-raid target
version 1.9.0+.

WHATS_NEW
lib/metadata/raid_manip.c
lib/metadata/segtype.h
lib/raid/raid.c
test/shell/lvcreate-large-raid.sh

index cdd401ebf38b3e73d65a92ed80469a2d3c02a65e..c7f8903ef2b6ef5353b450582c0e4f333448f3de 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 Version 2.02.172 - 
 ===============================
+  Linear to RAID1 upconverts now use "recover" sync action, not "resync".
   Improve lvcreate --cachepool arg validation.
   Limit maximal size of thin-pool for specific chunk size.
   Print a warning about in-use PVs with no VG using them.
index a19a7e9405fd7f1eace4bb933dfa2e2fc701c9ea..425abbbcb12a8409b4d827515b4917e523ba6996 100644 (file)
@@ -56,6 +56,25 @@ static int _reshape_is_supported(struct cmd_context *cmd, const struct segment_t
        return 1;
 }
 
+/*
+ * Check if rebuild CTR args are allowed when other images exist in the array
+ * with empty metadata areas for this kernel.
+ */
+static int _rebuild_with_emptymeta_is_supported(struct cmd_context *cmd,
+                                               const struct segment_type *segtype)
+{
+       unsigned attrs;
+
+       if (!segtype->ops->target_present ||
+            !segtype->ops->target_present(cmd, NULL, &attrs) ||
+            !(attrs & RAID_FEATURE_NEW_DEVICES_ACCEPT_REBUILD)) {
+               log_verbose("RAID module does not support rebuild+emptymeta.");
+               return 0;
+       }
+
+       return 1;
+}
+
 /*
  * Ensure region size exceeds the minimum for @lv because
  * MD's bitmap is limited to tracking 2^21 regions.
@@ -2550,6 +2569,7 @@ static int _raid_add_images_without_commit(struct logical_volume *lv,
        struct dm_list meta_lvs, data_lvs;
        struct lv_list *lvl;
        struct lv_segment_area *new_areas;
+       struct segment_type *segtype;
 
        if (lv_is_not_synced(lv)) {
                log_error("Can't add image to out-of-sync RAID LV:"
@@ -2581,8 +2601,19 @@ static int _raid_add_images_without_commit(struct logical_volume *lv,
         * LV to accompany it.
         */
        if (seg_is_linear(seg)) {
-               /* A complete resync will be done, no need to mark each sub-lv */
-               status_mask = ~(LV_REBUILD);
+               /*
+                * As of dm-raid version 1.9.0, it is possible to specify
+                * RAID table lines with the 'rebuild' parameters necessary
+                * to force a "recover" instead of a "resync" on upconvert.
+                *
+                * LVM's interaction with older kernels should be as before -
+                * performing a complete resync rather than a set of rebuilds.
+                */
+               if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_RAID1)))
+                       return_0;
+
+               if (!_rebuild_with_emptymeta_is_supported(lv->vg->cmd, segtype))
+                       status_mask = ~(LV_REBUILD);
 
                /* FIXME: allow setting region size on upconvert from linear */
                seg->region_size = get_default_region_size(lv->vg->cmd);
index 93132c39c4fba9f750de3c7a113c0c5626264f1d..2acb894310ce11abdb768ce1fd0e6b80ce38e96c 100644 (file)
@@ -290,6 +290,24 @@ struct segment_type *init_unknown_segtype(struct cmd_context *cmd,
 #define RAID_FEATURE_RAID4                     (1U << 3) /* ! version 1.8 or 1.9.0 */
 #define RAID_FEATURE_SHRINK                    (1U << 4) /* version 1.9.0 */
 #define RAID_FEATURE_RESHAPE                   (1U << 5) /* version 1.10.1 */
+/*
+ * RAID_FEATURE_NEW_DEVICES_ACCEPT_REBUILD
+ * This signifies a behavioral change in dm-raid.  Prior to upstream kernel
+ * commit 33e53f068, the kernel would refuse to allow 'rebuild' CTR args to
+ * be submitted when other devices in the array had uninitialized superblocks.
+ * After the commit, these parameters were allowed.
+ *
+ * The most obvious useful case of this new behavior is up-converting a
+ * linear device to RAID1.  A new superblock is allocated for the linear dev
+ * and it will be uninitialized, while all the new images are specified for
+ * 'rebuild'.  This valid scenario would not have been allowed prior to
+ * commit 33e53f068.
+ *
+ * Commit 33e53f068 did not bump the dm-raid version number.  So it exists
+ * in some, but not all 1.8.1 versions of dm-raid.  The only way to be
+ * certain the new behavior exists is to check for version 1.9.0.
+ */
+#define RAID_FEATURE_NEW_DEVICES_ACCEPT_REBUILD        (1U << 6) /* version 1.9.0 */
 
 #ifdef RAID_INTERNAL
 int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
index 25009f6a32ffec5cb235c72e26fd9c2c97a82feb..8a53d7ed4d8d8a2fba3e0e0d609d951b2c38b45c 100644 (file)
@@ -474,6 +474,7 @@ static int _raid_target_present(struct cmd_context *cmd,
                { 1, 3, 0, RAID_FEATURE_RAID10, SEG_TYPE_NAME_RAID10 },
                { 1, 7, 0, RAID_FEATURE_RAID0, SEG_TYPE_NAME_RAID0 },
                { 1, 9, 0, RAID_FEATURE_SHRINK, "shrinking" },
+               { 1, 9, 0, RAID_FEATURE_NEW_DEVICES_ACCEPT_REBUILD, "rebuild+emptymeta" },
                { 1, 10, 1, RAID_FEATURE_RESHAPE, "reshaping" },
        };
 
index ca3f71591a25b83ccda108de8ea2cc2e104a4ae9..7ec140bb1581085d3b0416d8dab176fff3bb4395 100644 (file)
@@ -101,7 +101,15 @@ lvremove -ff $vg1
 lvcreate -aey -L 200T -n $lv1 $vg1
 lvconvert -y --type raid1 -m 1 $vg1/$lv1
 check lv_field $vg1/$lv1 size "200.00t"
-check raid_leg_status $vg1 $lv1 "aa"
+if aux have_raid 1 9 0; then
+       # The 1.9.0 version of dm-raid is capable of performing
+       # linear -> RAID1 upconverts as "recover" not "resync"
+       # The LVM code now checks the dm-raid version when
+       # upconverting and if 1.9.0+ is found, it uses "recover"
+       check raid_leg_status $vg1 $lv1 "Aa"
+else
+       check raid_leg_status $vg1 $lv1 "aa"
+fi
 lvremove -ff $vg1
 
 # bz837927 END
This page took 0.052426 seconds and 5 git commands to generate.