/* * Test whether two segments could be merged by the current merging code */ static int _striped_segments_compatible(struct lv_segment *first, struct lv_segment *second) { uint32_t width; unsigned s; if ((first->area_count != second->area_count) || (first->stripe_size != second->stripe_size)) return 0; for (s = 0; s < first->area_count; s++) { /* FIXME Relax this to first area type != second area type */ /* plus the additional AREA_LV checks needed */ if ((seg_type(first, s) != AREA_PV) || (seg_type(second, s) != AREA_PV)) return 0; width = first->area_len; if ((seg_pv(first, s) != seg_pv(second, s)) || (seg_pe(first, s) + width != seg_pe(second, s))) return 0; } if (!str_list_lists_equal(&first->tags, &second->tags)) return 0; return 1; }
static int _detach_pvmove_mirror(struct cmd_context *cmd, struct logical_volume *lv_mirr) { uint32_t mimage_to_remove = 0; struct dm_list lvs_completed; struct lv_list *lvl; /* Update metadata to remove mirror segments and break dependencies */ dm_list_init(&lvs_completed); if (arg_is_set(cmd, abort_ARG) && (seg_type(first_seg(lv_mirr), 0) == AREA_LV)) mimage_to_remove = 1; /* remove the second mirror leg */ if (!lv_remove_mirrors(cmd, lv_mirr, 1, 0, _is_pvmove_image_removable, &mimage_to_remove, PVMOVE) || !remove_layers_for_segments_all(cmd, lv_mirr, PVMOVE, &lvs_completed)) { return 0; } dm_list_iterate_items(lvl, &lvs_completed) /* FIXME Assumes only one pvmove at a time! */ lvl->lv->status &= ~LOCKED; return 1; }
static int _is_pvmove_image_removable(struct logical_volume *mimage_lv, void *baton) { uint32_t mimage_to_remove = *((uint32_t *)baton); struct lv_segment *mirror_seg; if (!(mirror_seg = get_only_segment_using_this_lv(mimage_lv))) { log_error(INTERNAL_ERROR "%s is not a proper mirror image", mimage_lv->name); return 0; } if (seg_type(mirror_seg, 0) != AREA_LV) { log_error(INTERNAL_ERROR "%s is not a pvmove mirror of LV-type", mirror_seg->lv->name); return 0; } if (mimage_to_remove > mirror_seg->area_count) { log_error(INTERNAL_ERROR "Mirror image %" PRIu32 " not found in segment", mimage_to_remove); return 0; } if (seg_lv(mirror_seg, mimage_to_remove) == mimage_lv) return 1; return 0; }
static int _is_converting(struct logical_volume *lv) { struct lv_segment *seg; if (lv->status & MIRRORED) { seg = first_seg(lv); /* Can't use is_temporary_mirror() because the metadata for * seg_lv may not be read in and flags may not be set yet. */ if (seg_type(seg, 0) == AREA_LV && strstr(seg_lv(seg, 0)->name, MIRROR_SYNC_LAYER)) return 1; } return 0; }
static int _striped_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2) { uint32_t s; if (!_striped_segments_compatible(seg1, seg2)) return 0; seg1->len += seg2->len; seg1->area_len += seg2->area_len; for (s = 0; s < seg1->area_count; s++) if (seg_type(seg1, s) == AREA_PV) merge_pv_segments(seg_pvseg(seg1, s), seg_pvseg(seg2, s)); return 1; }
/* * Check all pv_segments in VG for consistency */ int check_pv_segments(struct volume_group *vg) { struct physical_volume *pv; struct pv_list *pvl; struct pv_segment *peg; unsigned s, segno; uint32_t start_pe, alloced; uint32_t pv_count = 0, free_count = 0, extent_count = 0; int ret = 1; //list_iterate_items(pvl, &vg->pvs) { list_iterate_items(pvl, struct pv_list, &vg->pvs) { pv = pvl->pv; segno = 0; start_pe = 0; alloced = 0; pv_count++; //list_iterate_items(peg, &pv->segments) { list_iterate_items(peg, struct pv_segment, &pv->segments) { s = peg->lv_area; /* FIXME Remove this next line eventually */ log_debug("%s %u: %6u %6u: %s(%u:%u)", dev_name(pv->dev), segno++, peg->pe, peg->len, peg->lvseg ? peg->lvseg->lv->name : "NULL", peg->lvseg ? peg->lvseg->le : 0, s); /* FIXME Add details here on failure instead */ if (start_pe != peg->pe) { log_error("Gap in pvsegs: %u, %u", start_pe, peg->pe); ret = 0; } if (peg->lvseg) { if (seg_type(peg->lvseg, s) != AREA_PV) { log_error("Wrong lvseg area type"); ret = 0; } if (seg_pvseg(peg->lvseg, s) != peg) { log_error("Inconsistent pvseg pointers"); ret = 0; } if (peg->lvseg->area_len != peg->len) { log_error("Inconsistent length: %u %u", peg->len, peg->lvseg->area_len); ret = 0; } alloced += peg->len; } start_pe += peg->len; } if (start_pe != pv->pe_count) { log_error("PV segment pe_count mismatch: %u != %u", start_pe, pv->pe_count); ret = 0; } if (alloced != pv->pe_alloc_count) { log_error("PV segment pe_alloc_count mismatch: " "%u != %u", alloced, pv->pe_alloc_count); ret = 0; } extent_count += start_pe; free_count += (start_pe - alloced); } if (pv_count != vg->pv_count) { log_error("PV segment VG pv_count mismatch: %u != %u", pv_count, vg->pv_count); ret = 0; } if (free_count != vg->free_count) { log_error("PV segment VG free_count mismatch: %u != %u", free_count, vg->free_count); ret = 0; } if (extent_count != vg->extent_count) { log_error("PV segment VG extent_count mismatch: %u != %u", extent_count, vg->extent_count); ret = 0; } return ret; }