1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-22 17:35:59 +03:00

Various allocation-related pvmove fixes.

This commit is contained in:
Alasdair Kergon 2005-06-14 17:54:48 +00:00
parent ca4e0c973a
commit 39fbb844f9
17 changed files with 197 additions and 52 deletions

View File

@ -1,10 +1,12 @@
Version 2.01.12 -
================================
Various allocation-related pvmove fixes.
Log an error if clvmd can't resolve a host name got from CCS
Fix potential spin loop in clvmd
Version 2.01.11 - 13th June 2005
================================
Added lvmconf.sh.
Use matchpathcon mode parameter.
Don't defer closing dead FDs in clvmd.
Remove hard-coded 64k text metadata writing restriction.

View File

@ -803,7 +803,7 @@ int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
(seg_pv(seg, s)->pe_start +
(esize * seg_pe(seg, s))),
trailing_space);
else {
else if (seg_type(seg, s) == AREA_LV) {
if (!(dl = hash_lookup(dm->layers,
seg_lv(seg, s)->lvid.s))) {
log_error("device layer %s missing from hash",
@ -822,6 +822,10 @@ int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
"%s %" PRIu64 "%s", devbuf,
esize * seg_le(seg, s),
trailing_space);
} else {
log_error("Internal error: Unassigned area found in LV %s.",
seg->lv);
return 0;
}
if (tw < 0) {
@ -1243,6 +1247,7 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
/* Add dependencies for any LVs that segments refer to */
list_iterate_items(seg, &lv->segments) {
// When do we need? _set_flag(dl, REMOVE) on the log?
if (seg->log_lv &&
!str_list_add(dm->mem, &dl->pre_create,
_build_dlid(dm->mem, seg->log_lv->lvid.s,
@ -1250,7 +1255,6 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
stack;
return 0;
}
// FIXME Check we don't want NOPROPAGATE here
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) != AREA_LV)
@ -1262,7 +1266,10 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
stack;
return 0;
}
// ? if (seg_lv(seg, s)->status & PVMOVE)
_set_flag(dl, NOPROPAGATE);
// When do we need? _set_flag(dl, REMOVE)
}
}

View File

@ -247,6 +247,8 @@ static int _insert_dev(const char *path, dev_t d)
/* Generate pretend device numbers for loopfiles */
if (!d) {
if (hash_lookup(_cache.names, path))
return 1;
d = ++loopfile_count;
loopfile = 1;
}
@ -627,6 +629,10 @@ struct device *dev_cache_get(const char *name, struct dev_filter *f)
if (!d) {
_insert(name, 0);
d = (struct device *) hash_lookup(_cache.names, name);
if (!d) {
_full_scan(0);
d = (struct device *) hash_lookup(_cache.names, name);
}
}
return (d && (!f || (d->flags & DEV_REGULAR) ||

View File

@ -471,7 +471,9 @@ void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
log_print("%sLogical extents\t%d to %d", pre,
seg_le(seg, s),
seg_le(seg, s) + seg->area_len - 1);
break;
case AREA_UNASSIGNED:
log_print("%sUnassigned area", pre);
}
}

View File

@ -395,7 +395,7 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
return 0;
}
if (seg_type(seg, s) != AREA_PV) {
log_error("LV stripe found in LV %s: "
log_error("Non-PV stripe found in LV %s: "
"unsupported by format1", lv->name);
return 0;
}

View File

@ -480,6 +480,9 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
seg_lv(seg, s)->name,
seg_le(seg, s),
(s == seg->area_count - 1) ? "" : ",");
break;
case AREA_UNASSIGNED:
return 0;
}
}

View File

