From b2e9c9e51aaa6ceaec1ae6d092ccf2056aeada9a Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 18 Feb 2020 16:09:34 -0600 Subject: integrity: convert between linear+integrity and raid1+integrity --- configure | 27 +++++++++++++++++++++++ lib/metadata/integrity_manip.c | 29 +++++++++++++++++++------ lib/metadata/lv_manip.c | 6 ++--- lib/metadata/metadata-exported.h | 9 ++++---- lib/metadata/raid_manip.c | 20 ++++++++++++++--- tools/lvconvert.c | 47 +++++++++++++++++++++++++++++++++------- 6 files changed, 111 insertions(+), 27 deletions(-) diff --git a/configure b/configure index 6dd7edac3..716ee9ca7 100755 --- a/configure +++ b/configure @@ -918,6 +918,7 @@ enable_cache_check_needs_check with_vdo with_vdo_format with_writecache +with_integrity enable_readline enable_realtime enable_ocf @@ -1716,6 +1717,7 @@ Optional Packages: --with-vdo=TYPE vdo support: internal/none [internal] --with-vdo-format=PATH vdoformat tool: [autodetect] --with-writecache=TYPE writecache support: internal/none [none] + --with-integrity=TYPE integrity support: internal/none [none] --with-ocfdir=DIR install OCF files in [PREFIX/lib/ocf/resource.d/lvm2] --with-default-pid-dir=PID_DIR @@ -9761,6 +9763,31 @@ $as_echo "#define WRITECACHE_INTERNAL 1" >>confdefs.h *) as_fn_error $? "--with-writecache parameter invalid" "$LINENO" 5 ;; esac +################################################################################ +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include integrity" >&5 +$as_echo_n "checking whether to include integrity... " >&6; } + +# Check whether --with-integrity was given. +if test "${with_integrity+set}" = set; then : + withval=$with_integrity; INTEGRITY=$withval +else + INTEGRITY="none" +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTEGRITY" >&5 +$as_echo "$INTEGRITY" >&6; } + +case "$INTEGRITY" in + none) ;; + internal) + +$as_echo "#define INTEGRITY_INTERNAL 1" >>confdefs.h + + ;; + *) as_fn_error $? "--with-integrity parameter invalid" "$LINENO" 5 ;; +esac + ################################################################################ # Check whether --enable-readline was given. if test "${enable_readline+set}" = set; then : diff --git a/lib/metadata/integrity_manip.c b/lib/metadata/integrity_manip.c index df734d95c..062f6b954 100644 --- a/lib/metadata/integrity_manip.c +++ b/lib/metadata/integrity_manip.c @@ -336,7 +336,7 @@ int lv_remove_integrity_from_raid(struct logical_volume *lv) return 1; } -int lv_remove_integrity(struct logical_volume *lv) +int lv_remove_integrity(struct logical_volume *lv, struct logical_volume **keep_lv_imeta) { struct cmd_context *cmd = lv->vg->cmd; struct volume_group *vg = lv->vg; @@ -394,7 +394,9 @@ int lv_remove_integrity(struct logical_volume *lv) if (!lv_remove(lv_iorig)) log_error("Failed to remove unused iorig LV %s.", lv_iorig->name); - if (!lv_remove(lv_imeta)) + if (keep_lv_imeta) + *keep_lv_imeta = lv_imeta; + else if (!lv_remove(lv_imeta)) log_error("Failed to remove unused imeta LV %s.", lv_imeta->name); if (!vg_write(vg) || !vg_commit(vg)) @@ -434,10 +436,11 @@ int lv_remove_integrity(struct logical_volume *lv) * */ -int lv_add_integrity_to_raid(struct logical_volume *lv, const char *arg, - struct integrity_settings *settings, - struct dm_list *pvh) +int lv_add_integrity_to_raid(struct logical_volume *lv, struct integrity_settings *settings, + struct dm_list *pvh, struct logical_volume *lv_imeta_0) { + char imeta_name[NAME_LEN]; + char *imeta_name_dup; struct lvcreate_params lp; struct dm_list allocatable_pvs; struct logical_volume *imeta_lvs[DEFAULT_RAID_MAX_IMAGES]; @@ -495,6 +498,19 @@ int lv_add_integrity_to_raid(struct logical_volume *lv, const char *arg, goto_bad; } + /* + * Use an existing lv_imeta from previous linear+integrity LV. + * FIXME: is it guaranteed that lv_image_0 is the existing? + */ + if (!s && lv_imeta_0) { + if (dm_snprintf(imeta_name, sizeof(imeta_name), "%s_imeta", lv_image->name) > 0) { + if ((imeta_name_dup = dm_pool_strdup(vg->vgmem, imeta_name))) + lv_imeta_0->name = imeta_name_dup; + } + imeta_lvs[0] = lv_imeta_0; + continue; + } + dm_list_init(&allocatable_pvs); if (!get_pv_list_for_lv(cmd->mem, lv_image, &allocatable_pvs)) { @@ -659,8 +675,7 @@ bad: return 0; } -int lv_add_integrity(struct logical_volume *lv, const char *arg, - struct integrity_settings *settings, +int lv_add_integrity(struct logical_volume *lv, struct integrity_settings *settings, struct dm_list *pvh) { struct lvcreate_params lp = { 0 }; diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 30ab7f145..989c9486b 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -8340,12 +8340,10 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, log_debug("Adding integrity to new LV"); if (seg_is_raid(lp)) { - if (!lv_add_integrity_to_raid(lv, lp->integrity_arg, - &lp->integrity_settings, lp->pvh)) + if (!lv_add_integrity_to_raid(lv, &lp->integrity_settings, lp->pvh, NULL)) goto revert_new_lv; } else { - if (!lv_add_integrity(lv, lp->integrity_arg, - &lp->integrity_settings, lp->pvh)) + if (!lv_add_integrity(lv, &lp->integrity_settings, lp->pvh)) goto revert_new_lv; } diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index 954d494f2..d96eec101 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -1406,11 +1406,10 @@ struct dm_list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int char **argv, int allocatable_only); struct dm_list *clone_pv_list(struct dm_pool *mem, struct dm_list *pvsl); -int lv_add_integrity(struct logical_volume *lv, const char *arg, - struct integrity_settings *settings, struct dm_list *pvh); -int lv_add_integrity_to_raid(struct logical_volume *lv, const char *arg, - struct integrity_settings *settings, struct dm_list *pvh); -int lv_remove_integrity(struct logical_volume *lv); +int lv_add_integrity(struct logical_volume *lv, struct integrity_settings *settings, struct dm_list *pvh); +int lv_add_integrity_to_raid(struct logical_volume *lv, struct integrity_settings *settings, struct dm_list *pvh, + struct logical_volume *lv_imeta_0); +int lv_remove_integrity(struct logical_volume *lv, struct logical_volume **keep_lv_imeta); int lv_remove_integrity_from_raid(struct logical_volume *lv); void lv_clear_integrity_recalculate_metadata(struct logical_volume *lv); int lv_has_integrity_recalculate_metadata(struct logical_volume *lv); diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c index fa1b91a7e..c986ea9e0 100644 --- a/lib/metadata/raid_manip.c +++ b/lib/metadata/raid_manip.c @@ -3132,6 +3132,18 @@ static int _raid_remove_images(struct logical_volume *lv, int yes, } lv->status &= ~(LV_NOTSYNCED | LV_WRITEMOSTLY); first_seg(lv)->writebehind = 0; + + if (seg_is_integrity(first_seg(lv))) { + char imeta_name[NAME_LEN]; + char *imeta_name_dup; + struct lv_segment *iseg = first_seg(lv); + struct logical_volume *lv_imeta = iseg->integrity_meta_dev; + + if (dm_snprintf(imeta_name, sizeof(imeta_name), "%s_imeta", lv->name) > 0) { + if ((imeta_name_dup = dm_pool_strdup(lv->vg->vgmem, imeta_name))) + lv_imeta->name = imeta_name_dup; + } + } } if (!commit) @@ -3328,9 +3340,11 @@ int lv_raid_split(struct logical_volume *lv, int yes, const char *split_name, } /* Convert to linear? */ - if ((new_count == 1) && !_raid_remove_top_layer(lv, &removal_lvs)) { - log_error("Failed to remove RAID layer after linear conversion."); - return 0; + if (new_count == 1) { + if (!_raid_remove_top_layer(lv, &removal_lvs)) { + log_error("Failed to remove RAID layer after linear conversion."); + return 0; + } } /* Get first item */ diff --git a/tools/lvconvert.c b/tools/lvconvert.c index 8dfa9db5d..e27516231 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -85,6 +85,8 @@ struct lvconvert_params { struct dm_list idls; const char *origin_name; + + struct logical_volume *prev_lv_imeta; }; struct convert_poll_id_list { @@ -1400,7 +1402,7 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l struct integrity_settings *isettings = NULL; if (!lv_get_raid_integrity_settings(lv, &isettings)) return_0; - if (!lv_add_integrity_to_raid(lv, "external", isettings, lp->pvh)) + if (!lv_add_integrity_to_raid(lv, isettings, lp->pvh, NULL)) return_0; } @@ -1450,7 +1452,7 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l struct integrity_settings *isettings = NULL; if (!lv_get_raid_integrity_settings(lv, &isettings)) return_0; - if (!lv_add_integrity_to_raid(lv, "external", isettings, lp->pvh)) + if (!lv_add_integrity_to_raid(lv, isettings, lp->pvh, NULL)) return_0; } @@ -1479,7 +1481,7 @@ try_new_takeover_or_reshape: struct integrity_settings *isettings = NULL; if (!lv_get_raid_integrity_settings(lv, &isettings)) return_0; - if (!lv_add_integrity_to_raid(lv, "external", isettings, lp->pvh)) + if (!lv_add_integrity_to_raid(lv, isettings, lp->pvh, NULL)) return_0; } @@ -1736,12 +1738,36 @@ static int _lvconvert_raid_types(struct cmd_context *cmd, struct logical_volume struct lvconvert_params *lp) { struct lv_segment *seg = first_seg(lv); + struct integrity_settings isettings; + int add_integrity = 0; int ret = 0; /* If LV is inactive here, ensure it's not active elsewhere. */ if (!lockd_lv(cmd, lv, "ex", 0)) return_ECMD_FAILED; + /* + * Converting integrity+linear to raid+integrity. The imeta + * used for the linear LV can be used for that same linear LV + * in its new position as a raid image. + * + * Remove the top integrity layer (saving the detached imeta LV), + * do the raid conversion on the linear LV, which makes the new + * top LV a raid LV. When integrity is added to the raid images, + * use the saved imeta LV and reattach it to the same linear LV + * that is now a raid image. + */ + if (lv_is_integrity(lv)) { + struct lv_segment *iseg = first_seg(lv); + + memcpy(&isettings, &iseg->integrity_settings, sizeof(isettings)); + add_integrity = 1; + + if (!lv_remove_integrity(lv, &lp->prev_lv_imeta)) + goto_out; + seg = first_seg(lv); + } + /* Set up segtype either from type_str or else to match the existing one. */ if (!*lp->type_str) lp->segtype = seg->segtype; @@ -1799,8 +1825,13 @@ static int _lvconvert_raid_types(struct cmd_context *cmd, struct logical_volume * If operations differ between striped and linear, split this case. */ if (segtype_is_striped(seg->segtype) || segtype_is_linear(seg->segtype)) { - ret = _convert_striped(cmd, lv, lp); - goto out; + if (!_convert_striped(cmd, lv, lp)) + goto_out; + + if (add_integrity) { + if (!lv_add_integrity_to_raid(lv, &isettings, lp->pvh, lp->prev_lv_imeta)) + goto_out; + } } /* @@ -5795,7 +5826,7 @@ static int _lvconvert_integrity_remove(struct cmd_context *cmd, if (lv_is_raid(lv)) ret = lv_remove_integrity_from_raid(lv); else - ret = lv_remove_integrity(lv); + ret = lv_remove_integrity(lv, NULL); if (!ret) return 0; @@ -5829,9 +5860,9 @@ static int _lvconvert_integrity_add(struct cmd_context *cmd, return_0; if (lv_is_raid(lv)) - ret = lv_add_integrity_to_raid(lv, "external", set, use_pvh); + ret = lv_add_integrity_to_raid(lv, set, use_pvh, NULL); else - ret = lv_add_integrity(lv, "external", set, use_pvh); + ret = lv_add_integrity(lv, set, use_pvh); if (!ret) return 0; -- cgit v1.2.1