Move functionality from lvconvert_merge (the command handler) into separate functions lvconvert_check_merge and lvconvert_do_merge. This is needed to cleanly implement merge-on-activate. Signed-off-by: Mikulas Patocka --- tools/lvconvert.c | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) Index: LVM2.2.02.39/tools/lvconvert.c =================================================================== --- LVM2.2.02.39.orig/tools/lvconvert.c 2008-08-04 20:42:45.000000000 +0200 +++ LVM2.2.02.39/tools/lvconvert.c 2008-08-04 20:42:48.000000000 +0200 @@ -800,20 +800,19 @@ static void swap_lvids(struct logical_vo lv2->minor = n; } -static int lvconvert_merge(struct cmd_context *cmd, - struct logical_volume *lv, - struct lvconvert_params *lp) +static int lvconvert_check_merge(struct cmd_context *cmd, + struct logical_volume *lv, + int type) { struct logical_volume *origin = origin_from_cow(lv); struct lv_segment *cow_seg = find_cow(lv); struct lvinfo info; - char *new_name; - const char *lv_name; if (cow_seg->status & SNAPSHOT_MERGE) { log_error("Snapshot %s is already merging", lv->name); return 0; } + if (origin->merging_snapshot) { log_error("Another snapshot is already merging"); return 0; @@ -825,23 +824,34 @@ static int lvconvert_merge(struct cmd_co return 0; } } + if (lv_info(cmd, lv, &info, 1, 0)) { - if (info.open_count && lp->merge != MERGE_AS_SNAPSHOT) { + if (info.open_count && type != MERGE_AS_SNAPSHOT) { log_error("Can't merge when snapshot is open"); return 0; } } - if (origin->origin_count != 1 && lp->merge == MERGE_AS_SNAPSHOT) { + if (origin->origin_count != 1 && type == MERGE_AS_SNAPSHOT) { log_error("There must not be other snapshots when preserving snapshot name"); return 0; } - lv_name = lv->name; + return 1; +} + +static int lvconvert_do_merge(struct cmd_context *cmd, + struct logical_volume *lv, + int type) +{ + struct logical_volume *origin = origin_from_cow(lv); + struct lv_segment *cow_seg = find_cow(lv); + char *new_name; + const char *lv_name; cow_seg->status |= SNAPSHOT_MERGE; origin->merging_snapshot = cow_seg; - if (lp->merge == MERGE_AS_SNAPSHOT) + if (type == MERGE_AS_SNAPSHOT) swap_lvids(origin, lv); new_name = dm_pool_alloc(cmd->mem, NAME_LEN); @@ -849,6 +859,7 @@ static int lvconvert_merge(struct cmd_co log_error("Failed to allocate memory for the new name"); return 0; } + if (!generate_lv_name(lv->vg, "snapshot%d", new_name, NAME_LEN)) { log_error("Failed to generate unique name for the new volume"); return 0; @@ -882,6 +893,24 @@ static int lvconvert_merge(struct cmd_co return 0; } + return 1; +} + +static int lvconvert_merge(struct cmd_context *cmd, + struct logical_volume *lv, + struct lvconvert_params *lp) +{ + struct logical_volume *origin = origin_from_cow(lv); + const char *lv_name; + + if (!lvconvert_check_merge(cmd, lv, lp->merge)) + return 0; + + lv_name = lv->name; + + if (!lvconvert_do_merge(cmd, lv, lp->merge)) + return 0; + lp->need_polling = 1; lp->lv_to_poll = origin;