@ -364,10 +364,6 @@ int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
stack;
return 0;
}
/*
* Adjust extent counts in the pv and vg.
*/
seg->lv->vg->free_count -= seg->area_len;
} else if ((lv1 = find_lv(seg->lv->vg, cv->v.str))) {
set_lv_segment_area_lv(seg, s, lv1, cv->next->v.i,
flags);

View File

@ -37,6 +37,10 @@ int set_lv_segment_area_pv(struct lv_segment *seg, uint32_t area_num,
void set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num,
struct logical_volume *lv, uint32_t le,
uint32_t flags);
int move_lv_segment_area(struct lv_segment *seg_to, uint32_t area_to,
struct lv_segment *seg_from, uint32_t area_from);
void release_lv_segment_area(struct lv_segment *seg, uint32_t s,
uint32_t area_reduction);
struct alloc_handle;
struct alloc_handle *allocate_extents(struct volume_group *vg,

View File

@ -125,6 +125,74 @@ struct lv_segment *alloc_snapshot_seg(struct logical_volume *lv,
return seg;
}
void release_lv_segment_area(struct lv_segment *seg, uint32_t s,
uint32_t area_reduction)
{
if (seg_type(seg, s) == AREA_UNASSIGNED)
return;
if (seg_type(seg, s) == AREA_PV) {
release_pv_segment(seg_pvseg(seg, s), area_reduction);
return;
}
if (seg_lv(seg, s)->status & MIRROR_IMAGE) {
lv_reduce(seg_lv(seg, s), area_reduction);
return;
}
if (area_reduction == seg->area_len) {
seg_lv(seg, s) = NULL;
seg_le(seg, s) = 0;
seg_type(seg, s) = AREA_UNASSIGNED;
}
}
/*
* Move a segment area from one segment to another
*/
int move_lv_segment_area(struct lv_segment *seg_to, uint32_t area_to,
struct lv_segment *seg_from, uint32_t area_from)
{
struct physical_volume *pv;
struct logical_volume *lv;
uint32_t pe, le;
switch (seg_type(seg_from, area_from)) {
case AREA_PV:
pv = seg_pv(seg_from, area_from);
pe = seg_pe(seg_from, area_from);
release_lv_segment_area(seg_from, area_from,
seg_from->area_len);
release_lv_segment_area(seg_to, area_to, seg_to->area_len);
if (!set_lv_segment_area_pv(seg_to, area_to, pv, pe)) {
stack;
return 0;
}
break;
case AREA_LV:
lv = seg_lv(seg_from, area_from);
le = seg_le(seg_from, area_from);
release_lv_segment_area(seg_from, area_from,
seg_from->area_len);
release_lv_segment_area(seg_to, area_to, seg_to->area_len);
set_lv_segment_area_lv(seg_to, area_to, lv, le, 0);
break;
case AREA_UNASSIGNED:
release_lv_segment_area(seg_to, area_to, seg_to->area_len);
}
return 1;
}
/*
* Link part of a PV to an LV segment.
*/
@ -132,7 +200,6 @@ int set_lv_segment_area_pv(struct lv_segment *seg, uint32_t area_num,
struct physical_volume *pv, uint32_t pe)
{
seg->area[area_num].type = AREA_PV;
pv->pe_alloc_count += seg->area_len;
if (!(seg_pvseg(seg, area_num) =
assign_peg_to_lvseg(pv, pe, seg->area_len, seg, area_num))) {
@ -175,24 +242,19 @@ static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction)
} else
area_reduction = reduction;
for (s = 0; s < seg->area_count; s++)
release_lv_segment_area(seg, s, area_reduction);
seg->len -= reduction;
seg->area_len -= area_reduction;
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) == AREA_PV) {
release_pv_segment(seg_pvseg(seg, s), area_reduction);
seg->lv->vg->free_count += area_reduction;
} else if (seg_lv(seg, s)->status & MIRROR_IMAGE)
lv_reduce(seg_lv(seg, s), area_reduction);
}
return 1;
}
/*
* Entry point for all LV reductions in size.
*/
int lv_reduce(struct logical_volume *lv, uint32_t extents)
static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
{
struct lv_list *lvl;
struct lv_segment *seg;
@ -225,6 +287,9 @@ int lv_reduce(struct logical_volume *lv, uint32_t extents)
lv->le_count -= extents;
lv->size = (uint64_t) lv->le_count * lv->vg->extent_size;
if (!delete)
return 1;
/* Remove the LV if it is now empty */
if (!lv->le_count) {
if (!(lvl = find_lv_in_vg(lv->vg, lv->name))) {
@ -244,6 +309,19 @@ int lv_reduce(struct logical_volume *lv, uint32_t extents)
return 1;
}
/*
* Empty an LV
*/
int lv_empty(struct logical_volume *lv)
{
return _lv_reduce(lv, 0, lv->le_count);
}
int lv_reduce(struct logical_volume *lv, uint32_t extents)
{
return _lv_reduce(lv, extents, 1);
}
/*
* Completely remove an LV.
*/
@ -406,8 +484,6 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint32_t status,
lv->le_count += extents;
lv->size += (uint64_t) extents *lv->vg->extent_size;
lv->vg->free_count -= aa[0].len * area_count;
if (segtype_is_mirrored(segtype))
lv->status |= MIRRORED;
@ -624,8 +700,8 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
/* Only allocate log_area the first time around */
if (ix + ix_offset < ah->area_count +
(ah->log_count && !ah->log_area.len) ?
ah->log_count : 0)
((ah->log_count && !ah->log_area.len) ?
ah->log_count : 0))
/* FIXME With ALLOC_ANYWHERE, need to split areas */
break;
@ -912,8 +988,6 @@ int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv)
log_lv->le_count += ah->log_area.len;
log_lv->size += (uint64_t) log_lv->le_count *log_lv->vg->extent_size;
log_lv->vg->free_count--;
if (log_lv->vg->fid->fmt->ops->lv_setup &&
!log_lv->vg->fid->fmt->ops->lv_setup(log_lv->vg->fid, log_lv)) {
stack;

View File

@ -86,7 +86,12 @@ int check_lv_segments(struct logical_volume *lv)
}
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) == AREA_PV) {
if (seg_type(seg, s) == AREA_UNASSIGNED) {
log_error("LV %s: segment %u has unassigned "
"area %u.",
lv->name, seg_count, s);
r = 0;
} else if (seg_type(seg, s) == AREA_PV) {
if (!seg_pvseg(seg, s) ||
seg_pvseg(seg, s)->lvseg != seg ||
seg_pvseg(seg, s)->lv_area != s) {
@ -104,6 +109,7 @@ int check_lv_segments(struct logical_volume *lv)
lv->name, seg_count, s);
r = 0;
}
/* FIXME I don't think this ever holds?
if (seg_le(seg, s) != le) {
log_error("LV %s: segment %u has "
"inconsistent LV area %u "
@ -111,6 +117,7 @@ int check_lv_segments(struct logical_volume *lv)
lv->name, seg_count, s);
r = 0;
}
*/
}
}
@ -205,9 +212,8 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
seg_pe(split_seg, s));
break;
default:
log_error("Unrecognised segment type %u",
seg_type(seg, s));
case AREA_UNASSIGNED:
log_error("Unassigned area %u found in segment", s);
return 0;
}
}

