--- lib/activate/activate.c | 23 +++++++++++++ lib/activate/activate.h | 2 + lib/activate/dev_manager.c | 18 ++++++++++ lib/activate/dev_manager.h | 3 + tools/lvconvert.c | 74 ++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 113 insertions(+), 7 deletions(-) Index: LVM2.2.02.73/tools/lvconvert.c =================================================================== --- LVM2.2.02.73.orig/tools/lvconvert.c 2010-09-10 19:23:57.000000000 +0200 +++ LVM2.2.02.73/tools/lvconvert.c 2010-09-10 19:25:29.000000000 +0200 @@ -1530,6 +1530,60 @@ out: return r; } +static int lvconvert_merge_shared(struct cmd_context *cmd, + struct logical_volume *lv, + struct lvconvert_params *lp) +{ + int r; + int merge_on_activate; + struct lvinfo info; + struct logical_volume *origin = first_seg(lv)->origin; + + merge_on_activate = lvconvert_merge_on_activate(cmd, lv, origin); + + if (!activation()) { + log_error("Can't merge shared snapshot without using " + "device-mapper kernel driver"); + return 0; + } + + if (!lv_info(cmd, origin, 0, &info, 1, 0)) { + log_error("Can't query origin state"); + return 0; + } + if (!info.exists) { + if (!activate_lv(cmd, origin)) { + log_error("Couldn't activate origin LV %s", origin->name); + return 0; + } + } + + r = lv_multisnap_prepare_merge(cmd, origin, first_seg(lv)->snapid); + + if (!info.exists) { + if (!deactivate_lv(cmd, origin)) + log_error("Couldn't deactivate origin LV %s", origin->name); + } + + if (!r) { + log_error("Couldn't merge LV %s", lv->name); + return 0; + } + + /* + * suppress the message "Logical volume successfully removed" + * in lv_remove_single + */ + lv->status &= ~VISIBLE_LV; + + r = lv_remove_single(cmd, lv, 1); + + if (r) + log_print("Logical volume \"%s\" is merging", lv->name); + + return r; +} + static int _lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv, void *handle) { @@ -1559,17 +1613,23 @@ static int _lvconvert_single(struct cmd_ } if (lp->merge) { - if (!lv_is_cow(lv) || lv->snapshot->status & SNAPSHOT_SHARED) { - log_error("Logical volume \"%s\" is not a snapshot", - lv->name); - return ECMD_FAILED; - } if (!archive(lv->vg)) { stack; return ECMD_FAILED; } - if (!lvconvert_merge(cmd, lv, lp)) { - stack; + if (lv_is_cow(lv) && !(lv->snapshot->status & SNAPSHOT_SHARED)) { + if (!lvconvert_merge(cmd, lv, lp)) { + stack; + return ECMD_FAILED; + } + } else if (lv_is_multisnap_cow(lv)) { + if (!lvconvert_merge_shared(cmd, lv, lp)) { + stack; + return ECMD_FAILED; + } + } else { + log_error("Logical volume \"%s\" is not a snapshot", + lv->name); return ECMD_FAILED; } } else if (lp->snapshot) { Index: LVM2.2.02.73/lib/activate/activate.c =================================================================== --- LVM2.2.02.73.orig/lib/activate/activate.c 2010-09-10 19:21:58.000000000 +0200 +++ LVM2.2.02.73/lib/activate/activate.c 2010-09-10 19:24:16.000000000 +0200 @@ -223,6 +223,11 @@ int lv_multisnap_delete(struct cmd_conte return 0; } +int lv_multisnap_prepare_merge(struct cmd_context *cmd, struct logical_volume *lv, const char *snapid) +{ + return 0; +} + int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv) { return 1; @@ -1387,6 +1392,24 @@ int lv_multisnap_delete(struct cmd_conte return r; } +int lv_multisnap_prepare_merge(struct cmd_context *cmd, struct logical_volume *lv, const char *snapid) +{ + struct dev_manager *dm; + int r; + + if (!activation()) + return 0; + + if (!(dm = dev_manager_create(cmd, lv->vg->name))) + return_0; + + r = dev_manager_multisnap_prepare_merge(dm, lv, snapid); + + dev_manager_destroy(dm); + + return r; +} + int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv) { int r = 1; Index: LVM2.2.02.73/lib/activate/activate.h =================================================================== --- LVM2.2.02.73.orig/lib/activate/activate.h 2010-09-10 19:21:58.000000000 +0200 +++ LVM2.2.02.73/lib/activate/activate.h 2010-09-10 19:24:16.000000000 +0200 @@ -67,6 +67,8 @@ int lv_multisnap_prepare_create(struct c const char *origin_snapid, char **snapid); int lv_multisnap_delete(struct cmd_context *cmd, struct logical_volume *lv, const char *snapid); +int lv_multisnap_prepare_merge(struct cmd_context *cmd, + struct logical_volume *lv, const char *snapid); int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv); Index: LVM2.2.02.73/lib/activate/dev_manager.c =================================================================== --- LVM2.2.02.73.orig/lib/activate/dev_manager.c 2010-09-10 19:21:58.000000000 +0200 +++ LVM2.2.02.73/lib/activate/dev_manager.c 2010-09-10 19:24:16.000000000 +0200 @@ -887,6 +887,24 @@ int dev_manager_multisnap_delete(struct return 1; } +int dev_manager_multisnap_prepare_merge(struct dev_manager *dm, + struct logical_volume *lv, + const char *snapid) +{ + const char *dlid; + + if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, NULL))) { + log_error("uuid build failed for %s", lv->name); + return 0; + } + + log_debug("Merging snapshot id %s from %s", snapid, lv->name); + + if (!_multisnap_message(dm, dlid, "prepare_merge %s", snapid)) + return 0; + + return 1; +} #if 0 log_very_verbose("%s %s", sus ? "Suspending" : "Resuming", name); Index: LVM2.2.02.73/lib/activate/dev_manager.h =================================================================== --- LVM2.2.02.73.orig/lib/activate/dev_manager.h 2010-09-10 19:21:58.000000000 +0200 +++ LVM2.2.02.73/lib/activate/dev_manager.h 2010-09-10 19:24:16.000000000 +0200 @@ -69,6 +69,9 @@ int dev_manager_multisnap_prepare_create int dev_manager_multisnap_delete(struct dev_manager *dm, struct logical_volume *lv, const char *snapid); +int dev_manager_multisnap_prepare_merge(struct dev_manager *dm, + struct logical_volume *lv, + const char *snapid); /* * Put the desired changes into effect.