diff options
Diffstat (limited to 'tools/lvconvert.c')
-rw-r--r-- | tools/lvconvert.c | 47 |
1 files changed, 39 insertions, 8 deletions
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; |