1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-02 01:18:26 +03:00

report: add full_ancestors field to display ancestors with history

The lv_full_ancestors reporting field is just like the existing
lv_ancestors field but it also takes into account any history and
indirect relations recorded.
This commit is contained in:
Peter Rajnoha 2016-03-01 15:24:40 +01:00
parent f228750386
commit 715f1fb4c4
3 changed files with 79 additions and 17 deletions

View File

@ -65,7 +65,8 @@ FIELD(LVS, lv, NUM, "#Seg", lvid, 4, lvsegcount, seg_count, "Number of segments
FIELD(LVS, lv, STR, "Origin", lvid, 6, origin, origin, "For snapshots, the origin device of this LV.", 0) FIELD(LVS, lv, STR, "Origin", lvid, 6, origin, origin, "For snapshots, the origin device of this LV.", 0)
FIELD(LVS, lv, STR, "Origin UUID", lvid, 38, originuuid, origin_uuid, "For snapshots, the UUID of origin device of this LV.", 0) FIELD(LVS, lv, STR, "Origin UUID", lvid, 38, originuuid, origin_uuid, "For snapshots, the UUID of origin device of this LV.", 0)
FIELD(LVS, lv, SIZ, "OSize", lvid, 5, originsize, origin_size, "For snapshots, the size of the origin device of this LV.", 0) FIELD(LVS, lv, SIZ, "OSize", lvid, 5, originsize, origin_size, "For snapshots, the size of the origin device of this LV.", 0)
FIELD(LVS, lv, STR_LIST, "Ancestors", lvid, 12, lvancestors, lv_ancestors, "Ancestors of this LV.", 0) FIELD(LVS, lv, STR_LIST, "Ancestors", lvid, 12, lvancestors, lv_ancestors, "LV ancestors ignoring any stored history of the ancestry chain.", 0)
FIELD(LVS, lv, STR_LIST, "FAncestors", lvid, 12, lvfullancestors, lv_full_ancestors, "LV ancestors including stored history of the ancestry chain.", 0)
FIELD(LVS, lv, STR_LIST, "Descendants", lvid, 12, lvdescendants, lv_descendants, "Descendants of this LV.", 0) FIELD(LVS, lv, STR_LIST, "Descendants", lvid, 12, lvdescendants, lv_descendants, "Descendants of this LV.", 0)
FIELD(LVS, lv, PCT, "Data%", lvid, 6, datapercent, data_percent, "For snapshot and thin pools and volumes, the percentage full if LV is active.", 0) FIELD(LVS, lv, PCT, "Data%", lvid, 6, datapercent, data_percent, "For snapshot and thin pools and volumes, the percentage full if LV is active.", 0)
FIELD(LVS, lv, PCT, "Snap%", lvid, 6, snpercent, snap_percent, "For snapshots, the percentage full if LV is active.", 0) FIELD(LVS, lv, PCT, "Snap%", lvid, 6, snpercent, snap_percent, "For snapshots, the percentage full if LV is active.", 0)

View File

@ -312,6 +312,8 @@ GET_LV_NUM_PROPERTY_FN(origin_size, (SECTOR_SIZE * lv_origin_size(lv)))
#define _origin_size_set prop_not_implemented_set #define _origin_size_set prop_not_implemented_set
#define _lv_ancestors_set prop_not_implemented_set #define _lv_ancestors_set prop_not_implemented_set
#define _lv_ancestors_get prop_not_implemented_get #define _lv_ancestors_get prop_not_implemented_get
#define _lv_full_ancestors_set prop_not_implemented_set
#define _lv_full_ancestors_get prop_not_implemented_get
#define _lv_descendants_set prop_not_implemented_set #define _lv_descendants_set prop_not_implemented_set
#define _lv_descendants_get prop_not_implemented_get #define _lv_descendants_get prop_not_implemented_get
GET_LV_NUM_PROPERTY_FN(snap_percent, _snap_percent(lv)) GET_LV_NUM_PROPERTY_FN(snap_percent, _snap_percent(lv))

View File

@ -1929,26 +1929,52 @@ static int _originuuid_disp(struct dm_report *rh, struct dm_pool *mem,
return _do_origin_disp(rh, mem, field, data, private, 1); return _do_origin_disp(rh, mem, field, data, private, 1);
} }
static int _find_ancestors(struct _str_list_append_baton *ancestors, static const char *_get_glv_str(char *buf, size_t buf_len,
struct logical_volume *lv) struct generic_logical_volume *glv)
{ {
struct logical_volume *ancestor_lv = NULL; if (!glv->is_historical)
struct lv_segment *seg; return glv->live->name;
if (lv_is_cow(lv)) { if (dm_snprintf(buf, buf_len, "%s%s", HISTORICAL_LV_PREFIX, glv->historical->name) < 0) {
ancestor_lv = origin_from_cow(lv); log_error("_get_glv_str: dm_snprintf failed");
} else if (lv_is_thin_volume(lv)) { return NULL;
seg = first_seg(lv);
if (seg->origin)
ancestor_lv = seg->origin;
else if (seg->external_lv)
ancestor_lv = seg->external_lv;
} }
if (ancestor_lv) { return buf;
if (!_str_list_append(ancestor_lv->name, ancestors)) }
static int _find_ancestors(struct _str_list_append_baton *ancestors,
struct generic_logical_volume glv,
int full, int include_historical_lvs)
{
struct lv_segment *seg;
void *orig_p = glv.live;
const char *ancestor_str;
char buf[NAME_LEN + strlen(HISTORICAL_LV_PREFIX) + 1];
if (glv.is_historical) {
if (full && glv.historical->indirect_origin)
glv = *glv.historical->indirect_origin;
} else if (lv_is_cow(glv.live)) {
glv.live = origin_from_cow(glv.live);
} else if (lv_is_thin_volume(glv.live)) {
seg = first_seg(glv.live);
if (seg->origin)
glv.live = seg->origin;
else if (seg->external_lv)
glv.live = seg->external_lv;
else if (full && seg->indirect_origin)
glv = *seg->indirect_origin;
}
if (orig_p != glv.live) {
if (!(ancestor_str = _get_glv_str(buf, sizeof(buf), &glv)))
return_0; return_0;
if (!_find_ancestors(ancestors, ancestor_lv)) if (!glv.is_historical || include_historical_lvs) {
if (!_str_list_append(ancestor_str, ancestors))
return_0;
}
if (!_find_ancestors(ancestors, glv, full, include_historical_lvs))
return_0; return_0;
} }
@ -1959,14 +1985,21 @@ static int _lvancestors_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)
{ {
struct cmd_context *cmd = (struct cmd_context *) private;
struct logical_volume *lv = (struct logical_volume *) data; struct logical_volume *lv = (struct logical_volume *) data;
struct _str_list_append_baton ancestors; struct _str_list_append_baton ancestors;
struct generic_logical_volume glv;
ancestors.mem = mem; ancestors.mem = mem;
if (!(ancestors.result = str_list_create(mem))) if (!(ancestors.result = str_list_create(mem)))
return_0; return_0;
if (!_find_ancestors(&ancestors, lv)) { if ((glv.is_historical = lv_is_historical(lv)))
glv.historical = lv->this_glv->historical;
else
glv.live = lv;
if (!_find_ancestors(&ancestors, glv, 0, cmd->include_historical_lvs)) {
dm_pool_free(ancestors.mem, ancestors.result); dm_pool_free(ancestors.mem, ancestors.result);
return_0; return_0;
} }
@ -1974,6 +2007,32 @@ static int _lvancestors_disp(struct dm_report *rh, struct dm_pool *mem,
return _field_set_string_list(rh, field, ancestors.result, private, 0, NULL); return _field_set_string_list(rh, field, ancestors.result, private, 0, NULL);
} }
static int _lvfullancestors_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
struct cmd_context *cmd = (struct cmd_context *) private;
struct logical_volume *lv = (struct logical_volume *) data;
struct _str_list_append_baton full_ancestors;
struct generic_logical_volume glv;
full_ancestors.mem = mem;
if (!(full_ancestors.result = str_list_create(mem)))
return_0;
if ((glv.is_historical = lv_is_historical(lv)))
glv.historical = lv->this_glv->historical;
else
glv.live = lv;
if (!_find_ancestors(&full_ancestors, glv, 1, cmd->include_historical_lvs)) {
dm_pool_free(full_ancestors.mem, full_ancestors.result);
return_0;
}
return _field_set_string_list(rh, field, full_ancestors.result, private, 0, NULL);
}
static int _find_descendants(struct _str_list_append_baton *descendants, static int _find_descendants(struct _str_list_append_baton *descendants,
struct logical_volume *lv) struct logical_volume *lv)
{ {