WHATS_NEW | 1 + lib/activate/activate.c | 25 +++++++++++++++++++++++++ lib/activate/activate.h | 3 ++- lib/metadata/lv.c | 16 +++++++++++++++- lib/metadata/segtype.h | 3 ++- lib/raid/raid.c | 10 ++++++++-- test/shell/lvconvert-raid-takeover.sh | 13 +++++++++++++ tools/lvconvert.c | 26 ++++++++++++++++++++++++++ tools/lvcreate.c | 6 ++++++ 9 files changed, 98 insertions(+), 5 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 6a0c311..519bbc9 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.167 - ====================================== + Prevent raid4 creation/conversion on non-supporting kernels Add direct striped -> raid4 conversion Fix raid4 parity image pair position on conversions from striped/raid0* Disable lvconvert of thin pool to raid while active. diff --git a/lib/activate/activate.c b/lib/activate/activate.c index 5550955..571f2b2 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -370,6 +370,11 @@ void activation_exit(void) { } +int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype) +{ + return 1; +} + int lv_is_active(const struct logical_volume *lv) { return 0; @@ -1489,6 +1494,26 @@ out: return r || l; } +/* + * Check if "raid4" @segtype is supported by kernel. + * + * if segment type is not raid4, return 1. + */ +int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype) +{ + unsigned attrs; + + if (segtype_is_raid4(segtype) && + (!segtype->ops->target_present || + !segtype->ops->target_present(cmd, NULL, &attrs) || + !(attrs & RAID_FEATURE_RAID4))) { + log_error("RAID module does not support RAID4."); + return 0; + } + + return 1; +} + int lv_is_active(const struct logical_volume *lv) { return _lv_is_active(lv, NULL, NULL, NULL); diff --git a/lib/activate/activate.h b/lib/activate/activate.h index 1e8d7a8..3922d78 100644 --- a/lib/activate/activate.h +++ b/lib/activate/activate.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * @@ -99,6 +99,7 @@ int target_present(struct cmd_context *cmd, const char *target_name, int use_modprobe); int target_version(const char *target_name, uint32_t *maj, uint32_t *min, uint32_t *patchlevel); +int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype); int lvm_dm_prefix_check(int major, int minor, const char *prefix); int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg, struct dm_list *modules); diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c index 53a1044..0f1b6e7 100644 --- a/lib/metadata/lv.c +++ b/lib/metadata/lv.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * @@ -1425,6 +1425,7 @@ int lv_active_change(struct cmd_context *cmd, struct logical_volume *lv, enum activation_change activate, int needs_exclusive) { const char *ay_with_mode = NULL; + struct lv_segment *seg = first_seg(lv); if (activate == CHANGE_ASY) ay_with_mode = "sh"; @@ -1461,6 +1462,9 @@ deactivate: break; case CHANGE_ALY: case CHANGE_AAY: + if (!raid4_is_supported(cmd, seg->segtype)) + goto no_raid4; + if (needs_exclusive || _lv_is_exclusive(lv)) { log_verbose("Activating logical volume %s exclusively locally.", display_lvname(lv)); @@ -1475,6 +1479,9 @@ deactivate: break; case CHANGE_AEY: exclusive: + if (!raid4_is_supported(cmd, seg->segtype)) + goto no_raid4; + log_verbose("Activating logical volume %s exclusively.", display_lvname(lv)); if (!activate_lv_excl(cmd, lv)) @@ -1483,6 +1490,9 @@ exclusive: case CHANGE_ASY: case CHANGE_AY: default: + if (!raid4_is_supported(cmd, seg->segtype)) + goto no_raid4; + if (needs_exclusive || _lv_is_exclusive(lv)) goto exclusive; log_verbose("Activating logical volume %s.", display_lvname(lv)); @@ -1495,6 +1505,10 @@ exclusive: log_error("Failed to unlock logical volume %s.", display_lvname(lv)); return 1; + +no_raid4: + log_error("Failed to activate %s LV %s", lvseg_name(seg), display_lvname(lv)); + return 0; } char *lv_active_dup(struct dm_pool *mem, const struct logical_volume *lv) diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h index 9ca740d..292b8b6 100644 --- a/lib/metadata/segtype.h +++ b/lib/metadata/segtype.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * @@ -268,6 +268,7 @@ struct segment_type *init_unknown_segtype(struct cmd_context *cmd, #define RAID_FEATURE_RAID10 (1U << 0) /* version 1.3 */ #define RAID_FEATURE_RAID0 (1U << 1) /* version 1.7 */ #define RAID_FEATURE_RESHAPING (1U << 2) /* version 1.8 */ +#define RAID_FEATURE_RAID4 (1U << 3) /* ! version 1.8 or 1.9.0 */ #ifdef RAID_INTERNAL int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib); diff --git a/lib/raid/raid.c b/lib/raid/raid.c index 3bc3c75..92a96a3 100644 --- a/lib/raid/raid.c +++ b/lib/raid/raid.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2013 Red Hat, Inc. All rights reserved. + * Copyright (C) 2011-2016 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * @@ -366,7 +366,7 @@ static int _raid_target_present(struct cmd_context *cmd, static int _raid_checked = 0; static int _raid_present = 0; - static int _raid_attrs = 0; + static unsigned _raid_attrs = 0; uint32_t maj, min, patchlevel; unsigned i; @@ -389,6 +389,12 @@ static int _raid_target_present(struct cmd_context *cmd, else log_very_verbose("Target raid does not support %s.", _features[i].feature); + + if (!(maj == 1 && (min == 8 || (min == 9 && patchlevel == 0)))) + _raid_attrs |= RAID_FEATURE_RAID4; + else + log_very_verbose("Target raid does not support %s.", + SEG_TYPE_NAME_RAID4); } if (attributes) diff --git a/test/shell/lvconvert-raid-takeover.sh b/test/shell/lvconvert-raid-takeover.sh index 0140e22..332786d 100644 --- a/test/shell/lvconvert-raid-takeover.sh +++ b/test/shell/lvconvert-raid-takeover.sh @@ -16,6 +16,8 @@ SKIP_WITH_LVMPOLLD=1 aux have_raid 1 9 0 || skip +[ `aux have_raid 1.9.1` ] && correct_raid4_layout=1 + aux prepare_vg 9 288 # Delay 1st leg so that rebuilding status characters @@ -99,6 +101,9 @@ check lv_field $vg/$lv3 stripes 3 echo y | mkfs -t ext4 /dev/mapper/$vg-$lv3 fsck -fn /dev/mapper/$vg-$lv3 +if [ $correct_raid4_layout -eq 1 ] +then + # Create 3-way raid4 lvcreate -y -aey --type raid4 -i 3 -L 64M -n $lv4 $vg check lv_field $vg/$lv4 segtype "raid4" @@ -164,4 +169,12 @@ check lv_field $vg/$lv1 segtype "striped" check lv_field $vg/$lv1 stripes 3 fsck -fn /dev/mapper/$vg-$lv1 +else + +not lvcreate -y -aey --type raid4 -i 3 -L 64M -n $lv4 $vg +not lvconvert -y --ty raid4 $vg/$lv1 +not lvconvert -y --ty raid4 $vg/$lv2 + +fi + vgremove -ff $vg diff --git a/tools/lvconvert.c b/tools/lvconvert.c index 541df72..7a4215a 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -1821,6 +1821,25 @@ static void _lvconvert_raid_repair_ask(struct cmd_context *cmd, } } +/* Check for dm-raid target supporting raid4 conversion properly. */ +static int _raid4_conversion_supported(struct logical_volume *lv, struct lvconvert_params *lp) +{ + int ret = 1; + struct lv_segment *seg = first_seg(lv); + + if (seg_is_raid4(seg)) + ret = raid4_is_supported(lv->vg->cmd, seg->segtype); + else if (segtype_is_raid4(lp->segtype)) + ret = raid4_is_supported(lv->vg->cmd, lp->segtype); + + if (ret) + return 1; + + log_error("Cannot convert %s LV %s to %s.", + lvseg_name(seg), display_lvname(lv), lp->segtype->name); + return 0; +} + static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *lp) { int replace = 0, image_count = 0; @@ -1945,6 +1964,9 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l return 0; } + if (!_raid4_conversion_supported(lv, lp)) + return 0; + if (!arg_is_set(cmd, stripes_long_ARG)) lp->stripes = 0; @@ -2018,6 +2040,10 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l } try_new_takeover_or_reshape: + + if (!_raid4_conversion_supported(lv, lp)) + return 0; + /* FIXME This needs changing globally. */ if (!arg_is_set(cmd, stripes_long_ARG)) lp->stripes = 0; diff --git a/tools/lvcreate.c b/tools/lvcreate.c index 387c8d4..dbc0708 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -1054,6 +1054,12 @@ static int _lvcreate_params(struct cmd_context *cmd, return 0; } + if (segtype_is_raid4(lp->segtype) && + !(lp->target_attr & RAID_FEATURE_RAID4)) { + log_error("RAID module does not support RAID4."); + return 0; + } + if (segtype_is_raid10(lp->segtype) && !(lp->target_attr & RAID_FEATURE_RAID10)) { log_error("RAID module does not support RAID10."); return 0;