mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
report: add new LVSSTATUS and SEGSSTATUS report type
Similar to LVSINFO type which gathers LV + its DM_DEVICE_INFO, the new LVSSTATUS/SEGSSTATUS report type will gather LV/segment + its DM_DEVICE_STATUS. Since we can report status only for certain segment, in case of LVSSTATUS we need to choose which segment related to the LV should be processed that represents the "LV status". In case of SEGSSTATUS type it's clear - the status is reported for the segment just processed.
This commit is contained in:
parent
d7e5f03888
commit
7f90ad84c1
@ -1749,9 +1749,11 @@ static const struct dm_report_object_type _report_types[] = {
|
||||
{ VGS, "Volume Group", "vg_", _obj_get_vg },
|
||||
{ LVS, "Logical Volume", "lv_", _obj_get_lv },
|
||||
{ LVSINFO, "Logical Volume Device Info", "lv_", _obj_get_lv_with_info_and_seg_status },
|
||||
{ LVSSTATUS, "Logical Volume Device Status", "lv_", _obj_get_lv_with_info_and_seg_status },
|
||||
{ PVS, "Physical Volume", "pv_", _obj_get_pv },
|
||||
{ LABEL, "Physical Volume Label", "pv_", _obj_get_label },
|
||||
{ SEGS, "Logical Volume Segment", "seg_", _obj_get_seg },
|
||||
{ SEGSSTATUS, "Logical Volume Device Segment Status", "seg_", _obj_get_lv_with_info_and_seg_status },
|
||||
{ PVSEGS, "Physical Volume Segment", "pvseg_", _obj_get_pvseg },
|
||||
{ 0, "", "", NULL },
|
||||
};
|
||||
|
@ -23,12 +23,14 @@
|
||||
typedef enum {
|
||||
LVS = 1,
|
||||
LVSINFO = 2,
|
||||
PVS = 4,
|
||||
VGS = 8,
|
||||
SEGS = 16,
|
||||
PVSEGS = 32,
|
||||
LABEL = 64,
|
||||
DEVTYPES = 128
|
||||
LVSSTATUS = 4,
|
||||
PVS = 8,
|
||||
VGS = 16,
|
||||
SEGS = 32,
|
||||
SEGSSTATUS = 64,
|
||||
PVSEGS = 128,
|
||||
LABEL = 256,
|
||||
DEVTYPES = 512
|
||||
} report_type_t;
|
||||
|
||||
struct field;
|
||||
|
122
tools/reporter.c
122
tools/reporter.c
@ -56,6 +56,11 @@ static void _get_lv_info_for_report(struct cmd_context *cmd,
|
||||
lvinfo->exists = 0;
|
||||
}
|
||||
|
||||
static void _get_lv_info_with_segment_status_for_report(struct cmd_context *cmd,
|
||||
struct lv_with_info_and_seg_status *lvdm)
|
||||
{
|
||||
}
|
||||
|
||||
static int _lvs_with_info_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
void *handle)
|
||||
{
|
||||
@ -68,6 +73,58 @@ static int _lvs_with_info_single(struct cmd_context *cmd, struct logical_volume
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
static void _choose_lv_segment_for_status_report(struct lv_with_info_and_seg_status *lvdm)
|
||||
{
|
||||
/*
|
||||
* By default, take the first LV segment to report status for.
|
||||
* If there's any other specific segment that needs to be
|
||||
* reported instead for the LV, choose it here and assign it
|
||||
* to lvdm->seg_status->seg. This is the segment whose
|
||||
* status line will be used for report exactly.
|
||||
*/
|
||||
lvdm->seg_status->seg = first_seg(lvdm->lv);
|
||||
}
|
||||
|
||||
static int _lvs_with_status_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
void *handle)
|
||||
{
|
||||
struct lvinfo lvinfo;
|
||||
struct lv_seg_status lv_seg_status = { .mem = lv->vg->vgmem,
|
||||
.type = SEG_STATUS_NONE,
|
||||
.status = NULL };
|
||||
struct lv_with_info_and_seg_status lvdm = { .lv = lv,
|
||||
.seg_status = &lv_seg_status };
|
||||
int r = ECMD_FAILED;
|
||||
|
||||
_choose_lv_segment_for_status_report(&lvdm);
|
||||
|
||||
if (lvdm.seg_status->seg->lv != lv) {
|
||||
/*
|
||||
* If the info is requested on one LV and segment
|
||||
* status on another LV, we need to call these separately.
|
||||
*/
|
||||
_get_lv_info_for_report(cmd, lv, &lvinfo);
|
||||
lvdm.info = NULL;
|
||||
_get_lv_info_with_segment_status_for_report(cmd, &lvdm);
|
||||
} else {
|
||||
/*
|
||||
* If the info is requested on the same LV as status,
|
||||
* we can get info and status in one go!
|
||||
*/
|
||||
lvdm.info = &lvinfo;
|
||||
_get_lv_info_with_segment_status_for_report(cmd, &lvdm);
|
||||
}
|
||||
|
||||
if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL, &lvinfo, lvdm.seg_status, NULL))
|
||||
goto out;
|
||||
|
||||
r = ECMD_PROCESSED;
|
||||
out:
|
||||
if (lvdm.seg_status->status)
|
||||
dm_pool_free(lvdm.seg_status->mem, lvdm.seg_status->status);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _segs_single(struct cmd_context *cmd __attribute__((unused)),
|
||||
struct lv_segment *seg, void *handle)
|
||||
{
|
||||
@ -89,6 +146,30 @@ static int _segs_with_lv_info_single(struct cmd_context *cmd __attribute__((unus
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
static int _segs_with_lv_status_single(struct cmd_context *cmd __attribute__((unused)),
|
||||
struct lv_segment *seg, void *handle)
|
||||
{
|
||||
struct lvinfo lvinfo;
|
||||
struct lv_seg_status lv_seg_status = { .seg = seg,
|
||||
.mem = seg->lv->vg->vgmem,
|
||||
.type = SEG_STATUS_NONE,
|
||||
.status = NULL };
|
||||
struct lv_with_info_and_seg_status lvdm = { .lv = seg->lv,
|
||||
.info = &lvinfo,
|
||||
.seg_status = &lv_seg_status };
|
||||
int r = ECMD_FAILED;
|
||||
|
||||
_get_lv_info_with_segment_status_for_report(cmd, &lvdm);
|
||||
if (!report_object(handle, seg->lv->vg, seg->lv, NULL, seg, NULL, lvdm.info, lvdm.seg_status, NULL))
|
||||
goto_out;
|
||||
|
||||
r = ECMD_PROCESSED;
|
||||
out:
|
||||
if (lvdm.seg_status->status)
|
||||
dm_pool_free(lvdm.seg_status->mem, lvdm.seg_status->status);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _do_pvsegs_sub_single(struct cmd_context *cmd,
|
||||
struct volume_group *vg,
|
||||
struct pv_segment *pvseg,
|
||||
@ -182,6 +263,16 @@ static int _lvsegs_with_lv_info_single(struct cmd_context *cmd,
|
||||
return process_each_segment_in_lv(cmd, lv, handle, _segs_with_lv_info_single);
|
||||
}
|
||||
|
||||
static int _lvsegs_with_lv_status_single(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
void *handle)
|
||||
{
|
||||
if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
|
||||
return ECMD_PROCESSED;
|
||||
|
||||
return process_each_segment_in_lv(cmd, lv, handle, _segs_with_lv_status_single);
|
||||
}
|
||||
|
||||
static int _pvsegs_single(struct cmd_context *cmd, struct volume_group *vg,
|
||||
struct physical_volume *pv, void *handle)
|
||||
{
|
||||
@ -254,7 +345,7 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
|
||||
int r = ECMD_PROCESSED;
|
||||
int aligned, buffered, headings, field_prefixes, quoted;
|
||||
int columns_as_rows;
|
||||
unsigned args_are_pvs, lv_info_needed;
|
||||
unsigned args_are_pvs, lv_info_needed, lv_segment_status_needed;
|
||||
int lock_global = 0;
|
||||
|
||||
aligned = find_config_tree_bool(cmd, report_aligned_CFG, NULL);
|
||||
@ -373,15 +464,18 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
|
||||
columns_as_rows, selection)))
|
||||
return_ECMD_FAILED;
|
||||
|
||||
/* Do we need lv_info to be called for LV device status? */
|
||||
/* Do we need to acquire LV device info in addition? */
|
||||
lv_info_needed = (report_type & LVSINFO) ? 1 : 0;
|
||||
|
||||
/* Do we need to acquire LV device status in addition? */
|
||||
lv_segment_status_needed = (report_type & (SEGSSTATUS | LVSSTATUS)) ? 1 : 0;
|
||||
|
||||
/* Ensure options selected are compatible */
|
||||
if (report_type & SEGS)
|
||||
if (report_type & (SEGS | SEGSSTATUS))
|
||||
report_type |= LVS;
|
||||
if (report_type & PVSEGS)
|
||||
report_type |= PVS;
|
||||
if ((report_type & (LVS | LVSINFO)) && (report_type & (PVS | LABEL)) && !args_are_pvs) {
|
||||
if ((report_type & (LVS | LVSINFO | LVSSTATUS)) && (report_type & (PVS | LABEL)) && !args_are_pvs) {
|
||||
log_error("Can't report LV and PV fields at the same time");
|
||||
dm_report_free(report_handle);
|
||||
return ECMD_FAILED;
|
||||
@ -389,15 +483,15 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
|
||||
|
||||
/* Change report type if fields specified makes this necessary */
|
||||
if ((report_type & PVSEGS) ||
|
||||
((report_type & (PVS | LABEL)) && (report_type & (LVS | LVSINFO))))
|
||||
((report_type & (PVS | LABEL)) && (report_type & (LVS | LVSINFO | LVSSTATUS))))
|
||||
report_type = PVSEGS;
|
||||
else if ((report_type & LABEL) && (report_type & VGS))
|
||||
report_type = PVS;
|
||||
else if (report_type & PVS)
|
||||
report_type = PVS;
|
||||
else if (report_type & SEGS)
|
||||
else if (report_type & (SEGS | SEGSSTATUS))
|
||||
report_type = SEGS;
|
||||
else if (report_type & (LVS | LVSINFO))
|
||||
else if (report_type & (LVS | LVSINFO | LVSSTATUS))
|
||||
report_type = LVS;
|
||||
|
||||
/*
|
||||
@ -419,10 +513,13 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
|
||||
break;
|
||||
case LVSINFO:
|
||||
/* fall through */
|
||||
case LVSSTATUS:
|
||||
/* fall through */
|
||||
case LVS:
|
||||
r = process_each_lv(cmd, argc, argv, 0, report_handle,
|
||||
lv_info_needed ? &_lvs_with_info_single
|
||||
: &_lvs_single);
|
||||
lv_segment_status_needed ? &_lvs_with_status_single
|
||||
: lv_info_needed ? &_lvs_with_info_single
|
||||
: &_lvs_single);
|
||||
break;
|
||||
case VGS:
|
||||
r = process_each_vg(cmd, argc, argv, 0,
|
||||
@ -440,10 +537,13 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
|
||||
r = process_each_vg(cmd, argc, argv, 0,
|
||||
report_handle, &_pvs_in_vg);
|
||||
break;
|
||||
case SEGSSTATUS:
|
||||
/* fall through */
|
||||
case SEGS:
|
||||
r = process_each_lv(cmd, argc, argv, 0, report_handle,
|
||||
lv_info_needed ? &_lvsegs_with_lv_info_single
|
||||
: &_lvsegs_single);
|
||||
lv_segment_status_needed ? &_lvsegs_with_lv_status_single
|
||||
:lv_info_needed ? &_lvsegs_with_lv_info_single
|
||||
: &_lvsegs_single);
|
||||
break;
|
||||
case PVSEGS:
|
||||
if (args_are_pvs)
|
||||
|
Loading…
Reference in New Issue
Block a user