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

lv: always check status type

Always validate status type has an expected value,
before accessing status struct members.
This commit is contained in:
Zdenek Kabelac 2016-12-01 10:43:55 +01:00
parent 6a450952ad
commit 325c2c5687
3 changed files with 25 additions and 21 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.169 - Version 2.02.169 -
===================================== =====================================
Test segment type before accessing segment members when checking status.
Implement compatible target function for stripe segment. Implement compatible target function for stripe segment.
Use status info to report merge failed and snapshot invalid lvs fields. Use status info to report merge failed and snapshot invalid lvs fields.

View File

@ -1184,7 +1184,8 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
if (lv_is_historical(lv)) { if (lv_is_historical(lv)) {
repstr[4] = 'h'; repstr[4] = 'h';
repstr[5] = '-'; repstr[5] = '-';
} else if (!activation() || !lvdm->info_ok) { } else if (!activation() || !lvdm->info_ok ||
(lvdm->seg_status.type == SEG_STATUS_UNKNOWN)) {
repstr[4] = 'X'; /* Unknown */ repstr[4] = 'X'; /* Unknown */
repstr[5] = 'X'; /* Unknown */ repstr[5] = 'X'; /* Unknown */
} else if (lvdm->info.exists) { } else if (lvdm->info.exists) {
@ -1216,8 +1217,10 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
/* 'c' when cache/thin-pool is active with needs_check flag /* 'c' when cache/thin-pool is active with needs_check flag
* 'C' for suspend */ * 'C' for suspend */
if ((lv_is_thin_pool(lv) && if ((lv_is_thin_pool(lv) &&
(lvdm->seg_status.type == SEG_STATUS_THIN_POOL) &&
lvdm->seg_status.thin_pool->needs_check) || lvdm->seg_status.thin_pool->needs_check) ||
(lv_is_cache(lv) && (lv_is_cache(lv) &&
(lvdm->seg_status.type == SEG_STATUS_CACHE) &&
lvdm->seg_status.cache->needs_check)) lvdm->seg_status.cache->needs_check))
repstr[4] = lvdm->info.suspended ? 'C' : 'c'; repstr[4] = lvdm->info.suspended ? 'C' : 'c';
@ -1259,6 +1262,10 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
repstr[7] = '-'; repstr[7] = '-';
repstr[8] = '-'; repstr[8] = '-';
/* TODO: also convert raid health
* lv_is_raid_type() is to wide
* NOTE: snapshot origin is 'mostly' showing it's layered status
*/
if (lv_is_partial(lv)) if (lv_is_partial(lv))
repstr[8] = 'p'; repstr[8] = 'p';
else if (lv_is_raid_type(lv)) { else if (lv_is_raid_type(lv)) {
@ -1272,31 +1279,23 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
repstr[8] = 'm'; /* RAID has 'm'ismatches */ repstr[8] = 'm'; /* RAID has 'm'ismatches */
} else if (lv->status & LV_WRITEMOSTLY) } else if (lv->status & LV_WRITEMOSTLY)
repstr[8] = 'w'; /* sub-LV has 'w'ritemostly */ repstr[8] = 'w'; /* sub-LV has 'w'ritemostly */
} else if (lv_is_cache(lv) && } else if (lvdm->seg_status.type == SEG_STATUS_CACHE) {
(lvdm->seg_status.type != SEG_STATUS_NONE)) { if (lvdm->seg_status.cache->fail)
if (lvdm->seg_status.type == SEG_STATUS_UNKNOWN)
repstr[8] = 'X'; /* Unknown */
else if (lvdm->seg_status.cache->fail)
repstr[8] = 'F'; repstr[8] = 'F';
else if (lvdm->seg_status.cache->read_only) else if (lvdm->seg_status.cache->read_only)
repstr[8] = 'M'; repstr[8] = 'M';
} else if (lv_is_thin_pool(lv) && } else if (lvdm->seg_status.type == SEG_STATUS_THIN_POOL) {
(lvdm->seg_status.type != SEG_STATUS_NONE)) { if (lvdm->seg_status.thin_pool->fail)
if (lvdm->seg_status.type == SEG_STATUS_UNKNOWN)
repstr[8] = 'X'; /* Unknown */
else if (lvdm->seg_status.thin_pool->fail)
repstr[8] = 'F'; repstr[8] = 'F';
else if (lvdm->seg_status.thin_pool->out_of_data_space) else if (lvdm->seg_status.thin_pool->out_of_data_space)
repstr[8] = 'D'; repstr[8] = 'D';
else if (lvdm->seg_status.thin_pool->read_only) else if (lvdm->seg_status.thin_pool->read_only)
repstr[8] = 'M'; repstr[8] = 'M';
} else if (lv_is_thin_volume(lv) && } else if (lvdm->seg_status.type == SEG_STATUS_THIN) {
(lvdm->seg_status.type != SEG_STATUS_NONE)) { if (lvdm->seg_status.thin->fail)
if (lvdm->seg_status.type == SEG_STATUS_UNKNOWN)
repstr[8] = 'X'; /* Unknown */
else if (lvdm->seg_status.thin->fail)
repstr[8] = 'F'; repstr[8] = 'F';
} } else if (lvdm->seg_status.type == SEG_STATUS_UNKNOWN)
repstr[8] = 'X'; /* Unknown */
if (lv->status & LV_ACTIVATION_SKIP) if (lv->status & LV_ACTIVATION_SKIP)
repstr[9] = 'k'; repstr[9] = 'k';

View File

@ -2936,12 +2936,16 @@ static int _metadatapercent_disp(struct dm_report *rh,
const void *data, void *private) const void *data, void *private)
{ {
const struct lv_with_info_and_seg_status *lvdm = (const struct lv_with_info_and_seg_status *) data; const struct lv_with_info_and_seg_status *lvdm = (const struct lv_with_info_and_seg_status *) data;
dm_percent_t percent = DM_PERCENT_INVALID; dm_percent_t percent;
if (lv_is_thin_pool(lvdm->lv) || switch (lvdm->seg_status.type) {
lv_is_cache(lvdm->lv) || case SEG_STATUS_CACHE:
lv_is_used_cache_pool(lvdm->lv)) case SEG_STATUS_THIN_POOL:
percent = lvseg_percent_with_info_and_seg_status(lvdm, PERCENT_GET_METADATA); percent = lvseg_percent_with_info_and_seg_status(lvdm, PERCENT_GET_METADATA);
break;
default:
percent = DM_PERCENT_INVALID;
}
return dm_report_field_percent(rh, field, &percent); return dm_report_field_percent(rh, field, &percent);
} }