1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

lvconvert: linear -> raid1 upconvert should cause "recover" not "resync"

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+.
This commit is contained in:
Jonathan Brassow 2017-06-14 08:33:42 -05:00
parent 14d563accc
commit c87907dcd5
5 changed files with 62 additions and 3 deletions

View File

@ -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.

View 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,7 +2601,18 @@ 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 */
/*
* 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 */

View 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);

View 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" },
};

View 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"
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