1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

Support for PE ranges in pvmove source PV.

This commit is contained in:
Alasdair Kergon 2004-08-17 22:09:02 +00:00
parent bcd4e5d50d
commit 392b28ec5c
6 changed files with 182 additions and 45 deletions

View File

@ -1,5 +1,10 @@
Version 2.00.21 -
=============================
Fix extents_moved metadata size comment.
Remove duplicate line in pvremove help text.
Support variable mirror region size.
Support PE ranges in pvmove source PV.
Fixes to as-yet-unused LV segment splitting code.
Change alloc_areas to pe_ranges and allow suppression of availability checks.
Add dev_size column to pvs.
Add report columns for in-kernel device number.

View File

@ -39,6 +39,9 @@ int lv_merge_segments(struct logical_volume *lv)
struct list *segh, *t;
struct lv_segment *current, *prev = NULL;
if (lv->status & LOCKED || lv->status & PVMOVE)
return 1;
list_iterate_safe(segh, t, &lv->segments) {
current = list_item(segh, struct lv_segment);
@ -77,6 +80,7 @@ int lv_check_segments(struct logical_volume *lv)
/*
* Split the supplied segment at the supplied logical extent
* NB Use LE numbering that works across stripes PV1: 0,2,4 PV2: 1,3,5 etc.
*/
static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
uint32_t le)
@ -85,6 +89,7 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
struct lv_segment *split_seg;
uint32_t s;
uint32_t offset = le - seg->le;
uint32_t area_offset;
if (!(seg->segtype->flags & SEG_CAN_SPLIT)) {
log_error("Unable to split the %s segment at LE %" PRIu32
@ -107,8 +112,9 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
}
/* In case of a striped segment, the offset has to be / stripes */
area_offset = offset;
if (seg->segtype->flags & SEG_AREAS_STRIPED)
offset /= seg->area_count;
area_offset /= seg->area_count;
/* Adjust the PV mapping */
for (s = 0; s < seg->area_count; s++) {
@ -116,12 +122,19 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
switch (seg->area[s].type) {
case AREA_LV:
split_seg->area[s].u.lv.le =
seg->area[s].u.lv.le + offset;
seg->area[s].u.lv.le + area_offset;
log_debug("Split %s:%u[%u] at %u: %s LE %u", lv->name,
seg->le, s, le, seg->area[s].u.lv.lv->name,
split_seg->area[s].u.lv.le);
break;
case AREA_PV:
split_seg->area[s].u.pv.pe =
seg->area[s].u.pv.pe + offset;
seg->area[s].u.pv.pe + area_offset;
log_debug("Split %s:%u[%u] at %u: %s PE %u", lv->name,
seg->le, s, le,
dev_name(seg->area[s].u.pv.pv->dev),
split_seg->area[s].u.pv.pe);
break;
default:
@ -131,8 +144,13 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
}
}
split_seg->area_len = seg->area_len - offset;
seg->area_len = offset;
split_seg->area_len -= area_offset;
seg->area_len = area_offset;
split_seg->len -= offset;
seg->len = offset;
split_seg->le = seg->le + seg->len;
/* Add split off segment to the list _after_ the original one */
list_add_h(&seg->list, &split_seg->list);

View File

@ -501,7 +501,7 @@ int vg_remove_snapshot(struct volume_group *vg, struct logical_volume *cow);
*/
int insert_pvmove_mirrors(struct cmd_context *cmd,
struct logical_volume *lv_mirr,
struct physical_volume *pv,
struct list *source_pvl,
struct logical_volume *lv,
struct list *allocatable_pvs,
struct list *lvs_changed);

View File

@ -26,7 +26,7 @@
*/
int insert_pvmove_mirrors(struct cmd_context *cmd,
struct logical_volume *lv_mirr,
struct physical_volume *pv,
struct list *source_pvl,
struct logical_volume *lv,
struct list *allocatable_pvs,
struct list *lvs_changed)
@ -34,9 +34,15 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
struct list *segh;
struct lv_segment *seg;
struct lv_list *lvl;
struct pv_list *pvl;
int lv_used = 0;
uint32_t s, start_le, extent_count = 0u;
struct segment_type *segtype;
struct pe_range *per;
uint32_t pe_start, pe_end, per_end, stripe_multiplier;
/* Only 1 PV may feature in source_pvl */
pvl = list_item(source_pvl->n, struct pv_list);
if (!(segtype = get_segtype_from_string(lv->vg->cmd, "mirror"))) {
stack;
@ -50,14 +56,74 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
return 0;
}
/* Split LV segments to match PE ranges */
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV ||
seg->area[s].u.pv.pv->dev != pvl->pv->dev)
continue;
/* Do these PEs need moving? */
list_iterate_items(per, pvl->pe_ranges) {
pe_start = seg->area[s].u.pv.pe;
pe_end = pe_start + seg->area_len - 1;
per_end = per->start + per->count - 1;
/* No overlap? */
if ((pe_end < per->start) ||
(pe_start > per_end))
continue;
if (seg->segtype->flags & SEG_AREAS_STRIPED)
stripe_multiplier = seg->area_count;
else
stripe_multiplier = 1;
if ((per->start != pe_start &&
per->start > pe_start) &&
!lv_split_segment(lv, seg->le +
(per->start - pe_start) *
stripe_multiplier)) {
stack;
return 0;
}
if ((per_end != pe_end &&
per_end < pe_end) &&
!lv_split_segment(lv, seg->le +
(per_end - pe_start + 1) *
stripe_multiplier)) {
stack;
return 0;
}
}
}
}
/* Work through all segments on the supplied PV */
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV ||
seg->area[s].u.pv.pv->dev != pv->dev)
seg->area[s].u.pv.pv->dev != pvl->pv->dev)
continue;
pe_start = seg->area[s].u.pv.pe;
/* Do these PEs need moving? */
list_iterate_items(per, pvl->pe_ranges) {
per_end = per->start + per->count - 1;
if ((pe_start < per->start) ||
(pe_start > per_end))
continue;
log_debug("Matched PE range %u-%u against "
"%s %u len %u", per->start, per_end,
dev_name(seg->area[s].u.pv.pv->dev),
seg->area[s].u.pv.pe, seg->area_len);
/* First time, add LV to list of LVs affected */
if (!lv_used) {
if (!(lvl = pool_alloc(cmd->mem, sizeof(*lvl)))) {
@ -69,6 +135,13 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
lv_used = 1;
}
log_very_verbose("Moving %s:%u-%u of %s/%s",
dev_name(pvl->pv->dev),
seg->area[s].u.pv.pe,
seg->area[s].u.pv.pe +
seg->area_len - 1,
lv->vg->name, lv->name);
start_le = lv_mirr->le_count;
if (!lv_extend(lv->vg->fid, lv_mirr, segtype, 1,
seg->area_len, 0u, seg->area_len,
@ -87,6 +160,9 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
extent_count += seg->area_len;
lv->status |= LOCKED;
break;
}
}
}
@ -167,8 +243,12 @@ int remove_pvmove_mirrors(struct volume_group *vg,
lv1->status &= ~LOCKED;
}
}
if (!lv_merge_segments(lv1))
stack;
}
return 1;
}

