mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
report: raid enhancements for --select
Enhance the raid report functions for the recently added LV fields reshape_len, reshape_len_le, data_offset, new_data_offset, data_copies, data_stripes and parity_chunks to cope with "lvs --select". Related: rhbz834579 Related: rhbz1191935 Related: rhbz1191978
This commit is contained in:
parent
6dea1ed5ae
commit
c5b6c9ad44
@ -1104,6 +1104,19 @@ int lv_raid_healthy(const struct logical_volume *lv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper: check for any sub LVs after a disk removing reshape */
|
||||||
|
static int _sublvs_remove_after_reshape(const struct logical_volume *lv)
|
||||||
|
{
|
||||||
|
uint32_t s;
|
||||||
|
struct lv_segment *seg = first_seg(lv);
|
||||||
|
|
||||||
|
for (s = seg->area_count -1; s; s--)
|
||||||
|
if (seg_lv(seg, s)->status & LV_REMOVE_AFTER_RESHAPE)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_with_info_and_seg_status *lvdm)
|
char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_with_info_and_seg_status *lvdm)
|
||||||
{
|
{
|
||||||
const struct logical_volume *lv = lvdm->lv;
|
const struct logical_volume *lv = lvdm->lv;
|
||||||
@ -1269,6 +1282,8 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
|
|||||||
repstr[8] = 'p';
|
repstr[8] = 'p';
|
||||||
else if (lv_is_raid_type(lv)) {
|
else if (lv_is_raid_type(lv)) {
|
||||||
uint64_t n;
|
uint64_t n;
|
||||||
|
char *sync_action;
|
||||||
|
|
||||||
if (!activation())
|
if (!activation())
|
||||||
repstr[8] = 'X'; /* Unknown */
|
repstr[8] = 'X'; /* Unknown */
|
||||||
else if (!lv_raid_healthy(lv))
|
else if (!lv_raid_healthy(lv))
|
||||||
@ -1276,6 +1291,12 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
|
|||||||
else if (lv_is_raid(lv)) {
|
else if (lv_is_raid(lv)) {
|
||||||
if (lv_raid_mismatch_count(lv, &n) && n)
|
if (lv_raid_mismatch_count(lv, &n) && n)
|
||||||
repstr[8] = 'm'; /* RAID has 'm'ismatches */
|
repstr[8] = 'm'; /* RAID has 'm'ismatches */
|
||||||
|
else if (lv_raid_sync_action(lv, &sync_action) &&
|
||||||
|
!strcmp(sync_action, "reshape"))
|
||||||
|
repstr[8] = 's'; /* LV is re(s)haping */
|
||||||
|
else if (_sublvs_remove_after_reshape(lv))
|
||||||
|
repstr[8] = 'R'; /* sub-LV got freed from raid set by reshaping
|
||||||
|
and has to be 'R'emoved */
|
||||||
} 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->status & LV_REMOVE_AFTER_RESHAPE)
|
else if (lv->status & LV_REMOVE_AFTER_RESHAPE)
|
||||||
|
@ -243,8 +243,8 @@ FIELD(VGS, vg, NUM, "#VMdaCps", cmd, 0, vgmdacopies, vg_mda_copies, "Target numb
|
|||||||
FIELD(SEGS, seg, STR, "Type", list, 0, segtype, segtype, "Type of LV segment.", 0)
|
FIELD(SEGS, seg, STR, "Type", list, 0, segtype, segtype, "Type of LV segment.", 0)
|
||||||
FIELD(SEGS, seg, NUM, "#Str", list, 0, seg_stripes, stripes, "Number of stripes or mirror/raid1 legs.", 0)
|
FIELD(SEGS, seg, NUM, "#Str", list, 0, seg_stripes, stripes, "Number of stripes or mirror/raid1 legs.", 0)
|
||||||
FIELD(SEGS, seg, NUM, "#DStr", list, 0, seg_data_stripes, data_stripes, "Number of data stripes or mirror/raid1 legs.", 0)
|
FIELD(SEGS, seg, NUM, "#DStr", list, 0, seg_data_stripes, data_stripes, "Number of data stripes or mirror/raid1 legs.", 0)
|
||||||
FIELD(SEGS, seg, NUM, "RSize", list, 0, seg_reshape_len, reshape_len, "Size of out-of-place reshape space in current units.", 0)
|
FIELD(SEGS, seg, SIZ, "RSize", list, 0, seg_reshape_len, reshape_len, "Size of out-of-place reshape space in current units.", 0)
|
||||||
FIELD(SEGS, seg, SIZ, "RSize", list, 0, seg_reshape_len_le, reshape_len_le, "Size of out-of-place reshape space in physical extents.", 0)
|
FIELD(SEGS, seg, NUM, "RSize", list, 0, seg_reshape_len_le, reshape_len_le, "Size of out-of-place reshape space in logical extents.", 0)
|
||||||
FIELD(SEGS, seg, NUM, "#Cpy", list, 0, seg_data_copies, data_copies, "Number of data copies.", 0)
|
FIELD(SEGS, seg, NUM, "#Cpy", list, 0, seg_data_copies, data_copies, "Number of data copies.", 0)
|
||||||
FIELD(SEGS, seg, NUM, "DOff", list, 0, seg_data_offset, data_offset, "Data offset on each image device.", 0)
|
FIELD(SEGS, seg, NUM, "DOff", list, 0, seg_data_offset, data_offset, "Data offset on each image device.", 0)
|
||||||
FIELD(SEGS, seg, NUM, "NOff", list, 0, seg_new_data_offset, new_data_offset, "New data offset after any reshape on each image device.", 0)
|
FIELD(SEGS, seg, NUM, "NOff", list, 0, seg_new_data_offset, new_data_offset, "New data offset after any reshape on each image device.", 0)
|
||||||
|
@ -2412,6 +2412,7 @@ static int _segstartpe_disp(struct dm_report *rh,
|
|||||||
return dm_report_field_uint32(rh, field, &seg->le);
|
return dm_report_field_uint32(rh, field, &seg->le);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hepler: get used stripes = total stripes minux any to remove after reshape */
|
||||||
static int _get_seg_used_stripes(const struct lv_segment *seg)
|
static int _get_seg_used_stripes(const struct lv_segment *seg)
|
||||||
{
|
{
|
||||||
uint32_t s;
|
uint32_t s;
|
||||||
@ -2437,6 +2438,7 @@ static int _seg_stripes_disp(struct dm_report *rh, struct dm_pool *mem,
|
|||||||
return dm_report_field_uint32(rh, field, &seg->area_count);
|
return dm_report_field_uint32(rh, field, &seg->area_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Report the number of data stripes, which is less than total stripes (e.g. 2 less for raid6) */
|
||||||
static int _seg_data_stripes_disp(struct dm_report *rh, struct dm_pool *mem,
|
static int _seg_data_stripes_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||||
struct dm_report_field *field,
|
struct dm_report_field *field,
|
||||||
const void *data, void *private)
|
const void *data, void *private)
|
||||||
@ -2451,95 +2453,111 @@ static int _seg_data_stripes_disp(struct dm_report *rh, struct dm_pool *mem,
|
|||||||
return dm_report_field_uint32(rh, field, &stripes);
|
return dm_report_field_uint32(rh, field, &stripes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper: return the top-level, reshapable raid LV in case @seg belongs to an raid rimage LV */
|
||||||
|
static struct logical_volume *_lv_for_raid_image_seg(const struct lv_segment *seg, struct dm_pool *mem)
|
||||||
|
{
|
||||||
|
char *lv_name;
|
||||||
|
|
||||||
|
if (seg_is_reshapable_raid(seg))
|
||||||
|
return seg->lv;
|
||||||
|
|
||||||
|
if (seg->lv &&
|
||||||
|
lv_is_raid_image(seg->lv) && !seg->le &&
|
||||||
|
(lv_name = dm_pool_strdup(mem, seg->lv->name))) {
|
||||||
|
char *p = strchr(lv_name, '_');
|
||||||
|
|
||||||
|
if (p) {
|
||||||
|
/* Handle duplicated sub LVs */
|
||||||
|
if (strstr(p, "_dup_"))
|
||||||
|
p = strchr(p + 5, '_');
|
||||||
|
|
||||||
|
if (p) {
|
||||||
|
struct lv_list *lvl;
|
||||||
|
|
||||||
|
*p = '\0';
|
||||||
|
if ((lvl = find_lv_in_vg(seg->lv->vg, lv_name)) &&
|
||||||
|
seg_is_reshapable_raid(first_seg(lvl->lv)))
|
||||||
|
return lvl->lv;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper: return the top-level raid LV in case it is reshapale for @seg or @seg if it is */
|
||||||
|
static const struct lv_segment *_get_reshapable_seg(const struct lv_segment *seg, struct dm_pool *mem)
|
||||||
|
{
|
||||||
|
return _lv_for_raid_image_seg(seg, mem) ? seg : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Display segment reshape length in current units */
|
||||||
static int _seg_reshape_len_disp(struct dm_report *rh, struct dm_pool *mem,
|
static int _seg_reshape_len_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||||
struct dm_report_field *field,
|
struct dm_report_field *field,
|
||||||
const void *data, void *private)
|
const void *data, void *private)
|
||||||
{
|
{
|
||||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
const struct lv_segment *seg = _get_reshapable_seg((const struct lv_segment *) data, mem);
|
||||||
uint32_t reshape_len = seg->reshape_len;
|
|
||||||
|
|
||||||
if (reshape_len && seg->lv) {
|
if (seg) {
|
||||||
reshape_len *= seg->area_count * seg->lv->vg->extent_size;
|
uint32_t reshape_len = seg->reshape_len * seg->area_count * seg->lv->vg->extent_size;
|
||||||
|
|
||||||
return _size32_disp(rh, mem, field, &reshape_len, private);
|
return _size32_disp(rh, mem, field, &reshape_len, private);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_32));
|
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Display segment reshape length of in logical extents */
|
||||||
static int _seg_reshape_len_le_disp(struct dm_report *rh, struct dm_pool *mem,
|
static int _seg_reshape_len_le_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||||
struct dm_report_field *field,
|
struct dm_report_field *field,
|
||||||
const void *data, void *private)
|
const void *data, void *private)
|
||||||
{
|
{
|
||||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
const struct lv_segment *seg = _get_reshapable_seg((const struct lv_segment *) data, mem);
|
||||||
uint32_t reshape_len = seg->reshape_len;
|
|
||||||
|
|
||||||
if (reshape_len) {
|
if (seg) {
|
||||||
reshape_len *= seg->area_count;
|
uint32_t reshape_len = seg->reshape_len* seg->area_count;
|
||||||
|
|
||||||
return dm_report_field_uint32(rh, field, &reshape_len);
|
return dm_report_field_uint32(rh, field, &reshape_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_32));
|
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Display segment data copies (e.g. 3 for raid6) */
|
||||||
static int _seg_data_copies_disp(struct dm_report *rh, struct dm_pool *mem,
|
static int _seg_data_copies_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||||
struct dm_report_field *field,
|
struct dm_report_field *field,
|
||||||
const void *data, void *private)
|
const void *data, void *private)
|
||||||
{
|
{
|
||||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
const struct lv_segment *seg = (const struct lv_segment *) data;
|
||||||
|
|
||||||
if (seg->data_copies > 1)
|
if (seg->data_copies)
|
||||||
return dm_report_field_uint32(rh, field, &seg->data_copies);
|
return dm_report_field_uint32(rh, field, &seg->data_copies);
|
||||||
|
|
||||||
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_32));
|
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper: display segment data offset/new data offset in sectors */
|
||||||
static int _segdata_offset(struct dm_report *rh, struct dm_pool *mem,
|
static int _segdata_offset(struct dm_report *rh, struct dm_pool *mem,
|
||||||
struct dm_report_field *field,
|
struct dm_report_field *field,
|
||||||
const void *data, void *private, int new_data_offset)
|
const void *data, void *private, int new_data_offset)
|
||||||
{
|
{
|
||||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
const struct lv_segment *seg = (const struct lv_segment *) data;
|
||||||
const char *what = "";
|
struct logical_volume *lv;
|
||||||
|
|
||||||
if (lv_is_raid_image(seg->lv) &&
|
if ((lv = _lv_for_raid_image_seg(seg, mem))) {
|
||||||
!seg->le &&
|
uint64_t data_offset;
|
||||||
(seg->reshape_len || !new_data_offset)) {
|
|
||||||
struct lv_list *lvl;
|
|
||||||
char *lv_name;
|
|
||||||
|
|
||||||
if ((lv_name = strdup(seg->lv->name))) {
|
if (lv_raid_data_offset(lv, &data_offset)) {
|
||||||
char *p = strchr(lv_name, '_');
|
if (new_data_offset && !lv_raid_image_in_sync(seg->lv))
|
||||||
|
data_offset = data_offset ? 0 : seg->reshape_len * lv->vg->extent_size;
|
||||||
|
|
||||||
if (p) {
|
return dm_report_field_uint64(rh, field, &data_offset);
|
||||||
/* Handle duplicated sub LVs */
|
|
||||||
if (strstr(p, "_dup_"))
|
|
||||||
p = strchr(p + 5, '_');
|
|
||||||
|
|
||||||
if (p) {
|
|
||||||
*p = '\0';
|
|
||||||
if ((lvl = find_lv_in_vg(seg->lv->vg, lv_name))) {
|
|
||||||
if (seg_is_reshapable_raid(first_seg(lvl->lv))) {
|
|
||||||
uint64_t data_offset;
|
|
||||||
|
|
||||||
if (lv_raid_data_offset(lvl->lv, &data_offset)) {
|
|
||||||
if (new_data_offset && !lv_raid_image_in_sync(seg->lv))
|
|
||||||
data_offset = data_offset ? 0 :
|
|
||||||
seg->reshape_len * seg->lv->vg->extent_size;
|
|
||||||
|
|
||||||
return dm_report_field_uint64(rh, field, &data_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
what = _str_unknown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _field_set_value(field, what, &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _seg_data_offset_disp(struct dm_report *rh, struct dm_pool *mem,
|
static int _seg_data_offset_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||||
@ -2582,7 +2600,7 @@ static int _seg_parity_chunks_disp(struct dm_report *rh, struct dm_pool *mem,
|
|||||||
return dm_report_field_uint32(rh, field, &parity_chunks);
|
return dm_report_field_uint32(rh, field, &parity_chunks);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_32));
|
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _segsize_disp(struct dm_report *rh, struct dm_pool *mem,
|
static int _segsize_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||||
|
Loading…
Reference in New Issue
Block a user