summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeinz Mauelshagen <heinzm@redhat.com>2016-01-19 22:21:15 +0100
committerHeinz Mauelshagen <heinzm@redhat.com>2016-01-19 22:21:15 +0100
commitf9611765d9f9d93eb65dddabdd7d5b76bee30c3d (patch)
treef371c1c83adad8e118a386af33bc8c56332f4b0a
parent43dff38daa71e9f38f47056fe8c92de9625e2d38 (diff)
downloadlvm2-f9611765d9f9d93eb65dddabdd7d5b76bee30c3d.tar.gz
RAID: support duplication/unduplication of thin volumes
-rw-r--r--lib/metadata/lv_manip.c56
-rw-r--r--lib/metadata/merge.c1
-rw-r--r--lib/metadata/raid_manip.c237
-rw-r--r--lib/misc/lib.h2
-rw-r--r--tools/lvconvert.c9
5 files changed, 175 insertions, 130 deletions
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index c587ad4a7..871d82e7c 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -4702,6 +4702,7 @@ static int _rename_sub_lv(struct logical_volume *lv,
* The suffix follows lv_name_old and includes '_'.
*/
len = strlen(lv_name_old);
+PFLA("lv=%s lv_name_old=%s lv_name_new=%s len=%u", display_lvname(lv), lv_name_old, lv_name_new, len);
if (strncmp(lv->name, lv_name_old, len) || lv->name[len] != '_') {
log_error("Cannot rename \"%s\": name format not recognized "
"for internal LV \"%s\"",
@@ -4766,27 +4767,33 @@ static int _for_each_sub_lv(struct logical_volume *lv, int skip_pools,
dm_list_iterate_items(seg, &lv->segments) {
if (seg->log_lv) {
+PFL();
if (!fn(seg->log_lv, data))
return_0;
if (!for_each_sub_lv(seg->log_lv, fn, data))
return_0;
}
- if (seg->metadata_lv) {
- if (!fn(seg->metadata_lv, data))
- return_0;
- if (!for_each_sub_lv(seg->metadata_lv, fn, data))
- return_0;
- }
+ if (!seg_is_thin(seg) && !seg_is_raid(seg)) {
+ if (seg->metadata_lv) {
+PFL();
+ if (!fn(seg->metadata_lv, data))
+ return_0;
+ if (!for_each_sub_lv(seg->metadata_lv, fn, data))
+ return_0;
+ }
- if (seg->pool_lv && !skip_pools) {
- if (!fn(seg->pool_lv, data))
- return_0;
- if (!for_each_sub_lv(seg->pool_lv, fn, data))
- return_0;
+ if (seg->pool_lv && !skip_pools) {
+PFL();
+ if (!fn(seg->pool_lv, data))
+ return_0;
+ if (!for_each_sub_lv(seg->pool_lv, fn, data))
+ return_0;
+ }
}
for (s = 0; s < seg->area_count; s++) {
+PFL();
if (seg_type(seg, s) != AREA_LV)
continue;
if (!fn(seg_lv(seg, s), data))
@@ -4794,12 +4801,14 @@ static int _for_each_sub_lv(struct logical_volume *lv, int skip_pools,
if (!for_each_sub_lv(seg_lv(seg, s), fn, data))
return_0;
}
-
+PFL();
if (!seg_is_raid(seg) || !seg->meta_areas)
continue;
+PFL();
/* RAID has meta_areas */
for (s = 0; s < seg->area_count; s++) {
+PFL();
if (seg_metatype(seg, s) != AREA_LV)
continue;
if (!fn(seg_metalv(seg, s), data))
@@ -4808,6 +4817,7 @@ static int _for_each_sub_lv(struct logical_volume *lv, int skip_pools,
return_0;
}
}
+PFL();
return 1;
}
@@ -5682,6 +5692,7 @@ PFL();
#endif
/* Perform any rounding to produce complete stripes. */
if (lp->stripes > 1) {
+PFLA("lp->stripes=%u", lp->stripes);
if (lp->stripe_size < STRIPE_SIZE_MIN) {
log_error("Invalid stripe size %s",
display_size(cmd, (uint64_t) lp->stripe_size));
@@ -6970,7 +6981,7 @@ int move_lv_segments(struct logical_volume *lv_to,
int remove_layer_from_lv(struct logical_volume *lv,
struct logical_volume *layer_lv)
{
- static const char _suffixes[][8] = { "_tdata", "_cdata", "_corig" };
+ static const char _suffixes[][8] = { "_tdata", "_cdata", "_corig", "_dup_" };
struct logical_volume *parent_lv;
struct lv_segment *parent_seg;
struct segment_type *segtype;
@@ -6996,7 +7007,7 @@ PFL();
* Before removal, the layer should be cleaned up,
* i.e. additional segments and areas should have been removed.
*/
-PFLA("lv=%s layer_lv=%s segments=%u area_count=%u layer_lv!=%u parent_lv->le_count=%u layer_lv->le_count=%u", display_lvname(lv), layer_lv ? display_lvname(layer_lv) : NULL, dm_list_size(&parent_lv->segments), parent_seg->area_count, layer_lv != seg_lv(parent_seg, 0), parent_lv->le_count, layer_lv->le_count)
+PFLA("lv=%s parent_lv=%s layer_lv=%s segments=%u area_count=%u layer_lv!=%u parent_lv->le_count=%u layer_lv->le_count=%u", display_lvname(lv), display_lvname(parent_lv), layer_lv ? display_lvname(layer_lv) : NULL, dm_list_size(&parent_lv->segments), parent_seg->area_count, layer_lv != seg_lv(parent_seg, 0), parent_lv->le_count, layer_lv->le_count)
if (dm_list_size(&parent_lv->segments) != 1 ||
parent_seg->area_count != 1 ||
seg_type(parent_seg, 0) != AREA_LV ||
@@ -7004,19 +7015,19 @@ PFLA("lv=%s layer_lv=%s segments=%u area_count=%u layer_lv!=%u parent_lv->le_cou
parent_lv->le_count != layer_lv->le_count)
return_0;
PFL();
-
if (!lv_empty(parent_lv))
return_0;
-
+PFL();
if (!move_lv_segments(parent_lv, layer_lv, 0, 0))
return_0;
-
+PFL();
/* Replace the empty layer with error segment */
if (!(segtype = get_segtype_from_string(lv->vg->cmd, "error")))
return_0;
+PFL();
if (!lv_add_virtual_segment(layer_lv, 0, parent_lv->le_count, segtype))
return_0;
-
+PFLA("parent_lv=%s layer_lv=%s", display_lvname(lv), display_lvname(parent_lv));
/*
* recuresively rename sub LVs
* currently supported only for thin data layer
@@ -7024,14 +7035,13 @@ PFL();
*/
if (!strstr(layer_lv->name, "_mimage"))
for (r = 0; r < DM_ARRAY_SIZE(_suffixes); ++r)
- if (strstr(layer_lv->name, _suffixes[r]) == 0) {
+ if (strstr(layer_lv->name, _suffixes[r])) {
lv_names.old = layer_lv->name;
lv_names.new = parent_lv->name;
if (!for_each_sub_lv(parent_lv, _rename_cb, (void *) &lv_names))
return_0;
break;
}
-
PFLA("%s", layer_lv->name);
return 1;
}
@@ -7621,6 +7631,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
return NULL;
}
+PFLA("lp->region_size=%u", lp->region_size);
if (!_vg_check_features(vg, lp))
return_NULL;
@@ -7757,6 +7768,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
return NULL;
}
+PFLA("lp->region_size=%u", lp->region_size);
if (origin_lv && seg_is_cache_pool(lp)) {
/* Converting exiting origin and creating cache pool */
if (!validate_lv_cache_create_origin(origin_lv))
@@ -7814,10 +7826,12 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
/* FIXME This will not pass cluster lock! */
init_mirror_in_sync(lp->nosync);
+PFLA("lp->region_size=%u", lp->region_size);
lp->region_size = adjusted_mirror_region_size(vg->extent_size,
lp->extents,
lp->region_size, 0,
vg_is_clustered(vg));
+PFLA("lp->region_size=%u", lp->region_size);
} else if (pool_lv && seg_is_thin_volume(lp)) {
if (!lv_is_thin_pool(pool_lv)) {
log_error("Logical volume %s is not a thin pool.",
@@ -7965,7 +7979,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
dm_list_splice(&lv->tags, &lp->tags);
-PFLA("lp->stripes=%u lp->stripe_size=%u lp->mirrors=%u", lp->stripes, lp->stripe_size, lp->mirrors);
+PFLA("lp->stripes=%u lp->stripe_size=%u lp->mirrors=%u lp->region_size=%u", lp->stripes, lp->stripe_size, lp->mirrors, lp->region_size);
if (!lv_extend(lv, create_segtype,
lp->stripes, lp->stripe_size,
lp->mirrors,
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 5b5806bd4..40c7c4aa0 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -93,6 +93,7 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
lv->name);
inc_error_count;
} else if (!seg_is_thin_volume(first_seg(lv))) {
+PFLA("segtype=%s", lvseg_name(first_seg(lv)));
log_error("LV %s is thin volume without first thin volume segment.",
lv->name);
inc_error_count;
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index db9cb495d..a94f432bc 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -132,7 +132,7 @@ static int _check_and_init_region_size(const struct logical_volume *lv)
static uint32_t _data_rimages_count(const struct lv_segment *seg, const uint32_t total_rimages)
{
RETURN_IF_ZERO(seg, "lv raid segment");
- RETURN_IF_NONZERO(total_rimages <= seg->segtype->parity_devs,
+ RETURN_IF_NONZERO(!seg_is_thin(seg) && total_rimages <= seg->segtype->parity_devs,
"total rimages count > parity devices");
return total_rimages - seg->segtype->parity_devs;
@@ -643,6 +643,11 @@ static int _lv_cond_repair(struct logical_volume *lv)
static int _seg_get_redundancy(const struct segment_type *segtype, unsigned total_images,
unsigned data_copies, unsigned *nr)
{
+ if (segtype_is_thin(segtype)) {
+ *nr = 0;
+ return 1;
+ }
+
RETURN_IF_ZERO(total_images, "total images");
RETURN_IF_ZERO(data_copies, "data copies");
RETURN_IF_ZERO(nr, "nr argument");
@@ -818,29 +823,32 @@ PFLA("new_image_count=%u seg->area_count=%u", new_image_count, seg->area_count);
}
if (data_copies_change &&
- yes_no_prompt("Do you really want to %s %s with %u to %u data copies %s resilience? [y/n]: ",
+ yes_no_prompt("Do you really want to %s %s with %u to %u data copies %s resilience%s? [y/n]: ",
duplicate ? "duplicate" : "convert",
display_lvname(lv), seg->data_copies, new_data_copies,
- seg->data_copies < new_data_copies ? "enhancing" : "reducing") == 'n') {
+ seg->data_copies < new_data_copies ? "enhancing" : "reducing",
+ duplicate ? " on the copy": "") == 'n') {
log_error("Logical volume %s NOT converted", display_lvname(lv));
return 0;
}
- if (stripes_change &&
- yes_no_prompt("Do you really want to %s %s with %u stripes to %u stripes? [y/n]: ",
- duplicate ? "duplicate" : "convert",
- display_lvname(lv), _data_rimages_count(seg, seg->area_count), new_stripes) == 'n') {
- log_error("Logical volume %s NOT converted", display_lvname(lv));
- return 0;
- }
+ if (!duplicate) {
+ if (stripes_change &&
+ yes_no_prompt("Do you really want to %s %s with %u stripes to %u stripes? [y/n]: ",
+ duplicate ? "duplicate" : "convert",
+ display_lvname(lv), _data_rimages_count(seg, seg->area_count), new_stripes) == 'n') {
+ log_error("Logical volume %s NOT converted", display_lvname(lv));
+ return 0;
+ }
- if (stripe_size_change &&
- yes_no_prompt("Do you really want to %s %s with stripesize %d to stripesize %d? [y/n]: ",
- duplicate ? "duplicate" : "convert",
- display_lvname(lv),
- seg->stripe_size, new_stripe_size) == 'n') {
- log_error("Logical volume %s NOT converted", display_lvname(lv));
- return 0;
+ if (stripe_size_change &&
+ yes_no_prompt("Do you really want to %s %s with stripesize %d to stripesize %d? [y/n]: ",
+ duplicate ? "duplicate" : "convert",
+ display_lvname(lv),
+ seg->stripe_size, new_stripe_size) == 'n') {
+ log_error("Logical volume %s NOT converted", display_lvname(lv));
+ return 0;
+ }
}
}
@@ -1807,16 +1815,18 @@ PFLA("lv_name=%s", lv_name);
}
static int _alloc_rmeta_for_lv(struct logical_volume *data_lv,
- struct logical_volume **meta_lv)
+ struct logical_volume **meta_lv,
+ struct dm_list *allocate_pvs)
{
RETURN_IF_LV_SEG_ZERO(data_lv, first_seg(data_lv));
RETURN_IF_ZERO(meta_lv, "meta_lv argument");
- return __alloc_rmeta_for_lv(data_lv, meta_lv, NULL);
+ return __alloc_rmeta_for_lv(data_lv, meta_lv, allocate_pvs);
}
/* HM Helper: allocate a metadata LV for @data_lv, set hidden and set @*meta_lv to it */
-static int _alloc_rmeta_for_lv_add_set_hidden(struct logical_volume *lv, uint32_t area_offset)
+static int _alloc_rmeta_for_lv_add_set_hidden(struct logical_volume *lv, uint32_t area_offset,
+ struct dm_list *allocate_pvs)
{
struct lv_segment *seg;
struct dm_list meta_lvs;
@@ -1826,7 +1836,7 @@ static int _alloc_rmeta_for_lv_add_set_hidden(struct logical_volume *lv, uint32_
dm_list_init(&meta_lvs);
- if (!_alloc_rmeta_for_lv(seg_lv(seg, area_offset), &lvl.lv))
+ if (!_alloc_rmeta_for_lv(seg_lv(seg, area_offset), &lvl.lv, allocate_pvs))
return 0;
dm_list_add(&meta_lvs, &lvl.list);
@@ -1845,7 +1855,8 @@ static int _alloc_rmeta_for_lv_add_set_hidden(struct logical_volume *lv, uint32_
*/
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_meta_lvs,
+ struct dm_list *allocate_pvs)
{
uint32_t a = 0, raid_devs = 0;
struct dm_list *l;
@@ -1871,7 +1882,7 @@ PFLA("lv=%s raid_devs=%u", display_lvname(lv), raid_devs);
dm_list_iterate_items(lvl, new_data_lvs) {
log_debug_metadata("Allocating new metadata LV for %s",
lvl->lv->name);
- if (!_alloc_rmeta_for_lv(lvl->lv, &lvl_array[a].lv)) {
+ if (!_alloc_rmeta_for_lv(lvl->lv, &lvl_array[a].lv, allocate_pvs)) {
log_error("Failed to allocate metadata LV for %s in %s",
lvl->lv->name, lv->vg->name);
return 0;
@@ -1889,7 +1900,9 @@ PFLA("lv=%s raid_devs=%u", display_lvname(lv), raid_devs);
*
* Allocate metadata devs for all data devs of an LV
*/
-static int _alloc_rmeta_devs_for_lv(struct logical_volume *lv, struct dm_list *meta_lvs)
+static int _alloc_rmeta_devs_for_lv(struct logical_volume *lv,
+ struct dm_list *meta_lvs,
+ struct dm_list *allocate_pvs)
{
uint32_t s;
struct lv_list *lvl_array;
@@ -1915,7 +1928,7 @@ static int _alloc_rmeta_devs_for_lv(struct logical_volume *lv, struct dm_list *m
dm_list_add(&data_lvs, &lvl_array[s].list);
}
- if (!_alloc_rmeta_devs_for_rimage_devs(lv, &data_lvs, meta_lvs)) {
+ if (!_alloc_rmeta_devs_for_rimage_devs(lv, &data_lvs, meta_lvs, allocate_pvs)) {
log_error("Failed to allocate metadata LVs for %s", lv->name);
return 0;
}
@@ -2552,11 +2565,13 @@ static int _lv_free_reshape_space(struct logical_volume *lv)
*/
static struct lv_segment *_convert_lv_to_raid1(struct logical_volume *lv, const char *suffix)
{
- struct lv_segment *seg;
+ int thin;
+ struct lv_segment *seg, *seg1;;
uint32_t le_count;
uint64_t flags;
RETURN_IF_LV_SEG_ZERO(lv, first_seg(lv));
+ thin = lv_is_thin_volume(lv);
le_count = lv->le_count - _reshape_len_per_lv(lv);
flags = RAID | LVM_READ | (lv->status & LVM_WRITE);
@@ -2567,17 +2582,26 @@ static struct lv_segment *_convert_lv_to_raid1(struct logical_volume *lv, const
/* First segment has changed because of layer insertion */
RETURN_IF_ZERO((seg = first_seg(lv)), "lv raid segment after layer insertion");
+ RETURN_IF_ZERO(seg_lv(seg, 0), "first sub-lv");
+ RETURN_IF_ZERO((seg1 = first_seg(seg_lv(seg, 0))), "first sub-lv segment");
seg->status |= SEG_RAID;
- seg_lv(seg, 0)->status |= RAID_IMAGE | flags;
- seg_lv(seg, 0)->status &= ~LV_REBUILD;
+
+ seg1->lv->status |= RAID_IMAGE | flags;
+ seg1->lv->status &= ~LV_REBUILD;
+
+ /* Correct thin volume flags not covered by insert_layer_for_lv() */
+ if (thin) {
+ seg1->status |= SEG_THIN_VOLUME;
+ seg1->lv->status |= THIN_VOLUME;
+ lv->status &= ~THIN_VOLUME;
+ }
/* Set raid1 segtype, so that the following image allocation works */
if (!(seg->segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID1)))
return NULL;
lv->status |= RAID;
- seg = first_seg(lv);
lv->le_count = seg->len = seg->area_len = le_count;
if (!_check_and_init_region_size(lv))
@@ -2941,7 +2965,7 @@ static int _vg_write_lv_suspend_vg_commit(struct logical_volume *lv)
*
* Update metadata and reload mappings if @update_and_reload
*/
-static int _alloc_and_add_rmeta_devs_for_lv(struct logical_volume *lv)
+static int _alloc_and_add_rmeta_devs_for_lv(struct logical_volume *lv, struct dm_list *allocate_pvs)
{
struct lv_segment *seg;
struct dm_list meta_lvs;
@@ -2952,7 +2976,7 @@ struct lv_list *lvl;
dm_list_init(&meta_lvs);
log_debug_metadata("Allocating metadata LVs for %s", display_lvname(lv));
- if (!_alloc_rmeta_devs_for_lv(lv, &meta_lvs)) {
+ if (!_alloc_rmeta_devs_for_lv(lv, &meta_lvs, allocate_pvs)) {
log_error("Failed to allocate metadata LVs for %s", display_lvname(lv));
return_0;
}
@@ -2985,6 +3009,7 @@ PFLA("meta_lv=%s", lvl->lv->name);
*/
static int _raid0_add_or_remove_metadata_lvs(struct logical_volume *lv,
int update_and_reload,
+ struct dm_list *allocate_pvs,
struct dm_list *removal_lvs)
{
uint64_t raid_type_flag;
@@ -3005,7 +3030,7 @@ PFL();
seg->meta_areas = NULL;
} else {
- if (!_alloc_and_add_rmeta_devs_for_lv(lv))
+ if (!_alloc_and_add_rmeta_devs_for_lv(lv, allocate_pvs))
return 0;
raid_type_flag = SEG_RAID0_META;
@@ -3576,7 +3601,7 @@ static int _convert_mirror_to_raid(struct logical_volume *lv,
}
/* Allocate metadata devs for all mimage ones (writes+commits metadata) */
- if (!_alloc_and_add_rmeta_devs_for_lv(lv))
+ if (!_alloc_and_add_rmeta_devs_for_lv(lv, allocate_pvs))
return 0;
/* Rename all data sub LVs from "*_mimage_*" to "*_rimage_*" and set their status */
@@ -3791,7 +3816,8 @@ static int _lv_has_segments_with_n_areas(struct logical_volume *lv, unsigned are
*/
static struct lv_segment *_convert_striped_to_raid0(struct logical_volume *lv,
int alloc_metadata_devs,
- int update_and_reload)
+ int update_and_reload,
+ struct dm_list *allocate_pvs)
{
uint32_t area_count, area_len = 0, stripe_size;
struct lv_segment *seg, *raid0_seg;
@@ -3800,6 +3826,7 @@ static struct lv_segment *_convert_striped_to_raid0(struct logical_volume *lv,
RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv)));
RETURN_IF_ZERO((area_count = seg->area_count), "now segment areas");
+ RETURN_IF_ZERO(allocate_pvs || dm_list_empty(allocate_pvs), "PVs to allocate");
if (!seg_is_striped(seg)) {
log_error(INTERNAL_ERROR "Cannot convert non-%s LV %s to %s",
@@ -3872,7 +3899,7 @@ static struct lv_segment *_convert_striped_to_raid0(struct logical_volume *lv,
lv->status |= RAID;
/* Allocate metadata LVs if requested */
- if (alloc_metadata_devs && !_raid0_add_or_remove_metadata_lvs(lv, 0, NULL))
+ if (alloc_metadata_devs && !_raid0_add_or_remove_metadata_lvs(lv, 0, allocate_pvs, NULL))
return NULL;
if (update_and_reload && !lv_update_and_reload(lv))
@@ -4064,7 +4091,7 @@ static int _convert_raid0_to_striped(struct logical_volume *lv,
/* Remove metadata devices */
if (seg_is_raid0_meta(seg) &&
- !_raid0_add_or_remove_metadata_lvs(lv, 0 /* update_and_reload */, removal_lvs))
+ !_raid0_add_or_remove_metadata_lvs(lv, 0 /* update_and_reload */, removal_lvs, NULL))
return_0;
/* Move the AREA_PV areas across to new top-level segments of type "striped" */
@@ -4520,7 +4547,7 @@ static int _activate_sub_lvs(struct logical_volume *lv, uint32_t start_idx)
struct cmd_context *cmd;
RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv)));
- RETURN_IF_ZERO(start_idx < seg->area_count, "proper start_idx argument");
+ RETURN_IF_NONZERO(seg->area_count && start_idx >= seg->area_count, "proper start_idx argument");
cmd = lv->vg->cmd;
log_debug_metadata("Activating %u image component%s of LV %s",
@@ -5804,11 +5831,13 @@ static int _rename_sub_lvs(struct logical_volume *lv, enum rename_dir dir)
struct lv_segment *seg;
RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv)));
+ if (seg_is_thin(seg))
+ return 1;
RETURN_IF_ZERO(seg->area_count, "areas");
-
+PFL();
if (!lv_is_raid(lv) && !lv_is_raid_image(lv))
return 1;
-
+PFL();
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");
@@ -5820,11 +5849,13 @@ static int _rename_sub_lvs(struct logical_volume *lv, enum rename_dir dir)
!_rename_lv(mlv, names[type][ft[0]+1], names[type][ft[1]+1]))
return 0;
+PFLA("seg_lv(seg, %u)=%s", s, display_lvname(seg_lv(seg, s)));
if (seg_type(seg, s) == AREA_LV &&
!_rename_lv(seg_lv(seg, s), names[type][ft[0]], names[type][ft[1]]))
return 0;
+PFLA("seg_lv(seg, %u)=%s", s, display_lvname(seg_lv(seg, s)));
}
-
+PFL();
return 1;
}
@@ -5869,25 +5900,34 @@ static int _remove_duplicating_layer(struct logical_volume *lv,
RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv)));
RETURN_IF_ZERO(seg->area_count == 1, "no single area");
RETURN_IF_ZERO((slv = seg_lv(seg, 0)), "no first sub-lv");
-
+PFLA("lv=%s", display_lvname(lv));
+PFLA("slv=%s", display_lvname(slv));
/* Ensure proper size of LV, sub LV may be larger due to rounding. */
lv->le_count = slv->le_count;
lv->size = lv->le_count * lv->vg->extent_size;
+PFLA("lv->le_count=%u lv->size=%llu", lv->le_count, (unsigned long long) lv->size);
if (!_lv_reset_raid_add_to_list(slv, removal_lvs))
return 0;
-
+PFLA("first_seg(slv)=%s", first_seg(slv) ? lvseg_name(first_seg(slv)) : "");
/* Remove the raid1 layer from the LV */
if (!remove_layer_from_lv(lv, slv))
return_0;
- /* HM FIXME: in case of _lv_reduce() recursion bugs, this may hit */
- RETURN_IF_ZERO(first_seg(lv), "first segment!?");
+ /* Adjust any thin volume flag not addressed by remove_layer_from_lv() */
+ slv->status &= ~THIN_VOLUME;
+PFLA("first_seg(lv)=%s", first_seg(lv) ? lvseg_name(first_seg(lv)) : "");
+ /* HM FIXME: in case of _lv_reduce() recursion bugs, this may hit */
+ RETURN_IF_ZERO((seg = first_seg(lv)), "first segment!?");
+PFL();
if (!_rename_sub_lvs(lv, from_flat))
return 0;
-
+PFL();
lv->status &= ~LV_DUPLICATED;
+ if (seg_is_thin(seg))
+ lv->status |= THIN_VOLUME;
+
lv_set_visible(lv);
return 1;
@@ -6139,8 +6179,8 @@ static int _raid_unduplicate(struct logical_volume *lv,
return 0;
}
- log_warn("This is a request to unduplicate LV %s keeping %s",
- display_lvname(lv), display_lvname(seg_lv(seg, keep_idx)));
+ log_warn("This is a request to unduplicate LV %s keeping %s LV %s",
+ display_lvname(lv), lvseg_name(first_seg(keep_lv)), display_lvname(keep_lv));
if (!yes) {
RETURN_IF_ZERO((seg1 = first_seg(keep_lv)), "segment in induplicate LV");
@@ -6222,8 +6262,8 @@ static struct logical_volume *_dup_lv_create(struct logical_volume *lv,
log_warn("Destination LV with %u extents is larger than source "
"with %u due to stripe boundary rounding",
r->le_count, extents);
- log_warn("You may want to resize your LV content after the "
- "duplication conversion got removed keeping this LV (e.g. resize fs)");
+ log_warn("You may want to resize your LV content after the duplication conversion");
+ log_warn("got removed keeping this LV or it got split off (e.g. resize fs)");
}
r->status |= RAID_IMAGE | LV_DUPLICATED;
@@ -6254,7 +6294,7 @@ static int _pre_raid_duplicate_rename_metadata_sub_lvs(struct logical_volume *lv
return _activate_sub_lvs(dup_lv, 0);
}
-/* Helper: callback function to rename metadata sub-lvs of top-level duplicating@lv back */
+/* HM 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;
@@ -6277,7 +6317,7 @@ static int _post_raid_duplicate_rename_metadata_sub_lvs_back(struct logical_volu
}
/*
- * Helper: raid to raid conversion by duplication
+ * HM Helper: raid to raid conversion by duplication
*
* Inserts a layer on top of the given @lv (if not duplicating already),
* creates and allocates a destination LV of ~ the same size (may be rounded)
@@ -6294,26 +6334,20 @@ static int _raid_duplicate(struct logical_volume *lv,
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;
+ uint32_t data_copies = new_data_copies, extents, new_area_idx, raid1_image_count, s;
char *lv_name, *p, *suffix;
struct logical_volume *dup_lv;
struct lv_segment *seg;
/* new_segtype may be naught */
RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv)));
- RETURN_IF_ZERO(seg->area_count, "lv segment areas");
+PFL();
+ RETURN_IF_NONZERO(!seg_is_thin(seg) && !seg->area_count, "lv segment areas");
RETURN_IF_ZERO(data_copies, "data copies argument");
RETURN_IF_ZERO(allocate_pvs, "allocate pvs");
- if ((duplicating = _lv_is_duplicating(lv)) && !_raid_in_sync(lv)) {
- log_warn("The duplicating LV needs to be in-sync before another duplicated sub-lv can be added!");
- return 0;
- }
-
raid1_image_count = seg->area_count + 1;
-PFLA("new_segtype=%s new_data_copies=%u new_stripes=%u image_count=%u new_stripe_size=%u", new_segtype->name, new_data_copies, new_stripes, raid1_image_count, new_stripe_size);
-PFLA("segtype=%s area_count=%u data_copies=%u stripe_size=%u", lvseg_name(seg), seg->area_count, seg->data_copies, seg->stripe_size);
if (data_copies < 2 &&
(segtype_is_mirror(new_segtype) ||
segtype_is_raid1(new_segtype) ||
@@ -6322,7 +6356,7 @@ PFLA("segtype=%s area_count=%u data_copies=%u stripe_size=%u", lvseg_name(seg),
log_warn("Adjusting data copies to %u", data_copies);
}
- if (duplicating)
+ if ((duplicating = _lv_is_duplicating(lv)))
log_warn("This is a request to add another LV to the existing "
"%u sub LVs of duplicating LV %s!",
seg->area_count, display_lvname(lv));
@@ -6351,6 +6385,8 @@ PFLA("segtype=%s area_count=%u data_copies=%u stripe_size=%u", lvseg_name(seg),
if (!_yes_no_conversion(lv, new_segtype, yes, force, 1, raid1_image_count, data_copies, new_stripes, new_stripe_size))
return 0;
+ log_warn("The duplicating LV needs to be in-sync before another duplicated sub-lv can be added!");
+
/*
* Creation of destination LV with intended layout and insertion of raid1 top-layer from here on
*/
@@ -6390,7 +6426,7 @@ PFLA("segtype=%s area_count=%u data_copies=%u stripe_size=%u", lvseg_name(seg),
}
if (!(dup_lv = _dup_lv_create(lv, new_segtype, lv_name,
- new_data_copies, region_size,
+ new_data_copies, new_region_size,
new_stripes, new_stripe_size,
extents, pool_lv_name, allocate_pvs)))
return 0;
@@ -6425,19 +6461,19 @@ PFLA("segtype=%s area_count=%u data_copies=%u stripe_size=%u", lvseg_name(seg),
display_lvname(dup_lv), display_lvname(lv));
return 0;
}
-
+PFLA("seg->area_count=%u", seg->area_count);
/* If not duplicating yet, allocate first top-level raid1 metadata LV */
if (!duplicating &&
- !_alloc_rmeta_for_lv_add_set_hidden(lv, 0))
+ !_alloc_rmeta_for_lv_add_set_hidden(lv, 0, allocate_pvs))
return 0;
-
+PFL();
/* Allocate new metadata LV for duplicated sub LV */
- if (!_alloc_rmeta_for_lv_add_set_hidden(lv, new_area_idx))
+ if (!_alloc_rmeta_for_lv_add_set_hidden(lv, new_area_idx, allocate_pvs))
return 0;
-
+PFL();
for (s = 0; s < new_area_idx; s++)
seg_lv(seg, s)->status &= ~LV_REBUILD;
-
+PFL();
dup_lv->status |= (LV_REBUILD|LV_NOTSYNCED);
lv_set_visible(lv);
@@ -6487,7 +6523,7 @@ TAKEOVER_HELPER_FN(_linear_raid0)
if (segtype_is_raid0_meta(new_segtype)) {
log_debug_metadata("Adding raid metadata device to %s",
display_lvname(lv));
- if (!_alloc_and_add_rmeta_devs_for_lv(lv))
+ if (!_alloc_and_add_rmeta_devs_for_lv(lv, allocate_pvs))
return 0;
}
@@ -6599,14 +6635,14 @@ PFLA("data_copies=%u", new_data_copies);
if (seg_is_striped(seg)) {
log_debug_metadata("Coverting LV %s from %s to %s",
display_lvname(lv), SEG_TYPE_NAME_STRIPED, SEG_TYPE_NAME_RAID0);
- if (!(seg = _convert_striped_to_raid0(lv, 1 /* alloc_metadata_devs */, 0 /* update_and_reload */)))
+ if (!(seg = _convert_striped_to_raid0(lv, 1 /* alloc_metadata_devs */, 0 /* update_and_reload */, allocate_pvs)))
return 0;
}
PFL();
/* Add metadata LVs */
if (seg_is_raid0(seg)) {
log_debug_metadata("Adding metadata LVs to %s", display_lvname(lv));
- if (!_raid0_add_or_remove_metadata_lvs(lv, 0 /* !update_and_reload */, NULL))
+ if (!_raid0_add_or_remove_metadata_lvs(lv, 0 /* !update_and_reload */, allocate_pvs, NULL))
return 0;
}
PFL();
@@ -6736,7 +6772,7 @@ TAKEOVER_HELPER_FN(_raid0_mirror)
if (seg_is_raid0(first_seg(lv))) {
log_debug_metadata("Adding raid metadata device to %s",
display_lvname(lv));
- if (!_alloc_and_add_rmeta_devs_for_lv(lv))
+ if (!_alloc_and_add_rmeta_devs_for_lv(lv, allocate_pvs))
return 0;
}
@@ -6784,7 +6820,7 @@ TAKEOVER_HELPER_FN(_raid0_raid1)
if (seg_is_raid0(seg)) {
log_debug_metadata("Adding raid metadata device to %s",
display_lvname(lv));
- if (!_alloc_and_add_rmeta_devs_for_lv(lv))
+ if (!_alloc_and_add_rmeta_devs_for_lv(lv, allocate_pvs))
return 0;
}
@@ -6977,7 +7013,7 @@ PFLA("seg->area_count=%u seg->len=%u seg->area_len=%u", seg->area_count, seg->le
return_0;
} else if (segtype_is_raid0(new_segtype) &&
- !_raid0_add_or_remove_metadata_lvs(lv, 0 /* update_and_reload */, &removal_lvs))
+ !_raid0_add_or_remove_metadata_lvs(lv, 0 /* update_and_reload */, allocate_pvs, &removal_lvs))
return_0;
first_seg(lv)->data_copies = 1;
@@ -7218,7 +7254,7 @@ PFLA("seg->len=%u seg->area_len=%u seg->area_count=%u", seg->len, seg->area_len,
/* -> raid0 (no mnetadata images) */
} else if (segtype_is_raid0(new_segtype) &&
- !_raid0_add_or_remove_metadata_lvs(lv, 0 /* update_and_reload */, removal_lvs))
+ !_raid0_add_or_remove_metadata_lvs(lv, 0 /* update_and_reload */, allocate_pvs, removal_lvs))
return 0;
PFLA("seg->stripe_size=%u", seg->stripe_size);
@@ -7342,7 +7378,7 @@ TAKEOVER_FN(_s_r0)
if (!archive(lv->vg))
return_0;
- return _convert_striped_to_raid0(lv, 0 /* !alloc_metadata_devs */, 1 /* update_and_reload */) ? 1 : 0;
+ return _convert_striped_to_raid0(lv, 0 /* !alloc_metadata_devs */, 1 /* update_and_reload */, allocate_pvs) ? 1 : 0;
}
/* Striped -> raid0_meta */
@@ -7357,7 +7393,7 @@ TAKEOVER_FN(_s_r0m)
if (!archive(lv->vg))
return_0;
- return _convert_striped_to_raid0(lv, 1 /* alloc_metadata_devs */, 1 /* update_and_reload */) ? 1 : 0;
+ return _convert_striped_to_raid0(lv, 1 /* alloc_metadata_devs */, 1 /* update_and_reload */, allocate_pvs) ? 1 : 0;
}
/* Striped -> raid4/5 */
@@ -7484,7 +7520,7 @@ TAKEOVER_FN(_r0_r0m)
if (!archive(lv->vg))
return_0;
- return _raid0_add_or_remove_metadata_lvs(lv, 1, NULL);
+ return _raid0_add_or_remove_metadata_lvs(lv, 1, allocate_pvs, NULL);
}
/* raid0 -> striped */
@@ -7564,7 +7600,7 @@ TAKEOVER_FN(_r0m_r0)
if (!archive(lv->vg))
return_0;
- return _raid0_add_or_remove_metadata_lvs(lv, 1, &removal_lvs);
+ return _raid0_add_or_remove_metadata_lvs(lv, 1, allocate_pvs, &removal_lvs);
}
/* raid0_meta -> striped */
@@ -8128,13 +8164,7 @@ static int _lv_create_raid01_image_lvs(struct logical_volume *lv,
RETURN_IF_ZERO(image_extents, "image extents");
RETURN_IF_ZERO(stripes, "stripes");
RETURN_IF_ZERO(stripe_size, "stripe_size");
-
-PFLA("start=%u end=%u data_copies=%u", start, end, data_copies);
- if (start > end ||
- data_copies < 2) {
- log_error(INTERNAL_ERROR "Called with bogus end/start/data_copies");
- return 0;
- }
+ RETURN_IF_NONZERO(start > end || data_copies < 2, "proper end/start/data_copies");
/* Create the #data_copies striped LVs to put under raid1 */
log_debug_metadata("Creating %u stripe%s for %s",
@@ -8147,10 +8177,7 @@ PFLA("start=%u end=%u data_copies=%u", start, end, data_copies);
* allocated (raid0) striped LV from being used for allocation
*/
for (ss = 0; ss < start; ss++) {
- if (seg_type(seg, ss) != AREA_LV) {
- log_error(INTERNAL_ERROR "Called with bogus segment");
- return 0;
- }
+ RETURN_IF_ZERO(seg_type(seg, ss) == AREA_LV, "segment area sub-lv");
if (!_avoid_pvs_with_other_images_of_lv(seg_lv(seg, ss), allocate_pvs)) {
log_error("Failed to prevent PVs holding image components "
@@ -8160,6 +8187,8 @@ PFLA("start=%u end=%u data_copies=%u", start, end, data_copies);
}
}
+ log_debug_metadata("Avoiding coallocation on PVs holding other sub-lvs of %s",
+ display_lvname(lv));
for (ss = start; ss < s; ss++)
if (!_avoid_pvs_with_other_images_of_lv(image_lvs[ss - start], allocate_pvs)) {
log_error("Failed to prevent PVs holding image components "
@@ -8168,7 +8197,7 @@ PFLA("start=%u end=%u data_copies=%u", start, end, data_copies);
return 0;
}
-PFLA("Creating %s in array slot %u", image_name, s - start);
+ log_debug_metadata("Creating %s in array slot %u", image_name, s - start);
if (!(image_lvs[s - start] = _lv_create(lv->vg, image_name, segtype,
1 /* data_copies */, 0 /* region_size */,
stripes, stripe_size, image_extents, CHANGE_AEY,
@@ -8177,7 +8206,7 @@ PFLA("Creating %s in array slot %u", image_name, s - start);
return 0;
}
}
-PFL();
+
for (s = start; s < end; s++) {
ss = s - start;
PFLA("image_lvs[%u]=%p", ss, image_lvs[ss]);
@@ -8190,7 +8219,6 @@ PFLA("image_lvs[%u]=%s", ss, image_lvs[ss]->name);
display_lvname(image_lvs[ss]), display_lvname(lv));
if (!set_lv_segment_area_lv(seg, s, image_lvs[ss], 0 /* le */, seg->status | RAID_IMAGE))
return_0;
-PFL();
}
return 1;
@@ -8230,7 +8258,7 @@ PFL();
log_debug_metadata("Allocating %u metadata images for %s", new_data_copies, display_lvname(lv));
seg->meta_areas = NULL; /* Reset to force rmeta device creation in raid01 segment */
- if (!_alloc_and_add_rmeta_devs_for_lv(lv))
+ if (!_alloc_and_add_rmeta_devs_for_lv(lv, allocate_pvs))
return 0;
PFL();
return lv_update_and_reload(lv);
@@ -8386,18 +8414,18 @@ 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_add_set_hidden(lv, s))
+ if (!_alloc_rmeta_for_lv_add_set_hidden(lv, s, allocate_pvs))
return 0;
seg_lv(seg, s)->status |= LV_REBUILD;
}
- seg->area_count = seg->data_copies = new_data_copies;
-
/* Remove mirrors aka data copies from raid01 */
} else if (!_raid01_remove_images(lv, new_data_copies, &removal_lvs))
return 0;
+ seg->area_count = seg->data_copies = new_data_copies;
+
return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL);
}
@@ -8568,8 +8596,6 @@ static int _raid_convert_define_parms(const struct lv_segment *seg,
*data_copies = *data_copies > -1 ? *data_copies : (duplicate ? 1 : seg->data_copies);
*region_size = *region_size ?: seg->region_size;
- *region_size = *region_size ?: seg->region_size;
-
/* Check region size */
if (!*region_size &&
(segtype_is_mirror(*segtype) ||
@@ -8580,7 +8606,8 @@ static int _raid_convert_define_parms(const struct lv_segment *seg,
display_lvname(seg->lv), *region_size);
}
- if (segtype_is_thin(*segtype)) {
+ if (segtype_is_thin(*segtype) || segtype_is_thin_pool(*segtype)) {
+ RETURN_IF_ZERO((*segtype = get_segtype_from_string(seg->lv->vg->cmd, "thin")), "thin segtype");
*data_copies = 1;
*region_size = 0;
*stripes = 1;
@@ -8838,12 +8865,12 @@ PFLA("seg1->segtype=%s", seg1->segtype ? seg1->segtype->name : "");
if (!_raid_convert_define_parms(seg1, &new_segtype, rcp.duplicate, &data_copies, &region_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);
+PFLA("new_segtype=%s data_copies=%d region_size=%u stripes=%u stripe_size=%u #allocate_pvs=%d", new_segtype ? new_segtype->name : "", data_copies, region_size, stripes, stripe_size, rcp.allocate_pvs ? dm_list_size(rcp.allocate_pvs) : 0);
if (lv_is_duplicated(lv) && !rcp.duplicate && !rcp.unduplicate) {
if (!seg_is_mirrored(seg1) &&
stripes && stripes != _data_rimages_count(seg1, seg1->area_count)) {
- log_error("Adding/removing stripes to/from duplicating LV leg %s "
+ log_error("Adding/removing stripes to/from duplicated LV %s "
"prohibited due sub-lv size change",
display_lvname(lv));
return 0;
@@ -8855,6 +8882,7 @@ PFLA("new_segtype=%s data_copies=%d region_size=%u stripes=%u stripe_size=%u", n
/* Given segtype of @lv */
if (!seg_is_striped(seg1) && /* Catches linear = "overloaded striped with one area" as well */
!seg_is_mirror(seg1) &&
+ !seg_is_thin(seg1) &&
!seg_is_raid(seg1))
goto err;
@@ -10204,8 +10232,5 @@ int lv_create_raid01(struct logical_volume *lv, const struct segment_type *segty
raid01_seg->meta_areas = NULL;
/* If metadata images fail to allocate, remove the LV */
- if (!_alloc_and_add_rmeta_devs_for_lv(lv))
- return lv_remove(lv);
-
- return 1;
+ return _alloc_and_add_rmeta_devs_for_lv(lv, allocate_pvs) ? 1 : lv_remove(lv);
}
diff --git a/lib/misc/lib.h b/lib/misc/lib.h
index 9c299e3c2..054477384 100644
--- a/lib/misc/lib.h
+++ b/lib/misc/lib.h
@@ -25,7 +25,7 @@
#endif
/* HM FIXME: REMOVEME: devel output */
-#if 0
+#if 1
#define PFL() printf("%s %u\n", __func__, __LINE__);
#define PFLA(format, arg...) printf("%s %u " format "\n", __func__, __LINE__, arg);
#else
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index c915564cc..ad3495ba9 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -1737,14 +1737,17 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
!seg_is_linear(seg) &&
!seg_is_raid(seg) &&
!seg_is_mirrored(seg) &&
+ !seg_is_thin_volume(seg) &&
!seg_is_striped(seg)) {
log_error("'--mirrors/-m' is not compatible with %s",
lvseg_name(seg));
return 0;
}
+#if 0
if (!_lvconvert_validate_thin(lv, lp))
return_0;
+#endif
/* Change number of RAID1 images */
if (arg_count(cmd, mirrors_ARG) || arg_count(cmd, splitmirrors_ARG)) {
@@ -1777,7 +1780,7 @@ PFLA("image_count=%u\n", image_count);
if (arg_count(cmd, splitmirrors_ARG))
return lv_raid_split(lv, lp->yes, lp->lv_split_name, image_count, lp->pvh);
- if ((seg_is_linear(seg) || seg_is_striped(seg) || seg_is_mirror(seg) || seg_is_raid(seg)) &&
+ if ((seg_is_linear(seg) || seg_is_striped(seg) || seg_is_thin(seg) || seg_is_mirror(seg) || seg_is_raid(seg)) &&
(arg_count(cmd, type_ARG) ||
arg_is_set(cmd, mirrors_ARG) ||
arg_is_set(cmd, regionsize_ARG) ||
@@ -1844,7 +1847,8 @@ PFLA("image_count=%u\n", image_count);
if (segtype_is_thin(lp->segtype) && arg_count(cmd, name_ARG))
lp->pool_data_name = arg_str_value(cmd, name_ARG, NULL);
-PFLA("lp->region_size=%u", lp->region_size);
+PFLA("lp->region_size=%u lp->segtype=%s lp->pool_data_name=%s", lp->region_size, lp->segtype ? lp->segtype->name : "", lp->pool_data_name ?: "");
+PFLA("lp->region_size=%u lp->segtype=%s", lp->region_size, lp->segtype ? lp->segtype->name : "");
PFLA("lp->pool_data_name=%s lp->lv_split_name=%s lp->lv_name=%s", lp->pool_data_name, lp->lv_split_name, lp->lv_name);
return lv_raid_convert(lv, (struct lv_raid_convert_params)
{ .segtype = arg_count(cmd, type_ARG) ? (struct segment_type *) lp->segtype : NULL,
@@ -3429,6 +3433,7 @@ static int _lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
if (arg_count(cmd, repair_ARG) && arg_count(cmd, use_policies_ARG))
_remove_missing_empty_pv(lv->vg, failed_pvs);
} else if (arg_is_set(cmd, duplicate_ARG) ||
+ arg_is_set(cmd, unduplicate_ARG) ||
segtype_is_raid(lp->segtype) ||
segtype_is_striped(lp->segtype) ||
(segtype_is_mirror(lp->segtype) && !arg_is_set(cmd, mirrorlog_ARG)) ||