[lvm-devel] [PATCH 02/15] lvm-merge-metadata
Mike Snitzer
snitzer at redhat.com
Fri Nov 20 22:35:42 UTC 2009
From: Mikulas Patocka <mpatocka at redhat.com>
Add 'SNAPSHOT_MERGE' lv_segment 'status' flag.
Make 'merging_snapshot' pointer that points from the origin to the
segment that represents the merging snapshot.
Import/export 'merging_store' metadata.
Do not allow creating snapshots while another snapshot is merging.
Snapshot created in this state would certainly contain invalid data.
Signed-off-by: Mikulas Patocka <mpatocka at redhat.com>
Signed-off-by: Mike Snitzer <snitzer at redhat.com>
---
lib/format_text/flags.c | 1 +
lib/metadata/lv_manip.c | 6 ++++++
lib/metadata/metadata-exported.h | 6 +++++-
lib/metadata/snapshot_manip.c | 13 +++++++++++--
lib/snapshot/snapshot.c | 15 +++++++++++----
5 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index 829d44a..342dc5a 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -61,6 +61,7 @@ static struct flag _lv_flags[] = {
{MIRRORED, NULL, 0},
{VIRTUAL, NULL, 0},
{SNAPSHOT, NULL, 0},
+ {SNAPSHOT_MERGE, NULL, 0},
{ACTIVATE_EXCL, NULL, 0},
{CONVERTING, NULL, 0},
{PARTIAL_LV, NULL, 0},
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 260a9ee..ecaab29 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1873,6 +1873,7 @@ struct logical_volume *alloc_lv(struct dm_pool *mem)
}
lv->snapshot = NULL;
+ lv->merging_snapshot = NULL;
dm_list_init(&lv->snapshot_segs);
dm_list_init(&lv->segments);
dm_list_init(&lv->tags);
@@ -2937,6 +2938,11 @@ int lv_create_single(struct volume_group *vg,
"supported yet");
return 0;
}
+ if (org->merging_snapshot) {
+ log_error("Snapshots while another snapshot "
+ "is merging is not supported");
+ return 0;
+ }
if ((org->status & MIRROR_IMAGE) ||
(org->status & MIRROR_LOG)) {
log_error("Snapshots of mirror %ss "
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index e9a3d5d..30073d3 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -60,6 +60,7 @@
//#define ACTIVATE_EXCL 0x00100000U /* LV - internal use only */
//#define PRECOMMITTED 0x00200000U /* VG - internal use only */
#define CONVERTING 0x00400000U /* LV */
+#define SNAPSHOT_MERGE 0x00800000U /* SEG */
#define MISSING_PV 0x00800000U /* PV */
#define PARTIAL_LV 0x01000000U /* LV - derived flag, not
@@ -328,6 +329,9 @@ struct logical_volume {
struct dm_list snapshot_segs;
struct lv_segment *snapshot;
+ /* A snapshot that is merging into this origin */
+ struct lv_segment *merging_snapshot;
+
struct dm_list segments;
struct dm_list tags;
struct dm_list segs_using_this_lv;
@@ -622,7 +626,7 @@ struct lv_segment *find_cow(const struct logical_volume *lv);
struct logical_volume *origin_from_cow(const struct logical_volume *lv);
void init_snapshot_seg(struct lv_segment *seg, struct logical_volume *origin,
- struct logical_volume *cow, uint32_t chunk_size);
+ struct logical_volume *cow, uint32_t chunk_size, int merge);
int vg_add_snapshot(struct logical_volume *origin, struct logical_volume *cow,
union lvid *lvid, uint32_t extent_count,
diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c
index 8f902af..86cab6f 100644
--- a/lib/metadata/snapshot_manip.c
+++ b/lib/metadata/snapshot_manip.c
@@ -37,6 +37,9 @@ int lv_is_visible(const struct logical_volume *lv)
if (lv_is_virtual_origin(origin_from_cow(lv)))
return 1;
+ if (find_cow(lv)->status & SNAPSHOT_MERGE)
+ return 0;
+
return lv_is_visible(origin_from_cow(lv));
}
@@ -62,7 +65,7 @@ struct logical_volume *origin_from_cow(const struct logical_volume *lv)
}
void init_snapshot_seg(struct lv_segment *seg, struct logical_volume *origin,
- struct logical_volume *cow, uint32_t chunk_size)
+ struct logical_volume *cow, uint32_t chunk_size, int merge)
{
seg->chunk_size = chunk_size;
seg->origin = origin;
@@ -79,6 +82,10 @@ void init_snapshot_seg(struct lv_segment *seg, struct logical_volume *origin,
origin->status |= VIRTUAL_ORIGIN;
seg->lv->status |= (SNAPSHOT | VIRTUAL);
+ if (merge) {
+ seg->status |= SNAPSHOT_MERGE;
+ origin->merging_snapshot = seg;
+ }
dm_list_add(&origin->snapshot_segs, &seg->origin_list);
}
@@ -113,7 +120,7 @@ int vg_add_snapshot(struct logical_volume *origin,
if (!(seg = alloc_snapshot_seg(snap, 0, 0)))
return_0;
- init_snapshot_seg(seg, origin, cow, chunk_size);
+ init_snapshot_seg(seg, origin, cow, chunk_size, 0);
return 1;
}
@@ -122,6 +129,8 @@ int vg_remove_snapshot(struct logical_volume *cow)
{
dm_list_del(&cow->snapshot->origin_list);
cow->snapshot->origin->origin_count--;
+ if (cow->snapshot->origin->merging_snapshot == cow->snapshot)
+ cow->snapshot->origin->merging_snapshot = NULL;
if (!lv_remove(cow->snapshot->lv)) {
log_error("Failed to remove internal snapshot LV %s",
diff --git a/lib/snapshot/snapshot.c b/lib/snapshot/snapshot.c
index 6b1a0e2..8a3378c 100644
--- a/lib/snapshot/snapshot.c
+++ b/lib/snapshot/snapshot.c
@@ -37,7 +37,7 @@ static int _snap_text_import(struct lv_segment *seg, const struct config_node *s
uint32_t chunk_size;
const char *org_name, *cow_name;
struct logical_volume *org, *cow;
- int old_suppress;
+ int old_suppress, merge = 0;
if (!get_config_uint32(sn, "chunk_size", &chunk_size)) {
log_error("Couldn't read chunk size for snapshot.");
@@ -46,7 +46,10 @@ static int _snap_text_import(struct lv_segment *seg, const struct config_node *s
old_suppress = log_suppress(1);
- if (!(cow_name = find_config_str(sn, "cow_store", NULL))) {
+ cow_name = find_config_str(sn, "merging_store", NULL);
+ if (cow_name) {
+ merge = 1;
+ } else if (!(cow_name = find_config_str(sn, "cow_store", NULL))) {
log_suppress(old_suppress);
log_error("Snapshot cow storage not specified.");
return 0;
@@ -72,7 +75,7 @@ static int _snap_text_import(struct lv_segment *seg, const struct config_node *s
return 0;
}
- init_snapshot_seg(seg, org, cow, chunk_size);
+ init_snapshot_seg(seg, org, cow, chunk_size, merge);
return 1;
}
@@ -81,7 +84,11 @@ static int _snap_text_export(const struct lv_segment *seg, struct formatter *f)
{
outf(f, "chunk_size = %u", seg->chunk_size);
outf(f, "origin = \"%s\"", seg->origin->name);
- outf(f, "cow_store = \"%s\"", seg->cow->name);
+ if (!(seg->status & SNAPSHOT_MERGE)) {
+ outf(f, "cow_store = \"%s\"", seg->cow->name);
+ } else {
+ outf(f, "merging_store = \"%s\"", seg->cow->name);
+ }
return 1;
}
--
1.6.5.2
More information about the lvm-devel
mailing list