summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZdenek Kabelac <zkabelac@redhat.com>2012-01-19 15:31:45 +0000
committerZdenek Kabelac <zkabelac@redhat.com>2012-01-19 15:31:45 +0000
commit53d7985fa1476a7c0e430c01a6cb2cd679d4912e (patch)
tree0bb54a14b410bd35b7ad5fc6807222276ded4dbb
parent76ee08995eb8271a34c77352ffd499983d6c5752 (diff)
downloadlvm2-53d7985fa1476a7c0e430c01a6cb2cd679d4912e.tar.gz
lvm2-53d7985fa1476a7c0e430c01a6cb2cd679d4912e.tar.xz
lvm2-53d7985fa1476a7c0e430c01a6cb2cd679d4912e.zip
Add support to keep info about creation time and host for each LV
Basic support to keep info when the LV was created. Host and time is stored into LV mda section. FIXME: Current version doesn't support configurable string via lvm.conf and used fixed version strftime "%Y-%m-%d %T %z".
-rw-r--r--WHATS_NEW1
-rw-r--r--lib/format_text/export.c15
-rw-r--r--lib/format_text/import_vsn1.c27
-rw-r--r--lib/metadata/lv.c61
-rw-r--r--lib/metadata/lv.h8
-rw-r--r--lib/metadata/lv_manip.c3
-rw-r--r--lib/metadata/vg.c7
-rw-r--r--lib/metadata/vg.h2
8 files changed, 122 insertions, 2 deletions
diff --git a/WHATS_NEW b/WHATS_NEW
index c118d49a..83fa4efd 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.89 -
==================================
+ Keep into about creation host and time for each logical volume.
Make error message hit when preallocated memlock memory exceeded clearer.
Use R lv_attr to indicate read-only activation of non-read-only device in lvs.
Show read-only activation override in lvdisplay & add 4 to perms in -c.
diff --git a/lib/format_text/export.c b/lib/format_text/export.c
index d0bf4877..0dfb8970 100644
--- a/lib/format_text/export.c
+++ b/lib/format_text/export.c
@@ -579,6 +579,8 @@ 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;
outnl(f);
outf(f, "%s {", lv->name);
@@ -596,6 +598,19 @@ static int _print_lv(struct formatter *f, struct logical_volume *lv)
if (!_out_tags(f, &lv->tags))
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;
+
+ outf(f, "creation_host = \"%s\"", lv->hostname);
+ outfc(f, buffer, "creation_time = %" PRIu64,
+ lv->timestamp);
+ }
+
if (lv->alloc != ALLOC_INHERIT)
outf(f, "allocation_policy = \"%s\"",
get_alloc_string(lv->alloc));
diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
index 03e77875..e3ad0b1c 100644
--- a/lib/format_text/import_vsn1.c
+++ b/lib/format_text/import_vsn1.c
@@ -494,6 +494,8 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)),
struct logical_volume *lv;
const char *lv_alloc;
const struct dm_config_value *cv;
+ const char *hostname;
+ uint64_t timestamp = 0;
if (!(lv = alloc_lv(mem)))
return_0;
@@ -512,6 +514,23 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)),
return 0;
}
+ if (dm_config_has_node(lvn, "creation_time")) {
+ if (!_read_uint64(lvn, "creation_time", &timestamp)) {
+ log_error("Invalid creation_time for logical volume %s.",
+ lv->name);
+ return 0;
+ }
+ if (!dm_config_get_str(lvn, "creation_host", &hostname)) {
+ log_error("Couldn't read creation_host for logical volume %s.",
+ lv->name);
+ return 0;
+ }
+ } else if (dm_config_has_node(lvn, "creation_host")) {
+ log_error("Missing creation_time for logical volume %s.",
+ lv->name);
+ return 0;
+ }
+
lv->alloc = ALLOC_INHERIT;
if (dm_config_get_str(lvn, "allocation_policy", &lv_alloc)) {
lv->alloc = get_alloc_from_string(lv_alloc);
@@ -548,7 +567,13 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)),
if (!dm_hash_insert(lv_hash, lv->name, lv))
return_0;
- return link_lv_to_vg(vg, lv);
+ if (!link_lv_to_vg(vg, lv))
+ return_0;
+
+ if (timestamp && !lv_set_creation(lv, hostname, timestamp))
+ return_0;
+
+ return 1;
}
static int _read_lvsegs(struct format_instance *fid __attribute__((unused)),
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index ed6b42dc..84e47796 100644
--- a/lib/metadata/lv.c
+++ b/lib/metadata/lv.c
@@ -21,6 +21,12 @@
#include "segtype.h"
#include "str_list.h"
+#include <time.h>
+#include <sys/utsname.h>
+
+static struct utsname _utsname;
+static int _utsinit = 0;
+
static char *_format_pvsegs(struct dm_pool *mem, const struct lv_segment *seg,
int range_format)
{
@@ -469,3 +475,58 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
out:
return repstr;
}
+
+int lv_set_creation(struct logical_volume *lv,
+ const char *hostname, uint64_t timestamp)
+{
+ const char *hn;
+
+ if (!hostname) {
+ if (!_utsinit) {
+ if (uname(&_utsname)) {
+ log_error("uname failed: %s", strerror(errno));
+ memset(&_utsname, 0, sizeof(_utsname));
+ }
+
+ _utsinit = 1;
+ }
+
+ hostname = _utsname.nodename;
+ }
+
+ if (!(hn = dm_hash_lookup(lv->vg->hostnames, hostname))) {
+ if (!(hn = dm_pool_strdup(lv->vg->vgmem, hostname))) {
+ log_error("Failed to duplicate hostname");
+ return 0;
+ }
+
+ if (!dm_hash_insert(lv->vg->hostnames, hostname, (void*)hn))
+ return_0;
+ }
+
+ lv->hostname = hn;
+ lv->timestamp = timestamp ? : time(NULL);
+
+ return 1;
+}
+
+char *lv_time_dup(struct dm_pool *mem, const struct logical_volume *lv)
+{
+ char buffer[50];
+ struct tm *local_tm;
+ time_t ts = (time_t)lv->timestamp;
+
+ if (!ts ||
+ !(local_tm = localtime(&ts)) ||
+ /* FIXME: make this lvm.conf configurable */
+ !strftime(buffer, sizeof(buffer),
+ "%Y-%m-%d %T %z", local_tm))
+ buffer[0] = 0;
+
+ return dm_pool_strdup(mem, buffer);
+}
+
+char *lv_host_dup(struct dm_pool *mem, const struct logical_volume *lv)
+{
+ return dm_pool_strdup(mem, lv->hostname ? : "");
+}
diff --git a/lib/metadata/lv.h b/lib/metadata/lv.h
index a54745f1..28ece5d4 100644
--- a/lib/metadata/lv.h
+++ b/lib/metadata/lv.h
@@ -46,6 +46,9 @@ struct logical_volume {
struct dm_list segments;
struct dm_list tags;
struct dm_list segs_using_this_lv;
+
+ uint64_t timestamp;
+ const char *hostname;
};
uint64_t lv_size(const struct logical_volume *lv);
@@ -71,5 +74,8 @@ char *lvseg_segtype_dup(struct dm_pool *mem, const struct lv_segment *seg);
char *lvseg_tags_dup(const struct lv_segment *seg);
char *lvseg_devices(struct dm_pool *mem, const struct lv_segment *seg);
char *lvseg_seg_pe_ranges(struct dm_pool *mem, const struct lv_segment *seg);
-
+char *lv_time_dup(struct dm_pool *mem, const struct logical_volume *lv);
+char *lv_host_dup(struct dm_pool *mem, const struct logical_volume *lv);
+int lv_set_creation(struct logical_volume *lv,
+ const char *hostname, uint64_t timestamp);
#endif /* _LVM_LV_H */
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 02ab5834..47f60a66 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -2993,6 +2993,9 @@ struct logical_volume *lv_create_empty(const char *name,
if (!link_lv_to_vg(vg, lv))
goto_bad;
+
+ if (!lv_set_creation(lv, NULL, 0))
+ goto_bad;
if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv))
goto_bad;
diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c
index 4dff7f29..b0ce3bf7 100644
--- a/lib/metadata/vg.c
+++ b/lib/metadata/vg.c
@@ -44,6 +44,12 @@ struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
vg->vgmem = vgmem;
vg->alloc = ALLOC_NORMAL;
+ if (!(vg->hostnames = dm_hash_create(16))) {
+ log_error("Failed to allocate VG hostname hashtable.");
+ dm_pool_destroy(vgmem);
+ return NULL;
+ }
+
dm_list_init(&vg->pvs);
dm_list_init(&vg->pvs_to_create);
dm_list_init(&vg->lvs);
@@ -67,6 +73,7 @@ static void _free_vg(struct volume_group *vg)
log_debug("Freeing VG %s at %p.", vg->name, vg);
+ dm_hash_destroy(vg->hostnames);
dm_pool_destroy(vg->vgmem);
}
diff --git a/lib/metadata/vg.h b/lib/metadata/vg.h
index 42871b5a..f0437113 100644
--- a/lib/metadata/vg.h
+++ b/lib/metadata/vg.h
@@ -109,6 +109,8 @@ struct volume_group {
*/
uint32_t read_status;
uint32_t mda_copies; /* target number of mdas for this VG */
+
+ struct dm_hash_table *hostnames; /* map of creation hostnames */
};
struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,