summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeinz Mauelshagen <heinzm@redhat.com>2016-01-23 01:59:49 +0100
committerHeinz Mauelshagen <heinzm@redhat.com>2016-01-23 01:59:49 +0100
commit0acbc568541d3aa50ca7c7a0e5f8522d0acc0a63 (patch)
treef2b6c1b557be7a74f92bc00af73d1d116161b6a6
parent186ed06062149c92d5a2d0e7e415a3f5e0f37319 (diff)
downloadlvm2-0acbc568541d3aa50ca7c7a0e5f8522d0acc0a63.tar.gz
raid_manip: fix extents/size
-rw-r--r--lib/activate/dev_manager.c5
-rw-r--r--lib/metadata/raid_manip.c121
-rw-r--r--lib/report/report.c15
-rw-r--r--libdm/libdm-deptree.c2
4 files changed, 77 insertions, 66 deletions
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index a6dc4ebdb..7153db362 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -181,7 +181,8 @@ typedef enum {
static uint32_t _seg_len(const struct lv_segment *seg)
{
if (seg_is_raid(seg))
- return seg->len - (seg->area_count - seg->segtype->parity_devs) * seg->reshape_len;
+ return seg->len - (((seg->area_count - seg->segtype->parity_devs) * seg->reshape_len) /
+ (seg_is_any_raid10(seg) ? seg->data_copies : 1));
return seg->len;
}
@@ -2765,7 +2766,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
/* Replace target and all its used devs with error mapping */
log_debug_activation("Using error for pending delete %s.",
seg->lv->name);
- if (!dm_tree_node_add_error_target(dnode, (uint64_t)seg->lv->vg->extent_size * _seg_len(seg)))
+ if (!dm_tree_node_add_error_target(dnode, (uint64_t) seg->lv->vg->extent_size * _seg_len(seg)))
return_0;
} else if (!_add_target_to_dtree(dm, dnode, seg, laopts))
return_0;
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index 1f1d36667..02a1ebed9 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -2534,6 +2534,7 @@ PFLA("data_offset=%llu dev_sectors=%llu seg->reshape_len=%u out_of_place_les_per
uint32_t data_rimages = _data_rimages_count(seg, seg->area_count);
uint32_t reshape_len = out_of_place_les_per_disk * data_rimages;
uint32_t prev_rimage_len = _lv_total_rimage_len(lv);
+ uint64_t lv_size = lv->size;
RETURN_IF_ZERO(allocate_pvs , "allocate pvs list argument");
RETURN_IF_NONZERO(dm_list_empty(allocate_pvs), "allocate pvs listed");
@@ -2552,13 +2553,11 @@ PFLA("first_seg(seg_lv(seg, 0)->len=%u", first_seg(seg_lv(seg, 0))->len);
return 0;
}
PFL();
+ lv->size = lv_size;
+
/* pay attention to lv_extend maybe having allocated more because of layout specific rounding */
if (!_lv_set_reshape_len(lv, _lv_total_rimage_len(lv) - prev_rimage_len))
return 0;
-
-PFLA("lv->le_count=%u seg->len=%u seg->area_len=%u seg->reshape_len=%u", lv->le_count, seg->len, seg->area_len, seg->reshape_len);
-PFLA("first_seg(seg_lv(seg, 0)->reshape_len=%u", first_seg(seg_lv(seg, 0))->reshape_len);
-PFLA("first_seg(seg_lv(seg, 0)->len=%u", first_seg(seg_lv(seg, 0))->len);
}
/* Preset data offset in case we fail relocating reshape space below */
@@ -3332,6 +3331,8 @@ int lv_raid_split(struct logical_volume *lv, int yes,
if (split_lv && !activate_lv_excl_local(cmd, split_lv))
return 0;
+ log_print_unless_silent("LV %s split off successfully from %s",
+ display_lvname(split_lv ?: dm_list_item(data_lvs.n, struct lv_list)->lv), display_lvname(lv));
return 1;
}
@@ -3587,7 +3588,7 @@ int lv_raid_merge(struct logical_volume *image_lv)
return 0;
}
- log_print_unless_silent("%s successfully merged back into %s",
+ log_print_unless_silent("LV %s successfully merged back into %s",
display_lvname(image_lv), display_lvname(lv));
return 1;
}
@@ -4181,8 +4182,7 @@ static int _convert_raid0_to_striped(struct logical_volume *lv,
/* Eliminate the residual LVs, write VG, commit it and take a backup */
return _eliminate_extracted_lvs(lv->vg, removal_lvs);
- }
-
+ }
return 1;
}
/* END: raid0 -> striped conversion */
@@ -4234,16 +4234,20 @@ static int _lv_reshape_get_new_len(struct logical_volume *lv,
{
struct lv_segment *seg;
uint32_t di_old, di_new;
+ uint32_t old_lv_reshape_len, new_lv_reshape_len;
uint64_t r;
RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv)));
- RETURN_IF_ZERO(len, "reshape length argumen");
- RETURN_IF_ZERO((di_old = _data_rimages_count(seg, old_image_count)), "new data images");
+ RETURN_IF_ZERO(len, "reshape length pointer argument");
+ RETURN_IF_ZERO((di_old = _data_rimages_count(seg, old_image_count)), "old data images");
RETURN_IF_ZERO((di_new = _data_rimages_count(seg, new_image_count)), "new data images");
- r = seg->len - _reshape_len_per_dev(seg) * di_old;
- RETURN_IF_NONZERO((r = r * di_new / di_old) > UINT_MAX, "New length is too large!");
+ old_lv_reshape_len = _reshape_len_per_dev(seg) * _data_rimages_count(seg, old_image_count);
+ new_lv_reshape_len = _reshape_len_per_dev(seg) * _data_rimages_count(seg, new_image_count);
+ r = (uint64_t) lv->le_count;
+ r -= old_lv_reshape_len;
+ RETURN_IF_NONZERO((r = new_lv_reshape_len + r * di_new / di_old) > UINT_MAX, "proper new segment length!");
*len = (uint32_t) r;
return 1;
@@ -4256,24 +4260,22 @@ static int _reshape_adjust_to_size(struct logical_volume *lv,
uint32_t old_image_count, uint32_t new_image_count)
{
struct lv_segment *seg;
- uint32_t lv_reshape_len;
+ uint32_t new_le_count;
RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv)));
- lv_reshape_len = _reshape_len_per_dev(seg) * _data_rimages_count(seg, new_image_count);
-
- if (!_lv_reshape_get_new_len(lv, old_image_count, new_image_count, &seg->len))
+ if (!_lv_reshape_get_new_len(lv, old_image_count, new_image_count, &new_le_count))
return 0;
/* Externally visible LV size w/o reshape space */
- lv->size = seg->len * lv->vg->extent_size;
- seg->len += lv_reshape_len;
- lv->le_count = seg->len;
+ lv->le_count = seg->len = new_le_count;
+ lv->size = (lv->le_count - new_image_count * _reshape_len_per_dev(seg)) * lv->vg->extent_size;
+ /* seg->area_len does not change */
if (old_image_count < new_image_count) {
_lv_set_reshape_len(lv, _reshape_len_per_dev(seg));
-PFLA("seg->len=%u lv_reshape_len=%u seg->area_len=%u seg->area_count=%u old_image_count=%u new_image_count=%u", seg->len, lv_reshape_len, seg->area_len, seg->area_count, old_image_count, new_image_count);
+PFLA("lv->size=%s seg->len=%u lv_reshape_len=%u seg->area_len=%u seg->area_count=%u old_image_count=%u new_image_count=%u", display_size(lv->vg->cmd, lv->size), seg->len, lv_reshape_len, seg->area_len, seg->area_count, old_image_count, new_image_count);
/* Extend from raid1 mapping */
if (old_image_count == 2 &&
!seg->stripe_size)
@@ -4299,7 +4301,7 @@ static int _raid_reshape_add_disks(struct logical_volume *lv,
const unsigned new_stripes, const unsigned new_stripe_size,
struct dm_list *allocate_pvs)
{
- uint32_t new_len, reduce_len, s;
+ uint32_t grown_le_count, current_le_count, s;
struct lv_segment *seg;
struct lvinfo info = { 0 };
@@ -4312,21 +4314,20 @@ static int _raid_reshape_add_disks(struct logical_volume *lv,
if (seg->segtype != new_segtype)
log_print_unless_silent("Ignoring layout change on device adding reshape");
PFL();
- if (!_lv_reshape_get_new_len(lv, old_image_count, new_image_count, &new_len))
+ if (!_lv_reshape_get_new_len(lv, old_image_count, new_image_count, &grown_le_count))
return 0;
-
PFL();
- reduce_len = seg->len - _reshape_len_per_lv(lv);
+ current_le_count = lv->le_count - _reshape_len_per_lv(lv);
+ grown_le_count -= _reshape_len_per_dev(seg) * _data_rimages_count(seg, new_image_count);
log_warn("WARNING: Adding stripes to active%s logical volume %s "
"will grow it from %u to %u extents!",
info.open_count ? " and open" : "",
- display_lvname(lv), reduce_len, new_len);
+ display_lvname(lv), current_le_count, grown_le_count);
log_print_unless_silent("Run \"lvresize -l%u %s\" to shrink it or use the additional capacity",
- reduce_len, display_lvname(lv));
+ current_le_count, display_lvname(lv));
if (!_yes_no_conversion(lv, new_segtype, yes, force, 0, new_image_count,
seg->data_copies, new_stripes, new_stripe_size))
return 0;
-
PFL();
/* Allocate new image component pairs for the additional stripes and grow LV size */
log_debug_metadata("Adding %u data and metadata image LV pair%s to %s",
@@ -4346,6 +4347,9 @@ PFL();
if (!_lv_alloc_reshape_space(lv, alloc_begin, NULL, allocate_pvs))
return 0;
+PFLA("lv->size=%s", display_size(lv->vg->cmd, lv->size));
+PFLA("lv->le_count=%u", lv->le_count);
+PFLA("seg->len=%u", first_seg(lv)->len);
/*
* Reshape adding image component pairs:
*
@@ -4376,8 +4380,8 @@ static int _raid_reshape_remove_disks(struct logical_volume *lv,
const unsigned new_stripes, const unsigned new_stripe_size,
struct dm_list *allocate_pvs, struct dm_list *removal_lvs)
{
- uint32_t active_lvs, new_len, removed_lvs, s;
- uint64_t extend_len;
+ uint32_t active_lvs, current_le_count, reduced_le_count, removed_lvs, s;
+ uint64_t extend_le_count;
unsigned devs_health, devs_in_sync;
struct lv_segment *seg;
struct lvinfo info = { 0 };
@@ -4404,24 +4408,25 @@ PFL();
return 0;
}
- if (!_lv_reshape_get_new_len(lv, old_image_count, new_image_count, &new_len))
+ if (!_lv_reshape_get_new_len(lv, old_image_count, new_image_count, &reduced_le_count))
return 0;
- extend_len = seg->len - seg->reshape_len * _data_rimages_count(seg, old_image_count);
- extend_len = extend_len * extend_len / new_len;
-PFLA("new_image_count=%u _data_rimages_count(seg, new_image_count)=%u new_len=%u", new_image_count, _data_rimages_count(seg, new_image_count), new_len);
- log_warn("WARNING: Removing stripes from active%s logical volume %s will shrink "
- "it from %s to %s!",
+ reduced_le_count -= seg->reshape_len * _data_rimages_count(seg, new_image_count);
+ current_le_count = lv->le_count - seg->reshape_len * _data_rimages_count(seg, old_image_count);
+ extend_le_count = current_le_count * current_le_count / reduced_le_count;
+PFLA("new_image_count=%u _data_rimages_count(seg, new_image_count)=%u current_le_count=%u", new_image_count, _data_rimages_count(seg, new_image_count), current_le_count);
+ log_warn("WARNING: Removing stripes from active%s logical "
+ "volume %s will shrink it from %s to %s!",
info.open_count ? " and open" : "", display_lvname(lv),
- display_size(lv->vg->cmd, seg->len * lv->vg->extent_size),
- display_size(lv->vg->cmd, new_len * lv->vg->extent_size));
+ display_size(lv->vg->cmd, (uint64_t) current_le_count * lv->vg->extent_size),
+ display_size(lv->vg->cmd, (uint64_t) reduced_le_count * lv->vg->extent_size));
log_warn("THIS MAY DESTROY (PARTS OF) YOUR DATA!");
if (!yes)
log_warn("Interrupt the conversion and run \"lvresize -y -l%u %s\" to "
"keep the current size if not done already!",
- (uint32_t) extend_len, display_lvname(lv));
+ (uint32_t) extend_le_count, display_lvname(lv));
log_print_unless_silent("If that leaves the logical volume larger than %u extents due to stripe rounding,",
- new_len);
+ reduced_le_count);
log_print_unless_silent("you may want to grow the content afterwards (filesystem etc.)");
log_warn("WARNING: too remove freed stripes after the conversion has finished, you have to run \"lvconvert --stripes %u %s\"",
new_stripes, display_lvname(lv));
@@ -4532,7 +4537,6 @@ static int _adjust_raid10_lv_size(struct logical_volume *lv,
seg->data_copies = 1;
}
- lv->size = (uint64_t) lv->le_count * lv->vg->extent_size;
seg->len = lv->le_count;
dm_list_iterate_items(seg1, &lv->segments)
seg1->segtype = segtype;
@@ -4686,6 +4690,12 @@ static int _raid_reshape(struct logical_volume *lv,
"raid set with less than parity devices");
RETURN_IF_ZERO(allocate_pvs , "allocate pvs list argument");
+ if (!_raid_in_sync(lv)) {
+ log_error("Unable to convert %s while it is not in-sync",
+ display_lvname(lv));
+ return 0;
+ }
+
PFLA("old_image_count=%u new_image_count=%u new_region_size=%u", old_image_count, new_image_count, new_region_size);
dm_list_init(&removal_lvs);
@@ -4861,8 +4871,7 @@ PFLA("new_segtype=%s seg->area_count=%u", new_segtype->name, seg->area_count);
/* _pre_raid_reshape to acivate any added image component pairs to avoid unsafe table loads */
if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs,
- _pre_raid_reshape, &old_image_count,
- NULL))
+ _pre_raid_reshape, &old_image_count, NULL))
return 0;
return force_repair ? _lv_cond_repair(lv) : 1;
@@ -4894,7 +4903,7 @@ static int _reshape_requested(const struct logical_volume *lv, const struct segm
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, (seg = first_seg(lv)), segtype);
- /* Keep current layout -> allow for removal of reshape space */
+ /* No layout change -> allow for removal of reshape space */
if (seg->segtype == segtype &&
data_copies == seg->data_copies &&
region_size == seg->region_size &&
@@ -4908,10 +4917,16 @@ PFLA("data_copies=%u seg->data_copies=%u stripes=%u seg->area_count=%u", data_co
data_copies != seg->data_copies))
goto err;
PFL();
- if (seg_is_raid10_far(seg) &&
- stripes != _data_rimages_count(seg, seg->area_count)) {
- log_error("Can't change stripes in raid10_far");
- goto err;
+ if (seg_is_raid10_far(seg)) {
+ if (stripes != _data_rimages_count(seg, seg->area_count)) {
+ log_error("Can't change stripes in raid10_far");
+ goto err;
+ }
+
+ if (stripe_size != seg->stripe_size) {
+ log_error("Can't change stripe size in raid10_far");
+ goto err;
+ }
}
PFL();
/* region_size may change on any raid LV but raid0 including raid10_far */
@@ -6426,10 +6441,10 @@ static int _raid_duplicate(struct logical_volume *lv,
log_warn("A new duplicated %s LV will be allocated and LV %s will be synced to it.",
_get_segtype_name(new_segtype, new_stripes), display_lvname(lv));
- log_warn("When unduplicating LV %s, you can select any sub LV providing its name via:",
- display_lvname(lv));
- log_warn("'lvconvert --unduplicate --name sub-lv-name %s' or 'lvconvert --unduplicate %s/sub-lv-name'",
- display_lvname(lv), lv->vg->name);
+ log_warn("When unduplicating LV %s or splitting off a sub-lv from %s, you can select any sub LV providing its name via:",
+ display_lvname(lv), display_lvname(lv));
+ log_warn("'lvconvert --unduplicate --name sub-lv-name %s' or 'lvconvert --splitmirror 1 --name sub-lv-name %s'",
+ display_lvname(lv), display_lvname(lv));
if (!_yes_no_conversion(lv, new_segtype, yes, force, 1, raid1_image_count, data_copies, new_stripes, new_stripe_size))
return 0;
@@ -9042,12 +9057,6 @@ PFL();
case 0:
break;
case 1:
- if (!_raid_in_sync(lv)) {
- log_error("Unable to convert %s while it is not in-sync",
- display_lvname(lv));
- return 0;
- }
-
if ((rcp.data_copies > 1 || stripes != seg->area_count - seg->segtype->parity_devs) &&
!is_same_level(seg->segtype, new_segtype)) {
log_error("Can't reshape and takeover %s at the same time",
diff --git a/lib/report/report.c b/lib/report/report.c
index a6edbf0b9..5a9877481 100644
--- a/lib/report/report.c
+++ b/lib/report/report.c
@@ -1957,6 +1957,12 @@ static int _vgsize_disp(struct dm_report *rh, struct dm_pool *mem,
return _size64_disp(rh, mem, field, &size, private);
}
+static int _seg_len(const struct lv_segment *seg)
+{
+ return seg->len - (((seg->area_count - seg->segtype->parity_devs) * seg->reshape_len) /
+ (seg_is_any_raid10(seg) ? seg->data_copies : 1));
+}
+
static int _lvsize_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
@@ -1967,8 +1973,7 @@ static int _lvsize_disp(struct dm_report *rh, struct dm_pool *mem,
if (seg_type(seg, 0) == AREA_LV &&
seg->area_count > 1)
- size = lv->size - seg->reshape_len *
- (seg->area_count - seg->segtype->parity_devs) * lv->vg->extent_size;
+ size = (uint64_t) _seg_len(seg) * lv->vg->extent_size;
return _size64_disp(rh, mem, field, &size, private);
}
@@ -2175,7 +2180,6 @@ static int _segsize_disp(struct dm_report *rh, struct dm_pool *mem,
{
const struct lv_segment *seg = (const struct lv_segment *) data;
uint64_t size = lvseg_size(seg);
-PFL();
return _size64_disp(rh, mem, field, &size, private);
}
@@ -2189,10 +2193,7 @@ static int _segsizepe_disp(struct dm_report *rh,
const struct lv_segment *seg = (const struct lv_segment *) data;
if (seg) {
- uint32_t len = seg->len;
-
- if (seg->area_count > 1)
- len -= seg->reshape_len * (seg->area_count - seg->segtype->parity_devs);
+ uint32_t len = (seg->area_count > 1) ? _seg_len(seg) : seg->len;
return dm_report_field_uint32(rh, field, &len);
}
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
index f740b7318..7c6106f21 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -2418,7 +2418,7 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
param_count += _get_params_count(seg->writemostly);
if ((seg->type == SEG_RAID1) && seg->stripe_size)
- log_error("WARNING: Ignoring RAID1 stripe size");
+ log_info("WARNING: Ignoring RAID1 stripe size");
/* Kernel only expects "raid0", not "raid0_meta" */
type = seg->type;