1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

Add --merge support to lvconvert to start merging a snapshot into its

origin, example usage:  lvconvert --merge vg/snaplv
This commit is contained in:
Mike Snitzer 2010-01-13 01:45:15 +00:00
parent 0b2d216f8e
commit 154b64d7a5
3 changed files with 114 additions and 10 deletions

View File

@ -105,6 +105,7 @@ arg(list_ARG, 'l', "list", NULL, 0)
arg(size_ARG, 'L', "size", size_mb_arg, 0)
arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign, 0)
arg(persistent_ARG, 'M', "persistent", yes_no_arg, 0)
arg(merge_ARG, '\0', "merge", NULL, 0)
arg(major_ARG, 'j', "major", major_arg, 0)
arg(mirrors_ARG, 'm', "mirrors", int_arg_with_sign, 0)
arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg, 0)

View File

@ -124,12 +124,21 @@ xx(lvconvert,
"\t[-v|--verbose]\n"
"\t[-Z|--zero {y|n}]\n"
"\t[--version]" "\n"
"\tOriginalLogicalVolume[Path] SnapshotLogicalVolume[Path]\n",
"\tOriginalLogicalVolume[Path] SnapshotLogicalVolume[Path]\n\n"
"lvconvert "
"--merge\n"
"\t[-b|--background]\n"
"\t[-i|--interval seconds]\n"
"\t[-d|--debug]\n"
"\t[-h|-?|--help]\n"
"\t[-v|--verbose]\n"
"\tSnapshotLogicalVolume[Path]\n",
alloc_ARG, background_ARG, chunksize_ARG, corelog_ARG, interval_ARG,
splitmirrors_ARG, name_ARG, mirrorlog_ARG, mirrors_ARG, noudevsync_ARG,
regionsize_ARG, repair_ARG, snapshot_ARG, test_ARG, use_policies_ARG,
yes_ARG, force_ARG, zero_ARG)
merge_ARG, mirrorlog_ARG, mirrors_ARG, name_ARG, noudevsync_ARG,
regionsize_ARG, repair_ARG, snapshot_ARG, splitmirrors_ARG, test_ARG,
use_policies_ARG, yes_ARG, force_ARG, zero_ARG)
xx(lvcreate,
"Create a logical volume",

View File

@ -18,6 +18,7 @@
struct lvconvert_params {
int snapshot;
int merge;
int zero;
const char *origin;
@ -52,7 +53,7 @@ static int _lvconvert_name_params(struct lvconvert_params *lp,
char *ptr;
const char *vg_name = NULL;
if (lp->snapshot) {
if (lp->snapshot && !lp->merge) {
if (!*pargc) {
log_error("Please specify a logical volume to act as "
"the snapshot origin.");
@ -102,6 +103,11 @@ static int _lvconvert_name_params(struct lvconvert_params *lp,
if (!apply_lvname_restrictions(lp->lv_name))
return_0;
if (*pargc && (lp->snapshot || lp->merge)) {
log_error("Too many arguments provided for snapshots");
return 0;
}
return 1;
}
@ -113,10 +119,10 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
memset(lp, 0, sizeof(*lp));
if (arg_count(cmd, snapshot_ARG) &&
if ((arg_count(cmd, snapshot_ARG) || arg_count(cmd, merge_ARG)) &&
(arg_count(cmd, mirrorlog_ARG) || arg_count(cmd, mirrors_ARG) ||
arg_count(cmd, repair_ARG))) {
log_error("--snapshot argument cannot be mixed "
log_error("--snapshot or --merge argument cannot be mixed "
"with --mirrors, --repair or --log");
return 0;
}
@ -127,6 +133,11 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
if (arg_count(cmd, snapshot_ARG))
lp->snapshot = 1;
if (arg_count(cmd, snapshot_ARG) && arg_count(cmd, merge_ARG)) {
log_error("--snapshot and --merge are mutually exclusive");
return 0;
}
if (arg_count(cmd, splitmirrors_ARG) && arg_count(cmd, mirrors_ARG)) {
log_error("--mirrors and --splitmirrors are "
"mutually exclusive");
@ -163,6 +174,9 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
return 0;
}
if (arg_count(cmd, merge_ARG))
lp->merge = 1;
if (arg_count(cmd, mirrors_ARG)) {
/*
* --splitmirrors has been chosen as the mechanism for
@ -175,7 +189,18 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
lp->alloc = arg_uint_value(cmd, alloc_ARG, ALLOC_INHERIT);
if (lp->snapshot) {
if (lp->merge) {
if (arg_count(cmd, regionsize_ARG) || arg_count(cmd, chunksize_ARG) ||
arg_count(cmd, zero_ARG) || arg_count(cmd, regionsize_ARG)) {
log_error("Only --background and --interval are valid "
"arguments for snapshot merge");
return 0;
}
if (!(lp->segtype = get_segtype_from_string(cmd, "snapshot")))
return_0;
} else if (lp->snapshot) {
if (arg_count(cmd, regionsize_ARG)) {
log_error("--regionsize is only available with mirrors");
return 0;
@ -1026,6 +1051,61 @@ out:
return r;
}
static int lvconvert_merge(struct cmd_context *cmd,
struct logical_volume *lv,
struct lvconvert_params *lp)
{
int r = 0;
struct logical_volume *origin = origin_from_cow(lv);
struct lv_segment *cow_seg = find_cow(lv);
/* Check if merge is possible */
if (cow_seg->status & SNAPSHOT_MERGE) {
log_error("Snapshot %s is already merging", lv->name);
return 0;
}
if (origin->merging_snapshot) {
log_error("Snapshot %s is already merging into the origin",
origin->merging_snapshot->cow->name);
return 0;
}
init_snapshot_merge(cow_seg, origin);
/* store vg on disk(s) */
if (!vg_write(lv->vg))
return_0;
/* Perform merge */
if (!suspend_lv(cmd, origin)) {
log_error("Failed to suspend origin %s", origin->name);
vg_revert(lv->vg);
goto out;
}
if (!vg_commit(lv->vg)) {
if (!resume_lv(cmd, origin))
stack;
goto_out;
}
if (!resume_lv(cmd, origin)) {
log_error("Failed to reactivate origin %s", origin->name);
goto out;
}
if (!deactivate_lv(cmd, lv)) {
log_warn("WARNING: Unable to deactivate merging snapshot %s", lv->name);
/* merge is running regardless of this deactivation failure */
}
r = 1;
log_print("Merging of volume %s started.", lv->name);
out:
backup(lv->vg);
return r;
}
static int lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
void *handle)
{
@ -1036,7 +1116,7 @@ static int lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_FAILED;
}
if (lv_is_cow(lv)) {
if (lv_is_cow(lv) && !lp->merge) {
log_error("Can't convert snapshot logical volume \"%s\"",
lv->name);
return ECMD_FAILED;
@ -1052,7 +1132,21 @@ static int lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_FAILED;
}
if (lp->snapshot) {
if (lp->merge) {
if (!lv_is_cow(lv)) {
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;
return ECMD_FAILED;
}
} else if (lp->snapshot) {
if (lv->status & MIRRORED) {
log_error("Unable to convert mirrored LV \"%s\" into a snapshot.", lv->name);
return ECMD_FAILED;