1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

check_lv_segment: split into incomplete complete

Split single check_lv_segments() into 2 separate
versions so they can be called independently.
This allow to 'skip' already checked segment
check after it's been imported to VG and also
avoid another repeated checking when validating
segment with complete vg.

**
check_lv_segments_incomplete_vg()

this check just basic LV segment properties and does not
validate those requiring full VG.

**
check_lv_segments_complete_vg()

Remaining check that expects complete VG is present.
This commit is contained in:
Zdenek Kabelac 2024-10-19 00:05:45 +02:00
parent fa11ef6846
commit 7c5cca600c
4 changed files with 102 additions and 93 deletions

View File

@ -591,7 +591,7 @@ static int _read_segments(struct cmd_context *cmd,
/*
* Check there are no gaps or overlaps in the lv.
*/
if (!check_lv_segments(lv, 0))
if (!check_lv_segments_incomplete_vg(lv))
return_0;
/*

View File

@ -605,14 +605,106 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
}
}
int check_lv_segments_complete_vg(struct logical_volume *lv)
{
struct lv_segment *seg, *seg2;
unsigned seg_count = 0, external_lv_found = 0;
uint32_t s;
struct seg_list *sl;
int error_count = 0;
dm_list_iterate_items(seg, &lv->segments) {
seg_count++;
_check_lv_segment(lv, seg, seg_count, &error_count);
for (s = 0; s < seg->area_count; s++) {
if ((seg_type(seg, s) == AREA_LV) &&
seg_lv(seg, s) &&
lv_is_mirror_image(seg_lv(seg, s)) &&
(!(seg2 = find_seg_by_le(seg_lv(seg, s),
seg_le(seg, s))) ||
find_mirror_seg(seg2) != seg)) {
log_error("LV %s: segment %u mirror "
"image %u missing mirror ptr",
lv->name, seg_count, s);
inc_error_count;
}
}
if (seg_is_mirrored(seg) && !seg_is_raid(seg) &&
seg_type(seg, s) == AREA_LV &&
seg_lv(seg, s)->le_count != seg->area_len) {
log_error("LV %s: mirrored LV segment %u has "
"wrong size %u (should be %u).",
lv->name, s, seg_lv(seg, s)->le_count,
seg->area_len);
inc_error_count;
}
}
/* Check LV flags match first segment type */
if ((seg_count != 1) &&
(lv_is_cache(lv) ||
lv_is_cache_pool(lv) ||
lv_is_raid(lv) ||
lv_is_snapshot(lv) ||
lv_is_thin_pool(lv) ||
lv_is_thin_volume(lv))) {
log_error("LV %s must have exactly one segment.",
lv->name);
inc_error_count;
}
if (lv_is_pool_data(lv) &&
(!(seg2 = first_seg(lv)) || !(seg2 = find_pool_seg(seg2)) ||
seg2->area_count != 1 || seg_type(seg2, 0) != AREA_LV ||
seg_lv(seg2, 0) != lv)) {
log_error("LV %s: segment 1 pool data LV does not point back to same LV",
lv->name);
inc_error_count;
}
if (lv_is_thin_pool_metadata(lv) && !strstr(lv->name, "_tmeta")) {
log_error("LV %s: thin pool metadata LV does not use _tmeta.",
lv->name);
inc_error_count;
} else if (lv_is_cache_pool_metadata(lv) && !strstr(lv->name, "_cmeta")) {
log_error("LV %s: cache pool metadata LV does not use _cmeta.",
lv->name);
inc_error_count;
}
if (lv_is_external_origin(lv)) {
/* Validation of external origin counter */
dm_list_iterate_items(sl, &lv->segs_using_this_lv)
if (sl->seg->external_lv == lv)
external_lv_found++;
if (lv->external_count != external_lv_found) {
log_error("LV %s: external origin count does not match.",
lv->name);
inc_error_count;
}
if (lv->status & LVM_WRITE) {
log_error("LV %s: external origin can't be writable.",
lv->name);
inc_error_count;
}
}
out:
return !error_count;
}
/*
* Verify that an LV's segments are consecutive, complete and don't overlap.
*/
int check_lv_segments(struct logical_volume *lv, int complete_vg)
int check_lv_segments_incomplete_vg(struct logical_volume *lv)
{
struct lv_segment *seg, *seg2;
uint32_t le = 0;
unsigned seg_count = 0, seg_found, external_lv_found = 0;
unsigned seg_count = 0, seg_found;
uint32_t data_rimage_count, s;
struct seg_list *sl;
struct glv_list *glvl;
@ -653,9 +745,6 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
}
}
if (complete_vg)
_check_lv_segment(lv, seg, seg_count, &error_count);
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) == AREA_UNASSIGNED) {
log_error("LV %s: segment %u has unassigned "
@ -681,16 +770,6 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
inc_error_count;
}
if (complete_vg && seg_lv(seg, s) &&
lv_is_mirror_image(seg_lv(seg, s)) &&
(!(seg2 = find_seg_by_le(seg_lv(seg, s),
seg_le(seg, s))) ||
find_mirror_seg(seg2) != seg)) {
log_error("LV %s: segment %u mirror "
"image %u missing mirror ptr",
lv->name, seg_count, s);
inc_error_count;
}
/* FIXME I don't think this ever holds?
if (seg_le(seg, s) != le) {
@ -722,16 +801,6 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
}
}
if (complete_vg &&
seg_is_mirrored(seg) && !seg_is_raid(seg) &&
seg_type(seg, s) == AREA_LV &&
seg_lv(seg, s)->le_count != seg->area_len) {
log_error("LV %s: mirrored LV segment %u has "
"wrong size %u (should be %u).",
lv->name, s, seg_lv(seg, s)->le_count,
seg->area_len);
inc_error_count;
}
}
le += seg->len;
@ -802,10 +871,6 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
lv->name);
inc_error_count;
}
/* Validation of external origin counter */
if (seg->external_lv == lv)
external_lv_found++;
}
dm_list_iterate_items(glvl, &lv->indirect_glvs) {
@ -827,53 +892,6 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
}
}
/* Check LV flags match first segment type */
if (complete_vg) {
if ((seg_count != 1) &&
(lv_is_cache(lv) ||
lv_is_cache_pool(lv) ||
lv_is_raid(lv) ||
lv_is_snapshot(lv) ||
lv_is_thin_pool(lv) ||
lv_is_thin_volume(lv))) {
log_error("LV %s must have exactly one segment.",
lv->name);
inc_error_count;
}
if (lv_is_pool_data(lv) &&
(!(seg2 = first_seg(lv)) || !(seg2 = find_pool_seg(seg2)) ||
seg2->area_count != 1 || seg_type(seg2, 0) != AREA_LV ||
seg_lv(seg2, 0) != lv)) {
log_error("LV %s: segment 1 pool data LV does not point back to same LV",
lv->name);
inc_error_count;
}
if (lv_is_thin_pool_metadata(lv) && !strstr(lv->name, "_tmeta")) {
log_error("LV %s: thin pool metadata LV does not use _tmeta.",
lv->name);
inc_error_count;
} else if (lv_is_cache_pool_metadata(lv) && !strstr(lv->name, "_cmeta")) {
log_error("LV %s: cache pool metadata LV does not use _cmeta.",
lv->name);
inc_error_count;
}
if (lv_is_external_origin(lv)) {
if (lv->external_count != external_lv_found) {
log_error("LV %s: external origin count does not match.",
lv->name);
inc_error_count;
}
if (lv->status & LVM_WRITE) {
log_error("LV %s: external origin can't be writable.",
lv->name);
inc_error_count;
}
}
}
out:
return !error_count;
}

