diff --git a/WHATS_NEW b/WHATS_NEW index ac31cf7d9..027d2368e 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,7 @@ Version 2.01.13 - ================================ + Fix pvmove segment splitting. + Abstract vg_validate. Only make one attempt at contiguous allocation. Fix lvm1 format metadata read. Fix lvm1 format non-mirror lvcreate. diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c index c2d5d009d..0e0c6d544 100644 --- a/lib/metadata/merge.c +++ b/lib/metadata/merge.c @@ -197,12 +197,13 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg, break; case AREA_PV: - if (!assign_peg_to_lvseg(seg_pv(seg, s), + if (!(seg_pvseg(split_seg, s) = + assign_peg_to_lvseg(seg_pv(seg, s), seg_pe(seg, s) + seg->area_len, seg_pvseg(seg, s)->len - seg->area_len, - split_seg, s)) { + split_seg, s))) { stack; return 0; } @@ -246,5 +247,10 @@ int lv_split_segment(struct logical_volume *lv, uint32_t le) return 0; } + if (!vg_validate(lv->vg)) { + stack; + return 0; + } + return 1; } diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 9377e9808..5e0e6d098 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -697,14 +697,8 @@ int vg_remove(struct volume_group *vg) return 1; } -/* - * After vg_write() returns success, - * caller MUST call either vg_commit() or vg_revert() - */ -int vg_write(struct volume_group *vg) +int vg_validate(struct volume_group *vg) { - struct list *mdah; - struct metadata_area *mda; struct lv_list *lvl; if (!check_pv_segments(vg)) { @@ -721,6 +715,23 @@ int vg_write(struct volume_group *vg) } } + return 1; +} + +/* + * After vg_write() returns success, + * caller MUST call either vg_commit() or vg_revert() + */ +int vg_write(struct volume_group *vg) +{ + struct list *mdah; + struct metadata_area *mda; + + if (!vg_validate(vg)) { + stack; + return 0; + } + if (vg->status & PARTIAL_VG) { log_error("Cannot change metadata for partial volume group %s", vg->name); diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index 280f2e442..e0ca234fd 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -391,6 +391,7 @@ struct format_handler { /* * Utility functions */ +int vg_validate(struct volume_group *vg); int vg_write(struct volume_group *vg); int vg_commit(struct volume_group *vg); int vg_revert(struct volume_group *vg); @@ -538,7 +539,6 @@ int vg_add_snapshot(struct format_instance *fid, const char *name, int vg_remove_snapshot(struct logical_volume *cow); - /* * Mirroring functions */ diff --git a/lib/metadata/pv_manip.c b/lib/metadata/pv_manip.c index dd0c1423b..76af8e384 100644 --- a/lib/metadata/pv_manip.c +++ b/lib/metadata/pv_manip.c @@ -100,6 +100,11 @@ static int _pv_split_segment(struct physical_volume *pv, struct pv_segment *peg, list_add_h(&peg->list, &peg_new->list); + if (peg->lvseg) { + peg->pv->pe_alloc_count -= peg_new->len; + peg->lvseg->lv->vg->free_count += peg_new->len; + } + return 1; } @@ -170,10 +175,16 @@ struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv, 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) { + log_error("release_pv_segment with unallocated segment: " + "%s PE %" PRIu32, dev_name(peg->pv->dev), peg->pe); + return 0; + } if (peg->lvseg->area_len == area_reduction) { + peg->pv->pe_alloc_count -= area_reduction; + peg->lvseg->lv->vg->free_count += area_reduction; + peg->lvseg = NULL; peg->lv_area = 0;