diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c index 8b51a49f9..af3217cf6 100644 --- a/lib/metadata/merge.c +++ b/lib/metadata/merge.c @@ -8,36 +8,51 @@ #include "metadata.h" /* - * Returns success if the segments were - * successfully merged. If the do merge, 'first' - * will be adjusted to contain both areas. + * Test whether two segments could be merged by the current merging code */ -static int _merge(struct lv_segment *first, struct lv_segment *second) +static int _segments_compatible(struct lv_segment *first, + struct lv_segment *second) { - unsigned int s; uint32_t width; + unsigned s; - if (!first || - (first->type != SEG_STRIPED) || - (first->type != second->type) || + /* FIXME Relax the seg type restriction */ + if (!first || !second || + (first->type != SEG_STRIPED) || (second->type != first->type) || (first->area_count != second->area_count) || (first->stripe_size != second->stripe_size)) return 0; for (s = 0; s < first->area_count; s++) { - width = first->area_len; - /* FIXME Relax this to first type != second type ? */ - if (first->area[s].type != AREA_PV || - second->area[s].type != AREA_PV) + /* 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; + width = first->area_len; + if ((first->area[s].u.pv.pv != second->area[s].u.pv.pv) || (first->area[s].u.pv.pe + width != second->area[s].u.pv.pe)) return 0; } - /* we should merge */ + return 1; +} + +/* + * Attempt to merge two adjacent segments. + * Currently only supports SEG_STRIPED on AREA_PV. + * Returns success if successful, in which case 'first' + * gets adjusted to contain both areas. + */ +static int _merge(struct lv_segment *first, struct lv_segment *second) +{ + + if (!_segments_compatible(first, second)) + return 0; + first->len += second->len; first->area_len += second->area_len; @@ -61,7 +76,27 @@ int lv_merge_segments(struct logical_volume *lv) return 1; } +/* + * Verify that an LV's segments are consecutive, complete and don't overlap. + */ int lv_check_segments(struct logical_volume *lv) { + struct lv_segment *seg; + uint32_t le = 0; + unsigned seg_count = 0; + + list_iterate_items(seg, &lv->segments) { + seg_count++; + if (seg->le != le) { + log_error("LV %s invalid: segment %u should begin at " + "LE %" PRIu32 " (found %" PRIu32 ").", + lv->name, seg_count, le, seg->le); + return 0; + } + + le += seg->len; + } + return 1; } +