Make pointer from the origin volume to the shared store. There may be only one shared store, so we do not need to build a list. Signed-off-by: Mikulas Patocka --- lib/metadata/lv_manip.c | 12 ++++++++++++ lib/metadata/metadata-exported.h | 4 ++++ lib/metadata/snapshot_manip.c | 22 ++++++++++++++++++++++ 3 files changed, 38 insertions(+) Index: LVM2.2.02.60/lib/metadata/lv_manip.c =================================================================== --- LVM2.2.02.60.orig/lib/metadata/lv_manip.c 2010-02-08 18:08:25.000000000 +0100 +++ LVM2.2.02.60/lib/metadata/lv_manip.c 2010-02-08 19:58:02.000000000 +0100 @@ -1881,6 +1881,7 @@ struct logical_volume *alloc_lv(struct d } lv->snapshot = NULL; + lv->shared_snapshot = NULL; dm_list_init(&lv->snapshot_segs); dm_list_init(&lv->segments); dm_list_init(&lv->tags); @@ -2955,6 +2956,17 @@ int lv_create_single(struct volume_group "supported yet."); return 0; } + if (lv_is_multisnap_origin(org)) { + log_error("It is not allowed to create more " + "shared snapshot stores."); + return 0; + } + if (lv_is_origin(org) && !lv_is_multisnap_origin(org) && + lp->shared_store) { + log_error("It is not allowed to mix shared " + "and unshared snapshots."); + return 0; + } if (org->status & LOCKED) { log_error("Snapshots of locked devices are not " "supported yet"); Index: LVM2.2.02.60/lib/metadata/metadata-exported.h =================================================================== --- LVM2.2.02.60.orig/lib/metadata/metadata-exported.h 2010-02-08 18:06:26.000000000 +0100 +++ LVM2.2.02.60/lib/metadata/metadata-exported.h 2010-02-08 19:58:02.000000000 +0100 @@ -332,6 +332,9 @@ struct logical_volume { struct dm_list snapshot_segs; struct lv_segment *snapshot; + /* A shared-snapshot segment for this origin */ + struct lv_segment *shared_snapshot; + struct dm_list segments; struct dm_list tags; struct dm_list segs_using_this_lv; @@ -619,6 +622,7 @@ int lv_is_virtual_origin(const struct lo int lv_is_cow(const struct logical_volume *lv); int lv_is_merging_origin(const struct logical_volume *origin); int lv_is_merging_cow(const struct logical_volume *snapshot); +int lv_is_multisnap_origin(const struct logical_volume *lv); /* Test if given LV is visible from user's perspective */ int lv_is_visible(const struct logical_volume *lv); Index: LVM2.2.02.60/lib/metadata/snapshot_manip.c =================================================================== --- LVM2.2.02.60.orig/lib/metadata/snapshot_manip.c 2010-02-08 18:10:12.000000000 +0100 +++ LVM2.2.02.60/lib/metadata/snapshot_manip.c 2010-02-08 19:58:02.000000000 +0100 @@ -28,6 +28,11 @@ int lv_is_cow(const struct logical_volum return (!lv_is_origin(lv) && lv->snapshot) ? 1 : 0; } +int lv_is_multisnap_origin(const struct logical_volume *lv) +{ + return lv_is_origin(lv) && lv->shared_snapshot; +} + int lv_is_visible(const struct logical_volume *lv) { if (lv->status & SNAPSHOT) @@ -114,6 +119,15 @@ int init_snapshot_seg(struct lv_segment if (merge) init_snapshot_merge(seg, origin); + if (seg->status & SNAPSHOT_SHARED) { + if (!origin->shared_snapshot) { + origin->shared_snapshot = seg; + } else { + log_err("Origin '%s' has already a shared snapshot.", origin->name); + return_0; + } + } + dm_list_add(&origin->snapshot_segs, &seg->origin_list); return 1; @@ -167,6 +181,11 @@ int vg_add_snapshot(struct logical_volum return 0; } + if (snapshot_flags & SNAPSHOT_SHARED && origin->shared_snapshot) { + log_error("Origin has already a shared snapshot."); + return 0; + } + if (!(snap = lv_create_empty("snapshot%d", lvid, LVM_READ | LVM_WRITE | VISIBLE_LV, ALLOC_INHERIT, origin->vg))) @@ -191,6 +210,9 @@ int vg_remove_snapshot(struct logical_vo if (find_merging_cow(origin) == find_cow(cow)) clear_snapshot_merge(origin_from_cow(cow)); + if (cow->snapshot->origin->shared_snapshot == cow->snapshot) + cow->snapshot->origin->shared_snapshot = NULL; + if (!lv_remove(cow->snapshot->lv)) { log_error("Failed to remove internal snapshot LV %s", cow->snapshot->lv->name);