mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-03 05:18:29 +03:00
Additional validation of LV segments read from metadata. [HM]
This commit is contained in:
parent
8fd3c219fd
commit
f1e6be4be1
@ -8,36 +8,51 @@
|
|||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns success if the segments were
|
* Test whether two segments could be merged by the current merging code
|
||||||
* successfully merged. If the do merge, 'first'
|
|
||||||
* will be adjusted to contain both areas.
|
|
||||||
*/
|
*/
|
||||||
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;
|
uint32_t width;
|
||||||
|
unsigned s;
|
||||||
|
|
||||||
if (!first ||
|
/* FIXME Relax the seg type restriction */
|
||||||
(first->type != SEG_STRIPED) ||
|
if (!first || !second ||
|
||||||
(first->type != second->type) ||
|
(first->type != SEG_STRIPED) || (second->type != first->type) ||
|
||||||
(first->area_count != second->area_count) ||
|
(first->area_count != second->area_count) ||
|
||||||
(first->stripe_size != second->stripe_size))
|
(first->stripe_size != second->stripe_size))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (s = 0; s < first->area_count; s++) {
|
for (s = 0; s < first->area_count; s++) {
|
||||||
width = first->area_len;
|
|
||||||
|
|
||||||
/* FIXME Relax this to first type != second type ? */
|
/* FIXME Relax this to first area type != second area type */
|
||||||
if (first->area[s].type != AREA_PV ||
|
/* plus the additional AREA_LV checks needed */
|
||||||
second->area[s].type != AREA_PV)
|
if ((first->area[s].type != AREA_PV) ||
|
||||||
|
(second->area[s].type != AREA_PV))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
width = first->area_len;
|
||||||
|
|
||||||
if ((first->area[s].u.pv.pv != second->area[s].u.pv.pv) ||
|
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))
|
(first->area[s].u.pv.pe + width != second->area[s].u.pv.pe))
|
||||||
return 0;
|
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->len += second->len;
|
||||||
first->area_len += second->area_len;
|
first->area_len += second->area_len;
|
||||||
|
|
||||||
@ -61,7 +76,27 @@ int lv_merge_segments(struct logical_volume *lv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify that an LV's segments are consecutive, complete and don't overlap.
|
||||||
|
*/
|
||||||
int lv_check_segments(struct logical_volume *lv)
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user