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 | 80 ++++++++++++++++++++++++++++++++------------- lib/metadata/lv_manip.c | 11 +++++- 2 files changed, 67 insertions(+), 24 deletions(-) Index: LVM2.2.02.85/lib/activate/dev_manager.c =================================================================== --- LVM2.2.02.85.orig/lib/activate/dev_manager.c 2011-05-23 15:58:54.000000000 +0200 +++ LVM2.2.02.85/lib/activate/dev_manager.c 2011-05-23 15:59:30.000000000 +0200 @@ -1202,13 +1202,28 @@ 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_dm_uuid(dm->mem, 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)) { + /* + * Using origin uuid so info-by-uuid -cow cleanup works. + * An origin with a shared snapshot store will only ever + * have one -cow device. + */ + if (!(cow_dlid = build_dm_uuid(dm->mem, lv->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; } @@ -1251,6 +1266,9 @@ static int _add_snapshot_target_to_dtree return 0; } + if (snap_seg->status & SNAPSHOT_SHARED) + return 1; + if (!(origin_dlid = build_dm_uuid(dm->mem, snap_seg->origin->lvid.s, "real"))) return_0; @@ -1291,7 +1309,9 @@ 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, + struct logical_volume *identity_lv, + const char *layer); /* Add all replicators' LVs */ static int _add_replicator_dev_target_to_dtree(struct dev_manager *dm, @@ -1303,7 +1323,8 @@ static int _add_replicator_dev_target_to /* For inactive replicator add linear mapping */ if (!lv_is_active_replicator_dev(seg->lv)) { - if (!_add_new_lv_to_dtree(dm, dtree, seg->lv->rdevice->lv, NULL)) + if (!_add_new_lv_to_dtree(dm, dtree, seg->lv->rdevice->lv, NULL, + NULL)) return_0; return 1; } @@ -1312,20 +1333,22 @@ static int _add_replicator_dev_target_to if (!seg->replicator || !first_seg(seg->replicator)->rlog_lv || !_add_new_lv_to_dtree(dm, dtree, - first_seg(seg->replicator)->rlog_lv, NULL) || - !_add_new_lv_to_dtree(dm, dtree, seg->replicator, NULL)) + first_seg(seg->replicator)->rlog_lv, NULL, + NULL) || + !_add_new_lv_to_dtree(dm, dtree, seg->replicator, NULL, NULL)) return_0; /* Activation of one replicator_dev node activates all other nodes */ dm_list_iterate_items(rsite, &seg->replicator->rsites) { dm_list_iterate_items(rdev, &rsite->rdevices) { if (rdev->lv && - !_add_new_lv_to_dtree(dm, dtree, rdev->lv, NULL)) + !_add_new_lv_to_dtree(dm, dtree, rdev->lv, NULL, + NULL)) return_0; if (rdev->slog && !_add_new_lv_to_dtree(dm, dtree, - rdev->slog, NULL)) + rdev->slog, NULL, NULL)) return_0; } } @@ -1340,7 +1363,7 @@ static int _add_replicator_dev_target_to if (!rdev->replicator_dev->lv || !_add_new_lv_to_dtree(dm, dtree, rdev->replicator_dev->lv, - NULL)) + NULL, NULL)) return_0; } } @@ -1379,7 +1402,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 (seg_is_replicator_dev(seg)) { @@ -1388,26 +1411,29 @@ static int _add_segment_to_dtree(struct /* If this is a snapshot origin, add real LV */ /* If this is a snapshot origin + merging snapshot, add cow + real LV */ } else if (lv_is_origin(seg->lv) && !layer) { - if (lv_is_merging_origin(seg->lv)) { + if (lv_is_multisnap_origin(seg->lv)) { + if (!_add_new_lv_to_dtree(dm, dtree, seg->lv->shared_snapshot->cow, seg->lv, "cow")) + return_0; + } else if (lv_is_merging_origin(seg->lv)) { if (!_add_new_lv_to_dtree(dm, dtree, - find_merging_cow(seg->lv)->cow, "cow")) + find_merging_cow(seg->lv)->cow, NULL, "cow")) return_0; /* * Must also add "real" LV for use when * snapshot-merge target is added */ } - if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, "real")) + 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))) + NULL, NULL))) return_0; } @@ -1429,14 +1455,18 @@ 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, + struct logical_volume *identity_lv, + const char *layer) { struct lv_segment *seg; struct lv_layer *lvlayer; @@ -1467,10 +1497,16 @@ static int _add_new_lv_to_dtree(struct d } } - if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) + if (lv_is_cow(lv) && find_cow(lv)->status & SNAPSHOT_SHARED && !layer) + return 1; + + if (!identity_lv) + identity_lv = lv; + + if (!(name = build_dm_name(dm->mem, lv->vg->name, identity_lv->name, layer))) return_0; - if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer))) + if (!(dlid = build_dm_uuid(dm->mem, identity_lv->lvid.s, layer))) return_0; /* We've already processed this node if it already has a context ptr */ @@ -1480,7 +1516,7 @@ static int _add_new_lv_to_dtree(struct d 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); + identity_lv->name, layer); return 0; } @@ -1693,7 +1729,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, origin_only ? "real" : NULL)) + if (!_add_new_lv_to_dtree(dm, dtree, lv, NULL, origin_only ? "real" : NULL)) goto_out; /* Preload any devices required before any suspensions */ Index: LVM2.2.02.85/lib/metadata/lv_manip.c =================================================================== --- LVM2.2.02.85.orig/lib/metadata/lv_manip.c 2011-05-23 15:59:26.000000000 +0200 +++ LVM2.2.02.85/lib/metadata/lv_manip.c 2011-05-23 15:59:30.000000000 +0200 @@ -3758,8 +3758,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;