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

report: use same info also for lv_attr

Recently the single 'status' code has been used for number of cache
features.

Extend the API a little bit to allow usage also for lv_attr_dup.

As the function itself is used in lvm2api - add a new function:
lv_attr_dup_with_info_and_seg_status() that is able to use
grabbed info & status information.

report_init() is now using directly passed lvdm struct pointer
which holds the infomation whether lv_info() was correctly obtained or
there was some error when trying to read it.

Move 'healt' attribute to status.
TODO convert raid function to use the already known status.
This commit is contained in:
Zdenek Kabelac 2015-01-20 13:14:16 +01:00
parent e34b004422
commit b3a348c03c
6 changed files with 67 additions and 54 deletions

View File

@ -44,7 +44,13 @@ struct lv_seg_status {
struct dm_pool *mem; /* input */
const struct lv_segment *seg; /* input */
lv_seg_status_type_t type; /* output */
const void *status; /* struct dm_status_* */ /* output */
union {
struct dm_status_cache *cache;
struct dm_status_raid *raid;
struct dm_status_snapshot *snapshot;
struct dm_status_thin *thin;
struct dm_status_thin_pool *thin_pool;
};
};
struct lv_with_info_and_seg_status {

View File

@ -121,6 +121,7 @@ static int _get_segment_status_from_target_params(const char *target_name,
{
struct segment_type *segtype;
seg_status->type = SEG_STATUS_UNKNOWN;
/*
* TODO: Add support for other segment types too!
* The segment to report status for must be properly
@ -142,30 +143,28 @@ static int _get_segment_status_from_target_params(const char *target_name,
}
if (!strcmp(segtype->name, "cache")) {
if (!dm_get_status_cache(seg_status->mem, params,
(struct dm_status_cache **) &seg_status->status))
return_0;
if (!dm_get_status_cache(seg_status->mem, params, &(seg_status->cache)))
return_0;
seg_status->type = SEG_STATUS_CACHE;
} else if (!strcmp(segtype->name, "raid")) {
if (!dm_get_status_raid(seg_status->mem, params,
(struct dm_status_raid **) &seg_status->status))
if (!dm_get_status_raid(seg_status->mem, params, &seg_status->raid))
return_0;
seg_status->type = SEG_STATUS_RAID;
} else if (!strcmp(segtype->name, "thin")) {
if (!dm_get_status_thin(seg_status->mem, params,
(struct dm_status_thin **) &seg_status->status))
if (!dm_get_status_thin(seg_status->mem, params, &seg_status->thin))
return_0;
seg_status->type = SEG_STATUS_THIN;
} else if (!strcmp(segtype->name, "thin-pool")) {
if (!dm_get_status_thin_pool(seg_status->mem, params,
(struct dm_status_thin_pool **) &seg_status->status))
if (!dm_get_status_thin_pool(seg_status->mem, params, &seg_status->thin_pool))
return_0;
seg_status->type = SEG_STATUS_THIN_POOL;
} else if (!strcmp(segtype->name, "snapshot")) {
if (!dm_get_status_snapshot(seg_status->mem, params,
(struct dm_status_snapshot **) &seg_status->status))
if (!dm_get_status_snapshot(seg_status->mem, params, &seg_status->snapshot))
return_0;
seg_status->type = SEG_STATUS_SNAPSHOT;
} else {
log_error(INTERNAL_ERROR "Unsupported segment type %s.", segtype->name);
return 0;
}
return 1;

View File

@ -644,12 +644,11 @@ int lv_raid_healthy(const struct logical_volume *lv)
return 1;
}
char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_with_info_and_seg_status *lvdm)
{
dm_percent_t snap_percent;
struct lvinfo info;
const struct logical_volume *lv = lvdm->lv;
struct lv_segment *seg;
struct lv_seg_status seg_status;
char *repstr;
if (!(repstr = dm_pool_zalloc(mem, 11))) {
@ -722,30 +721,30 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
repstr[3] = (lv->status & FIXED_MINOR) ? 'm' : '-';
if (!activation() || !lv_info(lv->vg->cmd, lv, 0, &info, 1, 0)) {
if (!activation() || !lvdm->info_ok) {
repstr[4] = 'X'; /* Unknown */
repstr[5] = 'X'; /* Unknown */
} else if (info.exists) {
if (info.suspended)
} else if (lvdm->info.exists) {
if (lvdm->info.suspended)
repstr[4] = 's'; /* Suspended */
else if (info.live_table)
else if (lvdm->info.live_table)
repstr[4] = 'a'; /* Active */
else if (info.inactive_table)
else if (lvdm->info.inactive_table)
repstr[4] = 'i'; /* Inactive with table */
else
repstr[4] = 'd'; /* Inactive without table */
/* Snapshot dropped? */
if (info.live_table && lv_is_cow(lv)) {
if (lvdm->info.live_table && lv_is_cow(lv)) {
if (!lv_snapshot_percent(lv, &snap_percent) ||
snap_percent == DM_PERCENT_INVALID) {
if (info.suspended)
if (lvdm->info.suspended)
repstr[4] = 'S'; /* Susp Inv snapshot */
else
repstr[4] = 'I'; /* Invalid snapshot */
}
else if (snap_percent == LVM_PERCENT_MERGE_FAILED) {
if (info.suspended)
if (lvdm->info.suspended)
repstr[4] = 'M'; /* Susp snapshot merge failed */
else
repstr[4] = 'm'; /* snapshot merge failed */
@ -756,10 +755,10 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
* 'R' indicates read-only activation of a device that
* does not have metadata flagging it as read-only.
*/
if (repstr[1] != 'r' && info.read_only)
if (repstr[1] != 'r' && lvdm->info.read_only)
repstr[1] = 'R';
repstr[5] = (info.open_count) ? 'o' : '-';
repstr[5] = (lvdm->info.open_count) ? 'o' : '-';
} else {
repstr[4] = '-';
repstr[5] = '-';
@ -803,15 +802,15 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
repstr[8] = 'm'; /* RAID has 'm'ismatches */
} else if (lv->status & LV_WRITEMOSTLY)
repstr[8] = 'w'; /* sub-LV has 'w'ritemostly */
} else if (lv_is_thin_pool(lv)) {
seg_status.mem = lv->vg->cmd->mem;
if (!lv_status(lv->vg->cmd, first_seg(lv), &seg_status))
} else if (lv_is_thin_pool(lv) &&
(lvdm->seg_status.type != SEG_STATUS_NONE)) {
if (lvdm->seg_status.type == SEG_STATUS_UNKNOWN)
repstr[8] = 'X'; /* Unknown */
else if (((struct dm_status_thin_pool *)seg_status.status)->fail)
else if (lvdm->seg_status.thin_pool->fail)
repstr[8] = 'F';
else if (((struct dm_status_thin_pool *)seg_status.status)->out_of_data_space)
else if (lvdm->seg_status.thin_pool->out_of_data_space)
repstr[8] = 'D';
else if (((struct dm_status_thin_pool *)seg_status.status)->read_only)
else if (lvdm->seg_status.thin_pool->read_only)
repstr[8] = 'M';
}
@ -824,6 +823,19 @@ out:
return repstr;
}
/* backward compatible internal API for lvm2api, TODO improve it */
char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
struct lv_with_info_and_seg_status status = {
.seg_status.type = SEG_STATUS_NONE
};
if (!lv_info_with_seg_status(lv->vg->cmd, lv, first_seg(lv), 1, &status, 1, 1))
return_NULL;
return lv_attr_dup_with_info_and_seg_status(mem, &status);
}
int lv_set_creation(struct logical_volume *lv,
const char *hostname, uint64_t timestamp)
{

View File

@ -54,8 +54,11 @@ struct logical_volume {
const char *hostname;
};
struct lv_with_info_and_seg_status;
uint64_t lv_size(const struct logical_volume *lv);
uint64_t lv_metadata_size(const struct logical_volume *lv);
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(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_uuid_dup(const struct logical_volume *lv);
char *lv_tags_dup(const struct logical_volume *lv);

View File

@ -38,7 +38,7 @@ FIELD(LVS, lv, STR, "LV", lvid, 4, lvfullname, lv_full_name, "Full name of LV in
FIELD(LVS, lv, STR, "Path", lvid, 4, lvpath, lv_path, "Full pathname for LV. Blank for internal LVs.", 0)
FIELD(LVS, lv, STR, "DMPath", lvid, 6, lvdmpath, lv_dm_path, "Internal device-mapper pathname for LV (in /dev/mapper directory).", 0)
FIELD(LVS, lv, STR, "Parent", lvid, 6, lvparent, lv_parent, "For LVs that are components of another LV, the parent LV.", 0)
FIELD(LVS, lv, STR, "Attr", lvid, 4, lvstatus, lv_attr, "Various attributes - see man page.", 0)
FIELD(LVSSTATUS, lv, STR, "Attr", lvid, 4, lvstatus, lv_attr, "Various attributes - see man page.", 0)
FIELD(LVS, lv, STR_LIST, "Layout", lvid, 10, lvlayout, lv_layout, "LV layout.", 0)
FIELD(LVS, lv, STR_LIST, "Role", lvid, 10, lvrole, lv_role, "LV role.", 0)
FIELD(LVS, lv, BIN, "InitImgSync", lvid, 10, lvinitialimagesync, lv_initial_image_sync, "Set if mirror/RAID images underwent initial resynchronization.", 0)
@ -50,7 +50,6 @@ FIELD(LVS, lv, BIN, "AllocLock", lvid, 10, lvallocationlocked, lv_allocation_loc
FIELD(LVS, lv, BIN, "FixMin", lvid, 10, lvfixedminor, lv_fixed_minor, "Set if LV has fixed minor number assigned.", 0)
FIELD(LVS, lv, BIN, "MergeFailed", lvid, 15, lvmergefailed, lv_merge_failed, "Set if snapshot merge failed.", 0)
FIELD(LVS, lv, BIN, "SnapInvalid", lvid, 15, lvsnapshotinvalid, lv_snapshot_invalid, "Set if snapshot LV is invalid.", 0)
FIELD(LVS, lv, STR, "Health", lvid, 15, lvhealthstatus, lv_health_status, "LV health status.", 0)
FIELD(LVS, lv, BIN, "SkipAct", lvid, 15, lvskipactivation, lv_skip_activation, "Set if LV is skipped on activation.", 0)
FIELD(LVS, lv, BIN, "WhenFull", lvid, 15, lverrorwhenfull, lv_error_when_full, "For thin pools, behavior when full.", 0)
FIELD(LVS, lv, STR, "Active", lvid, 6, lvactive, lv_active, "Active state of the LV.", 0)
@ -103,6 +102,7 @@ FIELD(LVSSTATUS, lv, NUM, "CacheReadHits", lvid, 16, cache_read_hits, cache_read
FIELD(LVSSTATUS, lv, NUM, "CacheReadMisses", lvid, 16, cache_read_misses, cache_read_misses, "Cache read misses.", 0)
FIELD(LVSSTATUS, lv, NUM, "CacheWriteHits", lvid, 16, cache_write_hits, cache_write_hits, "Cache write hits.", 0)
FIELD(LVSSTATUS, lv, NUM, "CacheWriteMisses", lvid, 16, cache_write_misses, cache_write_misses, "Cache write misses.", 0)
FIELD(LVSSTATUS, lv, STR, "Health", lvid, 15, lvhealthstatus, lv_health_status, "LV health status.", 0)
FIELD(LABEL, label, STR, "Fmt", type, 3, pvfmt, pv_fmt, "Type of metadata.", 0)
FIELD(LABEL, label, STR, "PV UUID", type, 38, pvuuid, pv_uuid, "Unique identifier.", 0)

View File

@ -415,10 +415,10 @@ static int _lvstatus_disp(struct dm_report *rh __attribute__((unused)), struct d
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const struct lv_with_info_and_seg_status *lvdm = (const struct lv_with_info_and_seg_status *) data;
char *repstr;
if (!(repstr = lv_attr_dup(mem, lv)))
if (!(repstr = lv_attr_dup_with_info_and_seg_status(mem, lvdm)))
return_0;
return _field_set_value(field, repstr, NULL);
@ -1770,8 +1770,8 @@ static int _lvhealthstatus_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct lv_seg_status seg_status;
const struct lv_with_info_and_seg_status *lvdm = (const struct lv_with_info_and_seg_status *) data;
const struct logical_volume *lv = lvdm->lv;
const char *health = "";
uint64_t n;
@ -1787,15 +1787,15 @@ static int _lvhealthstatus_disp(struct dm_report *rh, struct dm_pool *mem,
health = "mismatches exist";
} else if (lv->status & LV_WRITEMOSTLY)
health = "writemostly";
} else if (lv_is_thin_pool(lv)) {
seg_status.mem = lv->vg->cmd->mem;
if (!lv_status(lv->vg->cmd, first_seg(lv), &seg_status))
health = "unknown";
else if (((struct dm_status_thin_pool *)seg_status.status)->fail)
} else if (lv_is_thin_pool(lv) && (lvdm->seg_status.type != SEG_STATUS_NONE)) {
if (lvdm->seg_status.type != SEG_STATUS_THIN_POOL)
return _field_set_value(field, GET_FIRST_RESERVED_NAME(health_undef),
GET_FIELD_RESERVED_VALUE(health_undef));
else if (lvdm->seg_status.thin_pool->fail)
health = "failed";
else if (((struct dm_status_thin_pool *)seg_status.status)->out_of_data_space)
else if (lvdm->seg_status.thin_pool->out_of_data_space)
health = "out_of_data";
else if (((struct dm_status_thin_pool *)seg_status.status)->read_only)
else if (lvdm->seg_status.thin_pool->read_only)
health = "metadata_read_only";
}
@ -1824,7 +1824,7 @@ static int _cache_ ## cache_status_field_name ## _disp (struct dm_report *rh, \
const struct lv_with_info_and_seg_status *lvdm = (const struct lv_with_info_and_seg_status *) data; \
if (lvdm->seg_status.type != SEG_STATUS_CACHE) \
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64)); \
return dm_report_field_uint64(rh, field, (void *) ((char *) lvdm->seg_status.status + offsetof(struct dm_status_cache, cache_status_field_name))); \
return dm_report_field_uint64(rh, field, &lvdm->seg_status.cache->cache_status_field_name); \
}
GENERATE_CACHE_STATUS_DISP_FN(total_blocks)
@ -1997,27 +1997,20 @@ void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
int report_object(void *handle, const struct volume_group *vg,
const struct logical_volume *lv, const struct physical_volume *pv,
const struct lv_segment *seg, const struct pv_segment *pvseg,
const struct lvinfo *lvinfo, const struct lv_seg_status *lv_seg_status,
const struct lv_with_info_and_seg_status *lvdm,
const struct label *label)
{
struct device dummy_device = { .dev = 0 };
struct label dummy_label = { .dev = &dummy_device };
struct lv_with_info_and_seg_status lvdm = { .lv = lv };
struct lvm_report_object obj = {
.vg = (struct volume_group *) vg,
.lvdm = &lvdm,
.lvdm = (struct lv_with_info_and_seg_status *) lvdm,
.pv = (struct physical_volume *) pv,
.seg = (struct lv_segment *) seg,
.pvseg = (struct pv_segment *) pvseg,
.label = (struct label *) (label ? : (pv ? pv_label(pv) : NULL))
};
if (lvinfo)
lvdm.info = *lvinfo;
if (lv_seg_status)
lvdm.seg_status = *lv_seg_status;
/* FIXME workaround for pv_label going through cache; remove once struct
* physical_volume gains a proper "label" pointer */
if (!obj.label) {