View File

@ -2399,7 +2399,7 @@ int vg_validate(struct volume_group *vg)
}
}
if (!check_lv_segments(lvl->lv, 0)) {
if (!check_lv_segments_incomplete_vg(lvl->lv)) {
log_error(INTERNAL_ERROR "LV segments corrupted in %s.",
lvl->lv->name);
r = 0;
@ -2484,7 +2484,7 @@ int vg_validate(struct volume_group *vg)
r = 0;
}
if (!check_lv_segments(lvl->lv, 1)) {
if (!check_lv_segments_complete_vg(lvl->lv)) {
log_error(INTERNAL_ERROR "LV segments corrupted in %s.",
lvl->lv->name);
r = 0;
@ -5071,17 +5071,9 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, const
goto bad;
}
dm_list_iterate_items(lvl, &vg->lvs) {
if (!check_lv_segments(lvl->lv, 0)) {
log_error(INTERNAL_ERROR "LV segments corrupted in %s.", lvl->lv->name);
failure |= FAILED_INTERNAL_ERROR;
goto bad;
}
}
dm_list_iterate_items(lvl, &vg->lvs) {
/* Checks that cross-reference other LVs. */
if (!check_lv_segments(lvl->lv, 1)) {
if (!check_lv_segments_complete_vg(lvl->lv)) {
log_error(INTERNAL_ERROR "LV segments corrupted in %s.", lvl->lv->name);
failure |= FAILED_INTERNAL_ERROR;
goto bad;

View File

@ -418,11 +418,10 @@ const char *strip_dir(const char *vg_name, const char *dev_dir);
struct logical_volume *alloc_lv(struct dm_pool *mem);
/*
* 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 complete_vg);
/* Checks that an lv has no gaps or overlapping segments. */
int check_lv_segments_incomplete_vg(struct logical_volume *lv);
/* Aditional VG level checks on lv segment. */
int check_lv_segments_complete_vg(struct logical_volume *lv);
/*
* Does every LV segment have the same number of stripes?