Activate the shared store. With this patch, the user is able to create, activate and delete the shared snapshot store with the command. lvcreate -L 32M --sharedstore mikulas -s vg/lv or lvcreate -L 32M --sharedstore fujita-daniel -s vg/lv Creating snapshots within the store will be implemented in further patches. Signed-off-by: Mikulas Patocka --- lib/activate/dev_manager.c | 58 ++++++++++++++++++++++++++++++++++----------- lib/metadata/lv_manip.c | 11 ++++++-- 2 files changed, 53 insertions(+), 16 deletions(-) Index: LVM2.2.02.54/lib/activate/dev_manager.c =================================================================== --- LVM2.2.02.54.orig/lib/activate/dev_manager.c 2009-10-29 16:12:07.000000000 +0100 +++ LVM2.2.02.54/lib/activate/dev_manager.c 2009-10-29 17:55:31.000000000 +0100 @@ -865,13 +865,24 @@ static int _add_origin_target_to_dtree(s struct dm_tree_node *dnode, struct logical_volume *lv) { - const char *real_dlid; + const char *real_dlid, *cow_dlid; if (!(real_dlid = build_dlid(dm, lv->lvid.s, "real"))) return_0; - if (!dm_tree_node_add_snapshot_origin_target(dnode, lv->size, real_dlid)) - return_0; + if (lv_is_multisnap_origin(lv)) { + if (!(cow_dlid = build_dlid(dm, + lv->shared_snapshot->cow->lvid.s, "cow"))) + return_0; + if (!dm_tree_node_add_snapshot_shared_target(dnode, lv->size, + real_dlid, cow_dlid, + lv->shared_snapshot->exception_store, + lv->shared_snapshot->chunk_size)) + return_0; + } else { + if (!dm_tree_node_add_snapshot_origin_target(dnode, lv->size, real_dlid)) + return_0; + } return 1; } @@ -890,6 +901,9 @@ static int _add_snapshot_target_to_dtree return 0; } + if (snap_seg->status & SNAPSHOT_SHARED) + return 1; + if (!(origin_dlid = build_dlid(dm, snap_seg->origin->lvid.s, "real"))) return_0; @@ -924,7 +938,8 @@ static int _add_target_to_dtree(struct d } static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, - struct logical_volume *lv, const char *layer); + struct logical_volume *lv, + const char *lv_name, const char *layer); static int _add_segment_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, @@ -953,7 +968,7 @@ static int _add_segment_to_dtree(struct /* Add mirror log */ if (seg->log_lv && - !_add_new_lv_to_dtree(dm, dtree, seg->log_lv, NULL)) + !_add_new_lv_to_dtree(dm, dtree, seg->log_lv, NULL, NULL)) return_0; /* If this is a snapshot origin, add real LV */ @@ -962,16 +977,23 @@ static int _add_segment_to_dtree(struct log_error("Clustered snapshots are not yet supported"); return 0; } - if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, "real")) - return_0; + if (lv_is_multisnap_origin(seg->lv)) { + if (!_add_new_lv_to_dtree(dm, dtree, seg->lv->shared_snapshot->cow, seg->lv->name, "cow")) + return_0; + if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, NULL, "real")) + return_0; + } else { + if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, NULL, "real")) + return_0; + } } else if (lv_is_cow(seg->lv) && !layer) { - if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, "cow")) + if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, NULL, "cow")) return_0; } else { /* Add any LVs used by this segment */ for (s = 0; s < seg->area_count; s++) if ((seg_type(seg, s) == AREA_LV) && - (!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s), NULL))) + (!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s), NULL, NULL))) return_0; } @@ -988,14 +1010,17 @@ static int _add_segment_to_dtree(struct if (lv_is_origin(seg->lv) && !layer) /* Add any snapshots of this LV */ dm_list_iterate(snh, &seg->lv->snapshot_segs) - if (!_add_new_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow, NULL)) + if (!_add_new_lv_to_dtree(dm, dtree, + dm_list_struct_base(snh, struct lv_segment, + origin_list)->cow, NULL, NULL)) return_0; return 1; } static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, - struct logical_volume *lv, const char *layer) + struct logical_volume *lv, + const char *lv_name, const char *layer) { struct lv_segment *seg; struct lv_layer *lvlayer; @@ -1006,7 +1031,12 @@ static int _add_new_lv_to_dtree(struct d uint32_t read_ahead_flags = UINT32_C(0); uint16_t udev_flags = 0; - if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) + if (!lv_name) lv_name = lv->name; + + if (lv_is_cow(lv) && find_cow(lv)->status & SNAPSHOT_SHARED && !layer) + return 1; + + if (!(name = build_dm_name(dm->mem, lv->vg->name, lv_name, layer))) return_0; if (!(dlid = build_dlid(dm, lv->lvid.s, layer))) @@ -1018,7 +1048,7 @@ static int _add_new_lv_to_dtree(struct d return 1; if (!(lvlayer = dm_pool_alloc(dm->mem, sizeof(*lvlayer)))) { - log_error("_add_new_lv_to_dtree: pool alloc failed for %s %s.", lv->name, layer); + log_error("_add_new_lv_to_dtree: pool alloc failed for %s %s.", lv_name, layer); return 0; } @@ -1238,7 +1268,7 @@ static int _tree_action(struct dev_manag case PRELOAD: case ACTIVATE: /* Add all required new devices to tree */ - if (!_add_new_lv_to_dtree(dm, dtree, lv, NULL)) + if (!_add_new_lv_to_dtree(dm, dtree, lv, NULL, NULL)) goto_out; /* Preload any devices required before any suspensions */ Index: LVM2.2.02.54/lib/metadata/lv_manip.c =================================================================== --- LVM2.2.02.54.orig/lib/metadata/lv_manip.c 2009-10-29 17:52:38.000000000 +0100 +++ LVM2.2.02.54/lib/metadata/lv_manip.c 2009-10-29 17:55:31.000000000 +0100 @@ -3113,8 +3113,15 @@ int lv_create_single(struct volume_group if (!(lp->permission & LVM_WRITE)) lv->status &= ~LVM_WRITE; - /* COW area must be deactivated if origin is not active */ - if (!origin_active && !deactivate_lv(cmd, lv)) { + /* + * COW area must be deactivated if origin is not active + * We also don't want active cow if it is shared store, + * in this case the target is loaded through the origin + * and there's no reason why the user would want to access + * the cow directly. + */ + if ((!origin_active || lp->shared_store) && + !deactivate_lv(cmd, lv)) { log_error("Aborting. Couldn't deactivate snapshot " "COW area. Manual intervention required."); return 0;