Introduce find_shared_cow() and lv_is_shared_cow() wrappers. Signed-off-by: Mike Snitzer --- lib/activate/dev_manager.c | 11 ++++++----- lib/metadata/metadata-exported.h | 3 +++ lib/metadata/snapshot_manip.c | 39 +++++++++++++++++++++++++++++++-------- lib/report/report.c | 8 ++++---- tools/lvresize.c | 3 +-- 5 files changed, 45 insertions(+), 19 deletions(-) Index: lvm2/lib/activate/dev_manager.c =================================================================== --- lvm2.orig/lib/activate/dev_manager.c +++ lvm2/lib/activate/dev_manager.c @@ -1211,8 +1211,8 @@ static int _add_origin_target_to_dtree(s } 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, + find_shared_cow(lv)->exception_store, + find_shared_cow(lv)->chunk_size, n, snapids)) return_0; } else { @@ -1261,7 +1261,7 @@ static int _add_snapshot_target_to_dtree return 0; } - if (snap_seg->status & SNAPSHOT_SHARED) + if (lv_is_shared_cow(lv)) return 1; if (!(origin_dlid = build_dlid(dm, snap_seg->origin->lvid.s, "real"))) @@ -1346,7 +1346,8 @@ static int _add_segment_to_dtree(struct return 0; } if (lv_is_multisnap_origin(seg->lv)) { - if (!_add_new_lv_to_dtree(dm, dtree, seg->lv->shared_snapshot->cow, seg->lv, "cow")) + if (!_add_new_lv_to_dtree(dm, dtree, + find_shared_cow(seg->lv)->cow, seg->lv, "cow")) return_0; } else if (lv_is_merging_origin(seg->lv)) { if (!_add_new_lv_to_dtree(dm, dtree, @@ -1432,7 +1433,7 @@ static int _add_new_lv_to_dtree(struct d } } - if (lv_is_cow(lv) && find_cow(lv)->status & SNAPSHOT_SHARED && !layer) + if (lv_is_shared_cow(lv) && !layer) return 1; if (!identity_lv) Index: lvm2/lib/metadata/metadata-exported.h =================================================================== --- lvm2.orig/lib/metadata/metadata-exported.h +++ lvm2/lib/metadata/metadata-exported.h @@ -633,6 +633,7 @@ int lv_is_merging_origin(const struct lo int lv_is_merging_cow(const struct logical_volume *snapshot); int lv_is_multisnap_origin(const struct logical_volume *lv); int lv_is_multisnap_cow(const struct logical_volume *lv); +int lv_is_shared_cow(const struct logical_volume *lv); /* Test if given LV is visible from user's perspective */ int lv_is_visible(const struct logical_volume *lv); @@ -641,6 +642,8 @@ int pv_is_in_vg(struct volume_group *vg, struct lv_segment *find_merging_cow(const struct logical_volume *origin); +struct lv_segment *find_shared_cow(const struct logical_volume *origin); + /* Given a cow LV, return return the snapshot lv_segment that uses it */ struct lv_segment *find_cow(const struct logical_volume *lv); Index: lvm2/lib/metadata/snapshot_manip.c =================================================================== --- lvm2.orig/lib/metadata/snapshot_manip.c +++ lvm2/lib/metadata/snapshot_manip.c @@ -41,6 +41,11 @@ int lv_is_multisnap_cow(const struct log return seg && seg_is_virtual(seg) && seg->origin; } +int lv_is_shared_cow(const struct logical_volume *lv) +{ + return lv_is_cow(lv) && (find_cow(lv)->status & SNAPSHOT_SHARED); +} + int lv_is_visible(const struct logical_volume *lv) { if (lv->status & SNAPSHOT) @@ -89,12 +94,31 @@ struct lv_segment *find_cow(const struct return lv->snapshot; } +struct lv_segment *find_shared_cow(const struct logical_volume *origin) +{ + if (!lv_is_multisnap_origin(origin)) + return NULL; + + return origin->shared_snapshot; +} + /* Given a cow LV, return its origin */ struct logical_volume *origin_from_cow(const struct logical_volume *lv) { return lv->snapshot->origin; } +static void init_shared_snapshot(struct lv_segment *cow_seg, + struct logical_volume *origin) +{ + origin->shared_snapshot = cow_seg; +} + +static void clear_shared_snapshot(struct logical_volume *origin) +{ + origin->shared_snapshot = NULL; +} + int init_snapshot_seg(struct lv_segment *seg, struct logical_volume *origin, struct logical_volume *cow, const char *exception_store, uint32_t chunk_size, int merge) @@ -128,12 +152,11 @@ int init_snapshot_seg(struct lv_segment 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); + if (lv_is_multisnap_origin(origin)) { + log_err("Origin '%s' already has a shared snapshot.", origin->name); return_0; } + init_shared_snapshot(seg, origin); } dm_list_add(&origin->snapshot_segs, &seg->origin_list); @@ -189,8 +212,8 @@ 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."); + if (snapshot_flags & SNAPSHOT_SHARED && lv_is_multisnap_origin(origin)) { + log_error("Origin already has a shared snapshot."); return 0; } @@ -228,8 +251,8 @@ int vg_remove_snapshot(struct logical_vo preload_origin = 1; } - if (cow->snapshot->origin->shared_snapshot == cow->snapshot) - cow->snapshot->origin->shared_snapshot = NULL; + if (find_shared_cow(origin) == find_cow(cow)) + clear_shared_snapshot(origin); if (!lv_remove(cow->snapshot->lv)) { log_error("Failed to remove internal snapshot LV %s", Index: lvm2/lib/report/report.c =================================================================== --- lvm2.orig/lib/report/report.c +++ lvm2/lib/report/report.c @@ -383,8 +383,8 @@ static int _lvstatus_disp(struct dm_repo repstr[5] = '-'; } - if (lv_is_cow(lv) && lv->snapshot->status & SNAPSHOT_SHARED) - lv = lv->snapshot->origin; + if (lv_is_shared_cow(lv)) + lv = origin_from_cow(lv); else if (lv_is_multisnap_cow(lv)) lv = first_seg(lv)->origin; else @@ -1044,8 +1044,8 @@ report_empty: return 1; } - if (lv->snapshot->status & SNAPSHOT_SHARED) - lv = lv->snapshot->origin; + if (lv_is_shared_cow(lv)) + lv = origin_from_cow(lv); if (lv_info(lv->vg->cmd, lv, &info, 0, 0) && !info.exists) goto report_empty; Index: lvm2/tools/lvresize.c =================================================================== --- lvm2.orig/tools/lvresize.c +++ lvm2/tools/lvresize.c @@ -575,8 +575,7 @@ static int _lvresize(struct cmd_context return ECMD_FAILED; } } - if (lp->resize == LV_REDUCE && - lv_is_cow(lv) && lv->snapshot->status & SNAPSHOT_SHARED) { + if (lp->resize == LV_REDUCE && lv_is_shared_cow(lv)) { log_error("Shared snapshot cannot be reduced."); return ECMD_FAILED; }