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(size_ARG, 'L', "size", size_mb_arg, 0)
arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign, 0) arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign, 0)
arg(persistent_ARG, 'M', "persistent", yes_no_arg, 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(major_ARG, 'j', "major", major_arg, 0)
arg(mirrors_ARG, 'm', "mirrors", int_arg_with_sign, 0) arg(mirrors_ARG, 'm', "mirrors", int_arg_with_sign, 0)
arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg, 0) arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg, 0)

View File

@ -124,12 +124,21 @@ xx(lvconvert,
"\t[-v|--verbose]\n" "\t[-v|--verbose]\n"
"\t[-Z|--zero {y|n}]\n" "\t[-Z|--zero {y|n}]\n"
"\t[--version]" "\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, alloc_ARG, background_ARG, chunksize_ARG, corelog_ARG, interval_ARG,
splitmirrors_ARG, name_ARG, mirrorlog_ARG, mirrors_ARG, noudevsync_ARG, merge_ARG, mirrorlog_ARG, mirrors_ARG, name_ARG, noudevsync_ARG,
regionsize_ARG, repair_ARG, snapshot_ARG, test_ARG, use_policies_ARG, regionsize_ARG, repair_ARG, snapshot_ARG, splitmirrors_ARG, test_ARG,
yes_ARG, force_ARG, zero_ARG) use_policies_ARG, yes_ARG, force_ARG, zero_ARG)
xx(lvcreate, xx(lvcreate,
"Create a logical volume", "Create a logical volume",

View File

@ -18,6 +18,7 @@
struct lvconvert_params { struct lvconvert_params {
int snapshot; int snapshot;
int merge;
int zero; int zero;
const char *origin; const char *origin;
@ -52,7 +53,7 @@ static int _lvconvert_name_params(struct lvconvert_params *lp,
char *ptr; char *ptr;
const char *vg_name = NULL; const char *vg_name = NULL;
if (lp->snapshot) { if (lp->snapshot && !lp->merge) {
if (!*pargc) { if (!*pargc) {
log_error("Please specify a logical volume to act as " log_error("Please specify a logical volume to act as "
"the snapshot origin."); "the snapshot origin.");
@ -102,6 +103,11 @@ static int _lvconvert_name_params(struct lvconvert_params *lp,
if (!apply_lvname_restrictions(lp->lv_name)) if (!apply_lvname_restrictions(lp->lv_name))
return_0; return_0;
if (*pargc && (lp->snapshot || lp->merge)) {
log_error("Too many arguments provided for snapshots");
return 0;
}
return 1; return 1;
} }
@ -113,10 +119,10 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
memset(lp, 0, sizeof(*lp)); 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, mirrorlog_ARG) || arg_count(cmd, mirrors_ARG) ||
arg_count(cmd, repair_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"); "with --mirrors, --repair or --log");
return 0; return 0;
} }
@ -127,6 +133,11 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
if (arg_count(cmd, snapshot_ARG)) if (arg_count(cmd, snapshot_ARG))
lp->snapshot = 1; 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)) { if (arg_count(cmd, splitmirrors_ARG) && arg_count(cmd, mirrors_ARG)) {
log_error("--mirrors and --splitmirrors are " log_error("--mirrors and --splitmirrors are "
"mutually exclusive"); "mutually exclusive");
@ -163,6 +174,9 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
return 0; return 0;
} }
if (arg_count(cmd, merge_ARG))
lp->merge = 1;
if (arg_count(cmd, mirrors_ARG)) { if (arg_count(cmd, mirrors_ARG)) {
/* /*
* --splitmirrors has been chosen as the mechanism for * --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); 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)) { if (arg_count(cmd, regionsize_ARG)) {
log_error("--regionsize is only available with mirrors"); log_error("--regionsize is only available with mirrors");
return 0; return 0;
@ -1026,6 +1051,61 @@ out:
return r; 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, static int lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
void *handle) void *handle)
{ {
@ -1036,7 +1116,7 @@ static int lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_FAILED; return ECMD_FAILED;
} }
if (lv_is_cow(lv)) { if (lv_is_cow(lv) && !lp->merge) {
log_error("Can't convert snapshot logical volume \"%s\"", log_error("Can't convert snapshot logical volume \"%s\"",
lv->name); lv->name);
return ECMD_FAILED; return ECMD_FAILED;
@ -1052,7 +1132,21 @@ static int lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_FAILED; 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) { if (lv->status & MIRRORED) {
log_error("Unable to convert mirrored LV \"%s\" into a snapshot.", lv->name); log_error("Unable to convert mirrored LV \"%s\" into a snapshot.", lv->name);
return ECMD_FAILED; return ECMD_FAILED;