27199bd753
This is necessary for multi-disk backups where not all jobs are immediately started after they are created. QEMU commit 06e0a9c16405c0a4c1eca33cf286cc04c42066a2 did already part of the work, ensuring that new writes after job creation don't pass through to the backup, but not yet for the MIRROR_SYNC_MODE_BITMAP case which is used for PBS. Signed-off-by: Fabian Ebner <f.ebner@proxmox.com> Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
130 lines
5.1 KiB
Diff
130 lines
5.1 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Fabian Ebner <f.ebner@proxmox.com>
|
|
Date: Mon, 7 Feb 2022 14:21:01 +0100
|
|
Subject: [PATCH] qemu-img: dd: add -l option for loading a snapshot
|
|
|
|
Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
|
|
---
|
|
docs/tools/qemu-img.rst | 6 +++---
|
|
qemu-img-cmds.hx | 4 ++--
|
|
qemu-img.c | 33 +++++++++++++++++++++++++++++++--
|
|
3 files changed, 36 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
|
|
index a49badb158..1039aec01c 100644
|
|
--- a/docs/tools/qemu-img.rst
|
|
+++ b/docs/tools/qemu-img.rst
|
|
@@ -492,10 +492,10 @@ Command description:
|
|
it doesn't need to be specified separately in this case.
|
|
|
|
|
|
-.. option:: dd [--image-opts] [-U] [-f FMT] [-O OUTPUT_FMT] [-n] [bs=BLOCK_SIZE] [count=BLOCKS] [skip=BLOCKS] if=INPUT of=OUTPUT
|
|
+.. option:: dd [--image-opts] [-U] [-f FMT] [-O OUTPUT_FMT] [-n] [-l SNAPSHOT_PARAM] [bs=BLOCK_SIZE] [count=BLOCKS] [skip=BLOCKS] if=INPUT of=OUTPUT
|
|
|
|
- dd copies from *INPUT* file to *OUTPUT* file converting it from
|
|
- *FMT* format to *OUTPUT_FMT* format.
|
|
+ dd copies from *INPUT* file or snapshot *SNAPSHOT_PARAM* to *OUTPUT* file
|
|
+ converting it from *FMT* format to *OUTPUT_FMT* format.
|
|
|
|
The data is by default read and written using blocks of 512 bytes but can be
|
|
modified by specifying *BLOCK_SIZE*. If count=\ *BLOCKS* is specified
|
|
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
|
|
index f3b2b1b4de..e77ed9347f 100644
|
|
--- a/qemu-img-cmds.hx
|
|
+++ b/qemu-img-cmds.hx
|
|
@@ -58,9 +58,9 @@ SRST
|
|
ERST
|
|
|
|
DEF("dd", img_dd,
|
|
- "dd [--image-opts] [-U] [-f fmt] [-O output_fmt] [-n] [bs=block_size] [count=blocks] [skip=blocks] [osize=output_size] if=input of=output")
|
|
+ "dd [--image-opts] [-U] [-f fmt] [-O output_fmt] [-n] [-l snapshot_param] [bs=block_size] [count=blocks] [skip=blocks] [osize=output_size] if=input of=output")
|
|
SRST
|
|
-.. option:: dd [--image-opts] [-U] [-f FMT] [-O OUTPUT_FMT] [-n] [bs=BLOCK_SIZE] [count=BLOCKS] [skip=BLOCKS] [osize=OUTPUT_SIZE] if=INPUT of=OUTPUT
|
|
+.. option:: dd [--image-opts] [-U] [-f FMT] [-O OUTPUT_FMT] [-n] [-l SNAPSHOT_PARAM] [bs=BLOCK_SIZE] [count=BLOCKS] [skip=BLOCKS] [osize=OUTPUT_SIZE] if=INPUT of=OUTPUT
|
|
ERST
|
|
|
|
DEF("info", img_info,
|
|
diff --git a/qemu-img.c b/qemu-img.c
|
|
index 015d6d2ce4..7031195e32 100644
|
|
--- a/qemu-img.c
|
|
+++ b/qemu-img.c
|
|
@@ -4922,6 +4922,7 @@ static int img_dd(int argc, char **argv)
|
|
BlockDriver *drv = NULL, *proto_drv = NULL;
|
|
BlockBackend *blk1 = NULL, *blk2 = NULL;
|
|
QemuOpts *opts = NULL;
|
|
+ QemuOpts *sn_opts = NULL;
|
|
QemuOptsList *create_opts = NULL;
|
|
Error *local_err = NULL;
|
|
bool image_opts = false;
|
|
@@ -4931,6 +4932,7 @@ static int img_dd(int argc, char **argv)
|
|
int64_t size = 0, readsize = 0;
|
|
int64_t block_count = 0, out_pos, in_pos;
|
|
bool force_share = false, skip_create = false;
|
|
+ const char *snapshot_name = NULL;
|
|
struct DdInfo dd = {
|
|
.flags = 0,
|
|
.count = 0,
|
|
@@ -4968,7 +4970,7 @@ static int img_dd(int argc, char **argv)
|
|
{ 0, 0, 0, 0 }
|
|
};
|
|
|
|
- while ((c = getopt_long(argc, argv, ":hf:O:Un", long_options, NULL))) {
|
|
+ while ((c = getopt_long(argc, argv, ":hf:O:l:Un", long_options, NULL))) {
|
|
if (c == EOF) {
|
|
break;
|
|
}
|
|
@@ -4991,6 +4993,19 @@ static int img_dd(int argc, char **argv)
|
|
case 'n':
|
|
skip_create = true;
|
|
break;
|
|
+ case 'l':
|
|
+ if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
|
|
+ sn_opts = qemu_opts_parse_noisily(&internal_snapshot_opts,
|
|
+ optarg, false);
|
|
+ if (!sn_opts) {
|
|
+ error_report("Failed in parsing snapshot param '%s'",
|
|
+ optarg);
|
|
+ goto out;
|
|
+ }
|
|
+ } else {
|
|
+ snapshot_name = optarg;
|
|
+ }
|
|
+ break;
|
|
case 'U':
|
|
force_share = true;
|
|
break;
|
|
@@ -5050,11 +5065,24 @@ static int img_dd(int argc, char **argv)
|
|
if (dd.flags & C_IF) {
|
|
blk1 = img_open(image_opts, in.filename, fmt, 0, false, false,
|
|
force_share);
|
|
-
|
|
if (!blk1) {
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
+ if (sn_opts) {
|
|
+ bdrv_snapshot_load_tmp(blk_bs(blk1),
|
|
+ qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID),
|
|
+ qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME),
|
|
+ &local_err);
|
|
+ } else if (snapshot_name != NULL) {
|
|
+ bdrv_snapshot_load_tmp_by_id_or_name(blk_bs(blk1), snapshot_name,
|
|
+ &local_err);
|
|
+ }
|
|
+ if (local_err) {
|
|
+ error_reportf_err(local_err, "Failed to load snapshot: ");
|
|
+ ret = -1;
|
|
+ goto out;
|
|
+ }
|
|
}
|
|
|
|
if (dd.flags & C_OSIZE) {
|
|
@@ -5203,6 +5231,7 @@ static int img_dd(int argc, char **argv)
|
|
out:
|
|
g_free(arg);
|
|
qemu_opts_del(opts);
|
|
+ qemu_opts_del(sn_opts);
|
|
qemu_opts_free(create_opts);
|
|
blk_unref(blk1);
|
|
blk_unref(blk2);
|