View File

@ -95,7 +95,7 @@ static int _text_export(const struct lv_segment *seg, struct formatter *f)
{
outf(f, "mirror_count = %u", seg->area_count);
if (seg->status & PVMOVE)
out_size(f, (uint64_t) seg->extents_copied,
out_size(f, (uint64_t) seg->extents_copied * seg->lv->vg->extent_size,
"extents_moved = %u", seg->extents_copied);
return out_areas(f, seg, "mirror");
@ -130,6 +130,7 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
int mirror_status = MIRR_RUNNING;
int areas = seg->area_count;
int start_area = 0u;
uint32_t region_size, region_max;
if (!*target_state)
*target_state = _init_target(mem, cft);
@ -143,7 +144,7 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
if (seg->extents_copied == seg->area_len) {
mirror_status = MIRR_COMPLETED;
start_area = 1;
} else if (*pvmove_mirror_count++) {
} else if ((*pvmove_mirror_count)++) {
mirror_status = MIRR_DISABLED;
areas = 1;
}
@ -153,8 +154,20 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
*target = "linear";
} else {
*target = "mirror";
/* Find largest power of 2 region size unit we can use */
region_max = (1 << (ffs(seg->area_len) - 1)) *
seg->lv->vg->extent_size;
region_size = mirr_state->region_size;
if (region_max < region_size) {
region_size = region_max;
log_verbose("Using reduced mirror region size of %u sectors",
region_size);
}
if ((*pos = lvm_snprintf(params, paramsize, "core 1 %u %u ",
mirr_state->region_size, areas)) < 0) {
region_size, areas)) < 0) {
stack;
return -1;
}
@ -162,7 +175,6 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
return compose_areas_line(dm, seg, params, paramsize, pos, start_area,
areas);
}
static int _target_percent(void **target_state, struct pool *mem,
@ -188,8 +200,7 @@ static int _target_percent(void **target_state, struct pool *mem,
*total_denominator += denominator;
if (seg)
seg->extents_copied = mirr_state->region_size *
numerator / seg->lv->vg->extent_size;
seg->extents_copied = seg->area_len * numerator / denominator;
return 1;
}

View File

@ -123,7 +123,7 @@ static struct list *_get_allocatable_pvs(struct cmd_context *cmd, int argc,
/* Create new LV with mirror segments for the required copies */
static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
struct volume_group *vg,
struct physical_volume *pv,
struct list *source_pvl,
const char *lv_name,
struct list *allocatable_pvs,
struct list **lvs_changed)
@ -165,7 +165,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
log_print("Skipping locked LV %s", lv->name);
continue;
}
if (!insert_pvmove_mirrors(cmd, lv_mirr, pv, lv,
if (!insert_pvmove_mirrors(cmd, lv_mirr, source_pvl, lv,
allocatable_pvs, *lvs_changed)) {
stack;
return NULL;
@ -248,13 +248,19 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
int argc, char **argv)
{
const char *lv_name = NULL;
char *pv_name_arg;
struct volume_group *vg;
struct list *source_pvl;
struct list *allocatable_pvs;
struct list *lvs_changed;
struct physical_volume *pv;
struct logical_volume *lv_mirr;
int first_time = 1;
pv_name_arg = argv[0];
argc--;
argv++;
/* Find PV (in VG) */
if (!(pv = find_pv_by_name(cmd, pv_name))) {
stack;
@ -299,6 +305,13 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
first_time = 0;
} else {
/* Determine PE ranges to be moved */
if (!(source_pvl = create_pv_list(cmd->mem, vg, 1,
&pv_name_arg, 0))) {
stack;
unlock_vg(cmd, pv->vg_name);
return ECMD_FAILED;
}
/* Get PVs we can use for allocation */
if (!(allocatable_pvs = _get_allocatable_pvs(cmd, argc, argv,
@ -314,7 +327,7 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
return ECMD_FAILED;
}
if (!(lv_mirr = _set_up_pvmove_lv(cmd, vg, pv, lv_name,
if (!(lv_mirr = _set_up_pvmove_lv(cmd, vg, source_pvl, lv_name,
allocatable_pvs,
&lvs_changed))) {
stack;
@ -459,12 +472,21 @@ int pvmove_poll(struct cmd_context *cmd, const char *pv_name,
int pvmove(struct cmd_context *cmd, int argc, char **argv)
{
char *pv_name = NULL;
char *colon;
int ret;
if (argc) {
pv_name = argv[0];
argc--;
argv++;
/* Drop any PE lists from PV name */
if ((colon = strchr(pv_name, ':'))) {
if (!(pv_name = pool_strndup(cmd->mem, pv_name,
(unsigned) (colon -
pv_name)))) {
log_error("Failed to clone PV name");
return 0;
}
}
if (!arg_count(cmd, abort_ARG) &&
(ret = _set_up_pvmove(cmd, pv_name, argc, argv)) !=
@ -472,6 +494,7 @@ int pvmove(struct cmd_context *cmd, int argc, char **argv)
stack;
return ret;
}
}
return pvmove_poll(cmd, pv_name,