]>
Commit | Line | Data |
---|---|---|
f6d40bfd FE |
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 | |
5 | ||
6 | Signed-off-by: Fabian Ebner <f.ebner@proxmox.com> | |
2fd4ea28 | 7 | Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com> |
f6d40bfd FE |
8 | --- |
9 | docs/tools/qemu-img.rst | 6 +++--- | |
10 | qemu-img-cmds.hx | 4 ++-- | |
11 | qemu-img.c | 33 +++++++++++++++++++++++++++++++-- | |
12 | 3 files changed, 36 insertions(+), 7 deletions(-) | |
13 | ||
14 | diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst | |
dc9827a6 | 15 | index 33979b7430..68e9c80788 100644 |
f6d40bfd FE |
16 | --- a/docs/tools/qemu-img.rst |
17 | +++ b/docs/tools/qemu-img.rst | |
18 | @@ -492,10 +492,10 @@ Command description: | |
19 | it doesn't need to be specified separately in this case. | |
20 | ||
21 | ||
22 | -.. option:: dd [--image-opts] [-U] [-f FMT] [-O OUTPUT_FMT] [-n] [bs=BLOCK_SIZE] [count=BLOCKS] [skip=BLOCKS] if=INPUT of=OUTPUT | |
23 | +.. 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 | ||
25 | - dd copies from *INPUT* file to *OUTPUT* file converting it from | |
26 | - *FMT* format to *OUTPUT_FMT* format. | |
27 | + dd copies from *INPUT* file or snapshot *SNAPSHOT_PARAM* to *OUTPUT* file | |
28 | + converting it from *FMT* format to *OUTPUT_FMT* format. | |
29 | ||
30 | The data is by default read and written using blocks of 512 bytes but can be | |
31 | modified by specifying *BLOCK_SIZE*. If count=\ *BLOCKS* is specified | |
32 | diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx | |
dc9827a6 | 33 | index b5b0bb4467..36f97e1f19 100644 |
f6d40bfd FE |
34 | --- a/qemu-img-cmds.hx |
35 | +++ b/qemu-img-cmds.hx | |
36 | @@ -58,9 +58,9 @@ SRST | |
37 | ERST | |
38 | ||
39 | DEF("dd", img_dd, | |
40 | - "dd [--image-opts] [-U] [-f fmt] [-O output_fmt] [-n] [bs=block_size] [count=blocks] [skip=blocks] [osize=output_size] if=input of=output") | |
41 | + "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 | SRST | |
43 | -.. 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 | |
44 | +.. 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 | |
45 | ERST | |
46 | ||
47 | DEF("info", img_info, | |
48 | diff --git a/qemu-img.c b/qemu-img.c | |
dc9827a6 | 49 | index 35c2bdc95c..6e93bbd425 100644 |
f6d40bfd FE |
50 | --- a/qemu-img.c |
51 | +++ b/qemu-img.c | |
dc9827a6 | 52 | @@ -4938,6 +4938,7 @@ static int img_dd(int argc, char **argv) |
f6d40bfd FE |
53 | BlockDriver *drv = NULL, *proto_drv = NULL; |
54 | BlockBackend *blk1 = NULL, *blk2 = NULL; | |
55 | QemuOpts *opts = NULL; | |
56 | + QemuOpts *sn_opts = NULL; | |
57 | QemuOptsList *create_opts = NULL; | |
58 | Error *local_err = NULL; | |
59 | bool image_opts = false; | |
dc9827a6 | 60 | @@ -4947,6 +4948,7 @@ static int img_dd(int argc, char **argv) |
f6d40bfd FE |
61 | int64_t size = 0, readsize = 0; |
62 | int64_t block_count = 0, out_pos, in_pos; | |
63 | bool force_share = false, skip_create = false; | |
64 | + const char *snapshot_name = NULL; | |
65 | struct DdInfo dd = { | |
66 | .flags = 0, | |
67 | .count = 0, | |
dc9827a6 | 68 | @@ -4984,7 +4986,7 @@ static int img_dd(int argc, char **argv) |
f6d40bfd FE |
69 | { 0, 0, 0, 0 } |
70 | }; | |
71 | ||
72 | - while ((c = getopt_long(argc, argv, ":hf:O:Un", long_options, NULL))) { | |
73 | + while ((c = getopt_long(argc, argv, ":hf:O:l:Un", long_options, NULL))) { | |
74 | if (c == EOF) { | |
75 | break; | |
76 | } | |
dc9827a6 | 77 | @@ -5007,6 +5009,19 @@ static int img_dd(int argc, char **argv) |
f6d40bfd FE |
78 | case 'n': |
79 | skip_create = true; | |
80 | break; | |
81 | + case 'l': | |
82 | + if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) { | |
83 | + sn_opts = qemu_opts_parse_noisily(&internal_snapshot_opts, | |
84 | + optarg, false); | |
85 | + if (!sn_opts) { | |
86 | + error_report("Failed in parsing snapshot param '%s'", | |
87 | + optarg); | |
88 | + goto out; | |
89 | + } | |
90 | + } else { | |
91 | + snapshot_name = optarg; | |
92 | + } | |
93 | + break; | |
94 | case 'U': | |
95 | force_share = true; | |
96 | break; | |
dc9827a6 | 97 | @@ -5066,11 +5081,24 @@ static int img_dd(int argc, char **argv) |
f6d40bfd FE |
98 | if (dd.flags & C_IF) { |
99 | blk1 = img_open(image_opts, in.filename, fmt, 0, false, false, | |
100 | force_share); | |
101 | - | |
102 | if (!blk1) { | |
103 | ret = -1; | |
104 | goto out; | |
105 | } | |
106 | + if (sn_opts) { | |
107 | + bdrv_snapshot_load_tmp(blk_bs(blk1), | |
108 | + qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID), | |
109 | + qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME), | |
110 | + &local_err); | |
111 | + } else if (snapshot_name != NULL) { | |
112 | + bdrv_snapshot_load_tmp_by_id_or_name(blk_bs(blk1), snapshot_name, | |
113 | + &local_err); | |
114 | + } | |
115 | + if (local_err) { | |
116 | + error_reportf_err(local_err, "Failed to load snapshot: "); | |
117 | + ret = -1; | |
118 | + goto out; | |
119 | + } | |
120 | } | |
121 | ||
122 | if (dd.flags & C_OSIZE) { | |
dc9827a6 | 123 | @@ -5219,6 +5247,7 @@ static int img_dd(int argc, char **argv) |
f6d40bfd FE |
124 | out: |
125 | g_free(arg); | |
126 | qemu_opts_del(opts); | |
127 | + qemu_opts_del(sn_opts); | |
128 | qemu_opts_free(create_opts); | |
129 | blk_unref(blk1); | |
130 | blk_unref(blk2); |