1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-03-06 00:58:48 +03:00

introduces reshaping target version check; more reshape space coding

This commit is contained in:
Heinz Mauelshagen 2015-05-18 23:35:45 +02:00
parent 4180016bf5
commit 40040ebf29
5 changed files with 79 additions and 57 deletions

View File

@ -35,6 +35,14 @@
#include <math.h>
#include <sys/param.h>
#if 1
#define PFL() printf("%s %u\n", __func__, __LINE__);
#define PFLA(format, arg...) printf("%s %u " format "\n", __func__, __LINE__, arg);
#else
#define PFL()
#define PFLA(format, arg...)
#endif
static struct physical_volume *_pv_read(struct cmd_context *cmd,
struct dm_pool *pvmem,
const char *pv_name,

View File

@ -376,10 +376,11 @@ PFL();
* FIXME: only vg_[write|commit] if LVs are not already written
* as visible in the LVM metadata (which is never the case yet).
*/
PFL();
PFLA("vg_validate(vg)=%d", vg_validate(vg));
PFL();
if (!vg || !vg_write(vg) || !vg_commit(vg))
return_0;
PFL();
dm_list_iterate_items(lvl, lv_list)
if (!_clear_lv(lvl->lv))
@ -765,7 +766,6 @@ static int _add_image_component_list(struct lv_segment *seg, int delete_from_lis
else
lvl->lv->status &= ~LV_REBUILD;
if (!set_lv_segment_area_lv(seg, s++, lvl->lv, 0 /* le */,
lvl->lv->status)) {
log_error("Failed to add sublv %s", lvl->lv->name);
@ -1168,35 +1168,36 @@ static int _alloc_rmeta_for_linear(struct logical_volume *lv, struct dm_list *me
}
/*
* Relocate @out_of_place_les_per_disk from @data_lv begin <-> end depending on @to_end
* Relocate @out_of_place_les_per_disk from @lv's data images begin <-> end depending on @to_end
*
* to_end == 0 -> begin -> end
* to_end != 0 -> end -> begin
* to_end != 0 -> begin -> end
* to_end == 0 -> end -> begin
*/
static int _relocate_reshape_space(struct logical_volume *lv,
uint32_t out_of_place_les_per_disk, int to_end)
{
uint32_t s;
struct logical_volume *data_lv;
uint32_t le, les, s;
struct logical_volume *dlv;
struct lv_segment *seg = first_seg(lv);
struct lv_segment *data_seg, *new_seg;
uint32_t les = out_of_place_les_per_disk;
struct lv_segment *data_seg, *new_seg, *tmp_seg;
/* last -> last segment, !last -> first segment */
if (to_end)
les = data_seg->area_len - les;
/*
* Move the reshape LEs of each stripe (i.e. the data image sub lv)
* in the first/last segment across to new segments of just use
* them in case size fits
*/
for (s = 0; s < seg->area_count; s++) {
data_lv = seg_lv(seg, s);
data_seg = to_end ? first_seg(data_lv) : last_seg(data_lv);
dlv = seg_lv(seg, s);
le = to_end ? 0 : dlv->le_count - out_of_place_les_per_disk;
data_seg = find_seg_by_le(dlv, le);
/* to_end -> last segment, !to_end -> first segment */
les = out_of_place_les_per_disk;
if (to_end)
les = data_seg->len - les;
if (data_seg->area_len != out_of_place_les_per_disk) {
if (!(new_seg = alloc_lv_segment(data_seg->segtype, data_lv,
if (!(new_seg = alloc_lv_segment(data_seg->segtype, dlv,
0 /* le gets adjusted later */,
les, 0 /* no reshape_len on sub lvs */,
data_seg->status,
@ -1212,29 +1213,26 @@ PFLA("data_seg->len=%u data_seg->area_len=%u new_seg->len=%u new_seg->area_len=%
data_seg->len -= new_seg->area_len;
/* Insert the new segment as the first one */
dm_list_add_h(&data_lv->segments, &new_seg->list);
dm_list_add_h(&dlv->segments, &new_seg->list);
} else if (!to_end)
/* Segment at the end holding reshape space has correct length -> move upfront */
dm_list_move(data_lv->segments.n, &data_seg->list);
dm_list_move(dlv->segments.n, &data_seg->list);
if (to_end)
/*
* After a relocation from begin -> end, data_seg contains
* the reshape space of the first data lv segment
*/
dm_list_move(&data_lv->segments, &data_seg->list);
dm_list_move(&dlv->segments, &data_seg->list);
}
/* Adjust starting LEs of data lv segments */;
for (s = 0; s < seg->area_count; s++) {
uint32_t le;
struct lv_segment *tmp;
le = 0;
data_lv = seg_lv(seg, s);
dm_list_iterate_items(tmp, &data_lv->segments) {
tmp->le = le;
le += tmp->len;
dlv = seg_lv(seg, s);
dm_list_iterate_items(tmp_seg, &dlv->segments) {
tmp_seg->le = le;
le += tmp_seg->len;
}
}
@ -1290,12 +1288,10 @@ static int _lv_alloc_reshape_space(struct logical_volume *lv,
enum alloc_where where,
struct dm_list *allocate_pvs)
{
uint32_t s;
/* FIXME: les per disk dynamic to better address small extent size? at least one MiB for now... */
uint32_t out_of_place_les_per_disk = 2048 / lv->vg->extent_size, reshape_len;
uint64_t data_offset, dev_sectors;
struct logical_volume *data_lv;
struct lv_segment *seg = first_seg(lv), *new_seg, *data_seg;
struct lv_segment *seg = first_seg(lv);
if (!out_of_place_les_per_disk)
out_of_place_les_per_disk = 1;
@ -1380,12 +1376,12 @@ static int _lv_free_reshape_space(struct logical_volume *lv)
struct lv_segment *seg = first_seg(lv);
if (seg->reshape_len) {
/* Got reshape space, optinally remap it to the end and lvreduce it */
/* Got reshape space, optionally remap it to the end and lvreduce it */
if (!_lv_alloc_reshape_space(lv, alloc_end, NULL))
return 0;
return_0;
if (!lv_reduce(lv, seg->reshape_len))
return 0;
return_0;
seg->reshape_len = 0;
}
@ -1683,6 +1679,14 @@ PFL();
/* Need access to the new first segment after the linear -> raid1 conversion */
seg = first_seg(lv);
/* If we convert to raid1 via "lvconvert -mN", set segtype */
if (old_count != new_count &&
segtype == seg->segtype &&
!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_RAID1)))
return 0;
seg->segtype = segtype;
}
PFL();
/* Metadata LVs must be cleared before being added to the array */
@ -1690,6 +1694,7 @@ PFL();
if (!_clear_lvs(&meta_lvs))
goto fail;
PFL();
/*
* FIXME: It would be proper to activate the new LVs here, instead of having
* them activated by the suspend. However, this causes residual device nodes
@ -1739,10 +1744,14 @@ PFL();
* but this shows proper status chars.
*/
if (linear || (seg_is_any_raid0(seg) && old_count == 1)) {
#if 1
seg_lv(seg, 0)->status &= ~LV_REBUILD;
for (s = old_count; s < new_count; s++)
seg_lv(seg, s)->status |= LV_REBUILD;
#else
;
#endif
} else if (reshape_disks) {
uint32_t plus_extents = count * (lv->le_count / _data_rimages_count(seg, old_count));
@ -1772,6 +1781,7 @@ PFLA("lv->le_count=%u", lv->le_count);
seg->segtype = segtype;
PFL();
if (!lv_update_and_reload_origin(lv)) {
if (!_remove_image_component_list(seg, RAID_META, add_all_rmeta ? 0 : old_count, &meta_lvs) ||
!_remove_image_component_list(seg, RAID_IMAGE, old_count, &data_lvs))
@ -1982,18 +1992,12 @@ static int _raid_remove_images(struct logical_volume *lv,
PFLA("seg->segtype=%s segtype=%s new_count=%u", seg->segtype->name, segtype->name, new_count);
dm_list_init(&removal_list);
if (segtype_is_linear(segtype)) { /* if (new_count == 1) { */
uint32_t reshape_len = last_seg(lv)->reshape_len;
/* HM FIXME: proper place to reduce by reshape_len? */
if (reshape_len &&
!lv_reduce(lv, reshape_len / old_count)) {
log_error("Failed to remove RAID layer"
" after linear conversion");
return 0;
}
last_seg(lv)->reshape_len = 0;
/* If we convert away from raid4/5/6/10 -> remove any reshape space */
if (!(segtype_is_striped_raid(segtype) && !segtype_is_raid0(segtype)) &&
!_lv_free_reshape_space(lv)) {
log_error(INTERNAL_ERROR "Failed to remove reshape space from %s/%s",
lv->vg->name, lv->name);
return 0;
}
/* Reorder the areas in case this is a raid10 -> raid0 conversion */
@ -2882,21 +2886,21 @@ PFL();
while (le < seg->len) {
area_len = ~0;
/* Find shortest smallest segment of each of the data image lvs */
/* Find smallest segment of each of the data image lvs */
for (s = 0; s < seg->area_count; s++) {
dlv = seg_lv(seg, s);
seg_from = find_seg_by_le(dlv, area_le);
l = seg_from->len - (area_le - seg_from->le);
seg_from = find_seg_by_le(dlv, le);
l = seg_from->len - le;
if (l < area_len)
area_len = l;
PFLA("are_len=%u l=%u", area_len, l);
}
/* area_len now holds the smallest one */
/* Allocate a segment with area_count areas */
PFLA("seg->area_count=%u seg->stripe_size=%u", seg->area_count, seg->stripe_size);
if (!(seg_to = alloc_lv_segment(striped_segtype, lv, le, area_len * seg->area_count,
seg->reshape_len,
0 /* seg->reshape_len */,
seg->status & ~RAID,
seg->stripe_size, NULL, seg->area_count,
area_len, seg->chunk_size,
@ -2904,7 +2908,6 @@ PFLA("seg->area_count=%u seg->stripe_size=%u", seg->area_count, seg->stripe_size
return_0;
dm_list_add(&new_segments, &seg_to->list);
area_le += area_len;
le += area_len * seg->area_count;
PFL();
@ -3236,12 +3239,8 @@ PFL();
return_0;
/*
* HM FIXME: check if there's enough free space for backward
* out-of-place reshape
*
* If none, add an extent per image to the end of each data image
* Allocate free data image LVs space for forward out-of-place reshape at the end
*/
/* Do it here! */
if (!_lv_alloc_reshape_space(lv, alloc_end, allocate_pvs))
return 0;
@ -3298,7 +3297,9 @@ PFL();
return_0;
}
/* HM FIXME: allocate reshape space for layout reshape as well */
/*
* Allocate free data image LVs space for forward out-of-place reshape anywhere
*/
if (!_lv_alloc_reshape_space(lv, alloc_anywhere, allocate_pvs))
return 0;

View File

@ -151,7 +151,8 @@ struct segment_type *init_unknown_segtype(struct cmd_context *cmd,
const char *name);
#define RAID_FEATURE_RAID10 (1U << 0) /* version 1.3 */
#define RAID_FEATURE_RAID0 (1U << 1) /* version 1.6 */
#define RAID_FEATURE_RAID0 (1U << 1) /* version 1.7 */
#define RAID_FEATURE_RESHAPING (1U << 2) /* version 1.8 */
#ifdef RAID_INTERNAL
int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);

View File

@ -384,6 +384,7 @@ static int _raid_target_present(struct cmd_context *cmd,
} _features[] = {
{ 1, 3, RAID_FEATURE_RAID10, SEG_TYPE_NAME_RAID10 },
{ 1, 7, RAID_FEATURE_RAID0, SEG_TYPE_NAME_RAID0 },
{ 1, 8, RAID_FEATURE_RESHAPING, "reshaping" },
};
static int _raid_checked = 0;

View File

@ -1989,6 +1989,15 @@ PFLA("stripes=%u stripe_size=%u\n", stripes, stripe_size);
if (seg_is_striped(seg))
seg->region_size = lp->region_size;
/* Check for reshaping support if requested */
if (((seg->segtype != lp->segtype && !strncmp(seg->segtype->name, lp->segtype->name, 5)) ||
(stripes && stripes != seg->area_count - seg->segtype->parity_devs) ||
(stripe_size && stripe_size != seg->stripe_size)) &&
!(lp->target_attr & RAID_FEATURE_RESHAPING)) {
log_error("RAID module does not support reshaping.");
return 0;
}
return lv_raid_convert(lv, lp->segtype, lp->yes, lp->force, image_count, stripes, stripe_size, lp->pvh);
}
@ -3576,9 +3585,11 @@ static int lvconvert_single(struct cmd_context *cmd, struct lvconvert_params *lp
init_ignore_suspended_devices(1);
cmd->handles_missing_pvs = 1;
#if 1
/* Update PV metadata in cache too allow repair to spot recently lost PVs */
if (lvmetad_active())
lvmetad_pvscan_all_devs(cmd, NULL);
#endif
}
if (!(lv = get_vg_lock_and_logical_volume(cmd, lp->vg_name, lp->lv_name)))