1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-19 14:04:17 +03:00

raid_manip:

activate duplication tree to avod unsafe table loads on merge
	cleanup
lv_manip:
	fix raid specific stripe rounding
{columns,report}.c:
	introduce new_data_offset field
This commit is contained in:
Heinz Mauelshagen 2016-01-13 21:34:19 +01:00
parent 9467971cde
commit 82fde92c1e
7 changed files with 377 additions and 210 deletions

View File

@ -2334,8 +2334,10 @@ static int _for_each_pv(struct cmd_context *cmd, struct logical_volume *lv,
int r = 1;
if (!seg && !(seg = find_seg_by_le(lv, le))) {
#if 0
log_error("Failed to find segment for %s extent %" PRIu32,
lv->name, le);
#endif
return 0;
}
@ -5666,6 +5668,20 @@ PFL();
lp->resize = LV_EXTEND; /* lets pretend zero size extension */
}
#if 1
if (lv_is_raid(lv)) {
unsigned stripes = seg->area_count - seg->segtype->parity_devs;
PFLA("lp->extents=%u", lp->extents);
lp->extents = _round_to_stripe_boundary(lv, lp->extents, stripes,
lp->extents < existing_physical_extents);
PFLA("lp->extents=%u", lp->extents);
lp->extents = raid_total_extents(seg->segtype, lp->extents, stripes,
seg->data_copies) / seg->data_copies;
PFLA("lp->extents=%u", lp->extents);
} else
#endif
/* Perform any rounding to produce complete stripes. */
if (lp->stripes > 1) {
if (lp->stripe_size < STRIPE_SIZE_MIN) {

View File

@ -387,6 +387,7 @@ static int _lv_set_reshape_len(struct logical_volume *lv, uint32_t reshape_len)
RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv)));
RETURN_IF_ZERO(seg->area_count, "lv raid segment areas");
RETURN_IF_ZERO(reshape_len < lv->le_count - 1, "proper reshape_len");
seg->reshape_len = reshape_len;
@ -702,6 +703,7 @@ static int _yes_no_conversion(const struct logical_volume *lv,
segtype = seg->segtype;
segtype_change = new_segtype != segtype;
printf("new_data_copies=%u seg->data_copies=%u\n", new_data_copies, seg->data_copies);
data_copies_change = new_data_copies && (new_data_copies != seg->data_copies);
stripes_change = new_stripes && (new_stripes != _data_rimages_count(seg, seg->area_count));
stripe_size_change = new_stripe_size && (new_stripe_size != seg->stripe_size);
@ -805,9 +807,10 @@ 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? [y/n]: ",
yes_no_prompt("Do you really want to %s %s with %u to %u data copies %s resilience? [y/n]: ",
duplicate ? "duplicate" : "convert",
display_lvname(lv), seg->data_copies, new_data_copies) == 'n') {
display_lvname(lv), seg->data_copies, new_data_copies,
seg->data_copies < new_data_copies ? "enhancing" : "reducing") == 'n') {
log_error("Logical volume %s NOT converted", display_lvname(lv));
return 0;
}
@ -829,6 +832,7 @@ PFLA("new_image_count=%u seg->area_count=%u", new_image_count, seg->area_count);
return 0;
}
}
if (sigint_caught())
return_0;
@ -1326,8 +1330,6 @@ static char *_generate_raid_name(struct logical_volume *lv,
}
if (find_lv_in_vg(lv->vg, name)) {
log_error("Logical volume %s already exists in volume group %s.",
name, lv->vg->name);
dm_pool_free(lv->vg->vgmem, name);
return NULL;
}
@ -2421,27 +2423,27 @@ PFLA("data_offset=%llu dev_sectors=%llu seg->reshape_len=%u out_of_place_les_per
} else {
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 reshape_len = out_of_place_les_per_disk * data_rimages;
uint32_t prev_rimage_len = _lv_total_rimage_len(lv);
RETURN_IF_ZERO(allocate_pvs , "allocate pvs list argument");
RETURN_IF_NONZERO(dm_list_empty(allocate_pvs), "allocate pvs listed");
PFLA("lv->le_count=%u seg->len=%u seg->area_len=%u", lv->le_count, seg->len, seg->area_len);
// PFLA("data_rimages=%u area_count=%u reshape_len=%u", data_rimages, seg->area_count, reshape_len);
PFLA("data_rimages=%u area_count=%u reshape_len=%u", data_rimages, seg->area_count, 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);
if (!lv_extend(lv, seg->segtype, data_rimages,
seg->stripe_size, 1, seg->region_size,
1 /* reshape_len */ /* # of reshape LEs to add */,
allocate_pvs, lv->alloc, 0)) {
seg->stripe_size, 1, seg->region_size,
reshape_len /* # of reshape LEs to add */,
allocate_pvs, lv->alloc, 0)) {
log_error("Failed to allocate out-of-place reshape space for %s.",
display_lvname(lv));
return 0;
}
/* HM FIXME: lv_extend may have alocated more because of layout specific rounding */
PFL();
/* 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;
@ -2651,9 +2653,10 @@ static int _lv_update_reload_fns_reset_eliminate_lvs(struct logical_volume *lv,
va_list ap;
fn_on_lv_t fn_pre_on_lv = NULL, fn_post_on_lv;
void *fn_pre_data, *fn_post_data;
struct lv_segment *seg;
struct dm_list *removal_lvs;
RETURN_IF_ZERO(lv, "lv argument");
RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv)));
va_start(ap, lv);
removal_lvs = va_arg(ap, struct dm_list *);
@ -2663,18 +2666,21 @@ static int _lv_update_reload_fns_reset_eliminate_lvs(struct logical_volume *lv,
fn_pre_data = va_arg(ap, void *);
}
PFL();
/* 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;
PFL();
/* Update metadata and reload mappings including flags (e.g. LV_REBUILD) */
if (!lv_update_and_reload_origin(lv))
if (!lv_update_and_reload(lv))
goto err;
PFL();
/* Eliminate any residual LV, write VG, commit it and take a backup */
if (!_eliminate_extracted_lvs_optional_write_vg(lv->vg, removal_lvs, 0))
goto err;
PFL();
/*
* Now that any 'REBUILD' or 'RESHAPE_DELTA_DISKS' etc.
* has/have made its/their way to the kernel, we must
@ -2688,16 +2694,19 @@ static int _lv_update_reload_fns_reset_eliminate_lvs(struct logical_volume *lv,
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;
PFL();
/* 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;
PFL();
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;
}
PFL();
r = 1;
err:
@ -3249,7 +3258,7 @@ int lv_raid_split_and_track(struct logical_volume *lv,
return 0;
}
/* Find sub LV ba name if given, else selct last raid1 leg */
/* Find sub LV by name if given, else select last raid1 leg */
for (s = seg->area_count - 1; s >= 0; s--) {
if (sub_lv_name &&
!strstr(sub_lv_name, seg_lv(seg, s)->name))
@ -3257,16 +3266,13 @@ int lv_raid_split_and_track(struct logical_volume *lv,
if (lv_is_on_pvs(seg_lv(seg, s), splittable_pvs)) {
split_lv = seg_lv(seg, s);
lv_set_visible(split_lv);
split_lv->status &= ~LVM_WRITE;
lv_set_visible(split_lv);
break;
}
}
if (s < 0) {
log_error("Unable to find image to satisfy request");
return 0;
}
RETURN_IF_NONZERO(s < 0, "image found to satisfy request");
if (!yes && yes_no_prompt("Do you really want to split off tracking LV %s from %s [y/n]: ",
display_lvname(split_lv), display_lvname(lv)) == 'n')
@ -3338,6 +3344,43 @@ int lv_raid_split_and_track(struct logical_volume *lv,
return 1;
}
/* HM Helper: */
static int _lv_update_and_reload(struct logical_volume *lv, int recurse)
{
uint32_t s;
struct logical_volume *lv1;
struct lv_segment *seg;
RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv)));
if (!recurse && !_vg_write_lv_suspend_vg_commit(lv))
return_0;
for (s = 0; s < seg->area_count; s++) {
if ((lv1 = seg_lv(seg, s))) {
PFLA("lv1=%s recurse=%d", display_lvname(lv1), recurse);
if (seg_type(first_seg(lv1), 0) == AREA_LV) {
if (!_lv_update_and_reload(lv1, 1))
return_0;
} else if (!_activate_sublv_preserving_excl(lv, lv1))
return_0;
}
if ((lv1 = _seg_metalv_checked(seg, s)) &&
!_activate_sublv_preserving_excl(lv, lv1))
return_0;
}
if (!resume_lv(lv->vg->cmd, lv_lock_holder(lv))) {
log_error("Failed to resume %s after committing changes",
display_lvname(lv));
return 0;
}
return 1;
}
/*
* API function:
*
@ -3393,8 +3436,8 @@ int lv_raid_merge(struct logical_volume *image_lv)
/* Image LVs should not be resizable directly, but... */
/* HM FIXME: duplicating sub LVs can have different size! */
if (seg->len != image_lv->le_count) {
log_error(INTERNAL_ERROR "The image LV %s of %s has different size!",
if (seg->len > image_lv->le_count) {
log_error(INTERNAL_ERROR "The image LV %s of %s has invalid size!",
display_lvname(image_lv), display_lvname(lv));
return 0;
}
@ -3416,24 +3459,27 @@ int lv_raid_merge(struct logical_volume *image_lv)
return 0;
}
#if 0
if (!deactivate_lv(vg->cmd, meta_lv)) {
log_error("Failed to deactivate %s before merging.",
display_lvname(meta_lv));
return 0;
}
PFL();
if (!deactivate_lv(vg->cmd, image_lv)) {
log_error("Failed to deactivate %s before merging.",
display_lvname(image_lv));
return 0;
}
#endif
image_lv->status |= LVM_WRITE;
image_lv->status |= RAID_IMAGE;
lv_set_hidden(image_lv);
seg->data_copies++;
if (!lv_update_and_reload(lv))
if (!_lv_update_and_reload(lv, 0))
return_0;
log_print_unless_silent("%s successfully merged back into %s",
@ -4112,6 +4158,7 @@ static int _reshape_adjust_to_size(struct logical_volume *lv,
if (!_lv_reshape_get_new_len(lv, old_image_count, new_image_count, &seg->len))
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;
@ -4119,7 +4166,7 @@ static int _reshape_adjust_to_size(struct logical_volume *lv,
if (old_image_count < new_image_count) {
_lv_set_reshape_len(lv, _reshape_len_per_dev(seg));
PFLA("seg->len=%u seg->area_len=%u seg->area_count=%u old_image_count=%u new_image_count=%u", seg->len, seg->area_len, seg->area_count, old_image_count, new_image_count);
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);
/* Extend from raid1 mapping */
if (old_image_count == 2 &&
!seg->stripe_size)
@ -4157,10 +4204,11 @@ static int _raid_reshape_add_disks(struct logical_volume *lv,
}
if (seg->segtype != new_segtype)
log_warn("Ignoring layout change on device adding reshape");
PFL();
if (!_lv_reshape_get_new_len(lv, old_image_count, new_image_count, &new_len))
return 0;
PFL();
reduce_len = seg->len - _reshape_len_per_lv(lv);
log_warn("WARNING: Adding stripes to active%s logical volume %s will grow "
"it from %u to %u extents!\n"
@ -4174,6 +4222,7 @@ static int _raid_reshape_add_disks(struct logical_volume *lv,
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",
new_image_count - old_image_count, new_image_count - old_image_count > 1 ? "s" : "",
@ -4190,8 +4239,9 @@ PFLA("first_seg(seg_lv(seg, %u))->len=%u first_seg(seg_lv(seg, %u))->area_len=%u
log_error("Failed to adjust LV %s to new size!", display_lvname(lv));
return 0;
}
PFL();
/* Allocate forward out of place reshape space at the beginning of all data image LVs */
log_debug_metadata("(Re)allocating reshape space for %s", display_lvname(lv));
if (!_lv_alloc_reshape_space(lv, alloc_begin, NULL, allocate_pvs))
return 0;
@ -4369,82 +4419,110 @@ PFL();
return 1;
}
/* change striped/raid0/raid10_far number of slices in @lv to hold raid10_far @new_data_copies >= 2 and <= stripes */
static int _lv_raid10_far_change_slices(struct logical_volume *lv,
const struct segment_type *new_segtype,
const uint32_t new_data_copies,
struct dm_list *allocate_pvs)
/*
* HM Helper:
*
* adjust @lv size for lv_{extend/reduce} to work.
*
* Set all segments type (should be just one) to raid0_meta
* for resize (for extend, last one would suffice, but...).
*/
static int _adjust_raid10_lv_size(struct logical_volume *lv,
const struct segment_type *new_segtype,
const struct segment_type *raid0_meta_segtype,
const uint32_t data_copies, int to_exposed_size)
{
uint32_t data_copies, extents_per_slice;
uint32_t extents;
struct lv_segment *seg, *seg1;
const struct segment_type *raid0_meta_segtype;
const struct segment_type *segtype;
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, (seg = first_seg(lv)), new_segtype);
RETURN_IF_ZERO(raid0_meta_segtype, "no valid raid0_meta_segtype argument");
RETURN_IF_ZERO(data_copies > 1, "valid #data_copies");
RETURN_IF_ZERO(to_exposed_size == 0 || to_exposed_size == 1,
"valid to_exposed_size argument");
if (to_exposed_size) {
lv->le_count /= data_copies;
segtype = new_segtype;
seg->data_copies = data_copies;
} else {
lv->le_count *= data_copies;
segtype = raid0_meta_segtype;
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;
return 1;
}
/*
* HM Helper:
*
* resize striped/raid0/raid10 number of slices in @lv to hold raid10 @new_data_copies >= 2 and <= stripes
*
* This function could be used to change number of data copies
* on raid10_{new,offset} as well, but MD kernel does not
* supprt that (yet).
*/
static int _lv_raid10_resize_data_copies(struct logical_volume *lv,
const struct segment_type *new_segtype,
const uint32_t new_data_copies,
struct dm_list *allocate_pvs)
{
uint32_t data_copies, extents_per_data_copy, extents;
struct lv_segment *seg;
const struct segment_type *raid0_meta_segtype, *segtype;
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, (seg = first_seg(lv)), new_segtype);
/* HM FIXME: accept raid10* once (if ever) MD kernel supports it */
RETURN_IF_ZERO(seg_is_striped(seg) || seg_is_any_raid0(seg) || seg_is_raid10_far(seg),
"processable segment type");
RETURN_IF_ZERO(seg->area_count > 1, "area count > 1");
RETURN_IF_NONZERO((seg_is_striped(seg) || seg_is_any_raid0(seg)) && seg->data_copies != 1,
"#data_copies == 1 with striped/raid0");
RETURN_IF_NONZERO(seg_is_raid10_far(seg) && seg->data_copies < 2,
"#data_copies < 2 with raid10_far");
RETURN_IF_NONZERO(seg_is_raid10(seg) && seg->data_copies < 2,
"#data_copies < 2 with raid10_");
RETURN_IF_NONZERO(new_data_copies == seg->data_copies, "change in #data_copies");
RETURN_IF_NONZERO(new_data_copies > seg->area_count, "#data_copies <= stripes");
/* lv->count does reflect the raid10_far netto size expsed, not the total size but lets play save */
RETURN_IF_NONZERO(lv->le_count % seg->area_count, "divisibility of LV size by stripes");
RETURN_IF_ZERO((raid0_meta_segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID0_META)),
"raid0_meta segment type found?");
PFL();
segtype = seg->segtype;
data_copies = seg->data_copies;
extents_per_slice = lv->le_count;
extents_per_data_copy = lv->le_count; /* Netto extents exposed = size per data copy needed */
extents = (new_data_copies > data_copies ? /* Extents to extend/reduce LV */
new_data_copies - data_copies :
data_copies - new_data_copies) * extents_per_data_copy;
if (data_copies > 1) {
lv->le_count *= data_copies;
lv->size = (uint64_t) lv->le_count * lv->vg->extent_size;
seg->len = lv->le_count;
}
/* Adjust to total (internal) LV size */
if (!_adjust_raid10_lv_size(lv, new_segtype, raid0_meta_segtype, data_copies, 0))
return 0;
extents = (new_data_copies > data_copies ? new_data_copies - data_copies : data_copies - new_data_copies) * extents_per_slice;
PFLA("lv->le_count=%u seg->data_copies=%u extents_per_slice=%u extents=%u", lv->le_count, data_copies, extents_per_slice, extents);
seg->data_copies = 1;
dm_list_iterate_items(seg1, &lv->segments)
seg1->segtype = raid0_meta_segtype;
log_debug_metadata("%sing raid10_far %s LV %s before conversion to %s",
log_debug_metadata("%sing %s LV %s before conversion to %s",
new_data_copies > seg->data_copies ? "Extend": "Reduc",
lvseg_name(seg), display_lvname(lv), new_segtype->name);
segtype->name, display_lvname(lv), new_segtype->name);
if (new_data_copies > data_copies) {
PFL();
if (!lv_extend(lv, raid0_meta_segtype,
seg->area_count, seg->stripe_size, 1, 0,
/* # of raid10_far slices for data copies to add */
(new_data_copies - data_copies) * extents_per_slice,
allocate_pvs, lv->alloc, 0)) {
extents, allocate_pvs, lv->alloc, 0)) {
log_error("Failed to extend %s LV %s before conversion to %s",
lvseg_name(seg), display_lvname(lv), new_segtype->name);
segtype->name, display_lvname(lv), new_segtype->name);
return 0;
}
PFL();
} else if (!lv_reduce(lv,
/* # of raid10_far slices for data copies to remove */
(data_copies - new_data_copies) * extents_per_slice)) {
log_error("Failed to reduce raid10_far LV %s", display_lvname(lv));
} else if (!lv_reduce(lv, extents)) {
log_error("Failed to reduce %s LV %s", segtype->name, display_lvname(lv));
return 0;
}
PFL();
/* Adjust externally LV exposed size */
lv->le_count /= new_data_copies;
lv->size = (uint64_t) lv->le_count * lv->vg->extent_size;
seg->len = lv->le_count;
seg->data_copies = new_data_copies;
dm_list_iterate_items(seg1, &lv->segments)
seg1->segtype = new_segtype;
return 1;
/* Adjust to externally LV exposed size */
return _adjust_raid10_lv_size(lv, new_segtype, raid0_meta_segtype, new_data_copies, 1);
}
/*
@ -4491,7 +4569,7 @@ PFLA("old_image_count=%u new_image_count=%u new_region_size=%u", old_image_count
seg->stripe_size == new_stripe_size) {
/*
* No change in segment type, image count, region or stripe size has been requested ->
* assume user requests thi to remove any reshape space from the @lv or error if none
* user requests this to remove any reshape space from the @lv
*/
if (_reshape_len_per_dev(seg)) {
log_info("Freeing reshape space on %s", display_lvname(lv));
@ -4512,9 +4590,30 @@ 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_fns_reset_eliminate_lvs(lv, NULL, NULL);
if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, NULL, NULL))
return 0;
}
/* Check for removal of data copies and reduce LV size accordingly */
if (seg_is_any_raid10(seg) && !seg_is_raid10_far(seg)) {
uint32_t extents = raid_rimage_extents(seg->segtype, lv->le_count,
seg->area_count, seg->data_copies);
uint32_t le_count = seg_lv(seg, 0)->le_count;
if (extents < le_count * seg->data_copies) {
log_warn("extents=%u seg_lv(seg, 0)->le_count=%u", extents, seg_lv(seg, 0)->le_count);
le_count *= seg->data_copies;
log_warn("seg->data_copies=%u", seg->data_copies);
seg->data_copies = le_count / extents;
log_warn("seg->data_copies=%u", seg->data_copies);
return 0;
if (!_lv_raid10_resize_data_copies(lv, seg->segtype, new_data_copies, allocate_pvs))
return 0;
}
} else
return 1;
log_error("No reshape to do on %s", display_lvname(lv));
return 0;
}
@ -4584,40 +4683,68 @@ PFL();
/*
* Handle raid set layout reshaping
* (e.g. raid5_ls -> raid5_n or stripe size change or change #data_copies on raid10_far)
* (e.g. raid5_ls -> raid5_n or stripe size change or change #data_copies on raid10)
*/
} else {
PFL();
int alloc_reshape_space = 1;
PFLA("seg->data_copies=%u new_data_copies=%u", seg->data_copies, new_data_copies);
if (!_yes_no_conversion(lv, new_segtype, yes, force, 0, new_image_count,
new_data_copies, new_stripes, new_stripe_size))
return 0;
PFL();
/* Got a request to change the number of data copies in a raid10_far LV */
if (seg_is_raid10_far(seg)) {
/* Ensure resynchronisation of new slices */
force_repair = new_data_copies > seg->data_copies;
PFLA("new_data_copies=%u", new_data_copies);
if (new_data_copies != seg->data_copies &&
!_lv_raid10_far_change_slices(lv, new_segtype, new_data_copies, allocate_pvs))
return 0;
where = alloc_anywhere;
/* Check a request to change the number of data copies in a raid10 LV */
if (seg->data_copies != new_data_copies) {
if (seg_is_raid10_far(seg)) {
/*
* Ensure resynchronisation of new data copies
* No reshape space needed, because raid10_far uses distinct stripe zones
* for its data copies rather than rotating them in individual stripes.
*/
force_repair = new_data_copies > seg->data_copies;
alloc_reshape_space = 0;
if (!_lv_raid10_resize_data_copies(lv, new_segtype, new_data_copies, allocate_pvs))
return 0;
} else if (seg_is_any_raid10(seg)) {
/* Ensure resynchronisation */
force_repair = 1;
if (new_data_copies > seg->data_copies) {
where = alloc_end;
if (!_lv_raid10_resize_data_copies(lv, new_segtype, new_data_copies, allocate_pvs))
return 0;
} else {
where = alloc_begin;
seg->data_copies = new_data_copies;
}
}
}
/*
* Reshape layout or chunksize:
*
* Allocate free out of place reshape space anywhere, thus
* avoiding remapping it in case it is already allocated.
* Allocate free out of place reshape space unless raid10_far.
*
* If other raid10, allocate it appropriatly.
*
* Allocate it anywhere for raid4/5 to avoid remapping
* it in case it is already allocated.
*
* The dm-raid target is able to use the space whereever it
* is found by appropriately selecting forward or backward reshape.
*/
} else if (!_lv_alloc_reshape_space(lv, alloc_anywhere, NULL, allocate_pvs))
if (alloc_reshape_space &&
!_lv_alloc_reshape_space(lv, where, NULL, allocate_pvs))
return 0;
seg->segtype = new_segtype;
PFL();
}
/* HM FIXME: workaround for lvcreate not resetting "nosync" flag */
/* HM FIXME: workaround for 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_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL))
@ -4657,12 +4784,26 @@ static int _reshape_requested(const struct logical_volume *lv, const struct segm
data_copies == seg->data_copies &&
region_size == seg->region_size &&
stripes == _data_rimages_count(seg, seg->area_count) &&
stripe_size == seg->stripe_size)
return 1;
stripe_size == seg->stripe_size) {
if (_reshape_len_per_dev(seg)) {
log_info("Freeing reshape space on LV %s", display_lvname(lv));
return 1;
}
log_warn("LV %s does not have reshape space allocated",
display_lvname(lv));
return 2;
}
PFLA("data_copies=%u seg->data_copies=%u", data_copies, seg->data_copies);
if ((_lv_is_duplicating(lv) || lv_is_duplicated(lv)) &&
((seg_is_raid1(seg) ? 0 : (stripes != _data_rimages_count(seg, seg->area_count))) ||
data_copies != seg->data_copies))
goto err;
PFL();
/* region_size may change on any raid LV but raid0 including raid10_far */
if (!seg_is_any_raid0(seg) &&
region_size &&
if (region_size &&
region_size != seg->region_size &&
segtype == seg->segtype) {
int may = 1;
@ -4670,7 +4811,7 @@ static int _reshape_requested(const struct logical_volume *lv, const struct segm
if (seg_is_raid10_far(seg) &&
(stripes != _data_rimages_count(seg, seg->area_count) ||
stripe_size != seg->stripe_size))
may--;
may = 0;
return may ? 3 : 2;
}
@ -4678,6 +4819,12 @@ static int _reshape_requested(const struct logical_volume *lv, const struct segm
/* This segment type is not reshapable */
if (!seg_is_reshapable_raid(seg))
return 0;
PFL();
if ((!seg_is_raid10_far(seg) && segtype_is_raid10_far(segtype)) ||
(seg_is_raid10_far(seg) && !segtype_is_raid10_far(segtype))) {
log_error("Can't convert from/to raid10_far");
goto err;
}
PFL();
/* Switching raid levels is a takeover, no reshape */
if (!is_same_level(seg->segtype, segtype))
@ -4686,15 +4833,7 @@ PFL();
if (seg_is_any_raid10(seg) &&
stripes && stripes < seg->area_count - seg->segtype->parity_devs) {
log_error("Can't remove stripes from raid10");
return 2;
}
PFL();
/* raid10_near change number of data copies */
if (seg_is_raid10_near(seg) && segtype_is_raid10_near(segtype)) {
if (stripes > seg->area_count)
return 1;
return (data_copies && seg->data_copies != data_copies) ? 0 : 2;
goto err;
}
PFL();
/* raid10_{near,offset} case */
@ -4703,7 +4842,7 @@ PFL();
if (stripes >= seg->area_count)
return 1;
goto err_do_dup;
goto err;
}
PFL();
/*
@ -4712,31 +4851,44 @@ PFL();
*/
if (seg_is_raid10_far(seg) && segtype_is_raid10_far(segtype)) {
if (stripes && stripes == seg->area_count &&
data_copies > 1 && data_copies != seg->data_copies)
data_copies > 1 &&
data_copies <= seg->area_count &&
data_copies != seg->data_copies)
return 1;
}
goto err;
} else if (seg_is_any_raid10(seg) && segtype_is_any_raid10(segtype) &&
data_copies > 1 && data_copies != seg->data_copies)
goto err;
PFL();
/* raid10_{near,offset} can't reshape removing devices, just adding */
/* raid10_{near,offset} can't reshape removing devices, just add some */
if (seg_is_any_raid10(seg) &&
seg->segtype == segtype) {
if (stripes && stripes < seg->area_count) {
if (stripes &&
(stripes < seg->area_count || stripes < seg->data_copies)) {
log_error("Can't reshape %s LV %s removing devices.",
lvseg_name(seg), display_lvname(lv));
goto err_do_dup;
goto err;
} else
return 1;
}
PFL();
/* Change layout (e.g. raid5_ls -> raid5_ra) keeping # of stripes */
if (seg->segtype != segtype) {
PFL();
if (stripes && stripes != _data_rimages_count(seg, seg->area_count))
return 2;
goto err;
PFL();
if (stripe_size && stripe_size != seg->stripe_size)
return 2;
goto err;
PFL();
return 1;
}
PFL();
if (stripes && stripes == _data_rimages_count(seg, seg->area_count)) {
log_error("LV %s already has %u stripes.",
@ -4744,21 +4896,13 @@ PFL();
return 2;
}
PFL();
#if 0
if (stripe_size && stripe_size == seg->stripe_size) {
log_error("LV %s already has stripe size %u.",
display_lvname(lv), stripe_size);
return 2;
}
#endif
return (region_size || stripes || stripe_size) ? 1 : 0;
err_do_dup:
err:
if (lv_is_duplicated(lv))
log_error("Can't convert duplicating sub-lv %s to %s", display_lvname(lv), segtype->name);
log_error("Conversion of duplicating sub-lv %s rejected", display_lvname(lv));
else
log_error("Use \"lvconvert --duplicate --ty %s ... %s", segtype->name, display_lvname(lv));
log_error("Use \"lvconvert --duplicate --type %s ... %s", segtype->name, display_lvname(lv));
return 2;
}
@ -5862,7 +6006,7 @@ static int _raid_split_duplicate(struct logical_volume *lv, int yes,
seg->area_count--;
seg->data_copies--;
RETURN_IF_ZERO(seg->area_count == seg->data_copies, "valid data cpies");
RETURN_IF_ZERO(seg->area_count == seg->data_copies, "valid data copies");
lv_set_visible(split_lv);
split_lv->status &= ~LV_NOTSYNCED;
@ -6034,23 +6178,30 @@ static struct logical_volume *_dup_lv_create(struct logical_volume *lv,
}
/* 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, ...)
static int _pre_raid_duplicate_rename_metadata_sub_lvs(struct logical_volume *lv, void *data)
{
uint32_t s;
struct logical_volume *mlv;
struct lv_segment *seg;
struct logical_volume *dup_lv, *lv1;
struct lv_segment *seg, *seg1;
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 */
/* Rename top-level raid1 metadata sub LVs to their temporary 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_checked(seg, s)) &&
!_rename_lv(mlv, "_rmeta_", "__rmeta_"))
if ((lv1 = _seg_metalv_checked(seg, s)) &&
!_rename_lv(lv1, "_rmeta_", "__rmeta_"))
return 0;
/* Activate new duplicated LV to prevent unsafe table load */
if (!activate_lv_excl_local(lv->vg->cmd, dup_lv)) {
lv_remove(dup_lv);
return 0;
}
return 1;
}
@ -6059,11 +6210,12 @@ static int _post_raid_duplicate_rename_metadata_sub_lvs_back(struct logical_volu
{
uint32_t s;
struct lv_segment *seg;
struct logical_volume *dup_lv, *mlv;
struct logical_volume *mlv;
RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv)));
RETURN_IF_ZERO((dup_lv = data), "duplicated LV argument");
RETURN_IF_NONZERO(data, "duplicated LV argument allowed");
RETURN_IF_ZERO(seg->meta_areas, "metadata areas");
PFL();
/* Rename top-level raid1 metadata sub LVs to their final names */
log_debug_metadata("Renaming sub LVs of %s to final names",
@ -6072,10 +6224,7 @@ static int _post_raid_duplicate_rename_metadata_sub_lvs_back(struct logical_volu
if ((mlv = _seg_metalv_checked(seg, s)) &&
!_rename_lv(mlv, "__rmeta_", "_rmeta_"))
return 0;
/* Activate to prevent unsafe table load */
if (!activate_lv_excl_local(lv->vg->cmd, dup_lv))
return lv_remove(dup_lv);
PFL();
return 1;
}
@ -6127,8 +6276,8 @@ PFLA("segtype=%s area_count=%u data_copies=%u stripe_size=%u", lvseg_name(seg),
}
if (duplicating)
log_warn("This is a request to add another duplicated LV to the existing "
"duplicating %u sub LVs of duplicating LV %s!",
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));
else {
if (lv_is_duplicated(lv)) {
@ -6148,12 +6297,10 @@ PFLA("segtype=%s area_count=%u data_copies=%u stripe_size=%u", lvseg_name(seg),
log_warn("A new %s LV will be allocated and LV %s will be synced to it.",
_get_segtype_name(new_segtype, raid1_image_count), display_lvname(lv));
log_warn("When unduplicating LV %s, you can select any synchronized sub LV providing unique properties via:",
display_lvname(lv));
log_warn("'lvconvert --unduplicate --type X [--stripes N [--stripesize S] [--mirrors M] %s' or via",
display_lvname(lv));
log_warn("'lvconvert --unduplicate --name sub-lv-name %s'",
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);
if (!_yes_no_conversion(lv, new_segtype, yes, force, 1, raid1_image_count, data_copies, new_stripes, new_stripe_size))
return 0;
@ -6252,8 +6399,8 @@ PFLA("lv0->le_count=%u lv1->le_count=%u", seg_lv(seg, 0)->le_count, seg_lv(seg,
/* _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);
_post_raid_duplicate_rename_metadata_sub_lvs_back, NULL,
_pre_raid_duplicate_rename_metadata_sub_lvs, dup_lv);
}
/*
@ -6455,7 +6602,7 @@ PFL();
PFL();
} else if (segtype_is_raid10_far(new_segtype)) {
if (!_lv_raid10_far_change_slices(lv, new_segtype, new_data_copies, allocate_pvs))
if (!_lv_raid10_resize_data_copies(lv, new_segtype, new_data_copies, allocate_pvs))
return 0;
PFL();
@ -6846,21 +6993,15 @@ TAKEOVER_HELPER_FN(_raid145_raid1_raid6)
struct dm_list removal_lvs;
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, (seg = first_seg(lv)), new_segtype);
RETURN_IF_NONZERO(!seg_is_raid1(seg) && !seg_is_raid4(seg) && !seg_is_any_raid5(seg),
"valid segment type");
dm_list_init(&removal_lvs);
if (!seg_is_raid1(seg) &&
!seg_is_raid4(seg) &&
!seg_is_any_raid5(seg)) {
log_error(INTERNAL_ERROR "Called with wrong segment type %s",
lvseg_name(seg));
return 0;
}
if (!_raid_in_sync(lv))
return 0;
if (!_yes_no_conversion(lv, new_segtype, yes, force, 0, new_image_count, new_image_count, 0, 0))
if (!_yes_no_conversion(lv, new_segtype, yes, force, 0, new_image_count, new_data_copies, 0, 0))
return 0;
/* Archive metadata */
@ -6871,11 +7012,11 @@ TAKEOVER_HELPER_FN(_raid145_raid1_raid6)
return 0;
seg->segtype = new_segtype;
if (segtype_is_raid1(new_segtype))
if (segtype_is_raid1(new_segtype)) {
seg->stripe_size = 0;
seg->data_copies = new_image_count;
else if (segtype_is_any_raid6(new_segtype) &&
new_stripe_size)
seg->stripe_size = new_stripe_size;
} else
seg->data_copies = new_data_copies;
return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs, NULL);
}
@ -7008,7 +7149,7 @@ TAKEOVER_HELPER_FN_REMOVAL_LVS(_raid10_striped_r0)
lv->le_count = seg->len;
/* raid10_far: shrink LV size to striped/raid0* */
} else if (raid10_far && !_lv_raid10_far_change_slices(lv, new_segtype, 1, NULL)) {
} else if (raid10_far && !_lv_raid10_resize_data_copies(lv, new_segtype, 1, NULL)) {
log_error("Failed to reduce raid10_far LV %s to %s size",
display_lvname(lv), new_segtype->name);
return 0;
@ -7509,7 +7650,7 @@ TAKEOVER_FN(_r1_r1)
return 0;
}
return _raid145_raid1_raid6(lv, new_segtype, yes, force, new_image_count, 1 /* data_copies */, 0, 0, allocate_pvs);
return _raid145_raid1_raid6(lv, new_segtype, yes, force, new_image_count, new_image_count, 0, 0, allocate_pvs);
}
/* raid1 with 2 legs -> raid4/5 */
@ -7672,7 +7813,7 @@ TAKEOVER_FN(_r45_r6)
return_0;
}
return _raid145_raid1_raid6(lv, new_segtype, yes, force, seg->area_count + 1, 1 /* data_copies */, 0, 0, allocate_pvs);
return _raid145_raid1_raid6(lv, new_segtype, yes, force, seg->area_count + 1, 2 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid6 -> striped */
@ -7730,8 +7871,11 @@ TAKEOVER_FN(_r6_r45)
}
new_image_count = seg->area_count - 1;
#if 1
seg->data_copies = 2;
#endif
if (!_yes_no_conversion(lv, new_segtype, yes, force, 0, new_image_count, 2, 0, 0))
if (!_yes_no_conversion(lv, new_segtype, yes, force, 0, new_image_count, 1 /* data_copies */, 0, 0))
return 0;
dm_list_init(&removal_lvs);
@ -8374,7 +8518,9 @@ 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 ? 1 : seg->area_count);
*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 */
@ -8407,12 +8553,15 @@ static int _raid_convert_define_parms(const struct lv_segment *seg,
*stripes = 3;
} else if (segtype_is_striped(*segtype) ||
segtype_is_striped_raid(*segtype)) {
if (*stripes > 1 &&
!*stripe_size) {
*stripe_size = 64;
log_warn("Initializing stripe size on %s to %u sectors",
display_lvname(seg->lv), *stripe_size);
segtype_is_striped_raid(*segtype)) {
if (*stripes > 1 && !*stripe_size) {
if (seg->stripe_size)
*stripe_size = seg->stripe_size;
else {
*stripe_size = 64;
log_warn("Initializing stripe size on %s to %u sectors",
display_lvname(seg->lv), *stripe_size);
}
}
if (*stripes == 1 &&
@ -8428,6 +8577,11 @@ static int _raid_convert_define_parms(const struct lv_segment *seg,
}
}
if (segtype_is_raid(*segtype) && !segtype_is_raid1(*segtype) && *data_copies > *stripes) {
log_error("Number of data copies larger than number of stripes");
return 0;
}
return 1;
}
@ -8737,11 +8891,13 @@ PFLA("lv=%s lv_name=%s", display_lvname(lv), rcp.lv_name);
!(new_segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID1)))
return_0;
}
/*
* If not duplicating/unduplicating request ->
*
* reshape of capable raid type requested
*/
PFL();
switch (_reshape_requested(lv, new_segtype, data_copies, region_size, stripes, stripe_size)) {
case 0:
break;

View File

@ -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

View File

@ -141,6 +141,7 @@ static int _raid_text_import(struct lv_segment *seg,
}
}
/* FIXME: only necessary for givne matadata w/o new data_copies */
} else if (!strcmp(aip->name, "data_copies"))
seg->data_copies = seg_is_raid1(seg) ? seg->area_count : 1;
}
@ -160,7 +161,6 @@ static int _raid_text_import(struct lv_segment *seg,
seg->status |= RAID;
seg->area_len = raid_rimage_extents(seg->segtype, seg->len, seg->area_count - seg->segtype->parity_devs,
seg->segtype->parity_devs ? 1 : seg->data_copies);
return 1;
}
@ -174,7 +174,7 @@ static int _raid_text_export(const struct lv_segment *seg, struct formatter *f)
else {
outf(f, "device_count = %u", seg->area_count);
if (seg->data_copies > 1)
if (seg->data_copies > 0)
outf(f, "data_copies = %" PRIu32, seg->data_copies);
if (seg->region_size)
outf(f, "region_size = %" PRIu32, seg->region_size);

View File

@ -174,6 +174,8 @@ FIELD(SEGS, seg, NUM, "#Cpy", list, 4, segdata_copies, datacopies, "Number of da
FIELD(SEGS, seg, NUM, "#Cpy", list, 4, segdata_copies, data_copies, "Number of data copies.", 0)
FIELD(SEGS, seg, NUM, "data", list, 4, segdata_offset, dataoffset, "Data offset on each image device.", 0)
FIELD(SEGS, seg, NUM, "data", list, 4, segdata_offset, data_offset, "Data offset on each image device.", 0)
FIELD(SEGS, seg, NUM, "ndata", list, 4, segnewdata_offset, newdataoffset, "New data offset after any reshape on each image device.", 0)
FIELD(SEGS, seg, NUM, "ndata", list, 4, segnewdata_offset, new_data_offset, "New data offset after any reshape on each image device.", 0)
FIELD(SEGS, seg, NUM, "#Par", list, 4, seg_parity_chunks, parity, "Number of (rotating) parity chunks.", 0)
FIELD(SEGS, seg, NUM, "#Par", list, 4, seg_parity_chunks, parity_chunks, "Number of (rotating) parity chunks.", 0)
FIELD(SEGS, seg, NUM, "#Par", list, 4, seg_parity_chunks, parity_devs, "Number of (rotating) parity chunks.", 0)

View File

@ -409,6 +409,7 @@ GET_VG_STR_PROPERTY_FN(vg_profile, vg_profile_dup(vg))
#define _vg_profile_set prop_not_implemented_set
/* LVSEG */
#define _segtype_set prop_not_implemented_set
GET_LVSEG_STR_PROPERTY_FN(segtype, lvseg_segtype_dup(lvseg->lv->vg->vgmem, lvseg))
#define _datacopies_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(datacopies, lvseg->segtype->parity_devs ? lvseg->segtype->parity_devs + 1 : lvseg->data_copies)
@ -418,11 +419,14 @@ GET_LVSEG_NUM_PROPERTY_FN(data_copies, lvseg->segtype->parity_devs ? lvseg->segt
GET_LVSEG_NUM_PROPERTY_FN(reshapelen, (lvseg->reshape_len *lvseg->area_count / (lvseg->area_count - lvseg->segtype->parity_devs)))
#define _reshape_len_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(reshape_len, (lvseg->reshape_len *lvseg->area_count / (lvseg->area_count - lvseg->segtype->parity_devs)))
#define _dataoffset_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(dataoffset, lvseg->data_offset)
#define _data_offset_set prop_not_implemented_set
#define _dataoffset_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(data_offset, lvseg->data_offset)
#define _segtype_set prop_not_implemented_set
#define _data_offset_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(newdataoffset, lvseg->data_offset)
#define _newdataoffset_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(new_data_offset, lvseg->data_offset)
#define _new_data_offset_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(parity, lvseg->data_offset)
#define _parity_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(parity_chunks, lvseg->data_offset)

View File

@ -2057,31 +2057,22 @@ static int _segdata_copies_disp(struct dm_report *rh, struct dm_pool *mem,
const void *data, void *private)
{
const struct lv_segment *seg = (const struct lv_segment *) data;
uint32_t data_copies = seg->segtype->parity_devs ?
(seg->segtype->parity_devs + 1) : seg->data_copies;
#if 0
PFLA("seg->data_copies=%u data_copies=%u", seg->data_copies, data_copies);
if ((seg_is_raid1(seg) || seg_is_mirror(seg)) &&
!seg_is_any_raid10(seg))
data_copies = seg->area_count;
#endif
if (data_copies > 1)
return dm_report_field_uint32(rh, field, &data_copies);
if (seg->data_copies > 1)
return dm_report_field_uint32(rh, field, &seg->data_copies);
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_32));
}
#if 1
static int _segdata_offset_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
static int __segdata_offset_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private, int new_data_offset)
{
const struct lv_segment *seg = (const struct lv_segment *) data;
const char *what = "";
if (lv_is_raid_image(seg->lv) && !seg->le) {
if (lv_is_raid_image(seg->lv) && !seg->le &&
(seg->reshape_len || !new_data_offset)) {
struct lv_list *lvl;
char *lv_name = strdup(seg->lv->name);
@ -2095,8 +2086,13 @@ static int _segdata_offset_disp(struct dm_report *rh, struct dm_pool *mem,
if (seg_is_reshapable_raid(first_seg(lvl->lv))) {
uint64_t data_offset;
if (lv_raid_offset_and_sectors(lvl->lv, &data_offset, NULL))
if (lv_raid_offset_and_sectors(lvl->lv, &data_offset, NULL)) {
if (new_data_offset && !lv_raid_image_in_sync(seg->lv))
data_offset = data_offset ? 0 :
seg->reshape_len * seg->lv->vg->extent_size;
return dm_report_field_uint64(rh, field, &data_offset);
}
what = _str_unknown;
}
@ -2108,27 +2104,20 @@ static int _segdata_offset_disp(struct dm_report *rh, struct dm_pool *mem,
return _field_set_value(field, what, &GET_TYPE_RESERVED_VALUE(num_undef_64));
}
#else
static int _segdata_offset_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct lv_segment *seg = (const struct lv_segment *) data;
const char *what = "";
/* HM FIXME: display data offset on image LVs, not on the top-level raid LV? */
if (seg_is_reshapable_raid(seg)) {
uint64_t data_offset;
if (lv_raid_offset_and_sectors(seg->lv, &data_offset, NULL))
return dm_report_field_uint64(rh, field, &data_offset);
what = _str_unknown;
}
return _field_set_value(field, what, &GET_TYPE_RESERVED_VALUE(num_undef_64));
return __segdata_offset_disp(rh, mem, field, data, private, 0);
}
static int _segnewdata_offset_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
return __segdata_offset_disp(rh, mem, field, data, private, 1);
}
#endif
static int _seg_parity_chunks_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,