Make pointer that points from the origin to the segment that represents merging snapshot. Signed-off-by: Mikulas Patocka --- lib/metadata/lv_manip.c | 1 + lib/metadata/metadata-exported.h | 3 +++ lib/metadata/snapshot_manip.c | 12 +++++++++++- tools/lvconvert.c | 11 +++++++++-- 4 files changed, 24 insertions(+), 3 deletions(-) Index: LVM2.2.02.45/lib/metadata/lv_manip.c =================================================================== --- LVM2.2.02.45.orig/lib/metadata/lv_manip.c 2009-05-11 13:08:25.000000000 +0200 +++ LVM2.2.02.45/lib/metadata/lv_manip.c 2009-05-11 13:08:34.000000000 +0200 @@ -1822,6 +1822,7 @@ char *generate_lv_name(struct volume_gro void lv_init(struct logical_volume *lv) { lv->snapshot = NULL; + lv->merging_snapshot = NULL; dm_list_init(&lv->snapshot_segs); dm_list_init(&lv->segments); dm_list_init(&lv->tags); Index: LVM2.2.02.45/lib/metadata/metadata-exported.h =================================================================== --- LVM2.2.02.45.orig/lib/metadata/metadata-exported.h 2009-05-11 13:08:29.000000000 +0200 +++ LVM2.2.02.45/lib/metadata/metadata-exported.h 2009-05-11 13:08:34.000000000 +0200 @@ -334,6 +334,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; Index: LVM2.2.02.45/lib/metadata/snapshot_manip.c =================================================================== --- LVM2.2.02.45.orig/lib/metadata/snapshot_manip.c 2009-05-11 13:08:29.000000000 +0200 +++ LVM2.2.02.45/lib/metadata/snapshot_manip.c 2009-05-11 13:08:34.000000000 +0200 @@ -76,6 +76,11 @@ int vg_add_snapshot(const char *name, st return 0; } + if (cow->status & SNAPSHOT_MERGE && origin->merging_snapshot) { + log_error("Origin has already merging snapshot."); + return 0; + } + if (!(snap = lv_create_empty(name ? name : "snapshot%d", lvid, LVM_READ | LVM_WRITE | VISIBLE_LV, ALLOC_INHERIT, 1, origin->vg))) @@ -90,7 +95,10 @@ int vg_add_snapshot(const char *name, st seg->origin = origin; seg->cow = cow; seg->lv->status |= SNAPSHOT; - if (merge) seg->status |= SNAPSHOT_MERGE; + if (merge) { + seg->status |= SNAPSHOT_MERGE; + origin->merging_snapshot = seg; + } origin->origin_count++; origin->vg->snapshot_count++; @@ -108,6 +116,8 @@ int vg_remove_snapshot(struct logical_vo { 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", Index: LVM2.2.02.45/tools/lvconvert.c =================================================================== --- LVM2.2.02.45.orig/tools/lvconvert.c 2009-05-11 13:08:29.000000000 +0200 +++ LVM2.2.02.45/tools/lvconvert.c 2009-05-11 13:08:34.000000000 +0200 @@ -708,12 +708,19 @@ static int lvconvert_merge(struct cmd_co struct lvconvert_params *lp) { struct logical_volume *origin = origin_from_cow(lv); + struct lv_segment *cow_seg = find_cow(lv); - if (find_cow(lv)->status & SNAPSHOT_MERGE) { + if (cow_seg->status & SNAPSHOT_MERGE) { log_error("Snapshot %s is already merging", lv->name); return 0; } - find_cow(lv)->status |= SNAPSHOT_MERGE; + if (origin->merging_snapshot) { + log_error("Another snapshot is already merging"); + return 0; + } + + cow_seg->status |= SNAPSHOT_MERGE; + origin->merging_snapshot = cow_seg; /* store vg on disk(s) */ if (!vg_write(lv->vg))