From f8b3b0bc9a5758ab3cacf0de79ee48bb851b07a6 Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Fri, 11 Nov 2016 00:27:01 +0000 Subject: [PATCH] lvconvert: Introduce enum to separate cases. Start to separate out the different things that lvconvert does by using an enum to identify 12 distinct cases. --- tools/lvconvert.c | 283 ++++++++++++++++++++++++++++------------------ 1 file changed, 170 insertions(+), 113 deletions(-) diff --git a/tools/lvconvert.c b/tools/lvconvert.c index 8376565c1..4563adeb4 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -37,19 +37,72 @@ * deprecated. (The same is still needed for --merge.) */ +typedef enum { + /* Merge: + * If merge_snapshot is also set: + * merge thin snapshot LV into its origin + * merge old snapshot COW into its origin + * or if merge_mirror is also set + * merge LV previously split from mirror back into mirror + */ + CONV_MERGE = 1, + + /* Split: + * For a snapshot, split it apart into COW and origin for future recombination + * For a cached LV, split it apart into the cached LV and its pool + * For a mirrored or raid LV, split mirror into two mirrors, optionally tracking + * future changes to the main mirror to allow future recombination. + */ + CONV_SPLIT = 2, + CONV_SPLIT_SNAPSHOT = 3, + CONV_SPLIT_CACHE = 4, + CONV_SPLIT_MIRRORS = 5, + + /* Start to cache an LV */ + CONV_CACHE = 6, + + /* Destroy the cache attached to a cached LV */ + CONV_UNCACHE = 7, + + /* Reconstruct a snapshot from its origin and COW */ + CONV_SNAPSHOT = 8, + + /* Replace devices in a raid LV with alternatives */ + CONV_REPLACE = 9, + + /* Repair a mirror, raid or thin LV */ + CONV_REPAIR = 10, + + /* Convert normal LV into one in a thin pool */ + CONV_THIN = 11, + + /* Every other segment type or mirror log conversion we haven't separated out */ + CONV_OTHER = 12, +} conversion_type_t; + struct lvconvert_params { /* Exactly one of these 12 command categories is determined */ - int merge; /* Either merge_snapshot or merge_mirror is also set */ - int cache; - int keep_mimages; /* --splitmirrors */ - int repair; - int replace; - int snapshot; - int split; - int splitcache; - int splitsnapshot; - int thin; - int uncache; + int merge; /* 1 */ + int split; /* 2 */ + int splitsnapshot; /* 3 */ + int splitcache; /* 4 */ + int keep_mimages; /* 5 */ /* --splitmirrors */ + int cache; /* 6 */ + int uncache; /* 7 */ + int snapshot; /* 8 */ + int replace; /* 9 */ + int repair; /* 10 */ + int thin; /* 11 */ + /* other */ /* 12 */ + + /* FIXME Eliminate all cases where more than one of the above are set then use conv_type instead */ + conversion_type_t conv_type; + + int merge_snapshot; /* CONV_MERGE is set */ + int merge_mirror; /* CONV_MERGE is set */ + + int track_changes; /* CONV_SPLIT_MIRRORS is set */ + int corelog; /* Equivalent to --mirrorlog core */ int mirrorlog; /* Only one of corelog and mirrorlog may be set */ @@ -59,11 +112,6 @@ struct lvconvert_params { const struct segment_type *segtype; /* Holds what segment type you will get */ - int merge_snapshot; /* merge is also set */ - int merge_mirror; /* merge is also set */ - - int track_changes; /* keep_mimages is also set (--splitmirrors) */ - int poolmetadataspare; int force; int yes; @@ -124,6 +172,15 @@ struct convert_poll_id_list { unsigned is_merging_origin_thin:1; }; +/* FIXME Temporary function until the enum replaces the separate variables */ +static void _set_conv_type(struct lvconvert_params *lp, int conv_type) +{ + if (lp->conv_type != CONV_OTHER) + log_error(INTERNAL_ERROR "Changing conv_type from %d to %d.", lp->conv_type, conv_type); + + lp->conv_type = conv_type; +} + static int _lvconvert_validate_names(struct lvconvert_params *lp) { unsigned i, j; @@ -472,10 +529,8 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv, -1)) return_0; lp->merge = 1; - } - - /* If --repair, check for incompatible args. */ - if (arg_is_set(cmd, repair_ARG)) { + _set_conv_type(lp, CONV_MERGE); + } else if (arg_is_set(cmd, repair_ARG)) { if (arg_outside_list_is_set(cmd, "cannot be used with --repair", repair_ARG, alloc_ARG, usepolicies_ARG, @@ -483,12 +538,8 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv, -1)) return_0; lp->repair = 1; - } - - if (arg_is_set(cmd, replace_ARG)) - lp->replace = 1; - - if (arg_is_set(cmd, split_ARG)) { + _set_conv_type(lp, CONV_REPAIR); + } else if (arg_is_set(cmd, split_ARG)) { if (arg_outside_list_is_set(cmd, "cannot be used with --split", split_ARG, name_ARG, @@ -496,40 +547,40 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv, -1)) return_0; lp->split = 1; - } - - if (arg_is_set(cmd, splitcache_ARG)) { + _set_conv_type(lp, CONV_SPLIT); + } else if (arg_is_set(cmd, splitcache_ARG)) { if (arg_outside_list_is_set(cmd, "cannot be used with --splitcache", splitcache_ARG, force_ARG, noudevsync_ARG, test_ARG, -1)) return_0; lp->splitcache = 1; - } - - if (arg_is_set(cmd, splitsnapshot_ARG)) { + _set_conv_type(lp, CONV_SPLIT_CACHE); + } else if (arg_is_set(cmd, splitsnapshot_ARG)) { if (arg_outside_list_is_set(cmd, "cannot be used with --splitsnapshot", splitsnapshot_ARG, force_ARG, noudevsync_ARG, test_ARG, -1)) return_0; lp->splitsnapshot = 1; - } - - if (arg_is_set(cmd, trackchanges_ARG)) - lp->track_changes = 1; - - if (arg_is_set(cmd, uncache_ARG)) { + _set_conv_type(lp, CONV_SPLIT_SNAPSHOT); + } else if (arg_is_set(cmd, uncache_ARG)) { if (arg_outside_list_is_set(cmd, "cannot be used with --uncache", uncache_ARG, force_ARG, noudevsync_ARG, test_ARG, -1)) return_0; lp->uncache = 1; + _set_conv_type(lp, CONV_UNCACHE); + } else if (arg_is_set(cmd, replace_ARG)) { + lp->replace = 1; + _set_conv_type(lp, CONV_REPLACE); } - if (arg_is_set(cmd, cache_ARG)) + if (arg_is_set(cmd, cache_ARG)) { lp->cache = 1; + _set_conv_type(lp, CONV_CACHE); + } if (!strcmp(lp->type_str, SEG_TYPE_NAME_CACHE)) lp->cache = 1; @@ -541,8 +592,10 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv, lp->type_str = SEG_TYPE_NAME_CACHE; } - if (arg_is_set(cmd, thin_ARG)) + if (arg_is_set(cmd, thin_ARG)) { lp->thin = 1; + _set_conv_type(lp, CONV_THIN); + } if (!strcmp(lp->type_str, SEG_TYPE_NAME_THIN)) lp->thin = 1; @@ -554,6 +607,9 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv, lp->type_str = SEG_TYPE_NAME_THIN; } + if (arg_is_set(cmd, trackchanges_ARG)) + lp->track_changes = 1; + if (!_read_pool_params(cmd, &argc, &argv, lp)) return_0; @@ -563,6 +619,7 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv, return 0; } lp->snapshot = 1; + _set_conv_type(lp, CONV_SNAPSHOT); } if (lp->split) { @@ -588,6 +645,7 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv, lp->lv_split_name = arg_str_value(cmd, name_ARG, NULL); lp->keep_mimages = 1; + _set_conv_type(lp, CONV_SPLIT_MIRRORS); lp->mirrors = arg_uint_value(cmd, splitmirrors_ARG, 0); lp->mirrors_sign = SIGN_MINUS; } else { @@ -642,6 +700,7 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv, return 0; } + /* * Final checking of each case: * lp->merge @@ -658,23 +717,18 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv, * --type mirror|raid lp->mirrorlog lp->corelog * --type raid0|striped */ - if (lp->merge) /* Snapshot or mirror merge */ - ; - else if (lp->splitsnapshot) /* Destroy snapshot retaining cow as separate LV */ - ; - else if (lp->splitcache) - ; - else if (lp->split) - ; - else if (lp->uncache) - ; - else if (lp->cache) - ; - else if (lp->thin) - ; - else if (lp->keep_mimages) /* --splitmirrors */ - ; - else if (lp->snapshot) { /* Snapshot creation from pre-existing cow */ + switch(lp->conv_type) { + case CONV_MERGE: /* Snapshot or mirror merge */ + case CONV_SPLIT: + case CONV_SPLIT_CACHE: + case CONV_SPLIT_MIRRORS: + case CONV_SPLIT_SNAPSHOT: /* Destroy snapshot retaining cow as separate LV */ + case CONV_CACHE: + case CONV_UNCACHE: + case CONV_THIN: + case CONV_REPAIR: + break; + case CONV_SNAPSHOT: /* Snapshot creation from pre-existing cow */ if (!argc) { log_error("Please provide logical volume path for snapshot origin."); return 0; @@ -708,8 +762,9 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv, log_verbose("Setting chunk size to %s.", display_size(cmd, lp->chunk_size)); lp->type_str = SEG_TYPE_NAME_SNAPSHOT; + break; - } else if (lp->replace) { /* RAID device replacement */ + case CONV_REPLACE: /* RAID device replacement */ lp->replace_pv_count = arg_count(cmd, replace_ARG); lp->replace_pvs = dm_pool_alloc(cmd->mem, sizeof(char *) * lp->replace_pv_count); if (!lp->replace_pvs) @@ -729,72 +784,73 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv, tmp_str))) return_0; } - } else if (lp->repair) - ; - else if (_mirror_or_raid_type_requested(cmd, lp->type_str) || - lp->mirrorlog || lp->corelog) { /* Mirrors (and some RAID functions) */ - if (arg_is_set(cmd, chunksize_ARG)) { - log_error("--chunksize is only available with snapshots or pools."); - return 0; - } + break; - if (arg_is_set(cmd, zero_ARG)) { - log_error("--zero is only available with snapshots or thin pools."); - return 0; - } - - /* - * --regionsize is only valid if converting an LV into a mirror. - * Checked when we know the state of the LV being converted. - */ - if (arg_is_set(cmd, regionsize_ARG)) { - if (arg_sign_value(cmd, regionsize_ARG, SIGN_NONE) == - SIGN_MINUS) { - log_error("Negative regionsize is invalid."); + case CONV_OTHER: + if (_mirror_or_raid_type_requested(cmd, lp->type_str) || + lp->mirrorlog || lp->corelog) { /* Mirrors (and some RAID functions) */ + if (arg_is_set(cmd, chunksize_ARG)) { + log_error("--chunksize is only available with snapshots or pools."); return 0; } - lp->region_size = arg_uint_value(cmd, regionsize_ARG, 0); - } else { - region_size = get_default_region_size(cmd); - if (region_size < 0) { - log_error("Negative regionsize in " - "configuration file is invalid."); + + if (arg_is_set(cmd, zero_ARG)) { + log_error("--zero is only available with snapshots or thin pools."); return 0; } - lp->region_size = region_size; - } - if (lp->region_size % (pagesize >> SECTOR_SHIFT)) { - log_error("Region size (%" PRIu32 ") must be " - "a multiple of machine memory " - "page size (%d).", - lp->region_size, pagesize >> SECTOR_SHIFT); - return 0; - } + /* + * --regionsize is only valid if converting an LV into a mirror. + * Checked when we know the state of the LV being converted. + */ + if (arg_is_set(cmd, regionsize_ARG)) { + if (arg_sign_value(cmd, regionsize_ARG, SIGN_NONE) == + SIGN_MINUS) { + log_error("Negative regionsize is invalid."); + return 0; + } + lp->region_size = arg_uint_value(cmd, regionsize_ARG, 0); + } else { + region_size = get_default_region_size(cmd); + if (region_size < 0) { + log_error("Negative regionsize in " + "configuration file is invalid."); + return 0; + } + lp->region_size = region_size; + } - if (!is_power_of_2(lp->region_size)) { - log_error("Region size (%" PRIu32 - ") must be a power of 2.", lp->region_size); - return 0; - } + if (lp->region_size % (pagesize >> SECTOR_SHIFT)) { + log_error("Region size (%" PRIu32 ") must be " + "a multiple of machine memory " + "page size (%d).", + lp->region_size, pagesize >> SECTOR_SHIFT); + return 0; + } - if (!lp->region_size) { - log_error("Non-zero region size must be supplied."); - return 0; - } + if (!is_power_of_2(lp->region_size)) { + log_error("Region size (%" PRIu32 + ") must be a power of 2.", lp->region_size); + return 0; + } - /* FIXME man page says in one place that --type and --mirrors can't be mixed */ - if (lp->mirrors_supplied && !lp->mirrors) - /* down-converting to linear/stripe? */ - lp->type_str = SEG_TYPE_NAME_STRIPED; + if (!lp->region_size) { + log_error("Non-zero region size must be supplied."); + return 0; + } - } else if (_raid0_type_requested(lp->type_str) || _striped_type_requested(lp->type_str)) { /* striped or linear or raid0 */ - if (arg_from_list_is_set(cmd, "cannot be used with --type raid0 or --type striped or --type linear", - chunksize_ARG, corelog_ARG, mirrors_ARG, mirrorlog_ARG, regionsize_ARG, zero_ARG, - -1)) - return_0; + /* FIXME man page says in one place that --type and --mirrors can't be mixed */ + if (lp->mirrors_supplied && !lp->mirrors) + /* down-converting to linear/stripe? */ + lp->type_str = SEG_TYPE_NAME_STRIPED; - } /* else segtype will default to current type */ + } else if (_raid0_type_requested(lp->type_str) || _striped_type_requested(lp->type_str)) { /* striped or linear or raid0 */ + if (arg_from_list_is_set(cmd, "cannot be used with --type raid0 or --type striped or --type linear", + chunksize_ARG, corelog_ARG, mirrors_ARG, mirrorlog_ARG, regionsize_ARG, zero_ARG, + -1)) + return_0; + } /* else segtype will default to current type */ + } lp->force = arg_count(cmd, force_ARG); lp->yes = arg_count(cmd, yes_ARG); @@ -4693,6 +4749,7 @@ int lvconvert(struct cmd_context * cmd, int argc, char **argv) int poll_ret, ret; struct convert_poll_id_list *idl; struct lvconvert_params lp = { + .conv_type = CONV_OTHER, .target_attr = ~0, .idls = DM_LIST_HEAD_INIT(lp.idls), };