"using dm %s", pvid,
dev_name(existing->dev),
dev_name(dev));
+ /* FIXME If both dm, check dependencies */
+ //else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
+ //dm_is_dm_major(MAJOR(dev->dev)))
+ //
else
log_error("Found duplicate PV %s: using %s not "
"%s", pvid, dev_name(dev),
/*
* Check there are no gaps or overlaps in the lv.
*/
- if (!check_lv_segments(lv)) {
+ if (!check_lv_segments(lv, 0)) {
stack;
return 0;
}
goto bad;
}
+ if (!fixup_imported_mirrors(vg)) {
+ log_error("Failed to fixup mirror pointers after import for "
+ "volume group %s.", vg->name);
+ goto bad;
+ }
+
dm_hash_destroy(pv_hash);
if (vg->status & PARTIAL_VG) {
area_multiple = segtype_is_striped(segtype) ? area_count : 1;
- /* FIXME Shouldn't log_lv always be NULL here? */
- /* (As we set up log segments elsewhere) */
-
+ /* log_lv gets set up elsehere */
if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, segtype, lv,
lv->le_count,
aa[0].len * area_multiple,
- status, stripe_size, log_lv,
+ status, stripe_size, NULL,
area_count + extra_areas,
aa[0].len, 0u, region_size, 0u))) {
log_error("Couldn't allocate new LV segment.");
/*
* Verify that an LV's segments are consecutive, complete and don't overlap.
*/
-int check_lv_segments(struct logical_volume *lv)
+int check_lv_segments(struct logical_volume *lv, int complete_vg)
{
- struct lv_segment *seg;
+ struct lv_segment *seg, *seg2;
uint32_t le = 0;
unsigned seg_count = 0;
int r = 1;
r = 0;
}
- if (seg->log_lv) {
+ if (complete_vg && seg->log_lv) {
if (!seg_is_mirrored(seg)) {
log_error("LV %s: segment %u has log LV but "
"is not mirrored",
r = 0;
}
- if (!find_seg_by_le(seg->log_lv, 0) ||
- find_seg_by_le(seg->log_lv, 0)->mirror_seg != seg) {
+ if (!(seg2 = find_seg_by_le(seg->log_lv, 0)) ||
+ seg2->mirror_seg != seg) {
log_error("LV %s: segment %u log LV does not "
"point back to mirror segment",
lv->name, seg_count);
}
}
- if (seg->status & MIRROR_IMAGE) {
+ if (complete_vg && seg->status & MIRROR_IMAGE) {
if (!seg->mirror_seg ||
!seg_is_mirrored(seg->mirror_seg)) {
log_error("LV %s: segment %u mirror image "
r = 0;
}
- if (seg_lv(seg, s) &&
+ if (complete_vg && seg_lv(seg, s) &&
(seg_lv(seg, s)->status & MIRROR_IMAGE) &&
(find_seg_by_le(seg_lv(seg, s),
seg_le(seg, s))->mirror_seg
}
list_iterate_items(lvl, &vg->lvs) {
- if (!check_lv_segments(lvl->lv)) {
+ if (!check_lv_segments(lvl->lv, 1)) {
log_error("Internal error: LV segments corrupted in %s.",
lvl->lv->name);
return 0;
}
list_iterate_items(lvl, &vg->lvs) {
- if (!check_lv_segments(lvl->lv)) {
+ if (!check_lv_segments(lvl->lv, 1)) {
log_error("Internal error: LV segments corrupted in %s.",
lvl->lv->name);
return NULL;
/*
* Checks that an lv has no gaps or overlapping segments.
+ * Set complete_vg to perform additional VG level checks.
*/
-int check_lv_segments(struct logical_volume *lv);
+int check_lv_segments(struct logical_volume *lv, int complete_vg);
/*
* Sometimes (eg, after an lvextend), it is possible to merge two
* Given mirror image or mirror log segment, find corresponding mirror segment
*/
struct lv_segment *find_mirror_seg(struct lv_segment *seg);
+int fixup_imported_mirrors(struct volume_group *vg);
int insert_pvmove_mirrors(struct cmd_context *cmd,
struct logical_volume *lv_mirr,
return denominator ? (float) numerator *100 / denominator : 100.0;
}
+
+/*
+ * Fixup mirror pointers after single-pass segment import
+ */
+int fixup_imported_mirrors(struct volume_group *vg)
+{
+ struct lv_list *lvl;
+ struct lv_segment *seg;
+ uint32_t s;
+
+ list_iterate_items(lvl, &vg->lvs) {
+ list_iterate_items(seg, &lvl->lv->segments) {
+ if (seg->segtype !=
+ get_segtype_from_string(vg->cmd, "mirror"))
+ continue;
+
+ if (seg->log_lv)
+ find_seg_by_le(seg->log_lv, 0)->mirror_seg = seg;
+ for (s = 0; s < seg->area_count; s++)
+ if (seg_type(seg, s) == AREA_LV)
+ find_seg_by_le(seg_lv(seg, s), 0)->
+ mirror_seg = seg;
+ }
+ }
+}
+