View File

@ -465,9 +465,9 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
return 0;
}
break;
default:
log_error("Unrecognised segment type "
"%u", seg_type(seg, s));
case AREA_UNASSIGNED:
log_error("Unassigned area %u found in "
"segment", s);
return 0;
}
}
@ -1045,7 +1045,27 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
int *consistent)
{
return _vg_read(cmd, vgname, consistent, 0);
struct volume_group *vg;
struct lv_list *lvl;
if (!(vg = _vg_read(cmd, vgname, consistent, 0)))
return NULL;
if (!check_pv_segments(vg)) {
log_error("Internal error: PV segments corrupted in %s.",
vg->name);
return NULL;
}
list_iterate_items(lvl, &vg->lvs) {
if (!check_lv_segments(lvl->lv)) {
log_error("Internal error: LV segments corrupted in %s.",
lvl->lv->name);
return NULL;
}
}
return vg;
}
struct volume_group *vg_read_precommitted(struct cmd_context *cmd,

View File

@ -81,6 +81,7 @@ typedef enum {
} alloc_policy_t;
typedef enum {
AREA_UNASSIGNED = 0,
AREA_PV,
AREA_LV
} area_type_t;
@ -443,9 +444,12 @@ struct logical_volume *lv_create_empty(struct format_instance *fi,
int import,
struct volume_group *vg);
/* Entry point for all LV extent reductions */
/* Reduce the size of an LV by extents */
int lv_reduce(struct logical_volume *lv, uint32_t extents);
/* Empty an LV prior to deleting it */
int lv_empty(struct logical_volume *lv);
/* Entry point for all LV extent allocations */
int lv_extend(struct logical_volume *lv,
struct segment_type *segtype,

View File

@ -171,6 +171,8 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
struct lv_segment *seg;
struct lv_list *lvl;
struct pv_list *pvl;
struct physical_volume *pv;
uint32_t pe;
int lv_used = 0;
uint32_t s, start_le, extent_count = 0u;
struct segment_type *segtype;
@ -270,18 +272,19 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
lv_used = 1;
}
pv = seg_pv(seg, s);
pe = seg_pe(seg, s);
log_very_verbose("Moving %s:%u-%u of %s/%s",
dev_name(pvl->pv->dev),
seg_pe(seg, s),
seg_pe(seg, s) +
seg->area_len - 1,
pe, pe + seg->area_len - 1,
lv->vg->name, lv->name);
start_le = lv_mirr->le_count;
/* FIXME Clean this up */
release_lv_segment_area(seg, s, seg->area_len);
if (!lv_extend(lv_mirr, segtype, 1,
seg->area_len, 0u, seg->area_len,
seg_pv(seg, s),
seg_pe(seg, s),
pv, pe,
PVMOVE, allocatable_pvs,
alloc)) {
log_error("Unable to allocate "
@ -355,22 +358,22 @@ int remove_pvmove_mirrors(struct volume_group *vg,
else
c = 0;
if (!set_lv_segment_area_pv(seg, s,
seg_pv(mir_seg, c),
seg_pe(mir_seg, c))) {
if (!move_lv_segment_area(seg, s, mir_seg, c)) {
stack;
return 0;
}
/* Replace mirror with old area */
release_lv_segment_area(mir_seg, !c, mir_seg->area_len);
/* Replace mirror with error segment */
if (!
(mir_seg->segtype =
get_segtype_from_string(vg->cmd,
"striped"))) {
log_error("Missing striped segtype");
"error"))) {
log_error("Missing error segtype");
return 0;
}
mir_seg->area_count = 1;
mir_seg->area_count = 0;
/* FIXME Assumes only one pvmove at a time! */
lv1->status &= ~LOCKED;
@ -381,6 +384,10 @@ int remove_pvmove_mirrors(struct volume_group *vg,
}
if (!lv_empty(lv_mirr)) {
stack;
return 0;
}
return 1;
}
@ -392,7 +399,7 @@ const char *get_pvmove_pvname_from_lv_mirr(struct logical_volume *lv_mirr)
list_iterate_items(seg, &lv_mirr->segments) {
if (!seg_is_mirrored(seg))
continue;
if (seg->area[0].type != AREA_PV)
if (seg_type(seg, 0) != AREA_PV)
continue;
return dev_name(seg_dev(seg, 0));
}
@ -433,7 +440,7 @@ struct logical_volume *find_pvmove_lv(struct volume_group *vg,
/* Check segment origins point to pvname */
list_iterate_items(seg, &lv->segments) {
if (seg->area[0].type != AREA_PV)
if (seg_type(seg, 0) != AREA_PV)
continue;
if (seg_dev(seg, 0) != dev)
continue;

View File

@ -162,14 +162,18 @@ struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv,
peg->lvseg = seg;
peg->lv_area = area_num;
peg->pv->pe_alloc_count += area_len;
peg->lvseg->lv->vg->free_count -= area_len;
return peg;
}
int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction)
{
peg->pv->pe_alloc_count -= area_reduction;
peg->lvseg->lv->vg->free_count += area_reduction;
if (!peg->lvseg->area_len) {
if (peg->lvseg->area_len == area_reduction) {
peg->lvseg = NULL;
peg->lv_area = 0;
@ -178,7 +182,8 @@ int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction)
return 1;
}
if (!pv_split_segment(peg->pv, peg->pe + peg->lvseg->area_len)) {
if (!pv_split_segment(peg->pv, peg->pe + peg->lvseg->area_len -
area_reduction)) {
stack;
return 0;
}

View File

@ -163,8 +163,8 @@ static int _devices_disp(struct report_handle *rh, struct field *field,
name = dev_name(seg_dev(seg, s));
extent = seg_pe(seg, s);
break;
default:
name = "unknown";
case AREA_UNASSIGNED:
name = "unassigned";
extent = 0;
}

View File

@ -115,7 +115,8 @@ static int _segments_compatible(struct lv_segment *first,
/* FIXME Relax this to first area type != second area type */
/* plus the additional AREA_LV checks needed */
if ((first->area[s].type != AREA_PV) ||
(second->area[s].type != AREA_PV)) return 0;
(second->area[s].type != AREA_PV))
return 0;
width = first->area_len;

View File

@ -170,6 +170,14 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
log_print("Skipping mirror LV %s", lv->name);
continue;
}
if (lv->status & MIRROR_LOG) {
log_print("Skipping mirror log LV %s", lv->name);
continue;
}
if (lv->status & MIRROR_IMAGE) {
log_print("Skipping mirror image LV %s", lv->name);
continue;
}
if (lv->status & LOCKED) {
log_print("Skipping locked LV %s", lv->name);
continue;