mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-02 01:18:26 +03:00
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.
This commit is contained in:
parent
5e718ec666
commit
e573eca554
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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),
|
||||
};
|
||||
|
||||
|
@ -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),
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user