1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Fabian Ebner <f.ebner@proxmox.com>
3 Date: Mon, 7 Feb 2022 14:21:01 +0100
4 Subject: [PATCH] qemu-img: dd: add -l option for loading a snapshot
6 Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
8 docs/tools/qemu-img.rst | 6 +++---
9 qemu-img-cmds.hx | 4 ++--
10 qemu-img.c | 33 +++++++++++++++++++++++++++++++--
11 3 files changed, 36 insertions(+), 7 deletions(-)
13 diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
14 index a49badb158..1039aec01c 100644
15 --- a/docs/tools/qemu-img.rst
16 +++ b/docs/tools/qemu-img.rst
17 @@ -492,10 +492,10 @@ Command description:
18 it doesn't need to be specified separately in this case.
21 -.. option:: dd [--image-opts] [-U] [-f FMT] [-O OUTPUT_FMT] [-n] [bs=BLOCK_SIZE] [count=BLOCKS] [skip=BLOCKS] if=INPUT of=OUTPUT
22 +.. 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
24 - dd copies from *INPUT* file to *OUTPUT* file converting it from
25 - *FMT* format to *OUTPUT_FMT* format.
26 + dd copies from *INPUT* file or snapshot *SNAPSHOT_PARAM* to *OUTPUT* file
27 + converting it from *FMT* format to *OUTPUT_FMT* format.
29 The data is by default read and written using blocks of 512 bytes but can be
30 modified by specifying *BLOCK_SIZE*. If count=\ *BLOCKS* is specified
31 diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
32 index f3b2b1b4de..e77ed9347f 100644
33 --- a/qemu-img-cmds.hx
34 +++ b/qemu-img-cmds.hx
35 @@ -58,9 +58,9 @@ SRST
39 - "dd [--image-opts] [-U] [-f fmt] [-O output_fmt] [-n] [bs=block_size] [count=blocks] [skip=blocks] [osize=output_size] if=input of=output")
40 + "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")
42 -.. 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
43 +.. 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
47 diff --git a/qemu-img.c b/qemu-img.c
48 index 015d6d2ce4..7031195e32 100644
51 @@ -4922,6 +4922,7 @@ static int img_dd(int argc, char **argv)
52 BlockDriver *drv = NULL, *proto_drv = NULL;
53 BlockBackend *blk1 = NULL, *blk2 = NULL;
54 QemuOpts *opts = NULL;
55 + QemuOpts *sn_opts = NULL;
56 QemuOptsList *create_opts = NULL;
57 Error *local_err = NULL;
58 bool image_opts = false;
59 @@ -4931,6 +4932,7 @@ static int img_dd(int argc, char **argv)
60 int64_t size = 0, readsize = 0;
61 int64_t block_count = 0, out_pos, in_pos;
62 bool force_share = false, skip_create = false;
63 + const char *snapshot_name = NULL;
67 @@ -4968,7 +4970,7 @@ static int img_dd(int argc, char **argv)
71 - while ((c = getopt_long(argc, argv, ":hf:O:Un", long_options, NULL))) {
72 + while ((c = getopt_long(argc, argv, ":hf:O:l:Un", long_options, NULL))) {
76 @@ -4991,6 +4993,19 @@ static int img_dd(int argc, char **argv)
81 + if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
82 + sn_opts = qemu_opts_parse_noisily(&internal_snapshot_opts,
85 + error_report("Failed in parsing snapshot param '%s'",
90 + snapshot_name = optarg;
96 @@ -5050,11 +5065,24 @@ static int img_dd(int argc, char **argv)
97 if (dd.flags & C_IF) {
98 blk1 = img_open(image_opts, in.filename, fmt, 0, false, false,
106 + bdrv_snapshot_load_tmp(blk_bs(blk1),
107 + qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID),
108 + qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME),
110 + } else if (snapshot_name != NULL) {
111 + bdrv_snapshot_load_tmp_by_id_or_name(blk_bs(blk1), snapshot_name,
115 + error_reportf_err(local_err, "Failed to load snapshot: ");
121 if (dd.flags & C_OSIZE) {
122 @@ -5203,6 +5231,7 @@ static int img_dd(int argc, char **argv)
126 + qemu_opts_del(sn_opts);
127 qemu_opts_free(create_opts);