master - toollib: honour '-H|--history' switch while executing process_each_lv_in_vg
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=2e7a1210622e25...
Commit: 2e7a1210622e25a5a3d813b9a069767eaad3b4ac
Parent: f7e0a4cc1809c371a4aee2a3da8a3545379fcfbf
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Mar 1 15:23:05 2016 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Mar 3 13:49:14 2016 +0100
toollib: honour '-H|--history' switch while executing process_each_lv_in_vg
When processing LVs in a VG and when the -H|--history switch is used,
make process_each_lv_in_vg to iterate over historical volumes too.
For each historical LV, we use dummy struct logical_volume instance with
the "this_glv" reference set to a wrapper over proper struct
historical_logical_volume representation. This makes it possible to process
historical LVs just like normal live LVs (though a dummy one without any
segments and all the other fields zeroed and blank) and it also allows
for using all historical LV related information via lv->this_glv->historical
reference.
One can use a simple call to lv_is_historical to make a difference between
live and historical LV in all the code that is called by process_each_* fns.
---
tools/toollib.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 85 insertions(+), 0 deletions(-)
diff --git a/tools/toollib.c b/tools/toollib.c
index 3833581..9e866d6 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -2180,6 +2180,48 @@ out:
return ret_max;
}
+static struct dm_str_list *_str_list_match_item_with_prefix(const struct dm_list *sll, const char *prefix, const char *str)
+{
+ struct dm_str_list *sl;
+ size_t prefix_len = strlen(prefix);
+
+ dm_list_iterate_items(sl, sll) {
+ if (!strncmp(prefix, sl->str, prefix_len) &&
+ !strcmp(sl->str + prefix_len, str))
+ return sl;
+ }
+
+ return NULL;
+}
+
+/*
+ * Dummy LV, segment type and segment to represent all historical LVs.
+ */
+static struct logical_volume _historical_lv = {
+ .name = "",
+ .major = -1,
+ .minor = -1,
+ .snapshot_segs = DM_LIST_HEAD_INIT(_historical_lv.snapshot_segs),
+ .segments = DM_LIST_HEAD_INIT(_historical_lv.segments),
+ .tags = DM_LIST_HEAD_INIT(_historical_lv.tags),
+ .segs_using_this_lv = DM_LIST_HEAD_INIT(_historical_lv.segs_using_this_lv),
+ .indirect_glvs = DM_LIST_HEAD_INIT(_historical_lv.indirect_glvs),
+ .hostname = "",
+};
+
+static struct segment_type _historical_segment_type = {
+ .name = "historical",
+ .flags = SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED,
+};
+
+static struct lv_segment _historical_lv_segment = {
+ .lv = &_historical_lv,
+ .segtype = &_historical_segment_type,
+ .len = 0,
+ .tags = DM_LIST_HEAD_INIT(_historical_lv_segment.tags),
+ .origin_list = DM_LIST_HEAD_INIT(_historical_lv_segment.origin_list),
+};
+
int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
struct dm_list *arg_lvnames, const struct dm_list *tags_in,
int stop_on_error,
@@ -2199,6 +2241,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
struct dm_str_list *sl;
struct dm_list final_lvs;
struct lv_list *final_lvl;
+ struct glv_list *glvl, *tglvl;
dm_list_init(&final_lvs);
@@ -2340,6 +2383,48 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
goto_out;
}
+ if (handle->include_historical_lvs && !tags_supplied) {
+ if (!dm_list_size(&_historical_lv.segments))
+ dm_list_add(&_historical_lv.segments, &_historical_lv_segment.list);
+ _historical_lv.vg = vg;
+
+ dm_list_iterate_items_safe(glvl, tglvl, &vg->historical_lvs) {
+ process_lv = process_all;
+
+ if (lvargs_supplied &&
+ (sl = _str_list_match_item_with_prefix(arg_lvnames, HISTORICAL_LV_PREFIX, glvl->glv->historical->name))) {
+ str_list_del(arg_lvnames, glvl->glv->historical->name);
+ dm_list_del(&sl->list);
+ process_lv = 1;
+ }
+
+ process_lv = process_lv && select_match_lv(cmd, handle, vg, lvl->lv, &selected) && selected;
+
+ if (sigint_caught()) {
+ ret_max = ECMD_FAILED;
+ goto_out;
+ }
+
+ if (!process_lv)
+ continue;
+
+ _historical_lv.this_glv = glvl->glv;
+ _historical_lv.name = glvl->glv->historical->name;
+ log_very_verbose("Processing historical LV %s in VG %s.", glvl->glv->historical->name, vg->name);
+
+ ret = process_single_lv(cmd, &_historical_lv, handle);
+ if (handle_supplied)
+ _update_selection_result(handle, &whole_selected);
+ if (ret != ECMD_PROCESSED)
+ stack;
+ if (ret > ret_max)
+ ret_max = ret;
+
+ if (stop_on_error && ret != ECMD_PROCESSED)
+ goto_out;
+ }
+ }
+
if (lvargs_supplied) {
/*
* FIXME: lvm supports removal of LV with all its dependencies
7 years
master - cmd: add '-H|--history' switch and wire it up in cmd_context and processing_handle
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=f7e0a4cc1809c3...
Commit: f7e0a4cc1809c371a4aee2a3da8a3545379fcfbf
Parent: baee45a103846a995b847e04c1c2985bfd1743e0
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Mar 1 15:22:48 2016 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Mar 3 13:49:14 2016 +0100
cmd: add '-H|--history' switch and wire it up in cmd_context and processing_handle
This patch adds "include_historical_lvs" field to struct cmd_context to
make it possible for the command to switch between original funcionality
where no historical LVs are processed and functionality where historical
LVs are taken into account (and reported or processed further). The switch
between these modes is done using the '-H|--history' switch on command
line.
The include_historical_lvs state is then passed to process_each_* fns
using the "include_historical_lvs" field within struct processing_handle.
---
lib/commands/toolcontext.h | 1 +
tools/args.h | 1 +
tools/lvmcmdline.c | 1 +
tools/reporter.c | 5 +++++
tools/toollib.c | 1 +
tools/toollib.h | 1 +
6 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index 5fda9a9..b5328e8 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -128,6 +128,7 @@ struct cmd_context {
unsigned threaded:1; /* set if running within a thread e.g. clvmd */
unsigned independent_metadata_areas:1; /* active formats have MDAs outside PVs */
unsigned unknown_system_id:1;
+ unsigned include_historical_lvs:1; /* also process/report/display historical LVs */
unsigned include_foreign_vgs:1; /* report/display cmds can reveal foreign VGs */
unsigned include_shared_vgs:1; /* report/display cmds can reveal lockd VGs */
unsigned include_active_foreign_vgs:1; /* cmd should process foreign VGs with active LVs */
diff --git a/tools/args.h b/tools/args.h
index 68de524..8dfe744 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -163,6 +163,7 @@ arg(force_ARG, 'f', "force", NULL, ARG_COUNTABLE)
arg(full_ARG, 'f', "full", NULL, 0)
arg(help_ARG, 'h', "help", NULL, 0)
arg(cache_ARG, 'H', "cache", NULL, 0)
+arg(history_ARG, 'H', "history", NULL, 0)
arg(help2_ARG, '?', "", NULL, 0)
arg(interval_ARG, 'i', "interval", int_arg, 0)
arg(iop_version_ARG, 'i', "iop_version", NULL, 0)
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 29c1c7e..4a5cd23 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -1101,6 +1101,7 @@ static int _get_settings(struct cmd_context *cmd)
cmd->ignore_clustered_vgs = arg_is_set(cmd, ignoreskippedcluster_ARG);
cmd->include_foreign_vgs = arg_is_set(cmd, foreign_ARG) ? 1 : 0;
cmd->include_shared_vgs = arg_is_set(cmd, shared_ARG) ? 1 : 0;
+ cmd->include_historical_lvs = arg_is_set(cmd, history_ARG) ? 1 : 0;
/*
* This is set to zero by process_each which wants to print errors
diff --git a/tools/reporter.c b/tools/reporter.c
index 0c73a09..1a708c4 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -65,6 +65,10 @@ static int _do_info_and_status(struct cmd_context *cmd,
unsigned use_layer = lv_is_thin_pool(lv) ? 1 : 0;
status->lv = lv;
+
+ if (lv_is_historical(lv))
+ return 1;
+
if (do_status) {
if (!(status->seg_status.mem = dm_pool_create("reporter_pool", 1024)))
return_0;
@@ -866,6 +870,7 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
}
handle.internal_report_for_select = 0;
+ handle.include_historical_lvs = cmd->include_historical_lvs;
handle.custom_handle = report_handle;
switch (report_type) {
diff --git a/tools/toollib.c b/tools/toollib.c
index dba5023..3833581 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1692,6 +1692,7 @@ struct processing_handle *init_processing_handle(struct cmd_context *cmd)
* *The internal report for select is only needed for non-reporting tools!*
*/
handle->internal_report_for_select = arg_is_set(cmd, select_ARG);
+ handle->include_historical_lvs = cmd->include_historical_lvs;
return handle;
}
diff --git a/tools/toollib.h b/tools/toollib.h
index a67b3e6..19f4dd0 100644
--- a/tools/toollib.h
+++ b/tools/toollib.h
@@ -70,6 +70,7 @@ int become_daemon(struct cmd_context *cmd, int skip_lvm);
*/
struct processing_handle {
int internal_report_for_select;
+ int include_historical_lvs;
struct selection_handle *selection_handle;
void *custom_handle;
};
7 years
master - metadata: add lv_is_historical fn to test if the LV is historical one
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=baee45a103846a...
Commit: baee45a103846a995b847e04c1c2985bfd1743e0
Parent: 673bc0636cf1a73321656b2129a6db1681fbd8f4
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Mar 1 15:22:36 2016 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Mar 3 13:49:14 2016 +0100
metadata: add lv_is_historical fn to test if the LV is historical one
---
lib/metadata/lv.c | 5 +++++
lib/metadata/metadata-exported.h | 2 ++
lib/metadata/snapshot_manip.c | 3 +++
3 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index 459de6e..a5144e9 100644
--- a/lib/metadata/lv.c
+++ b/lib/metadata/lv.c
@@ -28,6 +28,11 @@
static struct utsname _utsname;
static int _utsinit = 0;
+int lv_is_historical(const struct logical_volume *lv)
+{
+ return lv->this_glv && lv->this_glv->is_historical;
+}
+
static struct dm_list *_format_pvsegs(struct dm_pool *mem, const struct lv_segment *seg,
int range_format, int metadata_areas_only,
int mark_hidden)
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index afd4723..b8699f7 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -1066,6 +1066,8 @@ int lv_is_cow_covering_origin(const struct logical_volume *lv);
/* Test if given LV is visible from user's perspective */
int lv_is_visible(const struct logical_volume *lv);
+int lv_is_historical(const struct logical_volume *lv);
+
int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv);
/* Given a cow or thin LV, return the snapshot lv_segment that uses it */
diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c
index 5fef001..e8a4dc5 100644
--- a/lib/metadata/snapshot_manip.c
+++ b/lib/metadata/snapshot_manip.c
@@ -113,6 +113,9 @@ int lv_is_cow_covering_origin(const struct logical_volume *lv)
int lv_is_visible(const struct logical_volume *lv)
{
+ if (lv_is_historical(lv))
+ return 1;
+
if (lv->status & SNAPSHOT)
return 0;
7 years
master - metadata: format_text: interconnect historical LVs among each other and also with live LVs
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=673bc0636cf1a7...
Commit: 673bc0636cf1a73321656b2129a6db1681fbd8f4
Parent: a61bc70f62a1648632985fa7ac81b89773da6d78
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Mar 1 15:22:28 2016 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Mar 3 13:49:13 2016 +0100
metadata: format_text: interconnect historical LVs among each other and also with live LVs
Interconnect historical LVs in an ancestry chain and also connect the first/last
one with its live ancestor/descendant if it exists.
---
lib/format_text/import_vsn1.c | 119 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 119 insertions(+), 0 deletions(-)
diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
index 3bc38b9..163ea38 100644
--- a/lib/format_text/import_vsn1.c
+++ b/lib/format_text/import_vsn1.c
@@ -770,6 +770,118 @@ bad:
return 0;
}
+static int _read_historical_lvnames_interconnections(struct format_instance *fid __attribute__((unused)),
+ struct volume_group *vg, const struct dm_config_node *hlvn,
+ const struct dm_config_node *vgn __attribute__((unused)),
+ struct dm_hash_table *pv_hash __attribute__((unused)),
+ struct dm_hash_table *lv_hash __attribute__((unused)),
+ unsigned *scan_done_once __attribute__((unused)),
+ unsigned report_missing_devices __attribute__((unused)))
+{
+ struct dm_pool *mem = vg->vgmem;
+ const char *historical_lv_name, *origin_name = NULL;
+ struct generic_logical_volume *glv, *origin_glv, *descendant_glv;
+ struct logical_volume *tmp_lv;
+ struct glv_list *glvl = NULL;
+ const struct dm_config_value *descendants = NULL;
+
+ historical_lv_name = hlvn->key;
+ hlvn = hlvn->child;
+
+ if (!(glv = find_historical_glv(vg, historical_lv_name, NULL))) {
+ log_error("Unknown historical logical volume %s/%s%s",
+ vg->name, HISTORICAL_LV_PREFIX, historical_lv_name);
+ goto bad;
+ }
+
+ if (dm_config_has_node(hlvn, "origin")) {
+ if (!dm_config_get_str(hlvn, "origin", &origin_name)) {
+ log_error("Couldn't read origin for historical logical "
+ "volume %s/%s%s", vg->name, HISTORICAL_LV_PREFIX, historical_lv_name);
+ goto bad;
+ }
+ }
+
+ if (dm_config_has_node(hlvn, "descendants")) {
+ if (!dm_config_get_list(hlvn, "descendants", &descendants)) {
+ log_error("Couldn't get descendants list for historical logical "
+ "volume %s/%s%s", vg->name, HISTORICAL_LV_PREFIX, historical_lv_name);
+ goto bad;
+ }
+ if (descendants->type == DM_CFG_EMPTY_ARRAY) {
+ log_error("Found empty descendants list for historical logical "
+ "volume %s/%s%s", vg->name, HISTORICAL_LV_PREFIX, historical_lv_name);
+ goto bad;
+ }
+ }
+
+ if (!origin_name && !descendants)
+ /* no interconnections */
+ return 1;
+
+ if (origin_name) {
+ if (!(glvl = dm_pool_zalloc(mem, sizeof(struct glv_list)))) {
+ log_error("Failed to allocate list item for historical logical "
+ "volume %s/%s%s", vg->name, HISTORICAL_LV_PREFIX, historical_lv_name);
+ goto bad;
+ }
+ glvl->glv = glv;
+
+ if (!strncmp(origin_name, HISTORICAL_LV_PREFIX, strlen(HISTORICAL_LV_PREFIX))) {
+ if (!(origin_glv = find_historical_glv(vg, origin_name + strlen(HISTORICAL_LV_PREFIX), NULL))) {
+ log_error("Unknown origin %s for historical logical volume %s/%s%s",
+ origin_name, vg->name, HISTORICAL_LV_PREFIX, historical_lv_name);
+ goto bad;
+ }
+ } else {
+ if (!(tmp_lv = find_lv(vg, origin_name))) {
+ log_error("Unknown origin %s for historical logical volume %s/%s%s",
+ origin_name, vg->name, HISTORICAL_LV_PREFIX, historical_lv_name);
+ goto bad;
+ }
+
+ if (!(origin_glv = get_or_create_glv(mem, tmp_lv, NULL)))
+ goto bad;
+ }
+
+ glv->historical->indirect_origin = origin_glv;
+ if (origin_glv->is_historical)
+ dm_list_add(&origin_glv->historical->indirect_glvs, &glvl->list);
+ else
+ dm_list_add(&origin_glv->live->indirect_glvs, &glvl->list);
+ }
+
+ if (descendants) {
+ do {
+ if (descendants->type != DM_CFG_STRING) {
+ log_error("Descendant value for historical logical volume %s/%s%s "
+ "is not a string.", vg->name, HISTORICAL_LV_PREFIX, historical_lv_name);
+ goto bad;
+ }
+
+ if (!(tmp_lv = find_lv(vg, descendants->v.str))) {
+ log_error("Failed to find descendant %s for historical LV %s.",
+ descendants->v.str, historical_lv_name);
+ goto bad;
+ }
+
+ if (!(descendant_glv = get_or_create_glv(mem, tmp_lv, NULL)))
+ goto bad;
+
+ if (!add_glv_to_indirect_glvs(mem, glv, descendant_glv))
+ goto bad;
+
+ descendants = descendants->next;
+ } while (descendants);
+ }
+
+ return 1;
+bad:
+ if (glvl)
+ dm_pool_free(mem, glvl);
+ return 0;
+}
+
static int _read_lvsegs(struct format_instance *fid,
struct volume_group *vg, const struct dm_config_node *lvn,
const struct dm_config_node *vgn __attribute__((unused)),
@@ -1067,6 +1179,13 @@ static struct volume_group *_read_vg(struct format_instance *fid,
goto bad;
}
+ if (!_read_sections(fid, "historical_logical_volumes", _read_historical_lvnames_interconnections,
+ vg, vgn, pv_hash, lv_hash, 1, NULL)) {
+ log_error("Couldn't read all removed logical volume interconnections "
+ "for volume group %s.", vg->name);
+ goto bad;
+ }
+
if (!fixup_imported_mirrors(vg)) {
log_error("Failed to fixup mirror pointers after import for "
"volume group %s.", vg->name);
7 years
master - metadata: add support for interconnection of thin pool LV segment with indirect origin
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=a61bc70f62a164...
Commit: a61bc70f62a1648632985fa7ac81b89773da6d78
Parent: c45af2df4ee1f3a7cf1e979ce5312acdc392ba68
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Mar 1 15:21:36 2016 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Mar 3 13:46:40 2016 +0100
metadata: add support for interconnection of thin pool LV segment with indirect origin
Add support for making an interconnection between thin LV segment and
its indirect origin (which may be historical or live LV) - add a new
"indirect_origin" argument to attach_pool_lv function.
---
lib/cache_segtype/cache.c | 2 +-
lib/metadata/cache_manip.c | 4 ++--
lib/metadata/lv_manip.c | 4 ++--
lib/metadata/metadata.h | 4 +++-
lib/metadata/pool_manip.c | 15 +++++++++++++++
lib/thin/thin.c | 3 ++-
6 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/lib/cache_segtype/cache.c b/lib/cache_segtype/cache.c
index 17d1b31..a645756 100644
--- a/lib/cache_segtype/cache.c
+++ b/lib/cache_segtype/cache.c
@@ -348,7 +348,7 @@ static int _cache_text_import(struct lv_segment *seg,
seg->lv->status |= strstr(seg->lv->name, "_corig") ? LV_PENDING_DELETE : 0;
- if (!attach_pool_lv(seg, pool_lv, NULL, NULL))
+ if (!attach_pool_lv(seg, pool_lv, NULL, NULL, NULL))
return_0;
if (!dm_list_empty(&pool_lv->segments) &&
diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c
index 4fe8613..115abcb 100644
--- a/lib/metadata/cache_manip.c
+++ b/lib/metadata/cache_manip.c
@@ -273,7 +273,7 @@ struct logical_volume *lv_cache_create(struct logical_volume *pool_lv,
seg = first_seg(cache_lv);
seg->segtype = segtype;
- if (!attach_pool_lv(seg, pool_lv, NULL, NULL))
+ if (!attach_pool_lv(seg, pool_lv, NULL, NULL, NULL))
return_NULL;
return cache_lv;
@@ -424,7 +424,7 @@ int lv_cache_remove(struct logical_volume *cache_lv)
corigin_lv->status |= LV_PENDING_DELETE;
/* Reattach cache pool */
- if (!attach_pool_lv(cache_seg, cache_pool_lv, NULL, NULL))
+ if (!attach_pool_lv(cache_seg, cache_pool_lv, NULL, NULL, NULL))
return_0;
/* Suspend/resume also deactivates deleted LV via support of LV_PENDING_DELETE */
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 399668c..ed46ad3 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -7335,13 +7335,13 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
if (origin_lv && lv_is_thin_volume(origin_lv) &&
(first_seg(origin_lv)->pool_lv == pool_lv)) {
/* For thin snapshot pool must match */
- if (!attach_pool_lv(seg, pool_lv, origin_lv, NULL))
+ if (!attach_pool_lv(seg, pool_lv, origin_lv, NULL, NULL))
return_NULL;
/* Use the same external origin */
if (!attach_thin_external_origin(seg, first_seg(origin_lv)->external_lv))
return_NULL;
} else {
- if (!attach_pool_lv(seg, pool_lv, NULL, NULL))
+ if (!attach_pool_lv(seg, pool_lv, NULL, NULL, NULL))
return_NULL;
/* If there is an external origin... */
if (!attach_thin_external_origin(seg, origin_lv))
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 33cbfa6..31c9346 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -487,7 +487,9 @@ int fixup_imported_mirrors(struct volume_group *vg);
* From thin_manip.c
*/
int attach_pool_lv(struct lv_segment *seg, struct logical_volume *pool_lv,
- struct logical_volume *origin_lv, struct logical_volume *merge_lv);
+ struct logical_volume *origin_lv,
+ struct generic_logical_volume *indirect_origin,
+ struct logical_volume *merge_lv);
int detach_pool_lv(struct lv_segment *seg);
int attach_pool_message(struct lv_segment *pool_seg, dm_thin_message_t type,
struct logical_volume *lv, uint32_t delete_id,
diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
index 20bb756..ac590b3 100644
--- a/lib/metadata/pool_manip.c
+++ b/lib/metadata/pool_manip.c
@@ -90,8 +90,11 @@ int attach_pool_data_lv(struct lv_segment *pool_seg,
int attach_pool_lv(struct lv_segment *seg,
struct logical_volume *pool_lv,
struct logical_volume *origin,
+ struct generic_logical_volume *indirect_origin,
struct logical_volume *merge_lv)
{
+ struct glv_list *glvl;
+
if (!seg_is_thin_volume(seg) && !seg_is_cache(seg)) {
log_error(INTERNAL_ERROR "Unable to attach pool to %s/%s"
" that is not cache or thin volume.",
@@ -109,6 +112,18 @@ int attach_pool_lv(struct lv_segment *seg,
if (origin && !add_seg_to_segs_using_this_lv(origin, seg))
return_0;
+ if (indirect_origin) {
+ if (!(glvl = get_or_create_glvl(seg->lv->vg->vgmem, seg->lv, NULL)))
+ return_0;
+
+ seg->indirect_origin = indirect_origin;
+ if (indirect_origin->is_historical)
+ dm_list_add(&indirect_origin->historical->indirect_glvs, &glvl->list);
+ else
+ dm_list_add(&indirect_origin->live->indirect_glvs, &glvl->list);
+
+ }
+
if (!add_seg_to_segs_using_this_lv(pool_lv, seg))
return_0;
diff --git a/lib/thin/thin.c b/lib/thin/thin.c
index 6a19055..a850757 100644
--- a/lib/thin/thin.c
+++ b/lib/thin/thin.c
@@ -473,6 +473,7 @@ static int _thin_text_import(struct lv_segment *seg,
{
const char *lv_name;
struct logical_volume *pool_lv, *origin = NULL, *external_lv = NULL, *merge_lv = NULL;
+ struct generic_logical_volume *indirect_origin = NULL;
if (!dm_config_get_str(sn, "thin_pool", &lv_name))
return SEG_LOG_ERROR("Thin pool must be a string in");
@@ -513,7 +514,7 @@ static int _thin_text_import(struct lv_segment *seg,
return SEG_LOG_ERROR("Unknown external origin %s in", lv_name);
}
- if (!attach_pool_lv(seg, pool_lv, origin, merge_lv))
+ if (!attach_pool_lv(seg, pool_lv, origin, indirect_origin, merge_lv))
return_0;
if (!attach_thin_external_origin(seg, external_lv))
7 years
master - metadata: add find_historical_glv fn
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=c45af2df4ee1f3...
Commit: c45af2df4ee1f3a7cf1e979ce5312acdc392ba68
Parent: a0842d1f259c467cb02a8dd94e3a53f543ade7fb
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Mar 1 15:21:21 2016 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Mar 3 13:46:39 2016 +0100
metadata: add find_historical_glv fn
The find_historical_glv is helper function that looks up historical
LV in struct volume_group's historical_lvs list and returns it if
found.
---
lib/metadata/metadata-exported.h | 5 +++++
lib/metadata/metadata.c | 26 ++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 0 deletions(-)
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 7f1d43c..afd4723 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -1026,6 +1026,11 @@ struct lv_list *find_lv_in_vg(const struct volume_group *vg,
/* FIXME Merge these functions with ones above */
struct logical_volume *find_lv(const struct volume_group *vg,
const char *lv_name);
+
+struct generic_logical_volume *find_historical_glv(const struct volume_group *vg,
+ const char *historical_lv_name,
+ struct glv_list **glvl_found);
+
struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
const char *pv_name,
int allow_orphan, int allow_unformatted);
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 0d2211a..8b3c53c 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -2120,6 +2120,32 @@ struct logical_volume *find_lv(const struct volume_group *vg,
return lvl ? lvl->lv : NULL;
}
+struct generic_logical_volume *find_historical_glv(const struct volume_group *vg,
+ const char *historical_lv_name,
+ struct glv_list **glvl_found)
+{
+ struct glv_list *glvl;
+ const char *ptr;
+
+ /* Use last component */
+ if ((ptr = strrchr(historical_lv_name, '/')))
+ ptr++;
+ else
+ ptr = historical_lv_name;
+
+ dm_list_iterate_items(glvl, &vg->historical_lvs) {
+ if (!strcmp(glvl->glv->historical->name, ptr)) {
+ if (glvl_found)
+ *glvl_found = glvl;
+ return glvl->glv;
+ }
+ }
+
+ if (glvl_found)
+ *glvl_found = NULL;
+ return NULL;
+}
+
struct physical_volume *find_pv(struct volume_group *vg, struct device *dev)
{
struct pv_list *pvl;
7 years
master - metadata: format_text: import historical LVs
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=a0842d1f259c46...
Commit: a0842d1f259c467cb02a8dd94e3a53f543ade7fb
Parent: 54d3d976c71d45748fef267b5c35a49467e781c5
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Mar 1 15:54:02 2016 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Mar 3 13:46:39 2016 +0100
metadata: format_text: import historical LVs
Import historical LV list from metadata and add it to struct
volume_group's historical_lvs list.
---
lib/format_text/import_vsn1.c | 78 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 78 insertions(+), 0 deletions(-)
diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
index 71181bd..3bc38b9 100644
--- a/lib/format_text/import_vsn1.c
+++ b/lib/format_text/import_vsn1.c
@@ -699,6 +699,77 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)),
return 1;
}
+static int _read_historical_lvnames(struct format_instance *fid __attribute__((unused)),
+ struct volume_group *vg, const struct dm_config_node *hlvn,
+ const struct dm_config_node *vgn __attribute__((unused)),
+ struct dm_hash_table *pv_hash __attribute__((unused)),
+ struct dm_hash_table *lv_hash __attribute__((unused)),
+ unsigned *scan_done_once __attribute__((unused)),
+ unsigned report_missing_devices __attribute__((unused)))
+{
+ struct dm_pool *mem = vg->vgmem;
+ struct generic_logical_volume *glv;
+ struct glv_list *glvl;
+ const char *str;
+ uint64_t timestamp;
+
+ if (!(glv = dm_pool_zalloc(mem, sizeof(struct generic_logical_volume))) ||
+ !(glv->historical = dm_pool_zalloc(mem, sizeof(struct historical_logical_volume))) ||
+ !(glvl = dm_pool_zalloc(mem, sizeof(struct glv_list)))) {
+ log_error("Removed logical volume structure allocation failed");
+ goto bad;
+ }
+
+ glv->is_historical = 1;
+ glv->historical->vg = vg;
+ dm_list_init(&glv->historical->indirect_glvs);
+
+ if (!(glv->historical->name = dm_pool_strdup(mem, hlvn->key)))
+ goto_bad;
+
+ if (!(hlvn = hlvn->child)) {
+ log_error("Empty removed logical volume section.");
+ goto_bad;
+ }
+
+ if (!_read_id(&glv->historical->lvid.id[1], hlvn, "id")) {
+ log_error("Couldn't read uuid for removed logical volume %s in vg %s.",
+ glv->historical->name, vg->name);
+ return 0;
+ }
+ memcpy(&glv->historical->lvid.id[0], &glv->historical->vg->id, sizeof(glv->historical->lvid.id[0]));
+
+ if (dm_config_get_str(hlvn, "name", &str)) {
+ if (!(glv->historical->name = dm_pool_strdup(mem, str)))
+ goto_bad;
+ }
+
+ if (dm_config_has_node(hlvn, "creation_time")) {
+ if (!_read_uint64(hlvn, "creation_time", ×tamp)) {
+ log_error("Invalid creation_time for removed logical volume %s.", str);
+ goto bad;
+ }
+ glv->historical->timestamp = timestamp;
+ }
+
+ if (dm_config_has_node(hlvn, "removal_time")) {
+ if (!_read_uint64(hlvn, "removal_time", ×tamp)) {
+ log_error("Invalid removal_time for removed logical volume %s.", str);
+ goto bad;
+ }
+ glv->historical->timestamp_removed = timestamp;
+ }
+
+ glvl->glv = glv;
+ dm_list_add(&vg->historical_lvs, &glvl->list);
+
+ return 1;
+bad:
+ if (glv)
+ dm_pool_free(mem, glv);
+ return 0;
+}
+
static int _read_lvsegs(struct format_instance *fid,
struct volume_group *vg, const struct dm_config_node *lvn,
const struct dm_config_node *vgn __attribute__((unused)),
@@ -982,6 +1053,13 @@ static struct volume_group *_read_vg(struct format_instance *fid,
goto bad;
}
+ if (!_read_sections(fid, "historical_logical_volumes", _read_historical_lvnames, vg,
+ vgn, pv_hash, lv_hash, 1, NULL)) {
+ log_error("Couldn't read all historical logical volumes for volume "
+ "group %s.", vg->name);
+ goto bad;
+ }
+
if (!_read_sections(fid, "logical_volumes", _read_lvsegs, vg,
vgn, pv_hash, lv_hash, 1, NULL)) {
log_error("Couldn't read all logical volumes for "
7 years
master - metadata: format_text: reuse _print_timestamp fn
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=54d3d976c71d45...
Commit: 54d3d976c71d45748fef267b5c35a49467e781c5
Parent: 3a0ef77305b179511aae6d8e5af05bbbebabee6b
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Mar 1 15:21:05 2016 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Mar 3 13:46:39 2016 +0100
metadata: format_text: reuse _print_timestamp fn
---
lib/format_text/export.c | 14 +++-----------
1 files changed, 3 insertions(+), 11 deletions(-)
diff --git a/lib/format_text/export.c b/lib/format_text/export.c
index f17ccf5..c4c7b38 100644
--- a/lib/format_text/export.c
+++ b/lib/format_text/export.c
@@ -675,8 +675,6 @@ static int _print_lv(struct formatter *f, struct logical_volume *lv)
struct lv_segment *seg;
char buffer[4096];
int seg_count;
- struct tm *local_tm;
- time_t ts;
uint64_t status = lv->status;
outnl(f);
@@ -705,16 +703,10 @@ static int _print_lv(struct formatter *f, struct logical_volume *lv)
return_0;
if (lv->timestamp) {
- ts = (time_t)lv->timestamp;
- strncpy(buffer, "# ", sizeof(buffer));
- if (!(local_tm = localtime(&ts)) ||
- !strftime(buffer + 2, sizeof(buffer) - 2,
- "%Y-%m-%d %T %z", local_tm))
- buffer[0] = 0;
-
+ if (!_print_timestamp(f, "creation_time", lv->timestamp,
+ buffer, sizeof(buffer)))
+ return_0;
outf(f, "creation_host = \"%s\"", lv->hostname);
- outfc(f, buffer, "creation_time = %" PRIu64,
- lv->timestamp);
}
if (lv->lock_args)
7 years
master - metadata: format_text: also export historical LVs
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=3a0ef77305b179...
Commit: 3a0ef77305b179511aae6d8e5af05bbbebabee6b
Parent: 790b2e874822767808f3c5bcc4ce1499944969ff
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Mar 1 15:20:49 2016 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Mar 3 13:46:18 2016 +0100
metadata: format_text: also export historical LVs
Also export historical LVs when exporting LVM2 metadata.
This is list of all historical LVs listed in
"historical_logical_volumes" metadata section with all
the properties exported for each historical LV.
For example, we have this thin snapshot sequence:
lvol1 --> lvol2 --> lvol3
\
--> lvol4
We end up with these metadata:
logical_volume {
...
(lvol1, lvol3 and lvol4 listed here as usual - no change here)
...
}
historical_logical_volumes {
lvol2 {
id = "S0Dw1U-v5sF-LwAb-W9SI-pNOF-Madd-5dxSv5"
creation_time = 1456919613 # 2016-03-02 12:53:33 +0100
removal_time = 1456919620 # 2016-03-02 12:53:40 +0100
origin = "lvol1"
descendants = ["lvol3", "lvol4"]
}
}
By removing lvol1 further, we end up with:
historical_logical_volumes {
lvol2 {
id = "S0Dw1U-v5sF-LwAb-W9SI-pNOF-Madd-5dxSv5"
creation_time = 1456919613 # 2016-03-02 12:53:33 +0100
removal_time = 1456919620 # 2016-03-02 12:53:40 +0100
origin = "-lvol1"
descendants = ["lvol3", "lvol4"]
}
lvol1 {
id = "me0mes-aYnK-nRfT-vNlV-UiR1-GP7r-ojbROr"
creation_time = 1456919608 # 2016-03-02 12:53:28 +0100
removal_time = 1456919767 # 2016-03-02 12:56:07 +0100
}
}
---
lib/format_text/export.c | 144 ++++++++++++++++++++++++++++++++++++++
lib/metadata/metadata-exported.h | 2 +
lib/thin/thin.c | 1 +
3 files changed, 147 insertions(+), 0 deletions(-)
diff --git a/lib/format_text/export.c b/lib/format_text/export.c
index 99ed200..f17ccf5 100644
--- a/lib/format_text/export.c
+++ b/lib/format_text/export.c
@@ -651,6 +651,25 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
return 1;
}
+static int _print_timestamp(struct formatter *f,
+ const char *name, time_t ts,
+ char *buf, size_t buf_size)
+{
+ struct tm *local_tm;
+
+ if (ts) {
+ strncpy(buf, "# ", buf_size);
+ if (!(local_tm = localtime(&ts)) ||
+ !strftime(buf + 2, buf_size - 2,
+ "%Y-%m-%d %T %z", local_tm))
+ buf[0] = 0;
+
+ outfc(f, buf, "%s = %" PRIu64, name, ts);
+ }
+
+ return 1;
+}
+
static int _print_lv(struct formatter *f, struct logical_volume *lv)
{
struct lv_segment *seg;
@@ -774,6 +793,127 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
return 1;
}
+static int _alloc_printed_indirect_descendants(struct dm_list *indirect_glvs, char **buffer)
+{
+ struct glv_list *user_glvl;
+ size_t buf_size = 0;
+ int first = 1;
+ char *buf;
+
+ *buffer = NULL;
+
+ dm_list_iterate_items(user_glvl, indirect_glvs) {
+ if (user_glvl->glv->is_historical)
+ continue;
+ /* '"' + name + '"' + ',' + ' ' */
+ buf_size += strlen(user_glvl->glv->live->name) + 4;
+ }
+
+ if (!buf_size)
+ return 1;
+
+ /* '[' + ']' + '\0' */
+ buf_size += 3;
+
+ if (!(*buffer = dm_malloc(buf_size))) {
+ log_error("Could not allocate memory for ancestor list buffer.");
+ return 0;
+ }
+ buf = *buffer;
+
+ if (!emit_to_buffer(&buf, &buf_size, "["))
+ goto_bad;
+
+ dm_list_iterate_items(user_glvl, indirect_glvs) {
+ if (user_glvl->glv->is_historical)
+ continue;
+ if (!first) {
+ if (!emit_to_buffer(&buf, &buf_size, ", "))
+ goto_bad;
+ } else
+ first = 0;
+
+ if (!emit_to_buffer(&buf, &buf_size, "\"%s\"", user_glvl->glv->live->name))
+ goto_bad;
+ }
+
+ if (!emit_to_buffer(&buf, &buf_size, "]"))
+ goto_bad;
+
+ return 1;
+bad:
+ if (*buffer) {
+ dm_free(*buffer);
+ *buffer = NULL;
+ }
+ return 0;
+}
+
+static int _print_historical_lv(struct formatter *f, struct historical_logical_volume *hlv)
+{
+ char buffer[40];
+ char *descendants_buffer = NULL;
+ int r = 0;
+
+ if (!id_write_format(&hlv->lvid.id[1], buffer, sizeof(buffer)))
+ goto_out;
+
+ if (!_alloc_printed_indirect_descendants(&hlv->indirect_glvs, &descendants_buffer))
+ goto_out;
+
+ outnl(f);
+ outf(f, "%s {", hlv->name);
+ _inc_indent(f);
+
+ outf(f, "id = \"%s\"", buffer);
+
+ if (!_print_timestamp(f, "creation_time", hlv->timestamp, buffer, sizeof(buffer)))
+ goto_out;
+
+ if (!_print_timestamp(f, "removal_time", hlv->timestamp_removed, buffer, sizeof(buffer)))
+ goto_out;
+
+ if (hlv->indirect_origin) {
+ if (hlv->indirect_origin->is_historical)
+ outf(f, "origin = \"%s%s\"", HISTORICAL_LV_PREFIX, hlv->indirect_origin->historical->name);
+ else
+ outf(f, "origin = \"%s\"", hlv->indirect_origin->live->name);
+ }
+
+ if (descendants_buffer)
+ outf(f, "descendants = %s", descendants_buffer);
+
+ _dec_indent(f);
+ outf(f, "}");
+
+ r = 1;
+out:
+ if (descendants_buffer)
+ dm_free(descendants_buffer);
+ return r;
+}
+
+static int _print_historical_lvs(struct formatter *f, struct volume_group *vg)
+{
+ struct glv_list *glvl;
+
+ if (dm_list_empty(&vg->historical_lvs))
+ return 1;
+
+ outf(f, "historical_logical_volumes {");
+ _inc_indent(f);
+
+ dm_list_iterate_items(glvl, &vg->historical_lvs) {
+ if (!_print_historical_lv(f, glvl->glv->historical))
+ return_0;
+ }
+
+ _dec_indent(f);
+ outf(f, "}");
+
+ return 1;
+}
+
/*
* In the text format we refer to pv's as 'pv1',
* 'pv2' etc. This function builds a hash table
@@ -840,6 +980,10 @@ static int _text_vg_export(struct formatter *f,
if (!_print_lvs(f, vg))
goto_out;
+ outnl(f);
+ if (!_print_historical_lvs(f, vg))
+ goto_out;
+
_dec_indent(f);
if (!out_text(f, "}"))
goto_out;
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 76597ba..7f1d43c 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -37,6 +37,8 @@
#define MAX_EXTENT_SIZE ((uint32_t) -1)
#define MIN_NON_POWER2_EXTENT_SIZE (128U * 2U) /* 128KB in sectors */
+#define HISTORICAL_LV_PREFIX "-"
+
/* Layer suffix */
#define MIRROR_SYNC_LAYER "_mimagetmp"
diff --git a/lib/thin/thin.c b/lib/thin/thin.c
index 221ac48..6a19055 100644
--- a/lib/thin/thin.c
+++ b/lib/thin/thin.c
@@ -532,6 +532,7 @@ static int _thin_text_export(const struct lv_segment *seg, struct formatter *f)
outf(f, "external_origin = \"%s\"", seg->external_lv->name);
if (seg->origin)
outf(f, "origin = \"%s\"", seg->origin->name);
+
if (seg->merge_lv)
outf(f, "merge = \"%s\"", seg->merge_lv->name);
7 years
master - metadata: create historical LVs when LVs are removed and interconnect with live LVs
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=790b2e87482276...
Commit: 790b2e874822767808f3c5bcc4ce1499944969ff
Parent: eeaa5a4481e04c0131152fd88e6ea2651949ae35
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Mar 1 15:20:09 2016 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Mar 3 11:26:51 2016 +0100
metadata: create historical LVs when LVs are removed and interconnect with live LVs
When an LV is being removed, we create an instance of
"struct historical_logical_volume" wrapped up in
"struct generic_logical_volume".
All instances of "struct historical_logical_volume" are then recorded in
"historical_lvs" list which is part of "struct volume_group".
The "historical LV" is then interconnected with "live LVs" to
connect a history chain for the live LV.
---
lib/metadata/metadata.c | 25 ++++++++++
lib/metadata/pool_manip.c | 118 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 143 insertions(+), 0 deletions(-)
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 5e84e96..0d2211a 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -32,6 +32,7 @@
#include "archiver.h"
#include "defaults.h"
#include "lvmlockd.h"
+#include "time.h"
#include <math.h>
#include <sys/param.h>
@@ -3182,6 +3183,25 @@ static int _check_old_pv_ext_for_vg(struct volume_group *vg)
return 1;
}
+static int _handle_historical_lvs(struct volume_group *vg)
+{
+ struct glv_list *glvl;
+ time_t current_timestamp = 0;
+ struct historical_logical_volume *hlv;
+
+ dm_list_iterate_items(glvl, &vg->historical_lvs) {
+ hlv = glvl->glv->historical;
+
+ if (!hlv->timestamp_removed) {
+ if (!current_timestamp)
+ current_timestamp = time(NULL);
+ hlv->timestamp_removed = (uint64_t) current_timestamp;
+ }
+ }
+
+ return 1;
+}
+
/*
* After vg_write() returns success,
* caller MUST call either vg_commit() or vg_revert()
@@ -3205,6 +3225,11 @@ int vg_write(struct volume_group *vg)
}
}
+ if (!_handle_historical_lvs(vg)) {
+ log_error("Failed to handle historical LVs in VG %s.", vg->name);
+ return 0;
+ }
+
if (!vg_validate(vg))
return_0;
diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
index cb12aaa..20bb756 100644
--- a/lib/metadata/pool_manip.c
+++ b/lib/metadata/pool_manip.c
@@ -26,6 +26,7 @@
#include "dev-type.h"
#include "display.h"
#include "toolcontext.h"
+#include <stddef.h>
int attach_pool_metadata_lv(struct lv_segment *pool_seg,
struct logical_volume *metadata_lv)
@@ -123,8 +124,98 @@ int attach_pool_lv(struct lv_segment *seg,
return 1;
}
+static struct glv_list *_init_historical_glvl(struct dm_pool *mem, struct lv_segment *seg)
+{
+ struct glv_list *glvl;
+ struct historical_logical_volume *hlv;
+
+ if (!(glvl = dm_pool_zalloc(mem, sizeof(struct glv_list))))
+ goto_bad;
+
+ if (!(glvl->glv = dm_pool_zalloc(mem, sizeof(struct generic_logical_volume))))
+ goto_bad;
+
+ if (!(hlv = dm_pool_zalloc(mem, sizeof(struct historical_logical_volume))))
+ goto_bad;
+
+ hlv->lvid = seg->lv->lvid;
+ hlv->name = seg->lv->name;
+ hlv->vg = seg->lv->vg;
+ hlv->timestamp = seg->lv->timestamp;
+ dm_list_init(&hlv->indirect_glvs);
+
+ glvl->glv->is_historical = 1;
+ glvl->glv->historical = hlv;
+
+ return glvl;
+bad:
+ log_error("Initialization of historical LV representation for removed logical "
+ "volume %s/%s failed.", seg->lv->vg->name, seg->lv->name);
+ if (glvl)
+ dm_pool_free(mem, glvl);
+ return NULL;
+}
+
+static struct generic_logical_volume *_create_historical_glv(struct lv_segment *seg_to_remove)
+{
+ struct dm_pool *mem = seg_to_remove->lv->vg->vgmem;
+ struct generic_logical_volume *historical_glv, *origin_glv = NULL;
+ struct glv_list *historical_glvl;
+ int origin_glv_created = 0;
+
+ if (!(historical_glvl = _init_historical_glvl(mem, seg_to_remove)))
+ goto_bad;
+ historical_glv = historical_glvl->glv;
+
+ if (seg_to_remove->origin) {
+ if (!(origin_glv = get_or_create_glv(mem, seg_to_remove->origin, &origin_glv_created)))
+ goto_bad;
+
+ if (!add_glv_to_indirect_glvs(mem, origin_glv, historical_glv))
+ goto_bad;
+ } else if (seg_to_remove->indirect_origin) {
+ origin_glv = seg_to_remove->indirect_origin;
+
+ if (!remove_glv_from_indirect_glvs(origin_glv, seg_to_remove->lv->this_glv))
+ goto_bad;
+
+ if (!add_glv_to_indirect_glvs(mem, origin_glv, historical_glv))
+ goto_bad;
+ }
+
+ dm_list_add(&seg_to_remove->lv->vg->historical_lvs, &historical_glvl->list);
+ return historical_glvl->glv;
+bad:
+ log_error("Failed to create historical LV representation for removed logical "
+ "volume %s/%s.", seg_to_remove->lv->vg->name, seg_to_remove->lv->name);
+ if (origin_glv_created)
+ seg_to_remove->origin->this_glv = NULL;
+ if (historical_glvl)
+ dm_pool_free(mem, historical_glvl);
+ return NULL;
+}
+
+static int _set_up_historical_lv(struct lv_segment *seg_to_remove,
+ struct generic_logical_volume **previous_glv)
+{
+ struct generic_logical_volume *glv = NULL;
+
+ if (seg_to_remove->origin || seg_to_remove->indirect_origin ||
+ dm_list_size(&seg_to_remove->lv->segs_using_this_lv) ||
+ dm_list_size(&seg_to_remove->lv->indirect_glvs)) {
+ if (!(glv = _create_historical_glv(seg_to_remove)))
+ return_0;
+ }
+
+ *previous_glv = glv;
+ return 1;
+}
+
+
int detach_pool_lv(struct lv_segment *seg)
{
+ struct generic_logical_volume *previous_glv = NULL, *glv, *user_glv;
+ struct glv_list *user_glvl, *tglvl;
struct lv_thin_message *tmsg, *tmp;
struct seg_list *sl, *tsl;
int no_update = 0;
@@ -177,6 +268,9 @@ int detach_pool_lv(struct lv_segment *seg)
}
}
+ if (!_set_up_historical_lv(seg, &previous_glv))
+ return_0;
+
if (!detach_thin_external_origin(seg))
return_0;
@@ -202,15 +296,39 @@ int detach_pool_lv(struct lv_segment *seg)
(seg->lv != sl->seg->origin))
continue;
+ if (previous_glv) {
+ if (!(user_glv = get_or_create_glv(seg->lv->vg->vgmem, sl->seg->lv, NULL)))
+ return_0;
+
+ if (!add_glv_to_indirect_glvs(seg->lv->vg->vgmem, previous_glv, user_glv))
+ return_0;
+ }
+
if (!remove_seg_from_segs_using_this_lv(seg->lv, sl->seg))
return_0;
/* Thin snapshot is now regular thin volume */
sl->seg->origin = NULL;
}
+ dm_list_iterate_items_safe(user_glvl, tglvl, &seg->lv->indirect_glvs) {
+ user_glv = user_glvl->glv;
+
+ if (!(glv = get_or_create_glv(seg->lv->vg->vgmem, seg->lv, NULL)))
+ return_0;
+
+ if (!remove_glv_from_indirect_glvs(glv, user_glv))
+ return_0;
+
+ if (previous_glv) {
+ if (!add_glv_to_indirect_glvs(seg->lv->vg->vgmem, previous_glv, user_glv))
+ return_0;
+ }
+ }
+
seg->lv->status &= ~THIN_VOLUME;
seg->pool_lv = NULL;
seg->origin = NULL;
+ seg->indirect_origin = NULL;
return 1;
}
7 years