diff options
author | Heinz Mauelshagen <heinzm@redhat.com> | 2015-12-19 03:06:22 +0100 |
---|---|---|
committer | Heinz Mauelshagen <heinzm@redhat.com> | 2015-12-19 03:06:22 +0100 |
commit | b5350b481ae151507d7cf9c717b33427fdefa4ec (patch) | |
tree | 010f78bf2d1d158b2d294e94c6624f88905e932e | |
parent | a725f292903fd5918e4bc89175e6417e1505a6f3 (diff) | |
download | lvm2-b5350b481ae151507d7cf9c717b33427fdefa4ec.tar.gz |
raid_manip:
duplication namespace adjustments; step 3
cleanup
-rw-r--r-- | lib/metadata/raid_manip.c | 564 |
1 files changed, 342 insertions, 222 deletions
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c index a9b526d4b..1e79a893a 100644 --- a/lib/metadata/raid_manip.c +++ b/lib/metadata/raid_manip.c @@ -74,6 +74,11 @@ RETURN_IF_LV_SEG_ZERO((lv), (seg)); \ RETURN_IF_SEGTYPE_ZERO((segtype)) +static struct logical_volume *_seg_metalv(struct lv_segment *seg, uint32_t s) +{ + return (seg->meta_areas && seg_metatype(seg, s) == AREA_LV) ? seg_metalv(seg, s) : NULL; +} + /* Ensure minimum region size on @lv */ static int _ensure_min_region_size(const struct logical_volume *lv) { @@ -156,12 +161,12 @@ static struct logical_volume *_find_lv_in_sub_lvs(struct logical_volume *lv, /* HM helper: return first hit strstr() of @str for string in @... */ static char *_strstr_strings(const char *str, ...) { - char *pattern, *r = NULL; + char *substr, *r = NULL; va_list ap; va_start(ap, str); - while ((pattern = va_arg(ap, char *))) - if ((r = strstr(str, pattern))) + while ((substr = va_arg(ap, char *))) + if ((r = strstr(str, substr))) break; va_end(ap); @@ -171,10 +176,10 @@ static char *_strstr_strings(const char *str, ...) /* HM helper: return top-level lv name for given image @lv */ static char *_top_level_lv_name(struct logical_volume *lv) { - char *p, *r = NULL; + char *p, *r; if ((r = dm_pool_strdup(lv->vg->vgmem, lv->name)) && - (p = _strstr_strings(r, "_dup_", "_rimage_", "_extracted"))) + (p = _strstr_strings(r, "_rimage_", "_dup_", "_extracted", NULL))) *p = '\0'; /* LV name returned is now that of top-level RAID */ return r; @@ -1152,7 +1157,7 @@ static int __shift_lv_name(char *shift_name, char **name, unsigned s, unsigned m log_very_verbose("Before shifting %s", *name); /* Handle duplicating sub LV names */ if ((numptr = strstr(shift_name, "_dup_")) && - (_strstr_strings(shift_name, "_rimage_", "_rmeta_"))) { + (_strstr_strings(shift_name, "_rimage_", "_rmeta_", NULL))) { char *suffix; log_very_verbose("shifting duplicating sub LV %s", shift_name); @@ -1331,28 +1336,40 @@ static char *_generate_raid_name(struct logical_volume *lv, /* * Eliminate the extracted LVs on @removal_lvs from @vg incl. vg write, commit and backup */ -static int _eliminate_extracted_lvs(struct volume_group *vg, struct dm_list *removal_lvs) +static int _eliminate_extracted_lvs_optional_write_vg(struct volume_group *vg, + struct dm_list *removal_lvs, + int write_requested) { RETURN_IF_ZERO(vg, "vg argument"); +struct lv_list *lvl; if (!removal_lvs || dm_list_empty(removal_lvs)) return 1; +dm_list_iterate_items(lvl, removal_lvs) +PFLA("removal_lv=%s", display_lvname(lvl->lv)); + sync_local_dev_names(vg->cmd); -PFL(); + if (!_deactivate_and_remove_lvs(vg, removal_lvs)) return 0; - if (!vg_write(vg) || !vg_commit(vg)) - return_0; + if (write_requested) { + if (!vg_write(vg) || !vg_commit(vg)) + return_0; - if (!backup(vg)) - log_error("Backup of VG %s failed after removal of image component LVs", vg->name); -PFL(); + if (!backup(vg)) + log_error("Backup of VG %s failed after removal of image component LVs", vg->name); + } return 1; } +static int _eliminate_extracted_lvs(struct volume_group *vg, struct dm_list *removal_lvs) +{ + return _eliminate_extracted_lvs_optional_write_vg(vg, removal_lvs, 1); +} + /* * Reallocate segment areas given by @type (i.e. data or metadata areas) * in first segment of @lv to amount in @areas copying the minimum of common areas across @@ -1531,8 +1548,8 @@ static int _extract_image_component_pair(struct lv_segment *seg, uint32_t idx, } /* - * Remove sub LVs of @type from @seg starting at @idx excluding @end and - * put them on @removal_lvs setting mappings to "erorr" if @error_seg + * Extract all sub LVs of @type from @seg starting at @idx excluding @end and + * put them on @removal_lvs setting mappings to "error" if @error_seg */ static int _extract_image_component_sublist(struct lv_segment *seg, uint64_t type, uint32_t idx, uint32_t end, @@ -1542,12 +1559,9 @@ static int _extract_image_component_sublist(struct lv_segment *seg, uint32_t s; struct lv_list *lvl; - if (idx >= seg->area_count || - end > seg->area_count || - end <= idx) { - log_error(INTERNAL_ERROR "area index wrong for segment"); - return 0; - } + RETURN_IF_ZERO(seg, "seg argument"); + RETURN_IF_NONZERO(idx >= seg->area_count || end > seg->area_count || end <= idx, + "area index wrong for segment"); if (!(lvl = dm_pool_alloc(seg_lv(seg, idx)->vg->vgmem, sizeof(*lvl) * (end - idx)))) return_0; @@ -1570,7 +1584,7 @@ static int _extract_image_component_sublist(struct lv_segment *seg, return 1; } -/* Extract sub LVs of @type from @seg starting with @idx and put them on @removal_Lvs */ +/* Extract all sub LVs of @type from @seg starting with @idx and put them on @removal_Lvs */ static int _extract_image_component_list(struct lv_segment *seg, uint64_t type, uint32_t idx, struct dm_list *removal_lvs) @@ -1722,6 +1736,7 @@ static int __alloc_rmeta_for_lv(struct logical_volume *data_lv, { int r = 1; uint32_t rmeta_extents; + char *lv_name; struct alloc_handle *ah; struct lv_segment *seg; struct dm_list pvs; @@ -1748,9 +1763,10 @@ static int __alloc_rmeta_for_lv(struct logical_volume *data_lv, if (!_check_and_init_region_size(data_lv)) return 0; - if (!_top_level_lv_name(data_lv)) + if (!(lv_name = _top_level_lv_name(data_lv))) return 0; +PFLA("lv_name=%s", lv_name); rmeta_extents = _raid_rmeta_extents(data_lv->vg->cmd, data_lv->le_count, 0 /* region_size */, data_lv->vg->extent_size); if (!(ah = allocate_extents(data_lv->vg, NULL, striped_segtype, @@ -1759,7 +1775,7 @@ static int __alloc_rmeta_for_lv(struct logical_volume *data_lv, allocate_pvs, data_lv->alloc, 0, NULL))) return_0; - if ((*meta_lv = _alloc_image_component(data_lv, data_lv->name, ah, 0, RAID_META))) { + if ((*meta_lv = _alloc_image_component(data_lv, lv_name, ah, 0, RAID_META))) { /* * Wipe metadata device at beginning in order to avoid * discovering a valid, but unrelated superblock in the kernel. @@ -1785,13 +1801,24 @@ static int _alloc_rmeta_for_lv(struct logical_volume *data_lv, } /* HM Helper: allocate a metadata LV for @data_lv, set hidden and set @*meta_lv to it */ -static int _alloc_rmeta_for_lv_and_set_hidden(struct logical_volume *data_lv, - struct logical_volume **meta_lv) +static int _alloc_rmeta_for_lv_add_set_hidden(struct logical_volume *lv, uint32_t area_offset) { - if (!_alloc_rmeta_for_lv(data_lv, meta_lv)) + struct lv_segment *seg; + struct dm_list meta_lvs; + struct lv_list lvl; + + RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv))); + + dm_list_init(&meta_lvs); + + if (!_alloc_rmeta_for_lv(seg_lv(seg, area_offset), &lvl.lv)) + return 0; + + dm_list_add(&meta_lvs, &lvl.list); + if (!_add_image_component_list(seg, 1, 0, &meta_lvs, area_offset)) return 0; - lv_set_hidden(*meta_lv); + lv_set_hidden(lvl.lv); return 1; } @@ -1802,8 +1829,8 @@ static int _alloc_rmeta_for_lv_and_set_hidden(struct logical_volume *data_lv, * Allocate metadata devs for all @new_data_devs and link them to list @new_meta_lvs */ static int _alloc_rmeta_devs_for_rimage_devs(struct logical_volume *lv, - struct dm_list *new_data_lvs, - struct dm_list *new_meta_lvs) + struct dm_list *new_data_lvs, + struct dm_list *new_meta_lvs) { uint32_t a = 0, raid_devs = 0; struct dm_list *l; @@ -1818,7 +1845,7 @@ static int _alloc_rmeta_devs_for_rimage_devs(struct logical_volume *lv, dm_list_iterate(l, new_data_lvs) raid_devs++; -PFLA("raid_devs=%u", raid_devs); +PFLA("lv=%s raid_devs=%u", display_lvname(lv), raid_devs); if (!raid_devs) return 0; @@ -2545,7 +2572,7 @@ static struct lv_segment *_convert_lv_to_raid1(struct logical_volume *lv, const } /* Reset any rebuild or reshape disk flags on @lv, first segment already passed to the kernel */ -static int _reset_flags_passed_to_kernel(struct logical_volume *lv) +static int _reset_flags_passed_to_kernel(struct logical_volume *lv, int write_requested) { int flags_cleared = 0; uint32_t s; @@ -2581,7 +2608,7 @@ static int _reset_flags_passed_to_kernel(struct logical_volume *lv) flags_cleared++; } - if (flags_cleared) { + if (write_requested && flags_cleared) { if (!vg_write(lv->vg) || !vg_commit(lv->vg)) { log_error("Failed to clear flags for %s components in metadata", display_lvname(lv)); @@ -2600,25 +2627,51 @@ static int _reset_flags_passed_to_kernel(struct logical_volume *lv) /* * HM Helper: * - * update metadata, reload origin @lv, eliminate any LVs listed on @removal_lvs - * and then clear flags passed to the kernel (if any) in the metadata or - * manipulate metadata before second update in case of @fn_on_lv + * Updates and reloads metadata, clears any flags passed to the kerne,l + * eliminates any residual LVs and updates and reloads metadata again. + * + * @lv mandatory argument, rest variable: + * + * @lv [ @removal_lvs [ @fn_pre_on_lv @fn_pre_data [ @fn_post_on_lv @fn_post_data ] ] ] + * + * Run optional variable args function fn_pre_on_lv with fn_pre_data on @lv before first metadata update + * and optional variable args function fn_post_on_lv with fn_post_data on @lv before second metadata update * - * This involves up to three metadata commits :( + * This minimaly involves 2 metadata commits or more, depending on + * pre and post functions carrying out any additional ones or not. + * + * WARNING: needs to be called with at least 3 arguments to suit va_list processing! */ -static int _lv_update_reload_fn_reset_eliminate_lvs(struct logical_volume *lv, - struct dm_list *removal_lvs, - int (*fn_on_lv)(struct logical_volume *lv, void *data), - void *fn_data) +typedef int (*fn_on_lv_t)(struct logical_volume *lv, void *data); +static int _lv_update_reload_fns_reset_eliminate_lvs(struct logical_volume *lv, ...) { + int r = 0; + va_list ap; + fn_on_lv_t fn_pre_on_lv = NULL, fn_post_on_lv; + void *fn_pre_data, *fn_post_data; + struct dm_list *removal_lvs; + RETURN_IF_ZERO(lv, "lv argument"); - if (!lv_update_and_reload(lv)) - return_0; + va_start(ap, lv); + removal_lvs = va_arg(ap, struct dm_list *); + if ((fn_post_on_lv = va_arg(ap, fn_on_lv_t))) { + fn_post_data = va_arg(ap, void *); + if ((fn_pre_on_lv = va_arg(ap, fn_on_lv_t))) + fn_pre_data = va_arg(ap, void *); + } + + /* Call any @fn_pre_on_lv before the first update and reload call (e.g. to rename LVs) */ + if (fn_pre_on_lv && !fn_pre_on_lv(lv, fn_pre_data)) + goto err; + + /* Update metadata and reload mappings including flags (e.g. LV_REBUILD) */ + if (!lv_update_and_reload_origin(lv)) + goto err; /* Eliminate any residual LV, write VG, commit it and take a backup */ - if (!_eliminate_extracted_lvs(lv->vg, removal_lvs)) - return 0; + if (!_eliminate_extracted_lvs_optional_write_vg(lv->vg, removal_lvs, 0)) + goto err; /* * Now that any 'REBUILD' or 'RESHAPE_DELTA_DISKS' etc. @@ -2629,30 +2682,25 @@ static int _lv_update_reload_fn_reset_eliminate_lvs(struct logical_volume *lv, * Writes and commits metadata if any flags have been reset * and if successful, performs metadata backup. */ - if (!_reset_flags_passed_to_kernel(lv)) - return 0; + /* Avoid vg write+commit in vvv and do it here _once_ in case of fn_on_lv() being called */ + log_debug_metadata("Clearing any flags for %s passed to the kernel", display_lvname(lv)); + if (!_reset_flags_passed_to_kernel(lv, 0)) + goto err; - /* Call any @fn_on_lv between the 2 metadata update and reload calls (e.g. to rename LVs) */ - if (fn_on_lv) { - if (!fn_on_lv(lv, fn_data)) - return 0; + /* Call any @fn_pre_on_lv before the second update and reload call (e.g. to rename LVs back) */ + if (fn_post_on_lv && !fn_post_on_lv(lv, fn_post_data)) + goto err; - log_debug_metadata("Clearing any flags for %s passed to the kernel and/or update changed metadata.", - display_lvname(lv)); - if (!lv_update_and_reload(lv)) { - log_error("second update of %s failed", display_lvname(lv)); - return 0; - } + log_debug_metadata("Updating metadata and reloading mappings for %s", display_lvname(lv)); + if (!lv_update_and_reload(lv)) { + log_error(INTERNAL_ERROR "Update and reload of LV %s failed", display_lvname(lv)); + goto err; } - return 1; -} - -/* HM Helper: convenience wrapper */ -static int _lv_update_reload_reset_eliminate_lvs(struct logical_volume *lv, - struct dm_list *removal_lvs) -{ - return _lv_update_reload_fn_reset_eliminate_lvs(lv, removal_lvs, NULL, NULL); + r = 1; +err: + va_end(ap); + return r; } /* Area reorder helper: swap 2 LV segment areas @a1 and @a2 */ @@ -2879,6 +2927,7 @@ static int _alloc_and_add_rmeta_devs_for_lv(struct logical_volume *lv) { struct lv_segment *seg; struct dm_list meta_lvs; +struct lv_list *lvl; RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv))); @@ -2890,6 +2939,8 @@ static int _alloc_and_add_rmeta_devs_for_lv(struct logical_volume *lv) return_0; } +dm_list_iterate_items(lvl, &meta_lvs) +PFLA("meta_lv=%s", lvl->lv->name); /* Metadata LVs must be cleared before being added to the array */ log_debug_metadata("Clearing newly allocated metadata LVs for %s", display_lvname(lv)); if (!_clear_lvs(&meta_lvs)) { @@ -3408,7 +3459,7 @@ static int _adjust_data_lvs(struct logical_volume *lv, enum mirror_raid_conv dir for (s = 0; s < seg->area_count; ++s) { struct logical_volume *dlv = seg_lv(seg, s); - if (!(p = _strstr_strings(dlv->name, "_mimage_", "_rimage_"))) { + if (!(p = _strstr_strings(dlv->name, "_mimage_", "_rimage_", NULL))) { log_error(INTERNAL_ERROR "name lags image part"); return 0; } @@ -3485,7 +3536,7 @@ static int _convert_mirror_to_raid(struct logical_volume *lv, return 0; } - return update_and_reload ? _lv_update_reload_reset_eliminate_lvs(lv, removal_lvs) : 1; + return update_and_reload ? _lv_update_reload_fns_reset_eliminate_lvs(lv, removal_lvs, NULL) : 1; } /* @@ -3557,7 +3608,7 @@ PFL(); } PFL(); - return update_and_reload ? _lv_update_reload_reset_eliminate_lvs(lv, removal_lvs) : 1; + return update_and_reload ? _lv_update_reload_fns_reset_eliminate_lvs(lv, removal_lvs, NULL) : 1; } /* BEGIN: striped -> raid0 conversion */ @@ -4450,7 +4501,7 @@ PFLA("old_image_count=%u new_image_count=%u new_region_size=%u", old_image_count if (where == alloc_begin) seg->data_offset = 1; - return _lv_update_reload_reset_eliminate_lvs(lv, NULL); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, NULL, NULL); } log_error("No reshape to do on %s", display_lvname(lv)); @@ -4558,7 +4609,7 @@ PFL(); /* HM FIXME: workaround for lvcreate not resetting "nosync" flag */ init_mirror_in_sync(0); PFLA("new_segtype=%s seg->area_count=%u", new_segtype->name, seg->area_count); - if (!_lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs)) + if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL)) return 0; return force_repair ? _lv_cond_repair(lv) : 1; @@ -5086,7 +5137,7 @@ static int _get_allowed_conversion_options(const struct lv_segment *seg_from, /* * Log any possible conversions for @lv */ -/* HM FIXEM: use log_info? */ +/* HM FIXME: use log_info? */ static int _log_possible_conversion_types(struct logical_volume *lv, const struct segment_type *new_segtype) { unsigned i; @@ -5427,7 +5478,7 @@ static int _rename_lv(struct logical_volume *lv, const char *from, const char *t RETURN_IF_ZERO(lv, "lv argument"); RETURN_IF_ZERO((name = (char *) lv->name), "lv name"); - RETURN_IF_ZERO((p = strstr(lv->name, from)), "from sting in LV name"); + RETURN_IF_ZERO((p = strstr(lv->name, from)), "from string in LV name"); sz = p - lv->name + strlen(to) + (strlen(p) - strlen(from)) + 1; RETURN_IF_ZERO((name = dm_pool_alloc(lv->vg->vgmem, sz)), "space for name"); @@ -5445,17 +5496,19 @@ static int _rename_lv(struct logical_volume *lv, const char *from, const char *t static int _rename_lv_and_sub_lvs(struct logical_volume *lv, const char *from, const char *to) { uint32_t s; + struct logical_volume *mlv; struct lv_segment *seg; RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv))); - for (s = 0; s < seg->area_count; s++) { - if (seg->meta_areas && seg_metalv(seg, s) && - !_rename_lv(seg_metalv(seg, s), from, to)) + if (seg->area_count > 1) + for (s = 0; s < seg->area_count; s++) { + if ((mlv = _seg_metalv(seg, s)) && + !_rename_lv(mlv, from, to)) return 0; - if (!_rename_lv(seg_lv(seg, s), from, to)) + if (!_rename_lv(seg_lv(seg, s), from, to)) return 0; - } + } lv->name = to; @@ -5505,7 +5558,7 @@ static int _prepare_seg_for_name_shift(struct logical_volume *lv) if (!_get_max_sub_lv_name_index(lv, &max_idx)) return 0; -PFL(); + seg->area_count++; RETURN_IF_ZERO((max_idx < seg->area_count), "valid maximum index"); @@ -5514,10 +5567,10 @@ PFL(); continue; RETURN_IF_ZERO(seg_metatype(seg, s) == AREA_LV, "valid metadata sub-lv") -PFL(); + if (!_lv_name_get_string_index(seg_lv(seg, s), &idx)) return 0; -PFLA("idx=%u", idx); + RETURN_IF_ZERO(idx < seg->area_count, "valid sub-lv index"); if (idx != s) { seg->areas[idx] = seg->areas[s]; @@ -5540,22 +5593,24 @@ static int _rename_sub_lvs(struct logical_volume *lv, enum rename_dir dir) { "_rimage_", "_rmeta_", "__rimage_", "__rmeta_" }, /* flat */ { "_dup_", "_rmeta_", "__dup_", "__rmeta_" }, /* dup */ }; + struct logical_volume *mlv; struct lv_segment *seg; RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv))); + RETURN_IF_ZERO(seg->area_count, "areas"); - if (!lv_is_raid(lv)) + if (!lv_is_raid(lv) && !lv_is_raid_image(lv)) return 1; - RETURN_IF_NONZERO(dir < 0 || dir > to_dup, "valid rename request"); + RETURN_IF_NONZERO(dir < to_flat || dir > to_dup, "valid rename request"); type = dir / 2; /* flat or dup names */ RETURN_IF_ZERO(type < ARRAY_SIZE(names), "valid type"); ft = from_to[!(dir % 2)]; /* from or to indexes */ log_debug_metadata("Renaming %s sub LVs to avoid name collision", display_lvname(lv)); for (s = 0; s < seg->area_count; s++) { - if (seg->meta_areas && seg_metatype(seg, s) == AREA_LV && seg_metalv(seg, s) && - !_rename_lv(seg_metalv(seg, s), names[type][ft[0]+1], names[type][ft[1]+1])) + if ((mlv = _seg_metalv(seg, s)) && + !_rename_lv(mlv, names[type][ft[0]+1], names[type][ft[1]+1])) return 0; if (seg_type(seg, s) == AREA_LV && @@ -5594,6 +5649,8 @@ static int _rename_split_duplicate_lv_and_sub_lvs(struct logical_volume *dlv, * * remove layer from @lv keeping @sub_lv, * add lv to be removed to @removal_lvs, + * rename from flat "_rimage_|_rmeta_" namespace + * to "__rimage_|__rmeta_" to avoid name collision, * reset duplicated flag and make visible */ static int _remove_duplicating_layer(struct logical_volume *lv, @@ -5610,7 +5667,6 @@ static int _remove_duplicating_layer(struct logical_volume *lv, lv->le_count = slv->le_count; lv->size = lv->le_count * lv->vg->extent_size; -PFLA("lv=%s slv=%s", display_lvname(lv), display_lvname(slv)); if (!_lv_reset_raid_add_to_list(slv, removal_lvs)) return 0; @@ -5618,20 +5674,86 @@ PFLA("lv=%s slv=%s", display_lvname(lv), display_lvname(slv)); if (!remove_layer_from_lv(lv, slv)) return_0; - /* HM FIXME: in case _lv_reduce() recursion bugs, this may hit */ + /* HM FIXME: in case of _lv_reduce() recursion bugs, this may hit */ RETURN_IF_ZERO(first_seg(lv), "first segment!?"); -PFL(); + + if (!_rename_sub_lvs(lv, from_flat)) + return 0; + lv->status &= ~LV_DUPLICATED; lv_set_visible(lv); return 1; } -/* HM Helper: callback to rename all sub_lvs of @lv to namespace requested by @dir */ -static int _raid_split_duplicate_rename_sub_lvs(struct logical_volume *lv, void *data) +/* HM Helper: callback to rename duplicated @lv and is sub LVs to __ namespacse to avoid collisions */ +static int _pre_rename_duplicated_lv_and_sub_lvs(struct logical_volume *lv, void *data) { -PFL(); - return (lv_is_raid(lv) && !_rename_sub_lvs(lv, *((enum rename_dir*) data))) ? 0 : 1; + uint32_t s; + struct lv_segment *seg; + + RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv))); + + /* Rename all remaning sub LVs temporarilly to allow for name shift w/o name collision */ + log_debug_metadata("Renaming split duplicate LV and sub LVs of %s", display_lvname(lv)); + for (s = 0; s < seg->area_count; s++) + if (!_rename_split_duplicate_lv_and_sub_lvs(seg_lv(seg, s), seg_metalv(seg, s), to_dup)) + return 0; + + return 1; +} + +/* HM Helper: callback to rename duplicated @lv and its sub LVs back from "__" infixed namespace */ +static int _post_rename_duplicated_lv_and_sub_lvs_back(struct logical_volume *lv, void *data) +{ + uint32_t s; + struct lv_segment *seg; + struct logical_volume *split_lv; + + RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv))); + RETURN_IF_ZERO((split_lv = data), "valid split LV"); + RETURN_IF_ZERO(seg->area_count, "areas"); + + if (!lv_update_and_reload(split_lv)) + return 0; + + for (s = 0; s < seg->area_count; s++) + if (!_rename_split_duplicate_lv_and_sub_lvs(seg_lv(seg, s), seg_metalv(seg, s), from_dup)) + return 0; + + /* Shift area numerical indexes down */ + return _prepare_seg_for_name_shift(lv) && + _shift_image_components(seg); +} + +/* HM Helper: callback to extract last metadata image of @lv and remove top-level raid1 layer */ +static int _pre_rename_duplicated_sub_lvs(struct logical_volume *lv, void *data) +{ + struct dm_list *removal_lvs; + struct lv_segment *seg; + + RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv))); + RETURN_IF_ZERO((removal_lvs = data), "remova LVs list"); + + log_debug_metadata("Extracting last metadata LV of %s", display_lvname(lv)); + if (!_extract_image_component_sublist(seg, RAID_META, 0, 1, removal_lvs, 1)) + return 0; + + log_debug_metadata("Removing top-level raid1 LV %s", display_lvname(lv)); + return _remove_duplicating_layer(lv, removal_lvs); +} + +/* HM Helper: callback to rename all sub_lvs of @lv (if raid) to flat namespace */ +static int _post_rename_duplicated_sub_lvs(struct logical_volume *lv, void *data) +{ + struct logical_volume *split_lv; + + RETURN_IF_ZERO((split_lv = data), "split LV"); + + if (!lv_update_and_reload(split_lv)) + return 0; + + return _rename_sub_lvs(lv, to_flat); } /* @@ -5648,16 +5770,18 @@ static int _raid_split_duplicate(struct logical_volume *lv, int yes, const char *split_name, uint32_t new_image_count) { uint32_t s; - enum rename_dir dir = to_flat; + void *fn_pre_data; const char *lv_name; struct dm_list removal_lvs; struct lv_segment *seg; struct logical_volume *split_lv = NULL; + fn_on_lv_t fn_pre_on_lv, fn_post_on_lv; RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv))); RETURN_IF_ZERO(_lv_is_duplicating(lv), "Called with non-duplicating LV"); RETURN_IF_ZERO(split_name, "split name argument"); RETURN_IF_ZERO(seg->area_count, "lv segment areas"); + RETURN_IF_ZERO(seg->meta_areas, "metadata segment areas"); if (!_lv_is_active((lv))) return 0; @@ -5716,80 +5840,63 @@ static int _raid_split_duplicate(struct logical_volume *lv, int yes, log_debug_metadata("Rename duplicated LV %s and and any of its sub LVs before splitting them off", display_lvname(split_lv)); - if (lv_is_raid(split_lv) && - !_rename_lv_and_sub_lvs(split_lv, split_lv->name, lv_name)) + if (!_rename_lv_and_sub_lvs(split_lv, split_lv->name, lv_name)) return 0; seg->area_count--; seg->data_copies--; RETURN_IF_ZERO(seg->area_count == seg->data_copies, "valid data cpies"); + lv_set_visible(split_lv); split_lv->status &= ~LV_NOTSYNCED; /* Shift areas down if not last one */ for ( ; s < seg->area_count; s++) { seg->areas[s] = seg->areas[s + 1]; - if (seg->meta_areas) - seg->meta_areas[s] = seg->meta_areas[s + 1]; + seg->meta_areas[s] = seg->meta_areas[s + 1]; } + /* We have more than one sub LVs -> rename and shift down */ if (seg->area_count > 1) { - /* Rename the sub-lv following the split off one temporarilly to allow for name shift w/o name collision */ - for (s = 0; s < seg->area_count; s++) - if (!_rename_split_duplicate_lv_and_sub_lvs(seg_lv(seg, s), seg_metalv(seg, s), to_dup)) - return 0; + fn_pre_data = NULL; + fn_pre_on_lv = _pre_rename_duplicated_lv_and_sub_lvs; + fn_post_on_lv = _post_rename_duplicated_lv_and_sub_lvs_back; - log_debug_metadata("Updating VG metadata and reactivating %s and %s", - display_lvname(lv), display_lvname(split_lv)); - if (!_lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs) || - !lv_update_and_reload(split_lv)) - return_0; + /* We are down to the last sub LV -> remove the top-level raid1 mapping */ + } else { + fn_pre_data = &removal_lvs; + fn_pre_on_lv = _pre_rename_duplicated_sub_lvs; + fn_post_on_lv = _post_rename_duplicated_sub_lvs; + } - /* Rename the sub-lv following the split off one back */ - for (s = 0; s < seg->area_count; s++) - if (!_rename_split_duplicate_lv_and_sub_lvs(seg_lv(seg, s), seg_metalv(seg, s), from_dup)) - return 0; + log_debug_metadata("Updating VG metadata, reloading %s and activating split LV %s", + display_lvname(lv), display_lvname(split_lv)); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, + fn_post_on_lv, split_lv, + fn_pre_on_lv, fn_pre_data); +} - /* Shift area numerical indexes down and reload */ - if (!_prepare_seg_for_name_shift(lv)) - return 0; -PFL(); - if (!_shift_image_components(seg)) - return 0; -PFL(); - log_debug_metadata("Updating VG metadata and reactivating %s", display_lvname(lv)); - return lv_update_and_reload_origin(lv); - } -PFL(); - /* We are down to the last sub LV -> remove the top-level raid1 mapping */ - if (!_extract_image_component_sublist(seg, RAID_META, 0, 1, &removal_lvs, 1)) - return 0; -PFL(); - /* r_dup_N */ - log_debug_metadata("Removing top-level raid1 LV %s", display_lvname(lv)); - if (!_remove_duplicating_layer(lv, &removal_lvs)) - return 0; +/* HM Helper: callback to rename any sub LVs of @lv to flat namespace */ +static int _post_rename_sub_lvs_on_unduplication(struct logical_volume *lv, void *data) +{ + if (!lv_is_raid(lv)) + return 1; - if (!_rename_sub_lvs(lv, from_flat)) - return 0; -PFL(); - log_debug_metadata("Updating VG metadata and reloading %s", - display_lvname(lv)); - return _lv_update_reload_fn_reset_eliminate_lvs(lv, &removal_lvs, _raid_split_duplicate_rename_sub_lvs, &dir) && - activate_lv_excl_local(lv->vg->cmd, split_lv); + return _rename_sub_lvs(lv, to_flat) && + lv_update_and_reload(lv); } /* * HM Helper: * - * remove top-level raid1 LV and replace with requested sub_lv_name + * remove top-level raid1 @lv and replace with requested @sub_lv_name */ -static int _raid_conv_unduplicate(struct logical_volume *lv, - int yes, const char *sub_lv_name) +static int _raid_unduplicate(struct logical_volume *lv, + int yes, const char *sub_lv_name) { uint32_t keep_idx; struct logical_volume *keep_lv; - struct lv_segment *seg; + struct lv_segment *seg, *seg1; struct dm_list removal_lvs; RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv))); @@ -5819,7 +5926,7 @@ static int _raid_conv_unduplicate(struct logical_volume *lv, log_warn("This is a request to unduplicate LV %s keeping %s", display_lvname(lv), display_lvname(seg_lv(seg, keep_idx))); if (!yes) { - struct lv_segment *seg1 = first_seg(keep_lv); + RETURN_IF_ZERO((seg1 = first_seg(keep_lv)), "segment in induplicate LV"); if (yes_no_prompt("Do you want to convert %s to type %s thus " "unduplicating it and removing %u duplicated LV(s)? [y/n]: ", @@ -5827,14 +5934,16 @@ static int _raid_conv_unduplicate(struct logical_volume *lv, _get_segtype_name(seg1->segtype, seg1->area_count), seg->area_count - 1) == 'n') return 0; + if (sigint_caught()) return_0; } -PFL(); + + dm_list_init(&removal_lvs); + /* - * Extract rmeta images of the raid1 top-level LV and all but @keep_idx data images + * Extract all rmeta images of the raid1 top-level LV and all but @keep_idx data images */ - dm_list_init(&removal_lvs); if (!_extract_image_component_sublist(seg, RAID_META, 0, seg->area_count, &removal_lvs, 1) || (keep_idx && !_extract_image_component_sublist(seg, RAID_IMAGE, 0, keep_idx, &removal_lvs, 0)) || @@ -5851,21 +5960,11 @@ PFL(); seg->area_count = 1; - /* Remove top-level raid1 layer keeping first sub LV */ - if (!_remove_duplicating_layer(lv, &removal_lvs)) - return 0; + /* Remove top-level raid1 layer keeping first sub LV and update+reload LV */ + return _remove_duplicating_layer(lv, &removal_lvs) && + _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, + _post_rename_sub_lvs_on_unduplication, lv, NULL); - if (!_lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs)) - return 0; - - if (lv_is_raid(lv)) { - if (!_rename_sub_lvs(lv, to_flat)) - return 0; - - return lv_update_and_reload_origin(lv); - } - - return 1; } /* @@ -5911,30 +6010,55 @@ static struct logical_volume *_dup_lv_create(struct logical_volume *lv, "duplication conversion got removed (e.g. resize fs)"); } - r->status |= RAID_IMAGE|LV_DUPLICATED; + r->status |= RAID_IMAGE | LV_DUPLICATED; lv_set_hidden(r); return r; } -/* Helper: callback function to rename metadata sub-lvs of top-level duplicating LV */ -static int _raid_conv_duplicate_rename_metadata_sub_lvs(struct logical_volume *lv, void *data) +/* Helper: callback function to rename metadata sub-lvs of top-level duplicating @lv */ +static int _pre_raid_duplicate_rename_metadata_sub_lvs(struct logical_volume *lv, ...) { uint32_t s; + struct logical_volume *mlv; struct lv_segment *seg; RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv))); + RETURN_IF_ZERO(seg->meta_areas, "metadata areas"); + + /* Rename top-level raid1 metadata sub LVs to their final names */ + log_debug_metadata("Renaming sub LVs of %s to temporary names", + display_lvname(lv)); + for (s = 0; s < seg->area_count; s++) + if ((mlv = _seg_metalv(seg, s)) && + !_rename_lv(mlv, "_rmeta_", "__rmeta_")) + return 0; + + return 1; +} + +/* Helper: callback function to rename metadata sub-lvs of top-level duplicating@lv back */ +static int _post_raid_duplicate_rename_metadata_sub_lvs_back(struct logical_volume *lv, void *data) +{ + uint32_t s; + struct lv_segment *seg; + struct logical_volume *dup_lv, *mlv; + + RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv))); + RETURN_IF_ZERO((dup_lv = data), "duplicated LV argument"); + RETURN_IF_ZERO(seg->meta_areas, "metadata areas"); /* Rename top-level raid1 metadata sub LVs to their final names */ log_debug_metadata("Renaming sub LVs of %s to final names", display_lvname(lv)); - for (s = 0; s < seg->area_count; s++) { - struct logical_volume *mlv; + for (s = 0; s < seg->area_count; s++) + if ((mlv = _seg_metalv(seg, s)) && + !_rename_lv(mlv, "__rmeta_", "_rmeta_")) + return 0; - RETURN_IF_NONZERO((seg_type(seg, s) != AREA_LV || !(mlv = seg_metalv(seg, s))), "metadata sub-lv"); - if (strstr(mlv->name, "_dup_")) - RETURN_IF_ZERO((mlv->name = _generate_raid_name(lv, "rmeta_", s)), "metadata sub LV name created"); - } + /* Activate to prevent unsafe table load */ + if (!activate_lv_excl_local(lv->vg->cmd, dup_lv)) + return lv_remove(dup_lv); return 1; } @@ -5946,15 +6070,15 @@ static int _raid_conv_duplicate_rename_metadata_sub_lvs(struct logical_volume *l * creates and allocates a destination LV of ~ the same size (may be rounded) * with the requested @new_segtype and properties (e.g. stripes). */ -static int _raid_conv_duplicate(struct logical_volume *lv, - const struct segment_type *new_segtype, - int yes, int force, - const int new_data_copies, - const uint32_t new_region_size, - const uint32_t new_stripes, - const uint32_t new_stripe_size, - const char *pool_lv_name, - struct dm_list *allocate_pvs) +static int _raid_duplicate(struct logical_volume *lv, + const struct segment_type *new_segtype, + int yes, int force, + const int new_data_copies, + const uint32_t new_region_size, + const uint32_t new_stripes, + const uint32_t new_stripe_size, + const char *pool_lv_name, + struct dm_list *allocate_pvs) { int duplicating; uint32_t data_copies = new_data_copies, extents, new_area_idx, raid1_image_count, region_size = 1024, s; @@ -6067,16 +6191,12 @@ PFLA("segtype=%s area_count=%u data_copies=%u stripe_size=%u", lvseg_name(seg), log_debug_metadata("Creating unique LV name for source sub LV"); RETURN_IF_ZERO((first_name = _generate_raid_name(lv, "dup_", 0)), "first sub LV name created"); RETURN_IF_ZERO((suffix = strstr(first_name, "_dup_")), "source prefix found"); - - /* _convert_lv_to_raid() returns the first segment of the new raid1 top-level LV */ log_debug_metadata("Inserting layer LV on top of source LV %s", display_lvname(lv)); lv->status |= LV_DUPLICATED; /* set duplicated flag on LV before it moves a level down */ RETURN_IF_ZERO((seg = _convert_lv_to_raid1(lv, suffix)), "conversion to raid1 possible"); + seg->meta_areas = NULL; } -PFLA("seg_lv(seg, 0)=%s", display_lvname(seg_lv(seg, 0))); -PFLA("seg->area_count=%u", seg->area_count); -PFLA("lv->name=%s lv->le_count=%u seg_lv(seg, 0)=%s", lv->name, lv->le_count, seg_lv(seg, 0)->name); /* Grow areas arrays for data and metadata devs to add new duplicated LV */ log_debug_metadata("Reallocating areas array of %s", display_lvname(lv)); RETURN_IF_ZERO(_realloc_meta_and_data_seg_areas(lv, seg->area_count + 1), @@ -6085,7 +6205,7 @@ PFLA("lv->name=%s lv->le_count=%u seg_lv(seg, 0)=%s", lv->name, lv->le_count, se new_area_idx = seg->area_count; seg->area_count++; /* Must update area count after resizing it */ seg->data_copies = seg->area_count; -PFL(); + /* Set @layer_lv as the LV of @area of @lv */ log_debug_metadata("Add duplicated LV %s to top-level LV %s as raid1 leg %u", display_lvname(dup_lv), display_lvname(lv), new_area_idx); @@ -6094,13 +6214,14 @@ PFL(); display_lvname(dup_lv), display_lvname(lv)); return NULL; } -PFLA("seg_lv(seg, %u)=%s", new_area_idx, display_lvname(seg_lv(seg, new_area_idx))); + /* If not duplicating yet, allocate first metadata LV */ if (!duplicating && - !_alloc_rmeta_for_lv_and_set_hidden(seg_lv(seg, 0), &seg_metalv(seg, 0))) + !_alloc_rmeta_for_lv_add_set_hidden(lv, 0)) return 0; - if (!_alloc_rmeta_for_lv_and_set_hidden(seg_lv(seg, new_area_idx), &seg_metalv(seg, new_area_idx))) + /* Allocate new metadata LV for duplicated sub LV */ + if (!_alloc_rmeta_for_lv_add_set_hidden(lv, new_area_idx)) return 0; for (s = 0; s < new_area_idx; s++) @@ -6110,16 +6231,12 @@ PFLA("seg_lv(seg, %u)=%s", new_area_idx, display_lvname(seg_lv(seg, new_area_idx lv_set_visible(lv); PFLA("lv0->le_count=%u lv1->le_count=%u", seg_lv(seg, 0)->le_count, seg_lv(seg, 1)->le_count); - /* Activate to prevent unsafe table load */ - if (!activate_lv_excl_local(lv->vg->cmd, dup_lv)) { - lv_remove(dup_lv); - return_0; - } -PFL(); init_mirror_in_sync(0); - /* _raid_conv_duplicate_rename_metadata_sub_lvs() will be called between the 2 update+reload calls */ - return _lv_update_reload_fn_reset_eliminate_lvs(lv, NULL, _raid_conv_duplicate_rename_metadata_sub_lvs, NULL); + /* _post_raid_duplicate_rename_metadata_sub_lvs_back() will be called between the 2 update+reload calls */ + return _lv_update_reload_fns_reset_eliminate_lvs(lv, NULL, + _post_raid_duplicate_rename_metadata_sub_lvs_back, dup_lv, + _pre_raid_duplicate_rename_metadata_sub_lvs, NULL); } /* @@ -6229,7 +6346,7 @@ TAKEOVER_HELPER_FN(_linear_raid14510) seg = first_seg(lv); seg->segtype = new_segtype; - return _lv_update_reload_reset_eliminate_lvs(lv, NULL); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, NULL, NULL); } /* Helper: striped/raid0* -> raid4/5/6/10 */ @@ -6339,7 +6456,7 @@ PFL(); log_debug_metadata("Updating VG metadata and reloading %s LV %s", lvseg_name(seg), display_lvname(lv)); - if (!_lv_update_reload_reset_eliminate_lvs(lv, NULL)) + if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, NULL, NULL)) return 0; PFL(); @@ -6379,7 +6496,7 @@ TAKEOVER_HELPER_FN(_raid0_linear) if (force) return 1; - return _lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL); } /* Helper: raid0* with one image -> mirror */ @@ -6471,7 +6588,7 @@ TAKEOVER_HELPER_FN(_raid0_raid1) /* Master leg is the first sub LV */ seg_lv(seg, 0)->status &= ~LV_REBUILD; - return _lv_update_reload_reset_eliminate_lvs(lv, NULL); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, NULL, NULL); } /* Helper: mirror -> raid0* */ @@ -6515,7 +6632,7 @@ TAKEOVER_HELPER_FN(_mirror_raid0) seg->segtype = new_segtype; - return _lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL); } /* Helper: convert mirror with 2 images <-> raid4/5 */ @@ -6561,7 +6678,7 @@ TAKEOVER_HELPER_FN(_mirror_r45) } else if (!_convert_mirror_to_raid(lv, new_segtype, 0, NULL, 0 /* update_and_reaload */, NULL)) return 0; - return _lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL); } /* Helper: raid1 -> raid0* */ @@ -6599,7 +6716,7 @@ TAKEOVER_HELPER_FN(_raid1_raid0) return 0; } - return _lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL); } /* raid45 -> raid0* / striped */ @@ -6654,7 +6771,7 @@ PFLA("seg->area_count=%u seg->len=%u seg->area_len=%u", seg->area_count, seg->le first_seg(lv)->data_copies = 1; - return _lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL); } /* helper raid1 with N images or raid4/5* with 2 images <-> linear */ @@ -6702,7 +6819,7 @@ PFL(); if (!_convert_raid_to_linear(lv, &removal_lvs)) return_0; - return _lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL); } /* Helper: raid1 with N images to M images (N != M) and raid4/5 to raid6* */ @@ -6743,7 +6860,7 @@ TAKEOVER_HELPER_FN(_raid145_raid1_raid6) new_stripe_size) seg->stripe_size = new_stripe_size; - return _lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL); } /* Helper: raid1/5 with 2 images <-> raid4/5/10 or raid4 <-> raid5_n with any image count (no change to count!) */ @@ -6805,7 +6922,7 @@ TAKEOVER_HELPER_FN(_raid145_raid4510) seg->stripe_size = new_stripe_size ?: DEFAULT_STRIPESIZE; - return _lv_update_reload_reset_eliminate_lvs(lv, NULL); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, NULL, NULL); } /* Helper: raid10 -> striped/raid0* */ @@ -6904,7 +7021,7 @@ PFLA("seg->chunk_size=%u", seg->chunk_size); seg->segtype = new_segtype; /* HM FIXME: overloading force argument here! */ - return force ? 1 : _lv_update_reload_reset_eliminate_lvs(lv, removal_lvs); + return force ? 1 : _lv_update_reload_fns_reset_eliminate_lvs(lv, removal_lvs, NULL); } /* Helper: raid10 with 2/N (if appropriate) images <-> raid1/raid4/raid5* */ @@ -6957,7 +7074,7 @@ TAKEOVER_HELPER_FN(_raid10_r1456) seg->segtype = new_segtype; - return _lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL); } /* End takeover helper funtions */ @@ -7609,7 +7726,7 @@ TAKEOVER_FN(_r6_r45) seg->segtype = new_segtype; - return _lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL); } /* raid10 with 2 images -> linear */ @@ -7669,7 +7786,7 @@ TAKEOVER_FN(_r10_m) !_convert_raid1_to_mirror(lv, new_segtype, new_image_count, allocate_pvs, 0, &removal_lvs)) return 0; - return _lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL); } /* raid10 -> raid0 */ @@ -7779,7 +7896,7 @@ PFL(); seg->segtype = raid10_segtype; PFL(); - return _lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL); } /* @@ -7962,7 +8079,7 @@ PFL(); if (!remove_layer_from_lv(lv, lv_tmp)) return_0; PFL(); - return _lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL); } /* Remove striped legs from raid01 */ @@ -8006,7 +8123,7 @@ TAKEOVER_FN(_r01_r10) if (!_raid01_remove_images(lv, 1, &removal_lvs)) return 0; - if (!_lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs)) + if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL)) return 0; return _striped_raid0_raid45610(lv, new_segtype, yes, force, @@ -8059,7 +8176,7 @@ PFL(); log_debug_metadata("Allocating metadata images for the new sub-lvs of %s", display_lvname(lv)); for (s = seg->area_count; s < new_data_copies; s++) { - if (!_alloc_rmeta_for_lv_and_set_hidden(seg_lv(seg, s), &seg_metalv(seg, s))) + if (!_alloc_rmeta_for_lv_add_set_hidden(lv, s)) return 0; seg_lv(seg, s)->status |= LV_REBUILD; @@ -8071,7 +8188,7 @@ PFL(); } else if (!_raid01_remove_images(lv, new_data_copies, &removal_lvs)) return 0; - return _lv_update_reload_reset_eliminate_lvs(lv, &removal_lvs); + return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL); } /* @@ -8238,7 +8355,7 @@ static int _raid_convert_define_parms(const struct lv_segment *seg, { *stripes = *stripes ?: ((duplicate) ? 2 : _data_rimages_count(seg, seg->area_count)); *stripe_size = *stripe_size ?: seg->stripe_size; - *data_copies = *data_copies > -1 ? *data_copies : (duplicate ? 2 : seg->area_count); + *data_copies = *data_copies > -1 ? *data_copies : (duplicate ? 1 : seg->area_count); *region_size = *region_size ?: seg->region_size; /* Check region size */ @@ -8263,10 +8380,12 @@ static int _raid_convert_define_parms(const struct lv_segment *seg, *stripes = 1; // *data_copies = *data_copies < 2 ? 2 : *data_copies; - } else if (segtype_is_any_raid10(*segtype)) + } else if (segtype_is_any_raid10(*segtype)) { *data_copies = *data_copies < 2 ? 2 : *data_copies; + if (*stripes < 3) + *stripes = 3; - else if (segtype_is_striped(*segtype) || + } else if (segtype_is_striped(*segtype) || segtype_is_striped_raid(*segtype)) { if (*stripes > 1 && !*stripe_size) { @@ -8324,7 +8443,7 @@ static int _region_size_change_requested(struct logical_volume *lv, int yes, uin } /* Check for new region size causing bitmap to still fit metadata image LV */ - if (seg_metalv(seg, 0)->le_count < + if (seg->meta_areas && seg_metatype(seg, 0) == AREA_LV && seg_metalv(seg, 0)->le_count < _raid_rmeta_extents(lv->vg->cmd, lv->le_count, seg->region_size, lv->vg->extent_size)) { log_error("Region size %u on %s is too small for metadata LV size", seg->region_size, display_lvname(lv)); @@ -8475,9 +8594,9 @@ int lv_raid_convert(struct logical_volume *lv, "mandatory on duplicating LV %s", display_lvname(lv)); return 0; } -PFL(); + } else if (rcp.unduplicate && !lv_is_duplicated(lv)) { - log_error("LV %s is not duplicating!", display_lvname(lv)); + log_error("LV %s is not duplicated!", display_lvname(lv)); return 0; } @@ -8485,9 +8604,10 @@ PFL(); seg1 = first_seg(lv); new_segtype = new_segtype ?: (struct segment_type *) seg1->segtype; -PFLA("new_segtype=%s data_copies=%d region_size=%u stripes=%u stripe_size=%u", new_segtype ? new_segtype->name : "", data_copies, region_size, stripes, stripe_size); + if (!_raid_convert_define_parms(seg1, &new_segtype, rcp.duplicate, &data_copies, ®ion_size, &stripes, &stripe_size)) return 0; + PFLA("new_segtype=%s data_copies=%d region_size=%u stripes=%u stripe_size=%u", new_segtype ? new_segtype->name : "", data_copies, region_size, stripes, stripe_size); if (lv_is_duplicated(lv) && !rcp.duplicate && !rcp.unduplicate) { @@ -8549,7 +8669,7 @@ PFLA("new_segtype=%s image_count=%u data_copies=%d region_size=%u stripes=%u str rcp.stripes, rcp.stripe_size)) return _log_possible_conversion_types(lv, new_segtype); - return _raid_conv_duplicate(lv, new_segtype, rcp.yes, rcp.force, data_copies, region_size, + return _raid_duplicate(lv, new_segtype, rcp.yes, rcp.force, data_copies, region_size, stripes, stripe_size, rcp.lv_name, rcp.allocate_pvs); PFLA("new_segtype=%s image_count=%u data_copies=%d stripes=%u", new_segtype ? new_segtype->name : "", image_count, data_copies, stripes); @@ -8565,7 +8685,7 @@ PFLA("lv=%s", display_lvname(lv)); return 0; PFLA("lv=%s lv_name=%s", display_lvname(lv), rcp.lv_name); - if (!_raid_conv_unduplicate(lv, rcp.yes, rcp.lv_name)) { + if (!_raid_unduplicate(lv, rcp.yes, rcp.lv_name)) { if (!_lv_is_duplicating(lv)) _log_possible_conversion_types(lv, new_segtype); @@ -9180,7 +9300,7 @@ int lv_raid_replace(struct logical_volume *lv, } PFL(); /* This'll reset the rebuild flags passed to the kernel */ - if (!_lv_update_reload_reset_eliminate_lvs(lv, &old_lvs)) + if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, &old_lvs, NULL)) return_0; PFL(); /* Update new sub-LVs to correct name and clear REBUILD flag in-kernel and in metadata */ |