diff options
author | Peter Rajnoha <prajnoha@redhat.com> | 2016-03-01 15:18:42 +0100 |
---|---|---|
committer | Peter Rajnoha <prajnoha@redhat.com> | 2016-03-03 11:26:51 +0100 |
commit | e573eca554374ba6889a7f89fcb9850ae13c793e (patch) | |
tree | c9432a7f9b7dc221d1e8c2cc9a9e4d6c0aee9487 | |
parent | 5e718ec66679aad42773901a40e168ba4c3f3f50 (diff) | |
download | lvm2-e573eca554374ba6889a7f89fcb9850ae13c793e.tar.gz |
metadata: add infrastructure to track LV history
Add new structures and new fields in existing structures to support
tracking history of LVs (the LVs which don't exist - the have been
removed already):
- new "struct historical_logical_volume"
This structure keeps information specific to historical LVs
(historical LV is very reduced form of struct logical_volume +
it contains a few specific fields to track historical LV
properties like removal time and connections among other LVs).
- new "struct generic_logical_volume"
Wrapper for "struct historical_logical_volume" and
"struct logical_volume" to make it possible to handle volumes
in uniform way, no matter if it's live or historical one.
- new "struct glv_list"
Wrapper for "struct generic_logical_volume" so it can be
added to a list.
- new "indirect_glvs" field in "struct logical_volume"
List that stores references to all indirect users of this LV - this
interconnects live LV with historical descendant LVs or even live
descendant LVs.
- new "indirect_origin" field in "struct lv_segment"
Reference to indirect origin of this segment - this interconnects
live LV (segment) with historical ancestor.
- new "this_glv" field in "struct logical_volume"
This references an existing generic_logical_volume wrapper for this
LV, if used. It can be NULL if not needed - which means we're not
handling historical LVs at all.
- new "historical_lvs" field in "struct volume group
List of all historical LVs read from VG metadata.
-rw-r--r-- | lib/metadata/lv.h | 48 | ||||
-rw-r--r-- | lib/metadata/lv_manip.c | 1 | ||||
-rw-r--r-- | lib/metadata/metadata-exported.h | 6 | ||||
-rw-r--r-- | lib/metadata/vg.c | 1 | ||||
-rw-r--r-- | lib/metadata/vg.h | 1 | ||||
-rw-r--r-- | lib/report/report.c | 2 | ||||
-rw-r--r-- | tools/reporter.c | 2 |
7 files changed, 61 insertions, 0 deletions
diff --git a/lib/metadata/lv.h b/lib/metadata/lv.h index 4b42eb7f5..f554bcef6 100644 --- a/lib/metadata/lv.h +++ b/lib/metadata/lv.h @@ -49,6 +49,15 @@ struct logical_volume { struct dm_list segments; struct dm_list tags; struct dm_list segs_using_this_lv; + struct dm_list indirect_glvs; /* For keeping track of historical LVs in ancestry chain */ + + /* + * this_glv variable is used as a helper for handling historical LVs. + * If this LVs has no role at all in keeping track of historical LVs, + * the this_glv variable is NULL. See also comments for struct + * generic_logical_volume and struct historical_logical_volume below. + */ + struct generic_logical_volume *this_glv; uint64_t timestamp; unsigned new_lock_args:1; @@ -56,6 +65,45 @@ struct logical_volume { const char *lock_args; }; +/* + * With the introduction of tracking historical LVs, we need to make + * a difference between live LV (struct logical_volume) and historical LV + * (struct historical_logical_volume). To minimize the impact of this change + * and to minimize the changes needed in the existing code, we use a + * little trick here - when processing LVs (e.g. while reporting LV + * properties), each historical LV is represented as dummy LV which is + * an instance of struct logical_volume with all its properties set to + * blank (hence "dummy LV") and with this_glv pointing to the struct + * historical_logical_volume. This way all the existing code working with + * struct logical_volume will see this historical LV as dummy live LV while + * the code that needs to recognize between live and historical LV will + * check this_glv first and then it will work either with the live + * or historical LV properties appropriately. + */ +struct generic_logical_volume; + +/* + * historical logical volume is an LV that has been removed already. + * This is used to keep track of LV history. + */ +struct historical_logical_volume { + union lvid lvid; + const char *name; + struct volume_group *vg; + uint64_t timestamp; + uint64_t timestamp_removed; + struct generic_logical_volume *indirect_origin; + struct dm_list indirect_glvs; /* list of struct generic_logical_volume */ +}; + +struct generic_logical_volume { + int is_historical; + union { + struct logical_volume *live; /* is_historical=0 */ + struct historical_logical_volume *historical; /* is_historical=1 */ + }; +}; + struct lv_with_info_and_seg_status; /* LV dependencies */ diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 1b431c1b4..069042c0f 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -5320,6 +5320,7 @@ struct logical_volume *alloc_lv(struct dm_pool *mem) dm_list_init(&lv->segments); dm_list_init(&lv->tags); dm_list_init(&lv->segs_using_this_lv); + dm_list_init(&lv->indirect_glvs); dm_list_init(&lv->rsites); return lv; diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index 8376a54e6..97cba5117 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -447,6 +447,7 @@ struct lv_segment { uint32_t chunk_size; /* For snapshots/thin_pool. In sectors. */ /* For thin_pool, 128..2097152. */ struct logical_volume *origin; /* snap and thin */ + struct generic_logical_volume *indirect_origin; struct logical_volume *merge_lv; /* thin, merge descendent lv into this ancestor */ struct logical_volume *cow; struct dm_list origin_list; @@ -505,6 +506,11 @@ struct lv_list { struct logical_volume *lv; }; +struct glv_list { + struct dm_list list; + struct generic_logical_volume *glv; +}; + struct vg_list { struct dm_list list; struct volume_group *vg; diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c index 1456fbb50..90c459e19 100644 --- a/lib/metadata/vg.c +++ b/lib/metadata/vg.c @@ -64,6 +64,7 @@ struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd, dm_list_init(&vg->pv_write_list); dm_list_init(&vg->pvs_outdated); dm_list_init(&vg->lvs); + dm_list_init(&vg->historical_lvs); dm_list_init(&vg->tags); dm_list_init(&vg->removed_lvs); dm_list_init(&vg->removed_pvs); diff --git a/lib/metadata/vg.h b/lib/metadata/vg.h index f41def8e7..c5197cb33 100644 --- a/lib/metadata/vg.h +++ b/lib/metadata/vg.h @@ -128,6 +128,7 @@ struct volume_group { * - one for the user-visible mirror LV */ struct dm_list lvs; + struct dm_list historical_lvs; struct dm_list tags; diff --git a/lib/report/report.c b/lib/report/report.c index 43987b1d3..056afd2d3 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -3386,6 +3386,7 @@ static struct volume_group _dummy_vg = { .lvm1_system_id = (char *) "", .pvs = DM_LIST_HEAD_INIT(_dummy_vg.pvs), .lvs = DM_LIST_HEAD_INIT(_dummy_vg.lvs), + .historical_lvs = DM_LIST_HEAD_INIT(_dummy_vg.historical_lvs), .tags = DM_LIST_HEAD_INIT(_dummy_vg.tags), }; @@ -3396,6 +3397,7 @@ static struct volume_group _unknown_vg = { .lvm1_system_id = (char *) "", .pvs = DM_LIST_HEAD_INIT(_unknown_vg.pvs), .lvs = DM_LIST_HEAD_INIT(_unknown_vg.lvs), + .historical_lvs = DM_LIST_HEAD_INIT(_unknown_vg.historical_lvs), .tags = DM_LIST_HEAD_INIT(_unknown_vg.tags), }; diff --git a/tools/reporter.c b/tools/reporter.c index 1a24698b3..0c73a0955 100644 --- a/tools/reporter.c +++ b/tools/reporter.c @@ -244,6 +244,7 @@ static int _do_pvsegs_sub_single(struct cmd_context *cmd, .name = "", .pvs = DM_LIST_HEAD_INIT(_free_vg.pvs), .lvs = DM_LIST_HEAD_INIT(_free_vg.lvs), + .historical_lvs = DM_LIST_HEAD_INIT(_free_vg.historical_lvs), .tags = DM_LIST_HEAD_INIT(_free_vg.tags), }; @@ -256,6 +257,7 @@ static int _do_pvsegs_sub_single(struct cmd_context *cmd, .tags = DM_LIST_HEAD_INIT(_free_logical_volume.tags), .segments = DM_LIST_HEAD_INIT(_free_logical_volume.segments), .segs_using_this_lv = DM_LIST_HEAD_INIT(_free_logical_volume.segs_using_this_lv), + .indirect_glvs = DM_LIST_HEAD_INIT(_free_logical_volume.indirect_glvs), .snapshot_segs = DM_LIST_HEAD_INIT(_free_logical_volume.snapshot_segs), }; |