[lvm-devel] master - metadata: format_text: also export historical LVs

Peter Rajnoha prajnoha at fedoraproject.org
Thu Mar 3 13:19:37 UTC 2016


Gitweb:        http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=3a0ef77305b179511aae6d8e5af05bbbebabee6b
Commit:        3a0ef77305b179511aae6d8e5af05bbbebabee6b
Parent:        790b2e874822767808f3c5bcc4ce1499944969ff
Author:        Peter Rajnoha <prajnoha at redhat.com>
AuthorDate:    Tue Mar 1 15:20:49 2016 +0100
Committer:     Peter Rajnoha <prajnoha at 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);
 




More information about the lvm-devel mailing list