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.39/lib/metadata/lv_manip.c =================================================================== --- LVM2.2.02.39.orig/lib/metadata/lv_manip.c 2008-07-06 21:07:30.000000000 +0200 +++ LVM2.2.02.39/lib/metadata/lv_manip.c 2008-07-08 19:43:51.000000000 +0200 @@ -1795,6 +1795,7 @@ char *generate_lv_name(struct volume_gro void lv_init(struct logical_volume *lv) { lv->snapshot = NULL; + lv->merging_snapshot = NULL; list_init(&lv->snapshot_segs); list_init(&lv->segments); list_init(&lv->tags); Index: LVM2.2.02.39/lib/metadata/metadata-exported.h =================================================================== --- LVM2.2.02.39.orig/lib/metadata/metadata-exported.h 2008-07-06 21:07:31.000000000 +0200 +++ LVM2.2.02.39/lib/metadata/metadata-exported.h 2008-07-06 21:07:31.000000000 +0200 @@ -292,6 +292,9 @@ struct logical_volume { struct list snapshot_segs; struct lv_segment *snapshot; + /* A snapshot that is merging into this origin */ + struct lv_segment *merging_snapshot; + struct list segments; struct list tags; struct list segs_using_this_lv; Index: LVM2.2.02.39/lib/metadata/snapshot_manip.c =================================================================== --- LVM2.2.02.39.orig/lib/metadata/snapshot_manip.c 2008-07-06 21:07:31.000000000 +0200 +++ LVM2.2.02.39/lib/metadata/snapshot_manip.c 2008-07-08 19:09:49.000000000 +0200 @@ -68,6 +68,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))) @@ -82,7 +87,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++; @@ -100,6 +108,8 @@ int vg_remove_snapshot(struct logical_vo { 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.39/tools/lvconvert.c =================================================================== --- LVM2.2.02.39.orig/tools/lvconvert.c 2008-07-06 21:07:31.000000000 +0200 +++ LVM2.2.02.39/tools/lvconvert.c 2008-07-08 19:43:51.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))