xref: /openbmc/qemu/qemu-img.c (revision 6370d13c62c300826f8eb80e4ed9d2e67bad3fa7)
1ea2384d3Sbellard /*
2fb43f4ddSbellard  * QEMU disk image utility
3ea2384d3Sbellard  *
468d0f70eSbellard  * Copyright (c) 2003-2008 Fabrice Bellard
5ea2384d3Sbellard  *
6ea2384d3Sbellard  * Permission is hereby granted, free of charge, to any person obtaining a copy
7ea2384d3Sbellard  * of this software and associated documentation files (the "Software"), to deal
8ea2384d3Sbellard  * in the Software without restriction, including without limitation the rights
9ea2384d3Sbellard  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10ea2384d3Sbellard  * copies of the Software, and to permit persons to whom the Software is
11ea2384d3Sbellard  * furnished to do so, subject to the following conditions:
12ea2384d3Sbellard  *
13ea2384d3Sbellard  * The above copyright notice and this permission notice shall be included in
14ea2384d3Sbellard  * all copies or substantial portions of the Software.
15ea2384d3Sbellard  *
16ea2384d3Sbellard  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17ea2384d3Sbellard  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18ea2384d3Sbellard  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19ea2384d3Sbellard  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20ea2384d3Sbellard  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21ea2384d3Sbellard  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22ea2384d3Sbellard  * THE SOFTWARE.
23ea2384d3Sbellard  */
24452fcdbcSMarkus Armbruster 
2580c71a24SPeter Maydell #include "qemu/osdep.h"
26c2a3d7daSEric Blake #include <getopt.h>
27c2a3d7daSEric Blake 
2849f95221SMarc-André Lureau #include "qemu/help-texts.h"
2916a18f26SMarc-André Lureau #include "qemu/qemu-progress.h"
3067a1de0dSFam Zheng #include "qemu-version.h"
31da34e65cSMarkus Armbruster #include "qapi/error.h"
323b51ab4bSEric Blake #include "qapi/qapi-commands-block-core.h"
339af23989SMarkus Armbruster #include "qapi/qapi-visit-block-core.h"
34b3db211fSDaniel P. Berrange #include "qapi/qobject-output-visitor.h"
357b1b5d19SPaolo Bonzini #include "qapi/qmp/qjson.h"
36452fcdbcSMarkus Armbruster #include "qapi/qmp/qdict.h"
37f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
383babeb15SDaniel P. Berrange #include "qemu/config-file.h"
391de7afc9SPaolo Bonzini #include "qemu/option.h"
401de7afc9SPaolo Bonzini #include "qemu/error-report.h"
4106a1e0c1SDenis V. Lunev #include "qemu/log.h"
42db725815SMarkus Armbruster #include "qemu/main-loop.h"
430b8fa32fSMarkus Armbruster #include "qemu/module.h"
4498c5d2e7SDaniel P. Berrangé #include "qemu/sockets.h"
4597ede57aSStefano Garzarella #include "qemu/units.h"
465df022cfSPeter Maydell #include "qemu/memalign.h"
473babeb15SDaniel P. Berrange #include "qom/object_interfaces.h"
4826f54e9aSMarkus Armbruster #include "sysemu/block-backend.h"
49737e150eSPaolo Bonzini #include "block/block_int.h"
50d4a3238aSMax Reitz #include "block/blockjob.h"
51e2c1c34fSMarkus Armbruster #include "block/dirty-bitmap.h"
52f364ec65SWenchao Xia #include "block/qapi.h"
53c2297088SDaniel P. Berrange #include "crypto/init.h"
5406a1e0c1SDenis V. Lunev #include "trace/control.h"
550c8c4895SZhengui #include "qemu/throttle.h"
560c8c4895SZhengui #include "block/throttle-groups.h"
57e8445331Sbellard 
587e563bfbSThomas Huth #define QEMU_IMG_VERSION "qemu-img version " QEMU_FULL_VERSION \
590781dd6eSThomas Huth                           "\n" QEMU_COPYRIGHT "\n"
605f6979cbSJeff Cody 
61c227f099SAnthony Liguori typedef struct img_cmd_t {
62153859beSStuart Brady     const char *name;
63153859beSStuart Brady     int (*handler)(int argc, char **argv);
64c227f099SAnthony Liguori } img_cmd_t;
65153859beSStuart Brady 
668599ea4cSFederico Simoncelli enum {
678599ea4cSFederico Simoncelli     OPTION_OUTPUT = 256,
688599ea4cSFederico Simoncelli     OPTION_BACKING_CHAIN = 257,
693babeb15SDaniel P. Berrange     OPTION_OBJECT = 258,
70eb769f74SDaniel P. Berrange     OPTION_IMAGE_OPTS = 259,
71b6495fa8SKevin Wolf     OPTION_PATTERN = 260,
7255d539c8SKevin Wolf     OPTION_FLUSH_INTERVAL = 261,
7355d539c8SKevin Wolf     OPTION_NO_DRAIN = 262,
74305b4c60SDaniel P. Berrange     OPTION_TARGET_IMAGE_OPTS = 263,
75fd03c2b8SStefan Hajnoczi     OPTION_SIZE = 264,
76dc5f690bSMax Reitz     OPTION_PREALLOCATION = 265,
774ffca890SPavel Butsykin     OPTION_SHRINK = 266,
788eaac025SMax Reitz     OPTION_SALVAGE = 267,
79168468feSDavid Edmondson     OPTION_TARGET_IS_ZERO = 268,
803b51ab4bSEric Blake     OPTION_ADD = 269,
813b51ab4bSEric Blake     OPTION_REMOVE = 270,
823b51ab4bSEric Blake     OPTION_CLEAR = 271,
833b51ab4bSEric Blake     OPTION_ENABLE = 272,
843b51ab4bSEric Blake     OPTION_DISABLE = 273,
853b51ab4bSEric Blake     OPTION_MERGE = 274,
8615e39ad9SEric Blake     OPTION_BITMAPS = 275,
87a3579bfaSMaxim Levitsky     OPTION_FORCE = 276,
88955171e4SEric Blake     OPTION_SKIP_BROKEN = 277,
898599ea4cSFederico Simoncelli };
908599ea4cSFederico Simoncelli 
918599ea4cSFederico Simoncelli typedef enum OutputFormat {
928599ea4cSFederico Simoncelli     OFORMAT_JSON,
938599ea4cSFederico Simoncelli     OFORMAT_HUMAN,
948599ea4cSFederico Simoncelli } OutputFormat;
958599ea4cSFederico Simoncelli 
96e6996143SKevin Wolf /* Default to cache=writeback as data integrity is not important for qemu-img */
97661a0f71SFederico Simoncelli #define BDRV_DEFAULT_CACHE "writeback"
98137519ceSaurel32 
format_print(void * opaque,const char * name)9900c6d403SStefan Hajnoczi static void format_print(void *opaque, const char *name)
100ea2384d3Sbellard {
10100c6d403SStefan Hajnoczi     printf(" %s", name);
1021a443c1bSMike Day }
103ea2384d3Sbellard 
1048905770bSMarc-André Lureau static G_NORETURN G_GNUC_PRINTF(1, 2)
error_exit(const char * fmt,...)1058905770bSMarc-André Lureau void error_exit(const char *fmt, ...)
106ac1307abSFam Zheng {
107ac1307abSFam Zheng     va_list ap;
108ac1307abSFam Zheng 
109ac1307abSFam Zheng     va_start(ap, fmt);
110e9e1d92dSMarkus Armbruster     error_vreport(fmt, ap);
111ac1307abSFam Zheng     va_end(ap);
112ac1307abSFam Zheng 
113e9e1d92dSMarkus Armbruster     error_printf("Try 'qemu-img --help' for more information\n");
114ac1307abSFam Zheng     exit(EXIT_FAILURE);
115ac1307abSFam Zheng }
116ac1307abSFam Zheng 
1178905770bSMarc-André Lureau static G_NORETURN
missing_argument(const char * option)1188905770bSMarc-André Lureau void missing_argument(const char *option)
119c9192973SStefan Hajnoczi {
120c9192973SStefan Hajnoczi     error_exit("missing argument for option '%s'", option);
121c9192973SStefan Hajnoczi }
122c9192973SStefan Hajnoczi 
1238905770bSMarc-André Lureau static G_NORETURN
unrecognized_option(const char * option)1248905770bSMarc-André Lureau void unrecognized_option(const char *option)
125c9192973SStefan Hajnoczi {
126c9192973SStefan Hajnoczi     error_exit("unrecognized option '%s'", option);
127c9192973SStefan Hajnoczi }
128c9192973SStefan Hajnoczi 
1290562adf5SEric Blake /* Please keep in synch with docs/tools/qemu-img.rst */
1308905770bSMarc-André Lureau static G_NORETURN
help(void)1318905770bSMarc-André Lureau void help(void)
132ea2384d3Sbellard {
133e00291c0SPaolo Bonzini     const char *help_msg =
1345f6979cbSJeff Cody            QEMU_IMG_VERSION
13510985131SDenis V. Lunev            "usage: qemu-img [standard options] command [command options]\n"
136ea2384d3Sbellard            "QEMU disk image utility\n"
137ea2384d3Sbellard            "\n"
13810985131SDenis V. Lunev            "    '-h', '--help'       display this help and exit\n"
13910985131SDenis V. Lunev            "    '-V', '--version'    output version information and exit\n"
14006a1e0c1SDenis V. Lunev            "    '-T', '--trace'      [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
14106a1e0c1SDenis V. Lunev            "                         specify tracing options\n"
14210985131SDenis V. Lunev            "\n"
143ea2384d3Sbellard            "Command syntax:\n"
144153859beSStuart Brady #define DEF(option, callback, arg_string)        \
145153859beSStuart Brady            "  " arg_string "\n"
146153859beSStuart Brady #include "qemu-img-cmds.h"
147153859beSStuart Brady #undef DEF
148ea2384d3Sbellard            "\n"
149ea2384d3Sbellard            "Command parameters:\n"
150ea2384d3Sbellard            "  'filename' is a disk image filename\n"
1513babeb15SDaniel P. Berrange            "  'objectdef' is a QEMU user creatable object definition. See the qemu(1)\n"
1523babeb15SDaniel P. Berrange            "    manual page for a description of the object properties. The most common\n"
1533babeb15SDaniel P. Berrange            "    object type is a 'secret', which is used to supply passwords and/or\n"
1543babeb15SDaniel P. Berrange            "    encryption keys.\n"
155ea2384d3Sbellard            "  'fmt' is the disk image format. It is guessed automatically in most cases\n"
156661a0f71SFederico Simoncelli            "  'cache' is the cache mode used to write the output disk image, the valid\n"
15780ccf93bSLiu Yuan            "    options are: 'none', 'writeback' (default, except for convert), 'writethrough',\n"
15880ccf93bSLiu Yuan            "    'directsync' and 'unsafe' (default for convert)\n"
159bb87fdf8SStefan Hajnoczi            "  'src_cache' is the cache mode used to read input disk images, the valid\n"
160bb87fdf8SStefan Hajnoczi            "    options are the same as for the 'cache' option\n"
16121eb3a2bSPierre Riteau            "  'size' is the disk image size in bytes. Optional suffixes\n"
1625e00984aSKevin Wolf            "    'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M),\n"
1635e00984aSKevin Wolf            "    'T' (terabyte, 1024G), 'P' (petabyte, 1024T) and 'E' (exabyte, 1024P)  are\n"
1645e00984aSKevin Wolf            "    supported. 'b' is ignored.\n"
165ea2384d3Sbellard            "  'output_filename' is the destination disk image filename\n"
166ea2384d3Sbellard            "  'output_fmt' is the destination format\n"
167eff44266SKevin Wolf            "  'options' is a comma separated list of format specific options in a\n"
1687f118b43SMarkus Armbruster            "    name=value format. Use -o help for an overview of the options supported by\n"
1697f118b43SMarkus Armbruster            "    the used format\n"
170ef80654dSWenchao Xia            "  'snapshot_param' is param used for internal snapshot, format\n"
171ef80654dSWenchao Xia            "    is 'snapshot.id=[ID],snapshot.name=[NAME]', or\n"
172ef80654dSWenchao Xia            "    '[ID_OR_NAME]'\n"
173ea2384d3Sbellard            "  '-c' indicates that target image must be compressed (qcow format only)\n"
1746e6e55f5SJohn Snow            "  '-u' allows unsafe backing chains. For rebasing, it is assumed that old and\n"
1756e6e55f5SJohn Snow            "       new backing file match exactly. The image doesn't need a working\n"
1766e6e55f5SJohn Snow            "       backing file before rebasing in this case (useful for renaming the\n"
1776e6e55f5SJohn Snow            "       backing file). For image creation, allow creating without attempting\n"
1786e6e55f5SJohn Snow            "       to open the backing file.\n"
179d2c639d6Sblueswir1            "  '-h' with or without a command shows this help and lists the supported formats\n"
1806b837bc4SJes Sorensen            "  '-p' show progress of command (only certain commands)\n"
181f382d43aSMiroslav Rezanina            "  '-q' use Quiet mode - do not print any output (except errors)\n"
18211b6699aSPeter Lieven            "  '-S' indicates the consecutive number of bytes (defaults to 4k) that must\n"
18311b6699aSPeter Lieven            "       contain only zeros for qemu-img to create a sparse image during\n"
18411b6699aSPeter Lieven            "       conversion. If the number of bytes is 0, the source will not be scanned for\n"
18511b6699aSPeter Lieven            "       unallocated or zero sectors, and the destination image will always be\n"
18611b6699aSPeter Lieven            "       fully allocated\n"
187c054b3fdSBenoît Canet            "  '--output' takes the format in which the output must be done (human or json)\n"
188b2e10493SAlexandre Derumier            "  '-n' skips the target volume creation (useful if the volume is created\n"
189b2e10493SAlexandre Derumier            "       prior to running qemu-img)\n"
190f7b4a940Saliguori            "\n"
1913b51ab4bSEric Blake            "Parameters to bitmap subcommand:\n"
1923b51ab4bSEric Blake            "  'bitmap' is the name of the bitmap to manipulate, through one or more\n"
1933b51ab4bSEric Blake            "       actions from '--add', '--remove', '--clear', '--enable', '--disable',\n"
1943b51ab4bSEric Blake            "       or '--merge source'\n"
1953b51ab4bSEric Blake            "  '-g granularity' sets the granularity for '--add' actions\n"
1963b51ab4bSEric Blake            "  '-b source' and '-F src_fmt' tell '--merge' actions to find the source\n"
1973b51ab4bSEric Blake            "       bitmaps from an alternative file\n"
1983b51ab4bSEric Blake            "\n"
1994534ff54SKevin Wolf            "Parameters to check subcommand:\n"
2004534ff54SKevin Wolf            "  '-r' tries to repair any inconsistencies that are found during the check.\n"
2014534ff54SKevin Wolf            "       '-r leaks' repairs only cluster leaks, whereas '-r all' fixes all\n"
2024534ff54SKevin Wolf            "       kinds of errors, with a higher risk of choosing the wrong fix or\n"
2030546b8c2SStefan Weil            "       hiding corruption that has already occurred.\n"
2044534ff54SKevin Wolf            "\n"
2052d9187bcSPeter Lieven            "Parameters to convert subcommand:\n"
20615e39ad9SEric Blake            "  '--bitmaps' copies all top-level persistent bitmaps to destination\n"
2072d9187bcSPeter Lieven            "  '-m' specifies how many coroutines work in parallel during the convert\n"
2082d9187bcSPeter Lieven            "       process (defaults to 8)\n"
2092d9187bcSPeter Lieven            "  '-W' allow to write to the target out of order rather than sequential\n"
2102d9187bcSPeter Lieven            "\n"
211f7b4a940Saliguori            "Parameters to snapshot subcommand:\n"
212f7b4a940Saliguori            "  'snapshot' is the name of the snapshot to create, apply or delete\n"
213f7b4a940Saliguori            "  '-a' applies a snapshot (revert disk to saved state)\n"
214f7b4a940Saliguori            "  '-c' creates a snapshot\n"
215f7b4a940Saliguori            "  '-d' deletes a snapshot\n"
216d14ed18cSMiroslav Rezanina            "  '-l' lists all snapshots in the given image\n"
217d14ed18cSMiroslav Rezanina            "\n"
218d14ed18cSMiroslav Rezanina            "Parameters to compare subcommand:\n"
219d14ed18cSMiroslav Rezanina            "  '-f' first image format\n"
220d14ed18cSMiroslav Rezanina            "  '-F' second image format\n"
22186ce1f6eSReda Sallahi            "  '-s' run in Strict mode - fail on different image size or sector allocation\n"
22286ce1f6eSReda Sallahi            "\n"
22386ce1f6eSReda Sallahi            "Parameters to dd subcommand:\n"
22486ce1f6eSReda Sallahi            "  'bs=BYTES' read and write up to BYTES bytes at a time "
22586ce1f6eSReda Sallahi            "(default: 512)\n"
22686ce1f6eSReda Sallahi            "  'count=N' copy only N input blocks\n"
22786ce1f6eSReda Sallahi            "  'if=FILE' read from FILE\n"
228f7c15533SReda Sallahi            "  'of=FILE' write to FILE\n"
229f7c15533SReda Sallahi            "  'skip=N' skip N bs-sized blocks at the start of input\n";
230e00291c0SPaolo Bonzini 
231e00291c0SPaolo Bonzini     printf("%s\nSupported formats:", help_msg);
2329ac404c5SAndrey Shinkevich     bdrv_iterate_format(format_print, NULL, false);
233f5048cb7SEric Blake     printf("\n\n" QEMU_HELP_BOTTOM "\n");
234ac1307abSFam Zheng     exit(EXIT_SUCCESS);
235ea2384d3Sbellard }
236ea2384d3Sbellard 
23780c710cbSMarkus Armbruster /*
23846bb944eSPhilippe Mathieu-Daudé  * Is @list safe for accumulate_options()?
23980c710cbSMarkus Armbruster  * It is when multiple of them can be joined together separated by ','.
24046bb944eSPhilippe Mathieu-Daudé  * To make that work, @list must not start with ',' (or else a
24180c710cbSMarkus Armbruster  * separating ',' preceding it gets escaped), and it must not end with
24280c710cbSMarkus Armbruster  * an odd number of ',' (or else a separating ',' following it gets
243f62514b3SMarkus Armbruster  * escaped), or be empty (or else a separating ',' preceding it can
244f62514b3SMarkus Armbruster  * escape a separating ',' following it).
245f62514b3SMarkus Armbruster  *
24680c710cbSMarkus Armbruster  */
is_valid_option_list(const char * list)24746bb944eSPhilippe Mathieu-Daudé static bool is_valid_option_list(const char *list)
24880c710cbSMarkus Armbruster {
24946bb944eSPhilippe Mathieu-Daudé     size_t len = strlen(list);
25080c710cbSMarkus Armbruster     size_t i;
25180c710cbSMarkus Armbruster 
25246bb944eSPhilippe Mathieu-Daudé     if (!list[0] || list[0] == ',') {
25380c710cbSMarkus Armbruster         return false;
25480c710cbSMarkus Armbruster     }
25580c710cbSMarkus Armbruster 
25646bb944eSPhilippe Mathieu-Daudé     for (i = len; i > 0 && list[i - 1] == ','; i--) {
25780c710cbSMarkus Armbruster     }
25880c710cbSMarkus Armbruster     if ((len - i) % 2) {
25980c710cbSMarkus Armbruster         return false;
26080c710cbSMarkus Armbruster     }
26180c710cbSMarkus Armbruster 
26280c710cbSMarkus Armbruster     return true;
26380c710cbSMarkus Armbruster }
26480c710cbSMarkus Armbruster 
accumulate_options(char ** options,char * list)26546bb944eSPhilippe Mathieu-Daudé static int accumulate_options(char **options, char *list)
2666d2b5cbaSMarkus Armbruster {
2676d2b5cbaSMarkus Armbruster     char *new_options;
2686d2b5cbaSMarkus Armbruster 
26946bb944eSPhilippe Mathieu-Daudé     if (!is_valid_option_list(list)) {
27046bb944eSPhilippe Mathieu-Daudé         error_report("Invalid option list: %s", list);
2716d2b5cbaSMarkus Armbruster         return -1;
2726d2b5cbaSMarkus Armbruster     }
2736d2b5cbaSMarkus Armbruster 
2746d2b5cbaSMarkus Armbruster     if (!*options) {
27546bb944eSPhilippe Mathieu-Daudé         *options = g_strdup(list);
2766d2b5cbaSMarkus Armbruster     } else {
27746bb944eSPhilippe Mathieu-Daudé         new_options = g_strdup_printf("%s,%s", *options, list);
2786d2b5cbaSMarkus Armbruster         g_free(*options);
2796d2b5cbaSMarkus Armbruster         *options = new_options;
2806d2b5cbaSMarkus Armbruster     }
2816d2b5cbaSMarkus Armbruster     return 0;
2826d2b5cbaSMarkus Armbruster }
2836d2b5cbaSMarkus Armbruster 
284eb769f74SDaniel P. Berrange static QemuOptsList qemu_source_opts = {
285eb769f74SDaniel P. Berrange     .name = "source",
286eb769f74SDaniel P. Berrange     .implied_opt_name = "file",
287eb769f74SDaniel P. Berrange     .head = QTAILQ_HEAD_INITIALIZER(qemu_source_opts.head),
288eb769f74SDaniel P. Berrange     .desc = {
289eb769f74SDaniel P. Berrange         { }
290eb769f74SDaniel P. Berrange     },
291eb769f74SDaniel P. Berrange };
292eb769f74SDaniel P. Berrange 
qprintf(bool quiet,const char * fmt,...)2939edc6313SMarc-André Lureau static int G_GNUC_PRINTF(2, 3) qprintf(bool quiet, const char *fmt, ...)
294f382d43aSMiroslav Rezanina {
295f382d43aSMiroslav Rezanina     int ret = 0;
296f382d43aSMiroslav Rezanina     if (!quiet) {
297f382d43aSMiroslav Rezanina         va_list args;
298f382d43aSMiroslav Rezanina         va_start(args, fmt);
299f382d43aSMiroslav Rezanina         ret = vprintf(fmt, args);
300f382d43aSMiroslav Rezanina         va_end(args);
301f382d43aSMiroslav Rezanina     }
302f382d43aSMiroslav Rezanina     return ret;
303f382d43aSMiroslav Rezanina }
304f382d43aSMiroslav Rezanina 
305ea2384d3Sbellard 
print_block_option_help(const char * filename,const char * fmt)3064ac8aacdSJes Sorensen static int print_block_option_help(const char *filename, const char *fmt)
3074ac8aacdSJes Sorensen {
3084ac8aacdSJes Sorensen     BlockDriver *drv, *proto_drv;
30983d0521aSChunyan Liu     QemuOptsList *create_opts = NULL;
310b65a5e12SMax Reitz     Error *local_err = NULL;
3114ac8aacdSJes Sorensen 
3124ac8aacdSJes Sorensen     /* Find driver and parse its options */
3134ac8aacdSJes Sorensen     drv = bdrv_find_format(fmt);
3144ac8aacdSJes Sorensen     if (!drv) {
31515654a6dSJes Sorensen         error_report("Unknown file format '%s'", fmt);
3164ac8aacdSJes Sorensen         return 1;
3174ac8aacdSJes Sorensen     }
3184ac8aacdSJes Sorensen 
319d402b6a2SMax Reitz     if (!drv->create_opts) {
320d402b6a2SMax Reitz         error_report("Format driver '%s' does not support image creation", fmt);
321d402b6a2SMax Reitz         return 1;
322d402b6a2SMax Reitz     }
323d402b6a2SMax Reitz 
324c282e1fdSChunyan Liu     create_opts = qemu_opts_append(create_opts, drv->create_opts);
325a283cb6eSKevin Wolf     if (filename) {
326b65a5e12SMax Reitz         proto_drv = bdrv_find_protocol(filename, true, &local_err);
3274ac8aacdSJes Sorensen         if (!proto_drv) {
3282867ce4aSMarkus Armbruster             error_report_err(local_err);
32983d0521aSChunyan Liu             qemu_opts_free(create_opts);
3304ac8aacdSJes Sorensen             return 1;
3314ac8aacdSJes Sorensen         }
332d402b6a2SMax Reitz         if (!proto_drv->create_opts) {
333f0998879SMax Reitz             error_report("Protocol driver '%s' does not support image creation",
334d402b6a2SMax Reitz                          proto_drv->format_name);
3353ecd5a4fSMax Reitz             qemu_opts_free(create_opts);
336d402b6a2SMax Reitz             return 1;
337d402b6a2SMax Reitz         }
338c282e1fdSChunyan Liu         create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
339a283cb6eSKevin Wolf     }
340a283cb6eSKevin Wolf 
341f4619af0SMax Reitz     if (filename) {
3427f3fb001SMax Reitz         printf("Supported options:\n");
343f4619af0SMax Reitz     } else {
344f4619af0SMax Reitz         printf("Supported %s options:\n", fmt);
345f4619af0SMax Reitz     }
34663898712SMax Reitz     qemu_opts_print_help(create_opts, false);
34783d0521aSChunyan Liu     qemu_opts_free(create_opts);
348f4619af0SMax Reitz 
349f4619af0SMax Reitz     if (!filename) {
350f4619af0SMax Reitz         printf("\n"
351f4619af0SMax Reitz                "The protocol level may support further options.\n"
352f4619af0SMax Reitz                "Specify the target filename to include those options.\n");
353f4619af0SMax Reitz     }
354f4619af0SMax Reitz 
3554ac8aacdSJes Sorensen     return 0;
3564ac8aacdSJes Sorensen }
3574ac8aacdSJes Sorensen 
358eb769f74SDaniel P. Berrange 
img_open_opts(const char * optstr,QemuOpts * opts,int flags,bool writethrough,bool quiet,bool force_share)359efaa7c4eSMax Reitz static BlockBackend *img_open_opts(const char *optstr,
360ce099547SKevin Wolf                                    QemuOpts *opts, int flags, bool writethrough,
361335e9937SFam Zheng                                    bool quiet, bool force_share)
362eb769f74SDaniel P. Berrange {
363eb769f74SDaniel P. Berrange     QDict *options;
364eb769f74SDaniel P. Berrange     Error *local_err = NULL;
365eb769f74SDaniel P. Berrange     BlockBackend *blk;
366eb769f74SDaniel P. Berrange     options = qemu_opts_to_qdict(opts, NULL);
367335e9937SFam Zheng     if (force_share) {
368335e9937SFam Zheng         if (qdict_haskey(options, BDRV_OPT_FORCE_SHARE)
3694615f878SMax Reitz             && strcmp(qdict_get_str(options, BDRV_OPT_FORCE_SHARE), "on")) {
370335e9937SFam Zheng             error_report("--force-share/-U conflicts with image options");
371cb3e7f08SMarc-André Lureau             qobject_unref(options);
372335e9937SFam Zheng             return NULL;
373335e9937SFam Zheng         }
3744615f878SMax Reitz         qdict_put_str(options, BDRV_OPT_FORCE_SHARE, "on");
375335e9937SFam Zheng     }
376efaa7c4eSMax Reitz     blk = blk_new_open(NULL, NULL, options, flags, &local_err);
377eb769f74SDaniel P. Berrange     if (!blk) {
378143605a2SDaniel P. Berrange         error_reportf_err(local_err, "Could not open '%s': ", optstr);
379eb769f74SDaniel P. Berrange         return NULL;
380eb769f74SDaniel P. Berrange     }
381ce099547SKevin Wolf     blk_set_enable_write_cache(blk, !writethrough);
382eb769f74SDaniel P. Berrange 
383eb769f74SDaniel P. Berrange     return blk;
384eb769f74SDaniel P. Berrange }
385eb769f74SDaniel P. Berrange 
img_open_file(const char * filename,QDict * options,const char * fmt,int flags,bool writethrough,bool quiet,bool force_share)386efaa7c4eSMax Reitz static BlockBackend *img_open_file(const char *filename,
38729cf9336SDaniel P. Berrange                                    QDict *options,
3887e7d56d9SMarkus Armbruster                                    const char *fmt, int flags,
389335e9937SFam Zheng                                    bool writethrough, bool quiet,
390335e9937SFam Zheng                                    bool force_share)
39175c23805Sbellard {
3927e7d56d9SMarkus Armbruster     BlockBackend *blk;
39334b5d2c6SMax Reitz     Error *local_err = NULL;
394ad717139SKevin Wolf 
39529cf9336SDaniel P. Berrange     if (!options) {
39629cf9336SDaniel P. Berrange         options = qdict_new();
39729cf9336SDaniel P. Berrange     }
39875c23805Sbellard     if (fmt) {
39946f5ac20SEric Blake         qdict_put_str(options, "driver", fmt);
40075c23805Sbellard     }
401b9eaf9ecSKevin Wolf 
402335e9937SFam Zheng     if (force_share) {
403579cf1d1SEric Blake         qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true);
404335e9937SFam Zheng     }
405efaa7c4eSMax Reitz     blk = blk_new_open(filename, NULL, options, flags, &local_err);
4065bd31326SMax Reitz     if (!blk) {
407c29b77f9SMarkus Armbruster         error_reportf_err(local_err, "Could not open '%s': ", filename);
408eb769f74SDaniel P. Berrange         return NULL;
40975c23805Sbellard     }
410ce099547SKevin Wolf     blk_set_enable_write_cache(blk, !writethrough);
411b9eaf9ecSKevin Wolf 
412eb769f74SDaniel P. Berrange     return blk;
413eb769f74SDaniel P. Berrange }
414eb769f74SDaniel P. Berrange 
415eb769f74SDaniel P. Berrange 
img_add_key_secrets(void * opaque,const char * name,const char * value,Error ** errp)41629cf9336SDaniel P. Berrange static int img_add_key_secrets(void *opaque,
41729cf9336SDaniel P. Berrange                                const char *name, const char *value,
41829cf9336SDaniel P. Berrange                                Error **errp)
41929cf9336SDaniel P. Berrange {
42029cf9336SDaniel P. Berrange     QDict *options = opaque;
42129cf9336SDaniel P. Berrange 
42229cf9336SDaniel P. Berrange     if (g_str_has_suffix(name, "key-secret")) {
423187f47e9SEric Blake         qdict_put_str(options, name, value);
42429cf9336SDaniel P. Berrange     }
42529cf9336SDaniel P. Berrange 
42629cf9336SDaniel P. Berrange     return 0;
42729cf9336SDaniel P. Berrange }
42829cf9336SDaniel P. Berrange 
42929cf9336SDaniel P. Berrange 
img_open(bool image_opts,const char * filename,const char * fmt,int flags,bool writethrough,bool quiet,bool force_share)430efaa7c4eSMax Reitz static BlockBackend *img_open(bool image_opts,
431eb769f74SDaniel P. Berrange                               const char *filename,
432ce099547SKevin Wolf                               const char *fmt, int flags, bool writethrough,
433335e9937SFam Zheng                               bool quiet, bool force_share)
434eb769f74SDaniel P. Berrange {
435eb769f74SDaniel P. Berrange     BlockBackend *blk;
436eb769f74SDaniel P. Berrange     if (image_opts) {
437eb769f74SDaniel P. Berrange         QemuOpts *opts;
438eb769f74SDaniel P. Berrange         if (fmt) {
439eb769f74SDaniel P. Berrange             error_report("--image-opts and --format are mutually exclusive");
440eb769f74SDaniel P. Berrange             return NULL;
441eb769f74SDaniel P. Berrange         }
442eb769f74SDaniel P. Berrange         opts = qemu_opts_parse_noisily(qemu_find_opts("source"),
443eb769f74SDaniel P. Berrange                                        filename, true);
444eb769f74SDaniel P. Berrange         if (!opts) {
445eb769f74SDaniel P. Berrange             return NULL;
446eb769f74SDaniel P. Berrange         }
447335e9937SFam Zheng         blk = img_open_opts(filename, opts, flags, writethrough, quiet,
448335e9937SFam Zheng                             force_share);
449eb769f74SDaniel P. Berrange     } else {
45029cf9336SDaniel P. Berrange         blk = img_open_file(filename, NULL, fmt, flags, writethrough, quiet,
451335e9937SFam Zheng                             force_share);
452eb769f74SDaniel P. Berrange     }
45344efba2dSKevin Wolf 
45444efba2dSKevin Wolf     if (blk) {
45544efba2dSKevin Wolf         blk_set_force_allow_inactivate(blk);
45644efba2dSKevin Wolf     }
45744efba2dSKevin Wolf 
458eb769f74SDaniel P. Berrange     return blk;
459eb769f74SDaniel P. Berrange }
460eb769f74SDaniel P. Berrange 
46175c23805Sbellard 
add_old_style_options(const char * fmt,QemuOpts * opts,const char * base_filename,const char * base_fmt)46283d0521aSChunyan Liu static int add_old_style_options(const char *fmt, QemuOpts *opts,
463eec77d9eSJes Sorensen                                  const char *base_filename,
464eec77d9eSJes Sorensen                                  const char *base_fmt)
465efa84d43SKevin Wolf {
466efa84d43SKevin Wolf     if (base_filename) {
467235e59cfSMarkus Armbruster         if (!qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename,
4689e194e06SMarkus Armbruster                           NULL)) {
46915654a6dSJes Sorensen             error_report("Backing file not supported for file format '%s'",
47015654a6dSJes Sorensen                          fmt);
471c2abccecSMORITA Kazutaka             return -1;
472efa84d43SKevin Wolf         }
473efa84d43SKevin Wolf     }
474efa84d43SKevin Wolf     if (base_fmt) {
4759e194e06SMarkus Armbruster         if (!qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt, NULL)) {
47615654a6dSJes Sorensen             error_report("Backing file format not supported for file "
47715654a6dSJes Sorensen                          "format '%s'", fmt);
478c2abccecSMORITA Kazutaka             return -1;
479efa84d43SKevin Wolf         }
480efa84d43SKevin Wolf     }
481c2abccecSMORITA Kazutaka     return 0;
482efa84d43SKevin Wolf }
483efa84d43SKevin Wolf 
cvtnum_full(const char * name,const char * value,int64_t min,int64_t max)48443d589b0SEyal Moscovici static int64_t cvtnum_full(const char *name, const char *value, int64_t min,
48543d589b0SEyal Moscovici                            int64_t max)
486606caa0aSMarkus Armbruster {
487f17fd4fdSMarkus Armbruster     int err;
48843d589b0SEyal Moscovici     uint64_t res;
489606caa0aSMarkus Armbruster 
49043d589b0SEyal Moscovici     err = qemu_strtosz(value, NULL, &res);
49143d589b0SEyal Moscovici     if (err < 0 && err != -ERANGE) {
49243d589b0SEyal Moscovici         error_report("Invalid %s specified. You may use "
49343d589b0SEyal Moscovici                      "k, M, G, T, P or E suffixes for", name);
49443d589b0SEyal Moscovici         error_report("kilobytes, megabytes, gigabytes, terabytes, "
49543d589b0SEyal Moscovici                      "petabytes and exabytes.");
496f17fd4fdSMarkus Armbruster         return err;
497f17fd4fdSMarkus Armbruster     }
49843d589b0SEyal Moscovici     if (err == -ERANGE || res > max || res < min) {
49943d589b0SEyal Moscovici         error_report("Invalid %s specified. Must be between %" PRId64
50043d589b0SEyal Moscovici                      " and %" PRId64 ".", name, min, max);
501f46bfdbfSMarkus Armbruster         return -ERANGE;
502f46bfdbfSMarkus Armbruster     }
50343d589b0SEyal Moscovici     return res;
50443d589b0SEyal Moscovici }
50543d589b0SEyal Moscovici 
cvtnum(const char * name,const char * value)50643d589b0SEyal Moscovici static int64_t cvtnum(const char *name, const char *value)
50743d589b0SEyal Moscovici {
50843d589b0SEyal Moscovici     return cvtnum_full(name, value, 0, INT64_MAX);
509606caa0aSMarkus Armbruster }
510606caa0aSMarkus Armbruster 
img_create(int argc,char ** argv)511ea2384d3Sbellard static int img_create(int argc, char **argv)
512ea2384d3Sbellard {
513a9300911SLuiz Capitulino     int c;
5141da7cfbdSJes Sorensen     uint64_t img_size = -1;
515ea2384d3Sbellard     const char *fmt = "raw";
5169230eaf6Saliguori     const char *base_fmt = NULL;
517ea2384d3Sbellard     const char *filename;
518ea2384d3Sbellard     const char *base_filename = NULL;
5199ea2ea71SKevin Wolf     char *options = NULL;
5209b37525aSLuiz Capitulino     Error *local_err = NULL;
521f382d43aSMiroslav Rezanina     bool quiet = false;
5226e6e55f5SJohn Snow     int flags = 0;
523ea2384d3Sbellard 
524ea2384d3Sbellard     for(;;) {
5253babeb15SDaniel P. Berrange         static const struct option long_options[] = {
5263babeb15SDaniel P. Berrange             {"help", no_argument, 0, 'h'},
5273babeb15SDaniel P. Berrange             {"object", required_argument, 0, OPTION_OBJECT},
5283babeb15SDaniel P. Berrange             {0, 0, 0, 0}
5293babeb15SDaniel P. Berrange         };
5306e6e55f5SJohn Snow         c = getopt_long(argc, argv, ":F:b:f:ho:qu",
5313babeb15SDaniel P. Berrange                         long_options, NULL);
532b8fb60daSJes Sorensen         if (c == -1) {
533ea2384d3Sbellard             break;
534b8fb60daSJes Sorensen         }
535ea2384d3Sbellard         switch(c) {
536c9192973SStefan Hajnoczi         case ':':
537c9192973SStefan Hajnoczi             missing_argument(argv[optind - 1]);
538c9192973SStefan Hajnoczi             break;
539ef87394cSJes Sorensen         case '?':
540c9192973SStefan Hajnoczi             unrecognized_option(argv[optind - 1]);
541c9192973SStefan Hajnoczi             break;
542ea2384d3Sbellard         case 'h':
543ea2384d3Sbellard             help();
544ea2384d3Sbellard             break;
5459230eaf6Saliguori         case 'F':
5469230eaf6Saliguori             base_fmt = optarg;
5479230eaf6Saliguori             break;
548ea2384d3Sbellard         case 'b':
549ea2384d3Sbellard             base_filename = optarg;
550ea2384d3Sbellard             break;
551ea2384d3Sbellard         case 'f':
552ea2384d3Sbellard             fmt = optarg;
553ea2384d3Sbellard             break;
5549ea2ea71SKevin Wolf         case 'o':
5556d2b5cbaSMarkus Armbruster             if (accumulate_options(&options, optarg) < 0) {
55677386bf6SKevin Wolf                 goto fail;
55777386bf6SKevin Wolf             }
5589ea2ea71SKevin Wolf             break;
559f382d43aSMiroslav Rezanina         case 'q':
560f382d43aSMiroslav Rezanina             quiet = true;
561f382d43aSMiroslav Rezanina             break;
5626e6e55f5SJohn Snow         case 'u':
5636e6e55f5SJohn Snow             flags |= BDRV_O_NO_BACKING;
5646e6e55f5SJohn Snow             break;
56599b1e646SKevin Wolf         case OPTION_OBJECT:
56699b1e646SKevin Wolf             user_creatable_process_cmdline(optarg);
56799b1e646SKevin Wolf             break;
568ea2384d3Sbellard         }
569ea2384d3Sbellard     }
5709230eaf6Saliguori 
571b50cbabcSMORITA Kazutaka     /* Get the filename */
572a283cb6eSKevin Wolf     filename = (optind < argc) ? argv[optind] : NULL;
573a283cb6eSKevin Wolf     if (options && has_help_option(options)) {
574a283cb6eSKevin Wolf         g_free(options);
575a283cb6eSKevin Wolf         return print_block_option_help(filename, fmt);
576a283cb6eSKevin Wolf     }
577a283cb6eSKevin Wolf 
578b8fb60daSJes Sorensen     if (optind >= argc) {
579ac1307abSFam Zheng         error_exit("Expecting image file name");
580b8fb60daSJes Sorensen     }
581a283cb6eSKevin Wolf     optind++;
582b50cbabcSMORITA Kazutaka 
5831da7cfbdSJes Sorensen     /* Get image size, if specified */
5841da7cfbdSJes Sorensen     if (optind < argc) {
58570b4f4bbSJes Sorensen         int64_t sval;
586606caa0aSMarkus Armbruster 
58743d589b0SEyal Moscovici         sval = cvtnum("image size", argv[optind++]);
588606caa0aSMarkus Armbruster         if (sval < 0) {
58977386bf6SKevin Wolf             goto fail;
5901da7cfbdSJes Sorensen         }
5911da7cfbdSJes Sorensen         img_size = (uint64_t)sval;
5921da7cfbdSJes Sorensen     }
593fc11eb26SKevin Wolf     if (optind != argc) {
594ac1307abSFam Zheng         error_exit("Unexpected argument: %s", argv[optind]);
595fc11eb26SKevin Wolf     }
5961da7cfbdSJes Sorensen 
5979b37525aSLuiz Capitulino     bdrv_img_create(filename, fmt, base_filename, base_fmt,
5986e6e55f5SJohn Snow                     options, img_size, flags, quiet, &local_err);
59984d18f06SMarkus Armbruster     if (local_err) {
600c29b77f9SMarkus Armbruster         error_reportf_err(local_err, "%s: ", filename);
60177386bf6SKevin Wolf         goto fail;
602c2abccecSMORITA Kazutaka     }
603a9300911SLuiz Capitulino 
60477386bf6SKevin Wolf     g_free(options);
605ea2384d3Sbellard     return 0;
60677386bf6SKevin Wolf 
60777386bf6SKevin Wolf fail:
60877386bf6SKevin Wolf     g_free(options);
60977386bf6SKevin Wolf     return 1;
610ea2384d3Sbellard }
611ea2384d3Sbellard 
dump_json_image_check(ImageCheck * check,bool quiet)612f382d43aSMiroslav Rezanina static void dump_json_image_check(ImageCheck *check, bool quiet)
6138599ea4cSFederico Simoncelli {
614eab3a467SMarkus Armbruster     GString *str;
6158599ea4cSFederico Simoncelli     QObject *obj;
6167d5e199aSDaniel P. Berrange     Visitor *v = qobject_output_visitor_new(&obj);
6173b098d56SEric Blake 
6183b098d56SEric Blake     visit_type_ImageCheck(v, NULL, &check, &error_abort);
6193b098d56SEric Blake     visit_complete(v, &obj);
6206589f459SMarkus Armbruster     str = qobject_to_json_pretty(obj, true);
6218599ea4cSFederico Simoncelli     assert(str != NULL);
622eab3a467SMarkus Armbruster     qprintf(quiet, "%s\n", str->str);
623cb3e7f08SMarc-André Lureau     qobject_unref(obj);
6243b098d56SEric Blake     visit_free(v);
625eab3a467SMarkus Armbruster     g_string_free(str, true);
6268599ea4cSFederico Simoncelli }
6278599ea4cSFederico Simoncelli 
dump_human_image_check(ImageCheck * check,bool quiet)628f382d43aSMiroslav Rezanina static void dump_human_image_check(ImageCheck *check, bool quiet)
6298599ea4cSFederico Simoncelli {
6308599ea4cSFederico Simoncelli     if (!(check->corruptions || check->leaks || check->check_errors)) {
631f382d43aSMiroslav Rezanina         qprintf(quiet, "No errors were found on the image.\n");
6328599ea4cSFederico Simoncelli     } else {
6338599ea4cSFederico Simoncelli         if (check->corruptions) {
634f382d43aSMiroslav Rezanina             qprintf(quiet, "\n%" PRId64 " errors were found on the image.\n"
6358599ea4cSFederico Simoncelli                     "Data may be corrupted, or further writes to the image "
6368599ea4cSFederico Simoncelli                     "may corrupt it.\n",
6378599ea4cSFederico Simoncelli                     check->corruptions);
6388599ea4cSFederico Simoncelli         }
6398599ea4cSFederico Simoncelli 
6408599ea4cSFederico Simoncelli         if (check->leaks) {
641f382d43aSMiroslav Rezanina             qprintf(quiet,
642f382d43aSMiroslav Rezanina                     "\n%" PRId64 " leaked clusters were found on the image.\n"
6438599ea4cSFederico Simoncelli                     "This means waste of disk space, but no harm to data.\n",
6448599ea4cSFederico Simoncelli                     check->leaks);
6458599ea4cSFederico Simoncelli         }
6468599ea4cSFederico Simoncelli 
6478599ea4cSFederico Simoncelli         if (check->check_errors) {
648f382d43aSMiroslav Rezanina             qprintf(quiet,
649f382d43aSMiroslav Rezanina                     "\n%" PRId64
650f382d43aSMiroslav Rezanina                     " internal errors have occurred during the check.\n",
6518599ea4cSFederico Simoncelli                     check->check_errors);
6528599ea4cSFederico Simoncelli         }
6538599ea4cSFederico Simoncelli     }
6548599ea4cSFederico Simoncelli 
6558599ea4cSFederico Simoncelli     if (check->total_clusters != 0 && check->allocated_clusters != 0) {
656f382d43aSMiroslav Rezanina         qprintf(quiet, "%" PRId64 "/%" PRId64 " = %0.2f%% allocated, "
657e6439d78SStefan Hajnoczi                 "%0.2f%% fragmented, %0.2f%% compressed clusters\n",
6588599ea4cSFederico Simoncelli                 check->allocated_clusters, check->total_clusters,
6598599ea4cSFederico Simoncelli                 check->allocated_clusters * 100.0 / check->total_clusters,
660e6439d78SStefan Hajnoczi                 check->fragmented_clusters * 100.0 / check->allocated_clusters,
661f382d43aSMiroslav Rezanina                 check->compressed_clusters * 100.0 /
662f382d43aSMiroslav Rezanina                 check->allocated_clusters);
6638599ea4cSFederico Simoncelli     }
6648599ea4cSFederico Simoncelli 
6658599ea4cSFederico Simoncelli     if (check->image_end_offset) {
666f382d43aSMiroslav Rezanina         qprintf(quiet,
667f382d43aSMiroslav Rezanina                 "Image end offset: %" PRId64 "\n", check->image_end_offset);
6688599ea4cSFederico Simoncelli     }
6698599ea4cSFederico Simoncelli }
6708599ea4cSFederico Simoncelli 
collect_image_check(BlockDriverState * bs,ImageCheck * check,const char * filename,const char * fmt,int fix)6718599ea4cSFederico Simoncelli static int collect_image_check(BlockDriverState *bs,
6728599ea4cSFederico Simoncelli                    ImageCheck *check,
6738599ea4cSFederico Simoncelli                    const char *filename,
6748599ea4cSFederico Simoncelli                    const char *fmt,
6758599ea4cSFederico Simoncelli                    int fix)
6768599ea4cSFederico Simoncelli {
6778599ea4cSFederico Simoncelli     int ret;
6788599ea4cSFederico Simoncelli     BdrvCheckResult result;
6798599ea4cSFederico Simoncelli 
6808599ea4cSFederico Simoncelli     ret = bdrv_check(bs, &result, fix);
6818599ea4cSFederico Simoncelli     if (ret < 0) {
6828599ea4cSFederico Simoncelli         return ret;
6838599ea4cSFederico Simoncelli     }
6848599ea4cSFederico Simoncelli 
6858599ea4cSFederico Simoncelli     check->filename                 = g_strdup(filename);
6868599ea4cSFederico Simoncelli     check->format                   = g_strdup(bdrv_get_format_name(bs));
6878599ea4cSFederico Simoncelli     check->check_errors             = result.check_errors;
6888599ea4cSFederico Simoncelli     check->corruptions              = result.corruptions;
6898599ea4cSFederico Simoncelli     check->has_corruptions          = result.corruptions != 0;
6908599ea4cSFederico Simoncelli     check->leaks                    = result.leaks;
6918599ea4cSFederico Simoncelli     check->has_leaks                = result.leaks != 0;
6928599ea4cSFederico Simoncelli     check->corruptions_fixed        = result.corruptions_fixed;
6931656324eSMax Reitz     check->has_corruptions_fixed    = result.corruptions_fixed != 0;
6948599ea4cSFederico Simoncelli     check->leaks_fixed              = result.leaks_fixed;
6951656324eSMax Reitz     check->has_leaks_fixed          = result.leaks_fixed != 0;
6968599ea4cSFederico Simoncelli     check->image_end_offset         = result.image_end_offset;
6978599ea4cSFederico Simoncelli     check->has_image_end_offset     = result.image_end_offset != 0;
6988599ea4cSFederico Simoncelli     check->total_clusters           = result.bfi.total_clusters;
6998599ea4cSFederico Simoncelli     check->has_total_clusters       = result.bfi.total_clusters != 0;
7008599ea4cSFederico Simoncelli     check->allocated_clusters       = result.bfi.allocated_clusters;
7018599ea4cSFederico Simoncelli     check->has_allocated_clusters   = result.bfi.allocated_clusters != 0;
7028599ea4cSFederico Simoncelli     check->fragmented_clusters      = result.bfi.fragmented_clusters;
7038599ea4cSFederico Simoncelli     check->has_fragmented_clusters  = result.bfi.fragmented_clusters != 0;
704e6439d78SStefan Hajnoczi     check->compressed_clusters      = result.bfi.compressed_clusters;
705e6439d78SStefan Hajnoczi     check->has_compressed_clusters  = result.bfi.compressed_clusters != 0;
7068599ea4cSFederico Simoncelli 
7078599ea4cSFederico Simoncelli     return 0;
7088599ea4cSFederico Simoncelli }
7098599ea4cSFederico Simoncelli 
710e076f338SKevin Wolf /*
711e076f338SKevin Wolf  * Checks an image for consistency. Exit codes:
712e076f338SKevin Wolf  *
713e076f338SKevin Wolf  *  0 - Check completed, image is good
714e076f338SKevin Wolf  *  1 - Check not completed because of internal errors
715e076f338SKevin Wolf  *  2 - Check completed, image is corrupted
716e076f338SKevin Wolf  *  3 - Check completed, image has leaked clusters, but is good otherwise
717d6635c4dSMax Reitz  * 63 - Checks are not supported by the image format
718e076f338SKevin Wolf  */
img_check(int argc,char ** argv)7191585969cSaliguori static int img_check(int argc, char **argv)
7201585969cSaliguori {
7211585969cSaliguori     int c, ret;
7228599ea4cSFederico Simoncelli     OutputFormat output_format = OFORMAT_HUMAN;
72340055951SMax Reitz     const char *filename, *fmt, *output, *cache;
72426f54e9aSMarkus Armbruster     BlockBackend *blk;
7251585969cSaliguori     BlockDriverState *bs;
7264534ff54SKevin Wolf     int fix = 0;
727ce099547SKevin Wolf     int flags = BDRV_O_CHECK;
728ce099547SKevin Wolf     bool writethrough;
7297e7d56d9SMarkus Armbruster     ImageCheck *check;
730f382d43aSMiroslav Rezanina     bool quiet = false;
731eb769f74SDaniel P. Berrange     bool image_opts = false;
732335e9937SFam Zheng     bool force_share = false;
7331585969cSaliguori 
7341585969cSaliguori     fmt = NULL;
7358599ea4cSFederico Simoncelli     output = NULL;
73640055951SMax Reitz     cache = BDRV_DEFAULT_CACHE;
737ce099547SKevin Wolf 
7381585969cSaliguori     for(;;) {
7398599ea4cSFederico Simoncelli         int option_index = 0;
7408599ea4cSFederico Simoncelli         static const struct option long_options[] = {
7418599ea4cSFederico Simoncelli             {"help", no_argument, 0, 'h'},
7428599ea4cSFederico Simoncelli             {"format", required_argument, 0, 'f'},
7434fd6a984SPrasad Joshi             {"repair", required_argument, 0, 'r'},
7448599ea4cSFederico Simoncelli             {"output", required_argument, 0, OPTION_OUTPUT},
7453babeb15SDaniel P. Berrange             {"object", required_argument, 0, OPTION_OBJECT},
746eb769f74SDaniel P. Berrange             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
747335e9937SFam Zheng             {"force-share", no_argument, 0, 'U'},
7488599ea4cSFederico Simoncelli             {0, 0, 0, 0}
7498599ea4cSFederico Simoncelli         };
750335e9937SFam Zheng         c = getopt_long(argc, argv, ":hf:r:T:qU",
7518599ea4cSFederico Simoncelli                         long_options, &option_index);
752b8fb60daSJes Sorensen         if (c == -1) {
7531585969cSaliguori             break;
754b8fb60daSJes Sorensen         }
7551585969cSaliguori         switch(c) {
756c9192973SStefan Hajnoczi         case ':':
757c9192973SStefan Hajnoczi             missing_argument(argv[optind - 1]);
758c9192973SStefan Hajnoczi             break;
759ef87394cSJes Sorensen         case '?':
760c9192973SStefan Hajnoczi             unrecognized_option(argv[optind - 1]);
761c9192973SStefan Hajnoczi             break;
7621585969cSaliguori         case 'h':
7631585969cSaliguori             help();
7641585969cSaliguori             break;
7651585969cSaliguori         case 'f':
7661585969cSaliguori             fmt = optarg;
7671585969cSaliguori             break;
7684534ff54SKevin Wolf         case 'r':
7694534ff54SKevin Wolf             flags |= BDRV_O_RDWR;
7704534ff54SKevin Wolf 
7714534ff54SKevin Wolf             if (!strcmp(optarg, "leaks")) {
7724534ff54SKevin Wolf                 fix = BDRV_FIX_LEAKS;
7734534ff54SKevin Wolf             } else if (!strcmp(optarg, "all")) {
7744534ff54SKevin Wolf                 fix = BDRV_FIX_LEAKS | BDRV_FIX_ERRORS;
7754534ff54SKevin Wolf             } else {
776ac1307abSFam Zheng                 error_exit("Unknown option value for -r "
777ac1307abSFam Zheng                            "(expecting 'leaks' or 'all'): %s", optarg);
7784534ff54SKevin Wolf             }
7794534ff54SKevin Wolf             break;
7808599ea4cSFederico Simoncelli         case OPTION_OUTPUT:
7818599ea4cSFederico Simoncelli             output = optarg;
7828599ea4cSFederico Simoncelli             break;
78340055951SMax Reitz         case 'T':
78440055951SMax Reitz             cache = optarg;
78540055951SMax Reitz             break;
786f382d43aSMiroslav Rezanina         case 'q':
787f382d43aSMiroslav Rezanina             quiet = true;
788f382d43aSMiroslav Rezanina             break;
789335e9937SFam Zheng         case 'U':
790335e9937SFam Zheng             force_share = true;
791335e9937SFam Zheng             break;
79299b1e646SKevin Wolf         case OPTION_OBJECT:
79399b1e646SKevin Wolf             user_creatable_process_cmdline(optarg);
79499b1e646SKevin Wolf             break;
795eb769f74SDaniel P. Berrange         case OPTION_IMAGE_OPTS:
796eb769f74SDaniel P. Berrange             image_opts = true;
797eb769f74SDaniel P. Berrange             break;
7981585969cSaliguori         }
7991585969cSaliguori     }
800fc11eb26SKevin Wolf     if (optind != argc - 1) {
801ac1307abSFam Zheng         error_exit("Expecting one image file name");
802b8fb60daSJes Sorensen     }
8031585969cSaliguori     filename = argv[optind++];
8041585969cSaliguori 
8058599ea4cSFederico Simoncelli     if (output && !strcmp(output, "json")) {
8068599ea4cSFederico Simoncelli         output_format = OFORMAT_JSON;
8078599ea4cSFederico Simoncelli     } else if (output && !strcmp(output, "human")) {
8088599ea4cSFederico Simoncelli         output_format = OFORMAT_HUMAN;
8098599ea4cSFederico Simoncelli     } else if (output) {
8108599ea4cSFederico Simoncelli         error_report("--output must be used with human or json as argument.");
8118599ea4cSFederico Simoncelli         return 1;
8128599ea4cSFederico Simoncelli     }
8138599ea4cSFederico Simoncelli 
814ce099547SKevin Wolf     ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
81540055951SMax Reitz     if (ret < 0) {
81640055951SMax Reitz         error_report("Invalid source cache option: %s", cache);
81740055951SMax Reitz         return 1;
81840055951SMax Reitz     }
81940055951SMax Reitz 
820335e9937SFam Zheng     blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet,
821335e9937SFam Zheng                    force_share);
8227e7d56d9SMarkus Armbruster     if (!blk) {
8237e7d56d9SMarkus Armbruster         return 1;
824c2abccecSMORITA Kazutaka     }
8257e7d56d9SMarkus Armbruster     bs = blk_bs(blk);
8268599ea4cSFederico Simoncelli 
8278599ea4cSFederico Simoncelli     check = g_new0(ImageCheck, 1);
8288599ea4cSFederico Simoncelli     ret = collect_image_check(bs, check, filename, fmt, fix);
829e076f338SKevin Wolf 
830e076f338SKevin Wolf     if (ret == -ENOTSUP) {
83115654a6dSJes Sorensen         error_report("This image format does not support checks");
832fefddf95SPeter Lieven         ret = 63;
8338599ea4cSFederico Simoncelli         goto fail;
8341585969cSaliguori     }
835e076f338SKevin Wolf 
8368599ea4cSFederico Simoncelli     if (check->corruptions_fixed || check->leaks_fixed) {
8378599ea4cSFederico Simoncelli         int corruptions_fixed, leaks_fixed;
8381656324eSMax Reitz         bool has_leaks_fixed, has_corruptions_fixed;
8398599ea4cSFederico Simoncelli 
8408599ea4cSFederico Simoncelli         leaks_fixed         = check->leaks_fixed;
8411656324eSMax Reitz         has_leaks_fixed     = check->has_leaks_fixed;
8428599ea4cSFederico Simoncelli         corruptions_fixed   = check->corruptions_fixed;
8431656324eSMax Reitz         has_corruptions_fixed = check->has_corruptions_fixed;
8448599ea4cSFederico Simoncelli 
8458599ea4cSFederico Simoncelli         if (output_format == OFORMAT_HUMAN) {
846f382d43aSMiroslav Rezanina             qprintf(quiet,
847f382d43aSMiroslav Rezanina                     "The following inconsistencies were found and repaired:\n\n"
8488599ea4cSFederico Simoncelli                     "    %" PRId64 " leaked clusters\n"
8498599ea4cSFederico Simoncelli                     "    %" PRId64 " corruptions\n\n"
850ccf34716SKevin Wolf                     "Double checking the fixed image now...\n",
8518599ea4cSFederico Simoncelli                     check->leaks_fixed,
8528599ea4cSFederico Simoncelli                     check->corruptions_fixed);
853ccf34716SKevin Wolf         }
854ccf34716SKevin Wolf 
855fc124ea1SPan Nengyuan         qapi_free_ImageCheck(check);
856fc124ea1SPan Nengyuan         check = g_new0(ImageCheck, 1);
8578599ea4cSFederico Simoncelli         ret = collect_image_check(bs, check, filename, fmt, 0);
8588599ea4cSFederico Simoncelli 
8598599ea4cSFederico Simoncelli         check->leaks_fixed          = leaks_fixed;
8601656324eSMax Reitz         check->has_leaks_fixed      = has_leaks_fixed;
8618599ea4cSFederico Simoncelli         check->corruptions_fixed    = corruptions_fixed;
8621656324eSMax Reitz         check->has_corruptions_fixed = has_corruptions_fixed;
8638599ea4cSFederico Simoncelli     }
8648599ea4cSFederico Simoncelli 
865832390a5SMax Reitz     if (!ret) {
8668599ea4cSFederico Simoncelli         switch (output_format) {
8678599ea4cSFederico Simoncelli         case OFORMAT_HUMAN:
868f382d43aSMiroslav Rezanina             dump_human_image_check(check, quiet);
8698599ea4cSFederico Simoncelli             break;
8708599ea4cSFederico Simoncelli         case OFORMAT_JSON:
871f382d43aSMiroslav Rezanina             dump_json_image_check(check, quiet);
8728599ea4cSFederico Simoncelli             break;
8738599ea4cSFederico Simoncelli         }
874832390a5SMax Reitz     }
8758599ea4cSFederico Simoncelli 
8768599ea4cSFederico Simoncelli     if (ret || check->check_errors) {
877832390a5SMax Reitz         if (ret) {
878832390a5SMax Reitz             error_report("Check failed: %s", strerror(-ret));
879832390a5SMax Reitz         } else {
880832390a5SMax Reitz             error_report("Check failed");
881832390a5SMax Reitz         }
8828599ea4cSFederico Simoncelli         ret = 1;
8838599ea4cSFederico Simoncelli         goto fail;
8848599ea4cSFederico Simoncelli     }
8858599ea4cSFederico Simoncelli 
8868599ea4cSFederico Simoncelli     if (check->corruptions) {
8878599ea4cSFederico Simoncelli         ret = 2;
8888599ea4cSFederico Simoncelli     } else if (check->leaks) {
8898599ea4cSFederico Simoncelli         ret = 3;
890e076f338SKevin Wolf     } else {
8918599ea4cSFederico Simoncelli         ret = 0;
892e076f338SKevin Wolf     }
893e076f338SKevin Wolf 
8948599ea4cSFederico Simoncelli fail:
8958599ea4cSFederico Simoncelli     qapi_free_ImageCheck(check);
89626f54e9aSMarkus Armbruster     blk_unref(blk);
8978599ea4cSFederico Simoncelli     return ret;
898e076f338SKevin Wolf }
8991585969cSaliguori 
900d4a3238aSMax Reitz typedef struct CommonBlockJobCBInfo {
901d4a3238aSMax Reitz     BlockDriverState *bs;
902d4a3238aSMax Reitz     Error **errp;
903d4a3238aSMax Reitz } CommonBlockJobCBInfo;
904d4a3238aSMax Reitz 
common_block_job_cb(void * opaque,int ret)905d4a3238aSMax Reitz static void common_block_job_cb(void *opaque, int ret)
906d4a3238aSMax Reitz {
907d4a3238aSMax Reitz     CommonBlockJobCBInfo *cbi = opaque;
908d4a3238aSMax Reitz 
909d4a3238aSMax Reitz     if (ret < 0) {
910d4a3238aSMax Reitz         error_setg_errno(cbi->errp, -ret, "Block job failed");
911d4a3238aSMax Reitz     }
912d4a3238aSMax Reitz }
913d4a3238aSMax Reitz 
run_block_job(BlockJob * job,Error ** errp)914d4a3238aSMax Reitz static void run_block_job(BlockJob *job, Error **errp)
915d4a3238aSMax Reitz {
916a7b4f8fcSEmanuele Giuseppe Esposito     uint64_t progress_current, progress_total;
917df9a3165SVladimir Sementsov-Ogievskiy     AioContext *aio_context = block_job_get_aio_context(job);
9184172a003Ssochin.jiang     int ret = 0;
919d4a3238aSMax Reitz 
920880eeec6SEmanuele Giuseppe Esposito     job_lock();
921880eeec6SEmanuele Giuseppe Esposito     job_ref_locked(&job->job);
922d4a3238aSMax Reitz     do {
92330a5c887SKevin Wolf         float progress = 0.0f;
924880eeec6SEmanuele Giuseppe Esposito         job_unlock();
925d4a3238aSMax Reitz         aio_poll(aio_context, true);
926a7b4f8fcSEmanuele Giuseppe Esposito 
927a7b4f8fcSEmanuele Giuseppe Esposito         progress_get_snapshot(&job->job.progress, &progress_current,
928a7b4f8fcSEmanuele Giuseppe Esposito                               &progress_total);
929a7b4f8fcSEmanuele Giuseppe Esposito         if (progress_total) {
930a7b4f8fcSEmanuele Giuseppe Esposito             progress = (float)progress_current / progress_total * 100.f;
93130a5c887SKevin Wolf         }
93230a5c887SKevin Wolf         qemu_progress_print(progress, 0);
933880eeec6SEmanuele Giuseppe Esposito         job_lock();
934880eeec6SEmanuele Giuseppe Esposito     } while (!job_is_ready_locked(&job->job) &&
935880eeec6SEmanuele Giuseppe Esposito              !job_is_completed_locked(&job->job));
936d4a3238aSMax Reitz 
937880eeec6SEmanuele Giuseppe Esposito     if (!job_is_completed_locked(&job->job)) {
938880eeec6SEmanuele Giuseppe Esposito         ret = job_complete_sync_locked(&job->job, errp);
9394172a003Ssochin.jiang     } else {
9404ad35181SKevin Wolf         ret = job->job.ret;
9414172a003Ssochin.jiang     }
942880eeec6SEmanuele Giuseppe Esposito     job_unref_locked(&job->job);
943880eeec6SEmanuele Giuseppe Esposito     job_unlock();
944687fa1d8SMax Reitz 
9454172a003Ssochin.jiang     /* publish completion progress only when success */
9464172a003Ssochin.jiang     if (!ret) {
947687fa1d8SMax Reitz         qemu_progress_print(100.f, 0);
948d4a3238aSMax Reitz     }
9494172a003Ssochin.jiang }
950d4a3238aSMax Reitz 
img_commit(int argc,char ** argv)951ea2384d3Sbellard static int img_commit(int argc, char **argv)
952ea2384d3Sbellard {
953661a0f71SFederico Simoncelli     int c, ret, flags;
9541b22bffdSMax Reitz     const char *filename, *fmt, *cache, *base;
95526f54e9aSMarkus Armbruster     BlockBackend *blk;
956d4a3238aSMax Reitz     BlockDriverState *bs, *base_bs;
9574ef85a9cSKevin Wolf     BlockJob *job;
958687fa1d8SMax Reitz     bool progress = false, quiet = false, drop = false;
959ce099547SKevin Wolf     bool writethrough;
960d4a3238aSMax Reitz     Error *local_err = NULL;
961d4a3238aSMax Reitz     CommonBlockJobCBInfo cbi;
962eb769f74SDaniel P. Berrange     bool image_opts = false;
963a0441b66SZhengui     int64_t rate_limit = 0;
964ea2384d3Sbellard 
965ea2384d3Sbellard     fmt = NULL;
966661a0f71SFederico Simoncelli     cache = BDRV_DEFAULT_CACHE;
9671b22bffdSMax Reitz     base = NULL;
968ea2384d3Sbellard     for(;;) {
9693babeb15SDaniel P. Berrange         static const struct option long_options[] = {
9703babeb15SDaniel P. Berrange             {"help", no_argument, 0, 'h'},
9713babeb15SDaniel P. Berrange             {"object", required_argument, 0, OPTION_OBJECT},
972eb769f74SDaniel P. Berrange             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
9733babeb15SDaniel P. Berrange             {0, 0, 0, 0}
9743babeb15SDaniel P. Berrange         };
975a0441b66SZhengui         c = getopt_long(argc, argv, ":f:ht:b:dpqr:",
9763babeb15SDaniel P. Berrange                         long_options, NULL);
977b8fb60daSJes Sorensen         if (c == -1) {
978ea2384d3Sbellard             break;
979b8fb60daSJes Sorensen         }
980ea2384d3Sbellard         switch(c) {
981c9192973SStefan Hajnoczi         case ':':
982c9192973SStefan Hajnoczi             missing_argument(argv[optind - 1]);
983c9192973SStefan Hajnoczi             break;
984ef87394cSJes Sorensen         case '?':
985c9192973SStefan Hajnoczi             unrecognized_option(argv[optind - 1]);
986c9192973SStefan Hajnoczi             break;
987ea2384d3Sbellard         case 'h':
988ea2384d3Sbellard             help();
989ea2384d3Sbellard             break;
990ea2384d3Sbellard         case 'f':
991ea2384d3Sbellard             fmt = optarg;
992ea2384d3Sbellard             break;
993661a0f71SFederico Simoncelli         case 't':
994661a0f71SFederico Simoncelli             cache = optarg;
995661a0f71SFederico Simoncelli             break;
9961b22bffdSMax Reitz         case 'b':
9971b22bffdSMax Reitz             base = optarg;
9981b22bffdSMax Reitz             /* -b implies -d */
9991b22bffdSMax Reitz             drop = true;
10001b22bffdSMax Reitz             break;
10019a86fe48SMax Reitz         case 'd':
10029a86fe48SMax Reitz             drop = true;
10039a86fe48SMax Reitz             break;
1004687fa1d8SMax Reitz         case 'p':
1005687fa1d8SMax Reitz             progress = true;
1006687fa1d8SMax Reitz             break;
1007f382d43aSMiroslav Rezanina         case 'q':
1008f382d43aSMiroslav Rezanina             quiet = true;
1009f382d43aSMiroslav Rezanina             break;
1010a0441b66SZhengui         case 'r':
1011a0441b66SZhengui             rate_limit = cvtnum("rate limit", optarg);
1012a0441b66SZhengui             if (rate_limit < 0) {
1013a0441b66SZhengui                 return 1;
1014a0441b66SZhengui             }
1015a0441b66SZhengui             break;
101699b1e646SKevin Wolf         case OPTION_OBJECT:
101799b1e646SKevin Wolf             user_creatable_process_cmdline(optarg);
101899b1e646SKevin Wolf             break;
1019eb769f74SDaniel P. Berrange         case OPTION_IMAGE_OPTS:
1020eb769f74SDaniel P. Berrange             image_opts = true;
1021eb769f74SDaniel P. Berrange             break;
1022ea2384d3Sbellard         }
1023ea2384d3Sbellard     }
1024687fa1d8SMax Reitz 
1025687fa1d8SMax Reitz     /* Progress is not shown in Quiet mode */
1026687fa1d8SMax Reitz     if (quiet) {
1027687fa1d8SMax Reitz         progress = false;
1028687fa1d8SMax Reitz     }
1029687fa1d8SMax Reitz 
1030fc11eb26SKevin Wolf     if (optind != argc - 1) {
1031ac1307abSFam Zheng         error_exit("Expecting one image file name");
1032b8fb60daSJes Sorensen     }
1033ea2384d3Sbellard     filename = argv[optind++];
1034ea2384d3Sbellard 
10359a86fe48SMax Reitz     flags = BDRV_O_RDWR | BDRV_O_UNMAP;
1036ce099547SKevin Wolf     ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
1037661a0f71SFederico Simoncelli     if (ret < 0) {
1038661a0f71SFederico Simoncelli         error_report("Invalid cache option: %s", cache);
1039a3981eb9SStefan Hajnoczi         return 1;
1040661a0f71SFederico Simoncelli     }
1041661a0f71SFederico Simoncelli 
1042335e9937SFam Zheng     blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet,
1043335e9937SFam Zheng                    false);
10447e7d56d9SMarkus Armbruster     if (!blk) {
10457e7d56d9SMarkus Armbruster         return 1;
1046c2abccecSMORITA Kazutaka     }
10477e7d56d9SMarkus Armbruster     bs = blk_bs(blk);
10487e7d56d9SMarkus Armbruster 
1049687fa1d8SMax Reitz     qemu_progress_init(progress, 1.f);
1050687fa1d8SMax Reitz     qemu_progress_print(0.f, 100);
1051687fa1d8SMax Reitz 
1052ad74751fSKevin Wolf     bdrv_graph_rdlock_main_loop();
10531b22bffdSMax Reitz     if (base) {
10541b22bffdSMax Reitz         base_bs = bdrv_find_backing_image(bs, base);
10551b22bffdSMax Reitz         if (!base_bs) {
10566b33f3aeSMax Reitz             error_setg(&local_err,
10576b33f3aeSMax Reitz                        "Did not find '%s' in the backing chain of '%s'",
10586b33f3aeSMax Reitz                        base, filename);
1059ad74751fSKevin Wolf             bdrv_graph_rdunlock_main_loop();
10601b22bffdSMax Reitz             goto done;
10611b22bffdSMax Reitz         }
10621b22bffdSMax Reitz     } else {
10631b22bffdSMax Reitz         /* This is different from QMP, which by default uses the deepest file in
10641b22bffdSMax Reitz          * the backing chain (i.e., the very base); however, the traditional
10651b22bffdSMax Reitz          * behavior of qemu-img commit is using the immediate backing file. */
10664a2061e6SMax Reitz         base_bs = bdrv_backing_chain_next(bs);
1067d4a3238aSMax Reitz         if (!base_bs) {
1068d4a3238aSMax Reitz             error_setg(&local_err, "Image does not have a backing file");
1069ad74751fSKevin Wolf             bdrv_graph_rdunlock_main_loop();
1070d4a3238aSMax Reitz             goto done;
1071ea2384d3Sbellard         }
10721b22bffdSMax Reitz     }
1073ad74751fSKevin Wolf     bdrv_graph_rdunlock_main_loop();
1074ea2384d3Sbellard 
1075d4a3238aSMax Reitz     cbi = (CommonBlockJobCBInfo){
1076d4a3238aSMax Reitz         .errp = &local_err,
1077d4a3238aSMax Reitz         .bs   = bs,
1078d4a3238aSMax Reitz     };
1079d4a3238aSMax Reitz 
1080a0441b66SZhengui     commit_active_start("commit", bs, base_bs, JOB_DEFAULT, rate_limit,
10810db832f4SKevin Wolf                         BLOCKDEV_ON_ERROR_REPORT, NULL, common_block_job_cb,
108278bbd910SFam Zheng                         &cbi, false, &local_err);
1083d4a3238aSMax Reitz     if (local_err) {
1084d4a3238aSMax Reitz         goto done;
1085d4a3238aSMax Reitz     }
1086d4a3238aSMax Reitz 
10873f09bfbcSKevin Wolf     /* When the block job completes, the BlockBackend reference will point to
10883f09bfbcSKevin Wolf      * the old backing file. In order to avoid that the top image is already
10893f09bfbcSKevin Wolf      * deleted, so we can still empty it afterwards, increment the reference
10903f09bfbcSKevin Wolf      * counter here preemptively. */
10919a86fe48SMax Reitz     if (!drop) {
10923f09bfbcSKevin Wolf         bdrv_ref(bs);
10939a86fe48SMax Reitz     }
10949a86fe48SMax Reitz 
10954ef85a9cSKevin Wolf     job = block_job_get("commit");
10962e2db260SLiam Merwick     assert(job);
10974ef85a9cSKevin Wolf     run_block_job(job, &local_err);
10989a86fe48SMax Reitz     if (local_err) {
10999a86fe48SMax Reitz         goto unref_backing;
11009a86fe48SMax Reitz     }
11019a86fe48SMax Reitz 
11022d97fde4SMax Reitz     if (!drop) {
11032d97fde4SMax Reitz         BlockBackend *old_backing_blk;
11042d97fde4SMax Reitz 
11052d97fde4SMax Reitz         old_backing_blk = blk_new_with_bs(bs, BLK_PERM_WRITE, BLK_PERM_ALL,
11062d97fde4SMax Reitz                                           &local_err);
11072d97fde4SMax Reitz         if (!old_backing_blk) {
11082d97fde4SMax Reitz             goto unref_backing;
11092d97fde4SMax Reitz         }
11102d97fde4SMax Reitz         ret = blk_make_empty(old_backing_blk, &local_err);
11112d97fde4SMax Reitz         blk_unref(old_backing_blk);
11122d97fde4SMax Reitz         if (ret == -ENOTSUP) {
11132d97fde4SMax Reitz             error_free(local_err);
11142d97fde4SMax Reitz             local_err = NULL;
11152d97fde4SMax Reitz         } else if (ret < 0) {
11169a86fe48SMax Reitz             goto unref_backing;
11179a86fe48SMax Reitz         }
11189a86fe48SMax Reitz     }
11199a86fe48SMax Reitz 
11209a86fe48SMax Reitz unref_backing:
11219a86fe48SMax Reitz     if (!drop) {
11223f09bfbcSKevin Wolf         bdrv_unref(bs);
11239a86fe48SMax Reitz     }
1124d4a3238aSMax Reitz 
1125d4a3238aSMax Reitz done:
1126687fa1d8SMax Reitz     qemu_progress_end();
1127687fa1d8SMax Reitz 
112844efba2dSKevin Wolf     /*
112944efba2dSKevin Wolf      * Manually inactivate the image first because this way we can know whether
113044efba2dSKevin Wolf      * an error occurred. blk_unref() doesn't tell us about failures.
113144efba2dSKevin Wolf      */
113244efba2dSKevin Wolf     ret = bdrv_inactivate_all();
113344efba2dSKevin Wolf     if (ret < 0 && !local_err) {
113444efba2dSKevin Wolf         error_setg_errno(&local_err, -ret, "Error while closing the image");
113544efba2dSKevin Wolf     }
113626f54e9aSMarkus Armbruster     blk_unref(blk);
1137d4a3238aSMax Reitz 
1138d4a3238aSMax Reitz     if (local_err) {
11396936f299SMarkus Armbruster         error_report_err(local_err);
1140c2abccecSMORITA Kazutaka         return 1;
1141c2abccecSMORITA Kazutaka     }
1142d4a3238aSMax Reitz 
1143d4a3238aSMax Reitz     qprintf(quiet, "Image committed.\n");
1144ea2384d3Sbellard     return 0;
1145ea2384d3Sbellard }
1146ea2384d3Sbellard 
1147f6a00aa1SDmitry Konishchev /*
1148debb38a4SEric Blake  * Returns -1 if 'buf' contains only zeroes, otherwise the byte index
1149debb38a4SEric Blake  * of the first sector boundary within buf where the sector contains a
1150debb38a4SEric Blake  * non-zero byte.  This function is robust to a buffer that is not
1151debb38a4SEric Blake  * sector-aligned.
1152debb38a4SEric Blake  */
find_nonzero(const uint8_t * buf,int64_t n)1153debb38a4SEric Blake static int64_t find_nonzero(const uint8_t *buf, int64_t n)
1154debb38a4SEric Blake {
1155debb38a4SEric Blake     int64_t i;
1156debb38a4SEric Blake     int64_t end = QEMU_ALIGN_DOWN(n, BDRV_SECTOR_SIZE);
1157debb38a4SEric Blake 
1158debb38a4SEric Blake     for (i = 0; i < end; i += BDRV_SECTOR_SIZE) {
1159debb38a4SEric Blake         if (!buffer_is_zero(buf + i, BDRV_SECTOR_SIZE)) {
1160debb38a4SEric Blake             return i;
1161debb38a4SEric Blake         }
1162debb38a4SEric Blake     }
1163debb38a4SEric Blake     if (i < n && !buffer_is_zero(buf + i, n - end)) {
1164debb38a4SEric Blake         return i;
1165debb38a4SEric Blake     }
1166debb38a4SEric Blake     return -1;
1167debb38a4SEric Blake }
1168debb38a4SEric Blake 
1169debb38a4SEric Blake /*
1170f58c7b35Sths  * Returns true iff the first sector pointed to by 'buf' contains at least
1171f58c7b35Sths  * a non-NUL byte.
1172f58c7b35Sths  *
1173f58c7b35Sths  * 'pnum' is set to the number of sectors (including and immediately following
1174f58c7b35Sths  * the first one) that are known to be in the same allocated/unallocated state.
11758dcd3c9bSPeter Lieven  * The function will try to align the end offset to alignment boundaries so
1176e3a6e0daSzhaolichang  * that the request will at least end aligned and consecutive requests will
11778dcd3c9bSPeter Lieven  * also start at an aligned offset.
1178f58c7b35Sths  */
is_allocated_sectors(const uint8_t * buf,int n,int * pnum,int64_t sector_num,int alignment)11798dcd3c9bSPeter Lieven static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum,
11808dcd3c9bSPeter Lieven                                 int64_t sector_num, int alignment)
1181ea2384d3Sbellard {
11821a6d39fdSStefan Hajnoczi     bool is_zero;
11838dcd3c9bSPeter Lieven     int i, tail;
1184ea2384d3Sbellard 
1185ea2384d3Sbellard     if (n <= 0) {
1186ea2384d3Sbellard         *pnum = 0;
1187ea2384d3Sbellard         return 0;
1188ea2384d3Sbellard     }
1189c075c42fSYi Li     is_zero = buffer_is_zero(buf, BDRV_SECTOR_SIZE);
1190ea2384d3Sbellard     for(i = 1; i < n; i++) {
1191c075c42fSYi Li         buf += BDRV_SECTOR_SIZE;
1192c075c42fSYi Li         if (is_zero != buffer_is_zero(buf, BDRV_SECTOR_SIZE)) {
1193ea2384d3Sbellard             break;
1194ea2384d3Sbellard         }
11951a6d39fdSStefan Hajnoczi     }
11968dcd3c9bSPeter Lieven 
119796054c76SVladimir Sementsov-Ogievskiy     if (i == n) {
119896054c76SVladimir Sementsov-Ogievskiy         /*
119996054c76SVladimir Sementsov-Ogievskiy          * The whole buf is the same.
120096054c76SVladimir Sementsov-Ogievskiy          * No reason to split it into chunks, so return now.
120196054c76SVladimir Sementsov-Ogievskiy          */
120296054c76SVladimir Sementsov-Ogievskiy         *pnum = i;
120396054c76SVladimir Sementsov-Ogievskiy         return !is_zero;
120496054c76SVladimir Sementsov-Ogievskiy     }
120596054c76SVladimir Sementsov-Ogievskiy 
12068dcd3c9bSPeter Lieven     tail = (sector_num + i) & (alignment - 1);
12078dcd3c9bSPeter Lieven     if (tail) {
12088dcd3c9bSPeter Lieven         if (is_zero && i <= tail) {
120996054c76SVladimir Sementsov-Ogievskiy             /*
121096054c76SVladimir Sementsov-Ogievskiy              * For sure next sector after i is data, and it will rewrite this
121196054c76SVladimir Sementsov-Ogievskiy              * tail anyway due to RMW. So, let's just write data now.
121296054c76SVladimir Sementsov-Ogievskiy              */
12138dcd3c9bSPeter Lieven             is_zero = false;
12148dcd3c9bSPeter Lieven         }
12158dcd3c9bSPeter Lieven         if (!is_zero) {
121696054c76SVladimir Sementsov-Ogievskiy             /* If possible, align up end offset of allocated areas. */
12178dcd3c9bSPeter Lieven             i += alignment - tail;
12188dcd3c9bSPeter Lieven             i = MIN(i, n);
12198dcd3c9bSPeter Lieven         } else {
122096054c76SVladimir Sementsov-Ogievskiy             /*
122196054c76SVladimir Sementsov-Ogievskiy              * For sure next sector after i is data, and it will rewrite this
122296054c76SVladimir Sementsov-Ogievskiy              * tail anyway due to RMW. Better is avoid RMW and write zeroes up
122396054c76SVladimir Sementsov-Ogievskiy              * to aligned bound.
122496054c76SVladimir Sementsov-Ogievskiy              */
12258dcd3c9bSPeter Lieven             i -= tail;
12268dcd3c9bSPeter Lieven         }
12278dcd3c9bSPeter Lieven     }
1228ea2384d3Sbellard     *pnum = i;
12291a6d39fdSStefan Hajnoczi     return !is_zero;
1230ea2384d3Sbellard }
1231ea2384d3Sbellard 
12323e85c6fdSKevin Wolf /*
1233a22f123cSKevin Wolf  * Like is_allocated_sectors, but if the buffer starts with a used sector,
1234a22f123cSKevin Wolf  * up to 'min' consecutive sectors containing zeros are ignored. This avoids
1235a22f123cSKevin Wolf  * breaking up write requests for only small sparse areas.
1236a22f123cSKevin Wolf  */
is_allocated_sectors_min(const uint8_t * buf,int n,int * pnum,int min,int64_t sector_num,int alignment)1237a22f123cSKevin Wolf static int is_allocated_sectors_min(const uint8_t *buf, int n, int *pnum,
12388dcd3c9bSPeter Lieven     int min, int64_t sector_num, int alignment)
1239a22f123cSKevin Wolf {
1240a22f123cSKevin Wolf     int ret;
1241a22f123cSKevin Wolf     int num_checked, num_used;
1242a22f123cSKevin Wolf 
1243a22f123cSKevin Wolf     if (n < min) {
1244a22f123cSKevin Wolf         min = n;
1245a22f123cSKevin Wolf     }
1246a22f123cSKevin Wolf 
12478dcd3c9bSPeter Lieven     ret = is_allocated_sectors(buf, n, pnum, sector_num, alignment);
1248a22f123cSKevin Wolf     if (!ret) {
1249a22f123cSKevin Wolf         return ret;
1250a22f123cSKevin Wolf     }
1251a22f123cSKevin Wolf 
1252a22f123cSKevin Wolf     num_used = *pnum;
1253a22f123cSKevin Wolf     buf += BDRV_SECTOR_SIZE * *pnum;
1254a22f123cSKevin Wolf     n -= *pnum;
12558dcd3c9bSPeter Lieven     sector_num += *pnum;
1256a22f123cSKevin Wolf     num_checked = num_used;
1257a22f123cSKevin Wolf 
1258a22f123cSKevin Wolf     while (n > 0) {
12598dcd3c9bSPeter Lieven         ret = is_allocated_sectors(buf, n, pnum, sector_num, alignment);
1260a22f123cSKevin Wolf 
1261a22f123cSKevin Wolf         buf += BDRV_SECTOR_SIZE * *pnum;
1262a22f123cSKevin Wolf         n -= *pnum;
12638dcd3c9bSPeter Lieven         sector_num += *pnum;
1264a22f123cSKevin Wolf         num_checked += *pnum;
1265a22f123cSKevin Wolf         if (ret) {
1266a22f123cSKevin Wolf             num_used = num_checked;
1267a22f123cSKevin Wolf         } else if (*pnum >= min) {
1268a22f123cSKevin Wolf             break;
1269a22f123cSKevin Wolf         }
1270a22f123cSKevin Wolf     }
1271a22f123cSKevin Wolf 
1272a22f123cSKevin Wolf     *pnum = num_used;
1273a22f123cSKevin Wolf     return 1;
1274a22f123cSKevin Wolf }
1275a22f123cSKevin Wolf 
1276a22f123cSKevin Wolf /*
1277c20c8ae7SAndrey Drobyshev  * Compares two buffers chunk by chunk, where @chsize is the chunk size.
1278c20c8ae7SAndrey Drobyshev  * If @chsize is 0, default chunk size of BDRV_SECTOR_SIZE is used.
1279c20c8ae7SAndrey Drobyshev  * Returns 0 if the first chunk of each buffer matches, non-zero otherwise.
12803e85c6fdSKevin Wolf  *
1281c20c8ae7SAndrey Drobyshev  * @pnum is set to the size of the buffer prefix aligned to @chsize that
1282c20c8ae7SAndrey Drobyshev  * has the same matching status as the first chunk.
12833e85c6fdSKevin Wolf  */
compare_buffers(const uint8_t * buf1,const uint8_t * buf2,int64_t bytes,uint64_t chsize,int64_t * pnum)1284dc61cd3bSEric Blake static int compare_buffers(const uint8_t *buf1, const uint8_t *buf2,
1285c20c8ae7SAndrey Drobyshev                            int64_t bytes, uint64_t chsize, int64_t *pnum)
12863e85c6fdSKevin Wolf {
12878c1ac475SRadim Krčmář     bool res;
1288c20c8ae7SAndrey Drobyshev     int64_t i;
12893e85c6fdSKevin Wolf 
1290dc61cd3bSEric Blake     assert(bytes > 0);
12913e85c6fdSKevin Wolf 
1292c20c8ae7SAndrey Drobyshev     if (!chsize) {
1293c20c8ae7SAndrey Drobyshev         chsize = BDRV_SECTOR_SIZE;
1294c20c8ae7SAndrey Drobyshev     }
1295c20c8ae7SAndrey Drobyshev     i = MIN(bytes, chsize);
1296c20c8ae7SAndrey Drobyshev 
1297dc61cd3bSEric Blake     res = !!memcmp(buf1, buf2, i);
1298dc61cd3bSEric Blake     while (i < bytes) {
1299c20c8ae7SAndrey Drobyshev         int64_t len = MIN(bytes - i, chsize);
13003e85c6fdSKevin Wolf 
1301dc61cd3bSEric Blake         if (!!memcmp(buf1 + i, buf2 + i, len) != res) {
13023e85c6fdSKevin Wolf             break;
13033e85c6fdSKevin Wolf         }
1304dc61cd3bSEric Blake         i += len;
13053e85c6fdSKevin Wolf     }
13063e85c6fdSKevin Wolf 
13073e85c6fdSKevin Wolf     *pnum = i;
13083e85c6fdSKevin Wolf     return res;
13093e85c6fdSKevin Wolf }
13103e85c6fdSKevin Wolf 
131197ede57aSStefano Garzarella #define IO_BUF_SIZE (2 * MiB)
1312ea2384d3Sbellard 
1313d14ed18cSMiroslav Rezanina /*
1314d14ed18cSMiroslav Rezanina  * Check if passed sectors are empty (not allocated or contain only 0 bytes)
1315d14ed18cSMiroslav Rezanina  *
13160608e40eSEric Blake  * Intended for use by 'qemu-img compare': Returns 0 in case sectors are
13170608e40eSEric Blake  * filled with 0, 1 if sectors contain non-zero data (this is a comparison
13180608e40eSEric Blake  * failure), and 4 on error (the exit status for read errors), after emitting
13190608e40eSEric Blake  * an error message.
1320d14ed18cSMiroslav Rezanina  *
1321f1d3cd79SMax Reitz  * @param blk:  BlockBackend for the image
1322c41508edSEric Blake  * @param offset: Starting offset to check
1323c41508edSEric Blake  * @param bytes: Number of bytes to check
1324d14ed18cSMiroslav Rezanina  * @param filename: Name of disk file we are checking (logging purpose)
1325d14ed18cSMiroslav Rezanina  * @param buffer: Allocated buffer for storing read data
1326d14ed18cSMiroslav Rezanina  * @param quiet: Flag for quiet mode
1327d14ed18cSMiroslav Rezanina  */
check_empty_sectors(BlockBackend * blk,int64_t offset,int64_t bytes,const char * filename,uint8_t * buffer,bool quiet)1328c41508edSEric Blake static int check_empty_sectors(BlockBackend *blk, int64_t offset,
1329c41508edSEric Blake                                int64_t bytes, const char *filename,
1330d14ed18cSMiroslav Rezanina                                uint8_t *buffer, bool quiet)
1331d14ed18cSMiroslav Rezanina {
1332debb38a4SEric Blake     int ret = 0;
1333debb38a4SEric Blake     int64_t idx;
1334debb38a4SEric Blake 
1335a9262f55SAlberto Faria     ret = blk_pread(blk, offset, bytes, buffer, 0);
1336d14ed18cSMiroslav Rezanina     if (ret < 0) {
1337d14ed18cSMiroslav Rezanina         error_report("Error while reading offset %" PRId64 " of %s: %s",
1338c41508edSEric Blake                      offset, filename, strerror(-ret));
13390608e40eSEric Blake         return 4;
1340d14ed18cSMiroslav Rezanina     }
1341c41508edSEric Blake     idx = find_nonzero(buffer, bytes);
1342debb38a4SEric Blake     if (idx >= 0) {
1343d14ed18cSMiroslav Rezanina         qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
1344c41508edSEric Blake                 offset + idx);
1345d14ed18cSMiroslav Rezanina         return 1;
1346d14ed18cSMiroslav Rezanina     }
1347d14ed18cSMiroslav Rezanina 
1348d14ed18cSMiroslav Rezanina     return 0;
1349d14ed18cSMiroslav Rezanina }
1350d14ed18cSMiroslav Rezanina 
1351d14ed18cSMiroslav Rezanina /*
1352d14ed18cSMiroslav Rezanina  * Compares two images. Exit codes:
1353d14ed18cSMiroslav Rezanina  *
135499b1e646SKevin Wolf  * 0 - Images are identical or the requested help was printed
1355d14ed18cSMiroslav Rezanina  * 1 - Images differ
1356d14ed18cSMiroslav Rezanina  * >1 - Error occurred
1357d14ed18cSMiroslav Rezanina  */
img_compare(int argc,char ** argv)1358d14ed18cSMiroslav Rezanina static int img_compare(int argc, char **argv)
1359d14ed18cSMiroslav Rezanina {
136040055951SMax Reitz     const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;
136126f54e9aSMarkus Armbruster     BlockBackend *blk1, *blk2;
1362d14ed18cSMiroslav Rezanina     BlockDriverState *bs1, *bs2;
1363033d9fc2SEric Blake     int64_t total_size1, total_size2;
1364d14ed18cSMiroslav Rezanina     uint8_t *buf1 = NULL, *buf2 = NULL;
136531826642SEric Blake     int64_t pnum1, pnum2;
1366d14ed18cSMiroslav Rezanina     int allocated1, allocated2;
1367d14ed18cSMiroslav Rezanina     int ret = 0; /* return value - 0 Ident, 1 Different, >1 Error */
1368d14ed18cSMiroslav Rezanina     bool progress = false, quiet = false, strict = false;
136940055951SMax Reitz     int flags;
1370ce099547SKevin Wolf     bool writethrough;
1371033d9fc2SEric Blake     int64_t total_size;
1372033d9fc2SEric Blake     int64_t offset = 0;
1373033d9fc2SEric Blake     int64_t chunk;
1374dc61cd3bSEric Blake     int c;
1375d14ed18cSMiroslav Rezanina     uint64_t progress_base;
1376eb769f74SDaniel P. Berrange     bool image_opts = false;
1377335e9937SFam Zheng     bool force_share = false;
1378d14ed18cSMiroslav Rezanina 
137940055951SMax Reitz     cache = BDRV_DEFAULT_CACHE;
1380d14ed18cSMiroslav Rezanina     for (;;) {
13813babeb15SDaniel P. Berrange         static const struct option long_options[] = {
13823babeb15SDaniel P. Berrange             {"help", no_argument, 0, 'h'},
13833babeb15SDaniel P. Berrange             {"object", required_argument, 0, OPTION_OBJECT},
1384eb769f74SDaniel P. Berrange             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
1385335e9937SFam Zheng             {"force-share", no_argument, 0, 'U'},
13863babeb15SDaniel P. Berrange             {0, 0, 0, 0}
13873babeb15SDaniel P. Berrange         };
1388335e9937SFam Zheng         c = getopt_long(argc, argv, ":hf:F:T:pqsU",
13893babeb15SDaniel P. Berrange                         long_options, NULL);
1390d14ed18cSMiroslav Rezanina         if (c == -1) {
1391d14ed18cSMiroslav Rezanina             break;
1392d14ed18cSMiroslav Rezanina         }
1393d14ed18cSMiroslav Rezanina         switch (c) {
1394c9192973SStefan Hajnoczi         case ':':
1395c9192973SStefan Hajnoczi             missing_argument(argv[optind - 1]);
1396c9192973SStefan Hajnoczi             break;
1397d14ed18cSMiroslav Rezanina         case '?':
1398c9192973SStefan Hajnoczi             unrecognized_option(argv[optind - 1]);
1399c9192973SStefan Hajnoczi             break;
1400d14ed18cSMiroslav Rezanina         case 'h':
1401d14ed18cSMiroslav Rezanina             help();
1402d14ed18cSMiroslav Rezanina             break;
1403d14ed18cSMiroslav Rezanina         case 'f':
1404d14ed18cSMiroslav Rezanina             fmt1 = optarg;
1405d14ed18cSMiroslav Rezanina             break;
1406d14ed18cSMiroslav Rezanina         case 'F':
1407d14ed18cSMiroslav Rezanina             fmt2 = optarg;
1408d14ed18cSMiroslav Rezanina             break;
140940055951SMax Reitz         case 'T':
141040055951SMax Reitz             cache = optarg;
141140055951SMax Reitz             break;
1412d14ed18cSMiroslav Rezanina         case 'p':
1413d14ed18cSMiroslav Rezanina             progress = true;
1414d14ed18cSMiroslav Rezanina             break;
1415d14ed18cSMiroslav Rezanina         case 'q':
1416d14ed18cSMiroslav Rezanina             quiet = true;
1417d14ed18cSMiroslav Rezanina             break;
1418d14ed18cSMiroslav Rezanina         case 's':
1419d14ed18cSMiroslav Rezanina             strict = true;
1420d14ed18cSMiroslav Rezanina             break;
1421335e9937SFam Zheng         case 'U':
1422335e9937SFam Zheng             force_share = true;
1423335e9937SFam Zheng             break;
142499b1e646SKevin Wolf         case OPTION_OBJECT:
142599b1e646SKevin Wolf             {
142699b1e646SKevin Wolf                 Error *local_err = NULL;
142799b1e646SKevin Wolf 
142899b1e646SKevin Wolf                 if (!user_creatable_add_from_str(optarg, &local_err)) {
142999b1e646SKevin Wolf                     if (local_err) {
143099b1e646SKevin Wolf                         error_report_err(local_err);
143199b1e646SKevin Wolf                         exit(2);
143299b1e646SKevin Wolf                     } else {
143399b1e646SKevin Wolf                         /* Help was printed */
143499b1e646SKevin Wolf                         exit(EXIT_SUCCESS);
14353babeb15SDaniel P. Berrange                     }
143699b1e646SKevin Wolf                 }
143799b1e646SKevin Wolf                 break;
143899b1e646SKevin Wolf             }
1439eb769f74SDaniel P. Berrange         case OPTION_IMAGE_OPTS:
1440eb769f74SDaniel P. Berrange             image_opts = true;
1441eb769f74SDaniel P. Berrange             break;
1442d14ed18cSMiroslav Rezanina         }
1443d14ed18cSMiroslav Rezanina     }
1444d14ed18cSMiroslav Rezanina 
1445d14ed18cSMiroslav Rezanina     /* Progress is not shown in Quiet mode */
1446d14ed18cSMiroslav Rezanina     if (quiet) {
1447d14ed18cSMiroslav Rezanina         progress = false;
1448d14ed18cSMiroslav Rezanina     }
1449d14ed18cSMiroslav Rezanina 
1450d14ed18cSMiroslav Rezanina 
1451fc11eb26SKevin Wolf     if (optind != argc - 2) {
1452ac1307abSFam Zheng         error_exit("Expecting two image file names");
1453d14ed18cSMiroslav Rezanina     }
1454d14ed18cSMiroslav Rezanina     filename1 = argv[optind++];
1455d14ed18cSMiroslav Rezanina     filename2 = argv[optind++];
1456d14ed18cSMiroslav Rezanina 
1457cbda016dSStefan Hajnoczi     /* Initialize before goto out */
1458cbda016dSStefan Hajnoczi     qemu_progress_init(progress, 2.0);
1459cbda016dSStefan Hajnoczi 
1460ce099547SKevin Wolf     flags = 0;
1461ce099547SKevin Wolf     ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
146240055951SMax Reitz     if (ret < 0) {
146340055951SMax Reitz         error_report("Invalid source cache option: %s", cache);
146440055951SMax Reitz         ret = 2;
146540055951SMax Reitz         goto out3;
146640055951SMax Reitz     }
146740055951SMax Reitz 
1468335e9937SFam Zheng     blk1 = img_open(image_opts, filename1, fmt1, flags, writethrough, quiet,
1469335e9937SFam Zheng                     force_share);
14707e7d56d9SMarkus Armbruster     if (!blk1) {
1471d14ed18cSMiroslav Rezanina         ret = 2;
14727e7d56d9SMarkus Armbruster         goto out3;
14737e7d56d9SMarkus Armbruster     }
14747e7d56d9SMarkus Armbruster 
1475335e9937SFam Zheng     blk2 = img_open(image_opts, filename2, fmt2, flags, writethrough, quiet,
1476335e9937SFam Zheng                     force_share);
14777e7d56d9SMarkus Armbruster     if (!blk2) {
14787e7d56d9SMarkus Armbruster         ret = 2;
147926f54e9aSMarkus Armbruster         goto out2;
1480d14ed18cSMiroslav Rezanina     }
1481eb769f74SDaniel P. Berrange     bs1 = blk_bs(blk1);
14827e7d56d9SMarkus Armbruster     bs2 = blk_bs(blk2);
1483d14ed18cSMiroslav Rezanina 
1484f1d3cd79SMax Reitz     buf1 = blk_blockalign(blk1, IO_BUF_SIZE);
1485f1d3cd79SMax Reitz     buf2 = blk_blockalign(blk2, IO_BUF_SIZE);
1486033d9fc2SEric Blake     total_size1 = blk_getlength(blk1);
1487033d9fc2SEric Blake     if (total_size1 < 0) {
148852bf1e72SMarkus Armbruster         error_report("Can't get size of %s: %s",
1489033d9fc2SEric Blake                      filename1, strerror(-total_size1));
149052bf1e72SMarkus Armbruster         ret = 4;
149152bf1e72SMarkus Armbruster         goto out;
149252bf1e72SMarkus Armbruster     }
1493033d9fc2SEric Blake     total_size2 = blk_getlength(blk2);
1494033d9fc2SEric Blake     if (total_size2 < 0) {
149552bf1e72SMarkus Armbruster         error_report("Can't get size of %s: %s",
1496033d9fc2SEric Blake                      filename2, strerror(-total_size2));
149752bf1e72SMarkus Armbruster         ret = 4;
149852bf1e72SMarkus Armbruster         goto out;
149952bf1e72SMarkus Armbruster     }
1500033d9fc2SEric Blake     total_size = MIN(total_size1, total_size2);
1501033d9fc2SEric Blake     progress_base = MAX(total_size1, total_size2);
1502d14ed18cSMiroslav Rezanina 
1503d14ed18cSMiroslav Rezanina     qemu_progress_print(0, 100);
1504d14ed18cSMiroslav Rezanina 
1505033d9fc2SEric Blake     if (strict && total_size1 != total_size2) {
1506d14ed18cSMiroslav Rezanina         ret = 1;
1507d14ed18cSMiroslav Rezanina         qprintf(quiet, "Strict mode: Image size mismatch!\n");
1508d14ed18cSMiroslav Rezanina         goto out;
1509d14ed18cSMiroslav Rezanina     }
1510d14ed18cSMiroslav Rezanina 
1511033d9fc2SEric Blake     while (offset < total_size) {
151231826642SEric Blake         int status1, status2;
151367a0fd2aSFam Zheng 
1514033d9fc2SEric Blake         status1 = bdrv_block_status_above(bs1, NULL, offset,
1515033d9fc2SEric Blake                                           total_size1 - offset, &pnum1, NULL,
1516033d9fc2SEric Blake                                           NULL);
151725ad8e6eSFam Zheng         if (status1 < 0) {
1518d14ed18cSMiroslav Rezanina             ret = 3;
1519d14ed18cSMiroslav Rezanina             error_report("Sector allocation test failed for %s", filename1);
1520d14ed18cSMiroslav Rezanina             goto out;
1521d14ed18cSMiroslav Rezanina         }
152225ad8e6eSFam Zheng         allocated1 = status1 & BDRV_BLOCK_ALLOCATED;
1523d14ed18cSMiroslav Rezanina 
1524033d9fc2SEric Blake         status2 = bdrv_block_status_above(bs2, NULL, offset,
1525033d9fc2SEric Blake                                           total_size2 - offset, &pnum2, NULL,
1526033d9fc2SEric Blake                                           NULL);
152725ad8e6eSFam Zheng         if (status2 < 0) {
1528d14ed18cSMiroslav Rezanina             ret = 3;
1529d14ed18cSMiroslav Rezanina             error_report("Sector allocation test failed for %s", filename2);
1530d14ed18cSMiroslav Rezanina             goto out;
1531d14ed18cSMiroslav Rezanina         }
153225ad8e6eSFam Zheng         allocated2 = status2 & BDRV_BLOCK_ALLOCATED;
15337daddc61SEric Blake 
15347daddc61SEric Blake         assert(pnum1 && pnum2);
1535033d9fc2SEric Blake         chunk = MIN(pnum1, pnum2);
1536d14ed18cSMiroslav Rezanina 
153725ad8e6eSFam Zheng         if (strict) {
153831826642SEric Blake             if (status1 != status2) {
153925ad8e6eSFam Zheng                 ret = 1;
154025ad8e6eSFam Zheng                 qprintf(quiet, "Strict mode: Offset %" PRId64
1541033d9fc2SEric Blake                         " block status mismatch!\n", offset);
154225ad8e6eSFam Zheng                 goto out;
154325ad8e6eSFam Zheng             }
154425ad8e6eSFam Zheng         }
154525ad8e6eSFam Zheng         if ((status1 & BDRV_BLOCK_ZERO) && (status2 & BDRV_BLOCK_ZERO)) {
15467daddc61SEric Blake             /* nothing to do */
154725ad8e6eSFam Zheng         } else if (allocated1 == allocated2) {
1548d14ed18cSMiroslav Rezanina             if (allocated1) {
1549dc61cd3bSEric Blake                 int64_t pnum;
1550dc61cd3bSEric Blake 
1551033d9fc2SEric Blake                 chunk = MIN(chunk, IO_BUF_SIZE);
1552a9262f55SAlberto Faria                 ret = blk_pread(blk1, offset, chunk, buf1, 0);
1553d14ed18cSMiroslav Rezanina                 if (ret < 0) {
1554d14ed18cSMiroslav Rezanina                     error_report("Error while reading offset %" PRId64
1555033d9fc2SEric Blake                                  " of %s: %s",
1556033d9fc2SEric Blake                                  offset, filename1, strerror(-ret));
1557d14ed18cSMiroslav Rezanina                     ret = 4;
1558d14ed18cSMiroslav Rezanina                     goto out;
1559d14ed18cSMiroslav Rezanina                 }
1560a9262f55SAlberto Faria                 ret = blk_pread(blk2, offset, chunk, buf2, 0);
1561033d9fc2SEric Blake                 if (ret < 0) {
1562033d9fc2SEric Blake                     error_report("Error while reading offset %" PRId64
1563033d9fc2SEric Blake                                  " of %s: %s",
1564033d9fc2SEric Blake                                  offset, filename2, strerror(-ret));
1565033d9fc2SEric Blake                     ret = 4;
1566033d9fc2SEric Blake                     goto out;
1567033d9fc2SEric Blake                 }
1568c20c8ae7SAndrey Drobyshev                 ret = compare_buffers(buf1, buf2, chunk, 0, &pnum);
1569033d9fc2SEric Blake                 if (ret || pnum != chunk) {
1570d14ed18cSMiroslav Rezanina                     qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
1571033d9fc2SEric Blake                             offset + (ret ? 0 : pnum));
157236452f12SFam Zheng                     ret = 1;
1573d14ed18cSMiroslav Rezanina                     goto out;
1574d14ed18cSMiroslav Rezanina                 }
1575d14ed18cSMiroslav Rezanina             }
1576d14ed18cSMiroslav Rezanina         } else {
1577033d9fc2SEric Blake             chunk = MIN(chunk, IO_BUF_SIZE);
1578d14ed18cSMiroslav Rezanina             if (allocated1) {
1579033d9fc2SEric Blake                 ret = check_empty_sectors(blk1, offset, chunk,
1580d14ed18cSMiroslav Rezanina                                           filename1, buf1, quiet);
1581d14ed18cSMiroslav Rezanina             } else {
1582033d9fc2SEric Blake                 ret = check_empty_sectors(blk2, offset, chunk,
1583d14ed18cSMiroslav Rezanina                                           filename2, buf1, quiet);
1584d14ed18cSMiroslav Rezanina             }
1585d14ed18cSMiroslav Rezanina             if (ret) {
1586d14ed18cSMiroslav Rezanina                 goto out;
1587d14ed18cSMiroslav Rezanina             }
1588d14ed18cSMiroslav Rezanina         }
1589033d9fc2SEric Blake         offset += chunk;
1590033d9fc2SEric Blake         qemu_progress_print(((float) chunk / progress_base) * 100, 100);
1591d14ed18cSMiroslav Rezanina     }
1592d14ed18cSMiroslav Rezanina 
1593033d9fc2SEric Blake     if (total_size1 != total_size2) {
1594f1d3cd79SMax Reitz         BlockBackend *blk_over;
1595d14ed18cSMiroslav Rezanina         const char *filename_over;
1596d14ed18cSMiroslav Rezanina 
1597d14ed18cSMiroslav Rezanina         qprintf(quiet, "Warning: Image size mismatch!\n");
1598033d9fc2SEric Blake         if (total_size1 > total_size2) {
1599f1d3cd79SMax Reitz             blk_over = blk1;
1600d14ed18cSMiroslav Rezanina             filename_over = filename1;
1601d14ed18cSMiroslav Rezanina         } else {
1602f1d3cd79SMax Reitz             blk_over = blk2;
1603d14ed18cSMiroslav Rezanina             filename_over = filename2;
1604d14ed18cSMiroslav Rezanina         }
1605d14ed18cSMiroslav Rezanina 
1606033d9fc2SEric Blake         while (offset < progress_base) {
1607033d9fc2SEric Blake             ret = bdrv_block_status_above(blk_bs(blk_over), NULL, offset,
1608033d9fc2SEric Blake                                           progress_base - offset, &chunk,
1609033d9fc2SEric Blake                                           NULL, NULL);
1610d14ed18cSMiroslav Rezanina             if (ret < 0) {
1611d14ed18cSMiroslav Rezanina                 ret = 3;
1612d14ed18cSMiroslav Rezanina                 error_report("Sector allocation test failed for %s",
1613d14ed18cSMiroslav Rezanina                              filename_over);
1614d14ed18cSMiroslav Rezanina                 goto out;
1615d14ed18cSMiroslav Rezanina 
1616d14ed18cSMiroslav Rezanina             }
1617391cb1aaSEric Blake             if (ret & BDRV_BLOCK_ALLOCATED && !(ret & BDRV_BLOCK_ZERO)) {
1618033d9fc2SEric Blake                 chunk = MIN(chunk, IO_BUF_SIZE);
1619033d9fc2SEric Blake                 ret = check_empty_sectors(blk_over, offset, chunk,
1620d14ed18cSMiroslav Rezanina                                           filename_over, buf1, quiet);
1621d14ed18cSMiroslav Rezanina                 if (ret) {
1622d14ed18cSMiroslav Rezanina                     goto out;
1623d14ed18cSMiroslav Rezanina                 }
1624d14ed18cSMiroslav Rezanina             }
1625033d9fc2SEric Blake             offset += chunk;
1626033d9fc2SEric Blake             qemu_progress_print(((float) chunk / progress_base) * 100, 100);
1627d14ed18cSMiroslav Rezanina         }
1628d14ed18cSMiroslav Rezanina     }
1629d14ed18cSMiroslav Rezanina 
1630d14ed18cSMiroslav Rezanina     qprintf(quiet, "Images are identical.\n");
1631d14ed18cSMiroslav Rezanina     ret = 0;
1632d14ed18cSMiroslav Rezanina 
1633d14ed18cSMiroslav Rezanina out:
1634d14ed18cSMiroslav Rezanina     qemu_vfree(buf1);
1635d14ed18cSMiroslav Rezanina     qemu_vfree(buf2);
163626f54e9aSMarkus Armbruster     blk_unref(blk2);
1637d14ed18cSMiroslav Rezanina out2:
163826f54e9aSMarkus Armbruster     blk_unref(blk1);
1639d14ed18cSMiroslav Rezanina out3:
1640d14ed18cSMiroslav Rezanina     qemu_progress_end();
1641d14ed18cSMiroslav Rezanina     return ret;
1642d14ed18cSMiroslav Rezanina }
1643d14ed18cSMiroslav Rezanina 
16446c729dd8SEric Blake /* Convenience wrapper around qmp_block_dirty_bitmap_merge */
do_dirty_bitmap_merge(const char * dst_node,const char * dst_name,const char * src_node,const char * src_name,Error ** errp)16456c729dd8SEric Blake static void do_dirty_bitmap_merge(const char *dst_node, const char *dst_name,
16466c729dd8SEric Blake                                   const char *src_node, const char *src_name,
16476c729dd8SEric Blake                                   Error **errp)
16486c729dd8SEric Blake {
16491466ef6cSVladimir Sementsov-Ogievskiy     BlockDirtyBitmapOrStr *merge_src;
16501466ef6cSVladimir Sementsov-Ogievskiy     BlockDirtyBitmapOrStrList *list = NULL;
16516c729dd8SEric Blake 
16521466ef6cSVladimir Sementsov-Ogievskiy     merge_src = g_new0(BlockDirtyBitmapOrStr, 1);
16536c729dd8SEric Blake     merge_src->type = QTYPE_QDICT;
16546c729dd8SEric Blake     merge_src->u.external.node = g_strdup(src_node);
16556c729dd8SEric Blake     merge_src->u.external.name = g_strdup(src_name);
165654aa3de7SEric Blake     QAPI_LIST_PREPEND(list, merge_src);
16576c729dd8SEric Blake     qmp_block_dirty_bitmap_merge(dst_node, dst_name, list, errp);
16581466ef6cSVladimir Sementsov-Ogievskiy     qapi_free_BlockDirtyBitmapOrStrList(list);
16596c729dd8SEric Blake }
16606c729dd8SEric Blake 
1661690c7301SKevin Wolf enum ImgConvertBlockStatus {
1662690c7301SKevin Wolf     BLK_DATA,
1663690c7301SKevin Wolf     BLK_ZERO,
1664690c7301SKevin Wolf     BLK_BACKING_FILE,
1665690c7301SKevin Wolf };
1666690c7301SKevin Wolf 
16672d9187bcSPeter Lieven #define MAX_COROUTINES 16
16680c8c4895SZhengui #define CONVERT_THROTTLE_GROUP "img_convert"
16692d9187bcSPeter Lieven 
1670690c7301SKevin Wolf typedef struct ImgConvertState {
1671690c7301SKevin Wolf     BlockBackend **src;
1672690c7301SKevin Wolf     int64_t *src_sectors;
1673af8d43d3SPeter Lieven     int *src_alignment;
16742d9187bcSPeter Lieven     int src_num;
1675690c7301SKevin Wolf     int64_t total_sectors;
1676690c7301SKevin Wolf     int64_t allocated_sectors;
16772d9187bcSPeter Lieven     int64_t allocated_done;
16782d9187bcSPeter Lieven     int64_t sector_num;
16792d9187bcSPeter Lieven     int64_t wr_offs;
1680690c7301SKevin Wolf     enum ImgConvertBlockStatus status;
1681690c7301SKevin Wolf     int64_t sector_next_status;
1682690c7301SKevin Wolf     BlockBackend *target;
1683690c7301SKevin Wolf     bool has_zero_init;
1684690c7301SKevin Wolf     bool compressed;
16854d7c487eSMax Reitz     bool target_is_new;
1686690c7301SKevin Wolf     bool target_has_backing;
1687351c8effSMax Reitz     int64_t target_backing_sectors; /* negative if unknown */
16882d9187bcSPeter Lieven     bool wr_in_order;
1689ee5306d0SFam Zheng     bool copy_range;
16908eaac025SMax Reitz     bool salvage;
16913d96cb91SMax Reitz     bool quiet;
1692690c7301SKevin Wolf     int min_sparse;
16938dcd3c9bSPeter Lieven     int alignment;
1694690c7301SKevin Wolf     size_t cluster_sectors;
1695690c7301SKevin Wolf     size_t buf_sectors;
16969fd77f99SPeter Lieven     long num_coroutines;
16972d9187bcSPeter Lieven     int running_coroutines;
16982d9187bcSPeter Lieven     Coroutine *co[MAX_COROUTINES];
16992d9187bcSPeter Lieven     int64_t wait_sector_num[MAX_COROUTINES];
17002d9187bcSPeter Lieven     CoMutex lock;
17012d9187bcSPeter Lieven     int ret;
1702690c7301SKevin Wolf } ImgConvertState;
1703690c7301SKevin Wolf 
convert_select_part(ImgConvertState * s,int64_t sector_num,int * src_cur,int64_t * src_cur_offset)17042d9187bcSPeter Lieven static void convert_select_part(ImgConvertState *s, int64_t sector_num,
17052d9187bcSPeter Lieven                                 int *src_cur, int64_t *src_cur_offset)
1706690c7301SKevin Wolf {
17072d9187bcSPeter Lieven     *src_cur = 0;
17082d9187bcSPeter Lieven     *src_cur_offset = 0;
17092d9187bcSPeter Lieven     while (sector_num - *src_cur_offset >= s->src_sectors[*src_cur]) {
17102d9187bcSPeter Lieven         *src_cur_offset += s->src_sectors[*src_cur];
17112d9187bcSPeter Lieven         (*src_cur)++;
17122d9187bcSPeter Lieven         assert(*src_cur < s->src_num);
1713690c7301SKevin Wolf     }
1714690c7301SKevin Wolf }
1715690c7301SKevin Wolf 
1716ad74751fSKevin Wolf static int coroutine_mixed_fn GRAPH_RDLOCK
convert_iteration_sectors(ImgConvertState * s,int64_t sector_num)1717ad74751fSKevin Wolf convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
1718690c7301SKevin Wolf {
171931826642SEric Blake     int64_t src_cur_offset;
172031826642SEric Blake     int ret, n, src_cur;
1721351c8effSMax Reitz     bool post_backing_zero = false;
1722690c7301SKevin Wolf 
17232d9187bcSPeter Lieven     convert_select_part(s, sector_num, &src_cur, &src_cur_offset);
1724690c7301SKevin Wolf 
1725690c7301SKevin Wolf     assert(s->total_sectors > sector_num);
1726690c7301SKevin Wolf     n = MIN(s->total_sectors - sector_num, BDRV_REQUEST_MAX_SECTORS);
1727690c7301SKevin Wolf 
1728351c8effSMax Reitz     if (s->target_backing_sectors >= 0) {
1729351c8effSMax Reitz         if (sector_num >= s->target_backing_sectors) {
17302253d86eSVladimir Sementsov-Ogievskiy             post_backing_zero = true;
1731351c8effSMax Reitz         } else if (sector_num + n > s->target_backing_sectors) {
1732351c8effSMax Reitz             /* Split requests around target_backing_sectors (because
1733351c8effSMax Reitz              * starting from there, zeros are handled differently) */
1734351c8effSMax Reitz             n = s->target_backing_sectors - sector_num;
1735351c8effSMax Reitz         }
1736351c8effSMax Reitz     }
1737351c8effSMax Reitz 
1738690c7301SKevin Wolf     if (s->sector_next_status <= sector_num) {
17398eaac025SMax Reitz         uint64_t offset = (sector_num - src_cur_offset) * BDRV_SECTOR_SIZE;
17408eaac025SMax Reitz         int64_t count;
1741af8d43d3SPeter Lieven         int tail;
17424a2061e6SMax Reitz         BlockDriverState *src_bs = blk_bs(s->src[src_cur]);
17434a2061e6SMax Reitz         BlockDriverState *base;
17444a2061e6SMax Reitz 
17454a2061e6SMax Reitz         if (s->target_has_backing) {
17464a2061e6SMax Reitz             base = bdrv_cow_bs(bdrv_skip_filters(src_bs));
17474a2061e6SMax Reitz         } else {
17484a2061e6SMax Reitz             base = NULL;
17494a2061e6SMax Reitz         }
17508eaac025SMax Reitz 
17518eaac025SMax Reitz         do {
17528eaac025SMax Reitz             count = n * BDRV_SECTOR_SIZE;
1753237d78f8SEric Blake 
17544a2061e6SMax Reitz             ret = bdrv_block_status_above(src_bs, base, offset, count, &count,
17554a2061e6SMax Reitz                                           NULL, NULL);
17568eaac025SMax Reitz 
1757690c7301SKevin Wolf             if (ret < 0) {
17588eaac025SMax Reitz                 if (s->salvage) {
17598eaac025SMax Reitz                     if (n == 1) {
17608eaac025SMax Reitz                         if (!s->quiet) {
17618eaac025SMax Reitz                             warn_report("error while reading block status at "
17628eaac025SMax Reitz                                         "offset %" PRIu64 ": %s", offset,
17638eaac025SMax Reitz                                         strerror(-ret));
17648eaac025SMax Reitz                         }
17658eaac025SMax Reitz                         /* Just try to read the data, then */
17668eaac025SMax Reitz                         ret = BDRV_BLOCK_DATA;
17678eaac025SMax Reitz                         count = BDRV_SECTOR_SIZE;
17688eaac025SMax Reitz                     } else {
17698eaac025SMax Reitz                         /* Retry on a shorter range */
17708eaac025SMax Reitz                         n = DIV_ROUND_UP(n, 4);
17718eaac025SMax Reitz                     }
17728eaac025SMax Reitz                 } else {
17738eaac025SMax Reitz                     error_report("error while reading block status at offset "
17748eaac025SMax Reitz                                  "%" PRIu64 ": %s", offset, strerror(-ret));
1775690c7301SKevin Wolf                     return ret;
1776690c7301SKevin Wolf                 }
17778eaac025SMax Reitz             }
17788eaac025SMax Reitz         } while (ret < 0);
17798eaac025SMax Reitz 
178031826642SEric Blake         n = DIV_ROUND_UP(count, BDRV_SECTOR_SIZE);
1781690c7301SKevin Wolf 
1782af8d43d3SPeter Lieven         /*
1783af8d43d3SPeter Lieven          * Avoid that s->sector_next_status becomes unaligned to the source
1784af8d43d3SPeter Lieven          * request alignment and/or cluster size to avoid unnecessary read
1785af8d43d3SPeter Lieven          * cycles.
1786af8d43d3SPeter Lieven          */
1787af8d43d3SPeter Lieven         tail = (sector_num - src_cur_offset + n) % s->src_alignment[src_cur];
1788af8d43d3SPeter Lieven         if (n > tail) {
1789af8d43d3SPeter Lieven             n -= tail;
1790af8d43d3SPeter Lieven         }
1791af8d43d3SPeter Lieven 
1792690c7301SKevin Wolf         if (ret & BDRV_BLOCK_ZERO) {
1793351c8effSMax Reitz             s->status = post_backing_zero ? BLK_BACKING_FILE : BLK_ZERO;
1794690c7301SKevin Wolf         } else if (ret & BDRV_BLOCK_DATA) {
1795690c7301SKevin Wolf             s->status = BLK_DATA;
1796263a6f4cSRen Kimura         } else {
17979f1b92adSVladimir Sementsov-Ogievskiy             s->status = s->target_has_backing ? BLK_BACKING_FILE : BLK_DATA;
1798690c7301SKevin Wolf         }
1799690c7301SKevin Wolf 
1800690c7301SKevin Wolf         s->sector_next_status = sector_num + n;
1801690c7301SKevin Wolf     }
1802690c7301SKevin Wolf 
1803690c7301SKevin Wolf     n = MIN(n, s->sector_next_status - sector_num);
1804690c7301SKevin Wolf     if (s->status == BLK_DATA) {
1805690c7301SKevin Wolf         n = MIN(n, s->buf_sectors);
1806690c7301SKevin Wolf     }
1807690c7301SKevin Wolf 
1808690c7301SKevin Wolf     /* We need to write complete clusters for compressed images, so if an
1809690c7301SKevin Wolf      * unallocated area is shorter than that, we must consider the whole
1810690c7301SKevin Wolf      * cluster allocated. */
1811690c7301SKevin Wolf     if (s->compressed) {
1812690c7301SKevin Wolf         if (n < s->cluster_sectors) {
1813690c7301SKevin Wolf             n = MIN(s->cluster_sectors, s->total_sectors - sector_num);
1814690c7301SKevin Wolf             s->status = BLK_DATA;
1815690c7301SKevin Wolf         } else {
1816690c7301SKevin Wolf             n = QEMU_ALIGN_DOWN(n, s->cluster_sectors);
1817690c7301SKevin Wolf         }
1818690c7301SKevin Wolf     }
1819690c7301SKevin Wolf 
1820690c7301SKevin Wolf     return n;
1821690c7301SKevin Wolf }
1822690c7301SKevin Wolf 
convert_co_read(ImgConvertState * s,int64_t sector_num,int nb_sectors,uint8_t * buf)18232d9187bcSPeter Lieven static int coroutine_fn convert_co_read(ImgConvertState *s, int64_t sector_num,
18242d9187bcSPeter Lieven                                         int nb_sectors, uint8_t *buf)
1825690c7301SKevin Wolf {
18268eaac025SMax Reitz     uint64_t single_read_until = 0;
18272d9187bcSPeter Lieven     int n, ret;
1828690c7301SKevin Wolf 
1829690c7301SKevin Wolf     assert(nb_sectors <= s->buf_sectors);
1830690c7301SKevin Wolf     while (nb_sectors > 0) {
1831690c7301SKevin Wolf         BlockBackend *blk;
18322d9187bcSPeter Lieven         int src_cur;
18332d9187bcSPeter Lieven         int64_t bs_sectors, src_cur_offset;
18348eaac025SMax Reitz         uint64_t offset;
1835690c7301SKevin Wolf 
1836690c7301SKevin Wolf         /* In the case of compression with multiple source files, we can get a
1837690c7301SKevin Wolf          * nb_sectors that spreads into the next part. So we must be able to
1838690c7301SKevin Wolf          * read across multiple BDSes for one convert_read() call. */
18392d9187bcSPeter Lieven         convert_select_part(s, sector_num, &src_cur, &src_cur_offset);
18402d9187bcSPeter Lieven         blk = s->src[src_cur];
18412d9187bcSPeter Lieven         bs_sectors = s->src_sectors[src_cur];
1842690c7301SKevin Wolf 
18438eaac025SMax Reitz         offset = (sector_num - src_cur_offset) << BDRV_SECTOR_BITS;
18442d9187bcSPeter Lieven 
18458eaac025SMax Reitz         n = MIN(nb_sectors, bs_sectors - (sector_num - src_cur_offset));
18468eaac025SMax Reitz         if (single_read_until > offset) {
18478eaac025SMax Reitz             n = 1;
18488eaac025SMax Reitz         }
18498eaac025SMax Reitz 
18508eaac025SMax Reitz         ret = blk_co_pread(blk, offset, n << BDRV_SECTOR_BITS, buf, 0);
1851690c7301SKevin Wolf         if (ret < 0) {
18528eaac025SMax Reitz             if (s->salvage) {
18538eaac025SMax Reitz                 if (n > 1) {
18548eaac025SMax Reitz                     single_read_until = offset + (n << BDRV_SECTOR_BITS);
18558eaac025SMax Reitz                     continue;
18568eaac025SMax Reitz                 } else {
18578eaac025SMax Reitz                     if (!s->quiet) {
18588eaac025SMax Reitz                         warn_report("error while reading offset %" PRIu64
18598eaac025SMax Reitz                                     ": %s", offset, strerror(-ret));
18608eaac025SMax Reitz                     }
18618eaac025SMax Reitz                     memset(buf, 0, BDRV_SECTOR_SIZE);
18628eaac025SMax Reitz                 }
18638eaac025SMax Reitz             } else {
1864690c7301SKevin Wolf                 return ret;
1865690c7301SKevin Wolf             }
18668eaac025SMax Reitz         }
1867690c7301SKevin Wolf 
1868690c7301SKevin Wolf         sector_num += n;
1869690c7301SKevin Wolf         nb_sectors -= n;
1870690c7301SKevin Wolf         buf += n * BDRV_SECTOR_SIZE;
1871690c7301SKevin Wolf     }
1872690c7301SKevin Wolf 
1873690c7301SKevin Wolf     return 0;
1874690c7301SKevin Wolf }
1875690c7301SKevin Wolf 
18762d9187bcSPeter Lieven 
convert_co_write(ImgConvertState * s,int64_t sector_num,int nb_sectors,uint8_t * buf,enum ImgConvertBlockStatus status)18772d9187bcSPeter Lieven static int coroutine_fn convert_co_write(ImgConvertState *s, int64_t sector_num,
18782d9187bcSPeter Lieven                                          int nb_sectors, uint8_t *buf,
18792d9187bcSPeter Lieven                                          enum ImgConvertBlockStatus status)
1880690c7301SKevin Wolf {
1881690c7301SKevin Wolf     int ret;
1882690c7301SKevin Wolf 
1883690c7301SKevin Wolf     while (nb_sectors > 0) {
1884690c7301SKevin Wolf         int n = nb_sectors;
1885db933fbeSLidong Chen         BdrvRequestFlags flags = s->compressed ? BDRV_REQ_WRITE_COMPRESSED : 0;
1886db933fbeSLidong Chen 
18872d9187bcSPeter Lieven         switch (status) {
1888690c7301SKevin Wolf         case BLK_BACKING_FILE:
1889690c7301SKevin Wolf             /* If we have a backing file, leave clusters unallocated that are
1890690c7301SKevin Wolf              * unallocated in the source image, so that the backing file is
1891690c7301SKevin Wolf              * visible at the respective offset. */
1892690c7301SKevin Wolf             assert(s->target_has_backing);
1893690c7301SKevin Wolf             break;
1894690c7301SKevin Wolf 
1895690c7301SKevin Wolf         case BLK_DATA:
1896db933fbeSLidong Chen             /* If we're told to keep the target fully allocated (-S 0) or there
1897db933fbeSLidong Chen              * is real non-zero data, we must write it. Otherwise we can treat
1898db933fbeSLidong Chen              * it as zero sectors.
1899db933fbeSLidong Chen              * Compressed clusters need to be written as a whole, so in that
1900db933fbeSLidong Chen              * case we can only save the write if the buffer is completely
1901db933fbeSLidong Chen              * zeroed. */
1902690c7301SKevin Wolf             if (!s->min_sparse ||
1903db933fbeSLidong Chen                 (!s->compressed &&
19048dcd3c9bSPeter Lieven                  is_allocated_sectors_min(buf, n, &n, s->min_sparse,
19058dcd3c9bSPeter Lieven                                           sector_num, s->alignment)) ||
1906db933fbeSLidong Chen                 (s->compressed &&
1907db933fbeSLidong Chen                  !buffer_is_zero(buf, n * BDRV_SECTOR_SIZE)))
1908690c7301SKevin Wolf             {
1909265a7e54SVladimir Sementsov-Ogievskiy                 ret = blk_co_pwrite(s->target, sector_num << BDRV_SECTOR_BITS,
1910265a7e54SVladimir Sementsov-Ogievskiy                                     n << BDRV_SECTOR_BITS, buf, flags);
1911690c7301SKevin Wolf                 if (ret < 0) {
1912690c7301SKevin Wolf                     return ret;
1913690c7301SKevin Wolf                 }
1914690c7301SKevin Wolf                 break;
1915690c7301SKevin Wolf             }
1916690c7301SKevin Wolf             /* fall-through */
1917690c7301SKevin Wolf 
1918690c7301SKevin Wolf         case BLK_ZERO:
1919690c7301SKevin Wolf             if (s->has_zero_init) {
1920db933fbeSLidong Chen                 assert(!s->target_has_backing);
1921690c7301SKevin Wolf                 break;
1922690c7301SKevin Wolf             }
19232d9187bcSPeter Lieven             ret = blk_co_pwrite_zeroes(s->target,
19242d9187bcSPeter Lieven                                        sector_num << BDRV_SECTOR_BITS,
1925a3d6ae22SNir Soffer                                        n << BDRV_SECTOR_BITS,
1926a3d6ae22SNir Soffer                                        BDRV_REQ_MAY_UNMAP);
1927690c7301SKevin Wolf             if (ret < 0) {
1928690c7301SKevin Wolf                 return ret;
1929690c7301SKevin Wolf             }
1930690c7301SKevin Wolf             break;
1931690c7301SKevin Wolf         }
1932690c7301SKevin Wolf 
1933690c7301SKevin Wolf         sector_num += n;
1934690c7301SKevin Wolf         nb_sectors -= n;
1935690c7301SKevin Wolf         buf += n * BDRV_SECTOR_SIZE;
1936690c7301SKevin Wolf     }
1937690c7301SKevin Wolf 
1938690c7301SKevin Wolf     return 0;
1939690c7301SKevin Wolf }
1940690c7301SKevin Wolf 
convert_co_copy_range(ImgConvertState * s,int64_t sector_num,int nb_sectors)1941ee5306d0SFam Zheng static int coroutine_fn convert_co_copy_range(ImgConvertState *s, int64_t sector_num,
1942ee5306d0SFam Zheng                                               int nb_sectors)
1943ee5306d0SFam Zheng {
1944ee5306d0SFam Zheng     int n, ret;
1945ee5306d0SFam Zheng 
1946ee5306d0SFam Zheng     while (nb_sectors > 0) {
1947ee5306d0SFam Zheng         BlockBackend *blk;
1948ee5306d0SFam Zheng         int src_cur;
1949ee5306d0SFam Zheng         int64_t bs_sectors, src_cur_offset;
1950ee5306d0SFam Zheng         int64_t offset;
1951ee5306d0SFam Zheng 
1952ee5306d0SFam Zheng         convert_select_part(s, sector_num, &src_cur, &src_cur_offset);
1953ee5306d0SFam Zheng         offset = (sector_num - src_cur_offset) << BDRV_SECTOR_BITS;
1954ee5306d0SFam Zheng         blk = s->src[src_cur];
1955ee5306d0SFam Zheng         bs_sectors = s->src_sectors[src_cur];
1956ee5306d0SFam Zheng 
1957ee5306d0SFam Zheng         n = MIN(nb_sectors, bs_sectors - (sector_num - src_cur_offset));
1958ee5306d0SFam Zheng 
1959ee5306d0SFam Zheng         ret = blk_co_copy_range(blk, offset, s->target,
1960ee5306d0SFam Zheng                                 sector_num << BDRV_SECTOR_BITS,
196167b51fb9SVladimir Sementsov-Ogievskiy                                 n << BDRV_SECTOR_BITS, 0, 0);
1962ee5306d0SFam Zheng         if (ret < 0) {
1963ee5306d0SFam Zheng             return ret;
1964ee5306d0SFam Zheng         }
1965ee5306d0SFam Zheng 
1966ee5306d0SFam Zheng         sector_num += n;
1967ee5306d0SFam Zheng         nb_sectors -= n;
1968ee5306d0SFam Zheng     }
1969ee5306d0SFam Zheng     return 0;
1970ee5306d0SFam Zheng }
1971ee5306d0SFam Zheng 
convert_co_do_copy(void * opaque)19722d9187bcSPeter Lieven static void coroutine_fn convert_co_do_copy(void *opaque)
19732d9187bcSPeter Lieven {
19742d9187bcSPeter Lieven     ImgConvertState *s = opaque;
19752d9187bcSPeter Lieven     uint8_t *buf = NULL;
19762d9187bcSPeter Lieven     int ret, i;
19772d9187bcSPeter Lieven     int index = -1;
19782d9187bcSPeter Lieven 
19792d9187bcSPeter Lieven     for (i = 0; i < s->num_coroutines; i++) {
19802d9187bcSPeter Lieven         if (s->co[i] == qemu_coroutine_self()) {
19812d9187bcSPeter Lieven             index = i;
19822d9187bcSPeter Lieven             break;
19832d9187bcSPeter Lieven         }
19842d9187bcSPeter Lieven     }
19852d9187bcSPeter Lieven     assert(index >= 0);
19862d9187bcSPeter Lieven 
19872d9187bcSPeter Lieven     s->running_coroutines++;
19882d9187bcSPeter Lieven     buf = blk_blockalign(s->target, s->buf_sectors * BDRV_SECTOR_SIZE);
19892d9187bcSPeter Lieven 
19902d9187bcSPeter Lieven     while (1) {
19912d9187bcSPeter Lieven         int n;
19922d9187bcSPeter Lieven         int64_t sector_num;
19932d9187bcSPeter Lieven         enum ImgConvertBlockStatus status;
1994ee5306d0SFam Zheng         bool copy_range;
19952d9187bcSPeter Lieven 
19962d9187bcSPeter Lieven         qemu_co_mutex_lock(&s->lock);
19972d9187bcSPeter Lieven         if (s->ret != -EINPROGRESS || s->sector_num >= s->total_sectors) {
19982d9187bcSPeter Lieven             qemu_co_mutex_unlock(&s->lock);
1999b91127edSAnton Nefedov             break;
20002d9187bcSPeter Lieven         }
20017ff9579eSKevin Wolf         WITH_GRAPH_RDLOCK_GUARD() {
20022d9187bcSPeter Lieven             n = convert_iteration_sectors(s, s->sector_num);
20037ff9579eSKevin Wolf         }
20042d9187bcSPeter Lieven         if (n < 0) {
20052d9187bcSPeter Lieven             qemu_co_mutex_unlock(&s->lock);
20062d9187bcSPeter Lieven             s->ret = n;
2007b91127edSAnton Nefedov             break;
20082d9187bcSPeter Lieven         }
20092d9187bcSPeter Lieven         /* save current sector and allocation status to local variables */
20102d9187bcSPeter Lieven         sector_num = s->sector_num;
20112d9187bcSPeter Lieven         status = s->status;
20122d9187bcSPeter Lieven         if (!s->min_sparse && s->status == BLK_ZERO) {
20132d9187bcSPeter Lieven             n = MIN(n, s->buf_sectors);
20142d9187bcSPeter Lieven         }
20152d9187bcSPeter Lieven         /* increment global sector counter so that other coroutines can
20162d9187bcSPeter Lieven          * already continue reading beyond this request */
20172d9187bcSPeter Lieven         s->sector_num += n;
20182d9187bcSPeter Lieven         qemu_co_mutex_unlock(&s->lock);
20192d9187bcSPeter Lieven 
20202d9187bcSPeter Lieven         if (status == BLK_DATA || (!s->min_sparse && status == BLK_ZERO)) {
20212d9187bcSPeter Lieven             s->allocated_done += n;
20222d9187bcSPeter Lieven             qemu_progress_print(100.0 * s->allocated_done /
20232d9187bcSPeter Lieven                                         s->allocated_sectors, 0);
20242d9187bcSPeter Lieven         }
20252d9187bcSPeter Lieven 
2026ee5306d0SFam Zheng retry:
2027ee5306d0SFam Zheng         copy_range = s->copy_range && s->status == BLK_DATA;
2028ee5306d0SFam Zheng         if (status == BLK_DATA && !copy_range) {
20292d9187bcSPeter Lieven             ret = convert_co_read(s, sector_num, n, buf);
20302d9187bcSPeter Lieven             if (ret < 0) {
203139f77cb6SEric Blake                 error_report("error while reading at byte %lld: %s",
203239f77cb6SEric Blake                              sector_num * BDRV_SECTOR_SIZE, strerror(-ret));
20332d9187bcSPeter Lieven                 s->ret = ret;
20342d9187bcSPeter Lieven             }
20352d9187bcSPeter Lieven         } else if (!s->min_sparse && status == BLK_ZERO) {
20362d9187bcSPeter Lieven             status = BLK_DATA;
20372d9187bcSPeter Lieven             memset(buf, 0x00, n * BDRV_SECTOR_SIZE);
20382d9187bcSPeter Lieven         }
20392d9187bcSPeter Lieven 
20402d9187bcSPeter Lieven         if (s->wr_in_order) {
20412d9187bcSPeter Lieven             /* keep writes in order */
2042b91127edSAnton Nefedov             while (s->wr_offs != sector_num && s->ret == -EINPROGRESS) {
20432d9187bcSPeter Lieven                 s->wait_sector_num[index] = sector_num;
20442d9187bcSPeter Lieven                 qemu_coroutine_yield();
20452d9187bcSPeter Lieven             }
20462d9187bcSPeter Lieven             s->wait_sector_num[index] = -1;
20472d9187bcSPeter Lieven         }
20482d9187bcSPeter Lieven 
2049b91127edSAnton Nefedov         if (s->ret == -EINPROGRESS) {
2050ee5306d0SFam Zheng             if (copy_range) {
2051742bf09bSEmanuele Giuseppe Esposito                 WITH_GRAPH_RDLOCK_GUARD() {
2052ee5306d0SFam Zheng                     ret = convert_co_copy_range(s, sector_num, n);
2053742bf09bSEmanuele Giuseppe Esposito                 }
2054ee5306d0SFam Zheng                 if (ret) {
2055ee5306d0SFam Zheng                     s->copy_range = false;
2056ee5306d0SFam Zheng                     goto retry;
2057ee5306d0SFam Zheng                 }
2058ee5306d0SFam Zheng             } else {
20592d9187bcSPeter Lieven                 ret = convert_co_write(s, sector_num, n, buf, status);
2060ee5306d0SFam Zheng             }
20612d9187bcSPeter Lieven             if (ret < 0) {
206239f77cb6SEric Blake                 error_report("error while writing at byte %lld: %s",
206339f77cb6SEric Blake                              sector_num * BDRV_SECTOR_SIZE, strerror(-ret));
20642d9187bcSPeter Lieven                 s->ret = ret;
2065b91127edSAnton Nefedov             }
20662d9187bcSPeter Lieven         }
20672d9187bcSPeter Lieven 
20682d9187bcSPeter Lieven         if (s->wr_in_order) {
20692d9187bcSPeter Lieven             /* reenter the coroutine that might have waited
20702d9187bcSPeter Lieven              * for this write to complete */
20712d9187bcSPeter Lieven             s->wr_offs = sector_num + n;
20722d9187bcSPeter Lieven             for (i = 0; i < s->num_coroutines; i++) {
20732d9187bcSPeter Lieven                 if (s->co[i] && s->wait_sector_num[i] == s->wr_offs) {
20742d9187bcSPeter Lieven                     /*
20752d9187bcSPeter Lieven                      * A -> B -> A cannot occur because A has
20762d9187bcSPeter Lieven                      * s->wait_sector_num[i] == -1 during A -> B.  Therefore
20772d9187bcSPeter Lieven                      * B will never enter A during this time window.
20782d9187bcSPeter Lieven                      */
20792d9187bcSPeter Lieven                     qemu_coroutine_enter(s->co[i]);
20802d9187bcSPeter Lieven                     break;
20812d9187bcSPeter Lieven                 }
20822d9187bcSPeter Lieven             }
20832d9187bcSPeter Lieven         }
20842d9187bcSPeter Lieven     }
20852d9187bcSPeter Lieven 
20862d9187bcSPeter Lieven     qemu_vfree(buf);
20872d9187bcSPeter Lieven     s->co[index] = NULL;
20882d9187bcSPeter Lieven     s->running_coroutines--;
20892d9187bcSPeter Lieven     if (!s->running_coroutines && s->ret == -EINPROGRESS) {
20902d9187bcSPeter Lieven         /* the convert job finished successfully */
20912d9187bcSPeter Lieven         s->ret = 0;
20922d9187bcSPeter Lieven     }
20932d9187bcSPeter Lieven }
20942d9187bcSPeter Lieven 
convert_do_copy(ImgConvertState * s)2095690c7301SKevin Wolf static int convert_do_copy(ImgConvertState *s)
2096690c7301SKevin Wolf {
20972d9187bcSPeter Lieven     int ret, i, n;
20982d9187bcSPeter Lieven     int64_t sector_num = 0;
2099690c7301SKevin Wolf 
2100690c7301SKevin Wolf     /* Check whether we have zero initialisation or can get it efficiently */
2101168468feSDavid Edmondson     if (!s->has_zero_init && s->target_is_new && s->min_sparse &&
2102168468feSDavid Edmondson         !s->target_has_backing) {
210306717986SKevin Wolf         bdrv_graph_rdlock_main_loop();
21044d7c487eSMax Reitz         s->has_zero_init = bdrv_has_zero_init(blk_bs(s->target));
210506717986SKevin Wolf         bdrv_graph_rdunlock_main_loop();
21064d7c487eSMax Reitz     }
2107690c7301SKevin Wolf 
2108690c7301SKevin Wolf     /* Allocate buffer for copied data. For compressed images, only one cluster
2109690c7301SKevin Wolf      * can be copied at a time. */
2110690c7301SKevin Wolf     if (s->compressed) {
2111690c7301SKevin Wolf         if (s->cluster_sectors <= 0 || s->cluster_sectors > s->buf_sectors) {
2112690c7301SKevin Wolf             error_report("invalid cluster size");
21132d9187bcSPeter Lieven             return -EINVAL;
2114690c7301SKevin Wolf         }
2115690c7301SKevin Wolf         s->buf_sectors = s->cluster_sectors;
2116690c7301SKevin Wolf     }
2117690c7301SKevin Wolf 
2118690c7301SKevin Wolf     while (sector_num < s->total_sectors) {
2119ad74751fSKevin Wolf         bdrv_graph_rdlock_main_loop();
2120690c7301SKevin Wolf         n = convert_iteration_sectors(s, sector_num);
2121ad74751fSKevin Wolf         bdrv_graph_rdunlock_main_loop();
2122690c7301SKevin Wolf         if (n < 0) {
21232d9187bcSPeter Lieven             return n;
2124690c7301SKevin Wolf         }
2125aad15de4SMax Reitz         if (s->status == BLK_DATA || (!s->min_sparse && s->status == BLK_ZERO))
2126aad15de4SMax Reitz         {
2127690c7301SKevin Wolf             s->allocated_sectors += n;
2128690c7301SKevin Wolf         }
2129690c7301SKevin Wolf         sector_num += n;
2130690c7301SKevin Wolf     }
2131690c7301SKevin Wolf 
2132690c7301SKevin Wolf     /* Do the copy */
2133690c7301SKevin Wolf     s->sector_next_status = 0;
21342d9187bcSPeter Lieven     s->ret = -EINPROGRESS;
2135690c7301SKevin Wolf 
21362d9187bcSPeter Lieven     qemu_co_mutex_init(&s->lock);
21372d9187bcSPeter Lieven     for (i = 0; i < s->num_coroutines; i++) {
21382d9187bcSPeter Lieven         s->co[i] = qemu_coroutine_create(convert_co_do_copy, s);
21392d9187bcSPeter Lieven         s->wait_sector_num[i] = -1;
21402d9187bcSPeter Lieven         qemu_coroutine_enter(s->co[i]);
2141690c7301SKevin Wolf     }
2142690c7301SKevin Wolf 
2143b91127edSAnton Nefedov     while (s->running_coroutines) {
21442d9187bcSPeter Lieven         main_loop_wait(false);
2145aad15de4SMax Reitz     }
2146690c7301SKevin Wolf 
21472d9187bcSPeter Lieven     if (s->compressed && !s->ret) {
2148690c7301SKevin Wolf         /* signal EOF to align */
21490cadf2c8SAlberto Faria         ret = blk_pwrite_compressed(s->target, 0, 0, NULL);
2150690c7301SKevin Wolf         if (ret < 0) {
21512d9187bcSPeter Lieven             return ret;
2152690c7301SKevin Wolf         }
2153690c7301SKevin Wolf     }
2154690c7301SKevin Wolf 
21552d9187bcSPeter Lieven     return s->ret;
2156690c7301SKevin Wolf }
2157690c7301SKevin Wolf 
215874a4320fSEric Blake /* Check that bitmaps can be copied, or output an error */
convert_check_bitmaps(BlockDriverState * src,bool skip_broken)2159955171e4SEric Blake static int convert_check_bitmaps(BlockDriverState *src, bool skip_broken)
216074a4320fSEric Blake {
216174a4320fSEric Blake     BdrvDirtyBitmap *bm;
216274a4320fSEric Blake 
216374a4320fSEric Blake     if (!bdrv_supports_persistent_dirty_bitmap(src)) {
216474a4320fSEric Blake         error_report("Source lacks bitmap support");
216574a4320fSEric Blake         return -1;
216674a4320fSEric Blake     }
216774a4320fSEric Blake     FOR_EACH_DIRTY_BITMAP(src, bm) {
216874a4320fSEric Blake         if (!bdrv_dirty_bitmap_get_persistence(bm)) {
216974a4320fSEric Blake             continue;
217074a4320fSEric Blake         }
2171955171e4SEric Blake         if (!skip_broken && bdrv_dirty_bitmap_inconsistent(bm)) {
217274a4320fSEric Blake             error_report("Cannot copy inconsistent bitmap '%s'",
217374a4320fSEric Blake                          bdrv_dirty_bitmap_name(bm));
2174955171e4SEric Blake             error_printf("Try --skip-broken-bitmaps, or "
2175955171e4SEric Blake                          "use 'qemu-img bitmap --remove' to delete it\n");
217674a4320fSEric Blake             return -1;
217774a4320fSEric Blake         }
217874a4320fSEric Blake     }
217974a4320fSEric Blake     return 0;
218074a4320fSEric Blake }
218174a4320fSEric Blake 
convert_copy_bitmaps(BlockDriverState * src,BlockDriverState * dst,bool skip_broken)2182955171e4SEric Blake static int convert_copy_bitmaps(BlockDriverState *src, BlockDriverState *dst,
2183955171e4SEric Blake                                 bool skip_broken)
218415e39ad9SEric Blake {
218515e39ad9SEric Blake     BdrvDirtyBitmap *bm;
218615e39ad9SEric Blake     Error *err = NULL;
218715e39ad9SEric Blake 
218815e39ad9SEric Blake     FOR_EACH_DIRTY_BITMAP(src, bm) {
218915e39ad9SEric Blake         const char *name;
219015e39ad9SEric Blake 
219115e39ad9SEric Blake         if (!bdrv_dirty_bitmap_get_persistence(bm)) {
219215e39ad9SEric Blake             continue;
219315e39ad9SEric Blake         }
219415e39ad9SEric Blake         name = bdrv_dirty_bitmap_name(bm);
2195955171e4SEric Blake         if (skip_broken && bdrv_dirty_bitmap_inconsistent(bm)) {
2196955171e4SEric Blake             warn_report("Skipping inconsistent bitmap '%s'", name);
2197955171e4SEric Blake             continue;
2198955171e4SEric Blake         }
219915e39ad9SEric Blake         qmp_block_dirty_bitmap_add(dst->node_name, name,
220015e39ad9SEric Blake                                    true, bdrv_dirty_bitmap_granularity(bm),
220115e39ad9SEric Blake                                    true, true,
220215e39ad9SEric Blake                                    true, !bdrv_dirty_bitmap_enabled(bm),
220315e39ad9SEric Blake                                    &err);
220415e39ad9SEric Blake         if (err) {
220515e39ad9SEric Blake             error_reportf_err(err, "Failed to create bitmap %s: ", name);
220615e39ad9SEric Blake             return -1;
220715e39ad9SEric Blake         }
220815e39ad9SEric Blake 
220915e39ad9SEric Blake         do_dirty_bitmap_merge(dst->node_name, name, src->node_name, name,
221015e39ad9SEric Blake                               &err);
221115e39ad9SEric Blake         if (err) {
221215e39ad9SEric Blake             error_reportf_err(err, "Failed to populate bitmap %s: ", name);
221374a4320fSEric Blake             qmp_block_dirty_bitmap_remove(dst->node_name, name, NULL);
221415e39ad9SEric Blake             return -1;
221515e39ad9SEric Blake         }
221615e39ad9SEric Blake     }
221715e39ad9SEric Blake 
221815e39ad9SEric Blake     return 0;
221915e39ad9SEric Blake }
222015e39ad9SEric Blake 
22216360ab27SPeter Lieven #define MAX_BUF_SECTORS 32768
22226360ab27SPeter Lieven 
set_rate_limit(BlockBackend * blk,int64_t rate_limit)22230c8c4895SZhengui static void set_rate_limit(BlockBackend *blk, int64_t rate_limit)
22240c8c4895SZhengui {
22250c8c4895SZhengui     ThrottleConfig cfg;
22260c8c4895SZhengui 
22270c8c4895SZhengui     throttle_config_init(&cfg);
22280c8c4895SZhengui     cfg.buckets[THROTTLE_BPS_WRITE].avg = rate_limit;
22290c8c4895SZhengui 
22300c8c4895SZhengui     blk_io_limits_enable(blk, CONVERT_THROTTLE_GROUP);
22310c8c4895SZhengui     blk_set_io_limits(blk, &cfg);
22320c8c4895SZhengui }
22330c8c4895SZhengui 
img_convert(int argc,char ** argv)2234ea2384d3Sbellard static int img_convert(int argc, char **argv)
2235ea2384d3Sbellard {
22360b8fb55cSKevin Wolf     int c, bs_i, flags, src_flags = BDRV_O_NO_SHARE;
2237305b4c60SDaniel P. Berrange     const char *fmt = NULL, *out_fmt = NULL, *cache = "unsafe",
22389fd77f99SPeter Lieven                *src_cache = BDRV_DEFAULT_CACHE, *out_baseimg = NULL,
22391899bf47SEric Blake                *out_filename, *out_baseimg_param, *snapshot_name = NULL,
22401899bf47SEric Blake                *backing_fmt = NULL;
2241305b4c60SDaniel P. Berrange     BlockDriver *drv = NULL, *proto_drv = NULL;
2242faea38e7Sbellard     BlockDriverInfo bdi;
22439fd77f99SPeter Lieven     BlockDriverState *out_bs;
22449fd77f99SPeter Lieven     QemuOpts *opts = NULL, *sn_opts = NULL;
224583d0521aSChunyan Liu     QemuOptsList *create_opts = NULL;
22468d65a3ccSDaniel P. Berrangé     QDict *open_opts = NULL;
2247efa84d43SKevin Wolf     char *options = NULL;
2248cc84d90fSMax Reitz     Error *local_err = NULL;
22493d96cb91SMax Reitz     bool writethrough, src_writethrough, image_opts = false,
2250305b4c60SDaniel P. Berrange          skip_create = false, progress = false, tgt_image_opts = false;
22519fd77f99SPeter Lieven     int64_t ret = -EINVAL;
2252335e9937SFam Zheng     bool force_share = false;
2253e11ce12fSFam Zheng     bool explict_min_sparse = false;
225415e39ad9SEric Blake     bool bitmaps = false;
2255955171e4SEric Blake     bool skip_broken = false;
22560c8c4895SZhengui     int64_t rate_limit = 0;
2257ea2384d3Sbellard 
22589fd77f99SPeter Lieven     ImgConvertState s = (ImgConvertState) {
22599fd77f99SPeter Lieven         /* Need at least 4k of zeros for sparse detection */
22609fd77f99SPeter Lieven         .min_sparse         = 8,
2261e11ce12fSFam Zheng         .copy_range         = false,
22629fd77f99SPeter Lieven         .buf_sectors        = IO_BUF_SIZE / BDRV_SECTOR_SIZE,
22639fd77f99SPeter Lieven         .wr_in_order        = true,
22649fd77f99SPeter Lieven         .num_coroutines     = 8,
22659fd77f99SPeter Lieven     };
22669fd77f99SPeter Lieven 
2267ea2384d3Sbellard     for(;;) {
22683babeb15SDaniel P. Berrange         static const struct option long_options[] = {
22693babeb15SDaniel P. Berrange             {"help", no_argument, 0, 'h'},
22703babeb15SDaniel P. Berrange             {"object", required_argument, 0, OPTION_OBJECT},
2271eb769f74SDaniel P. Berrange             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
2272335e9937SFam Zheng             {"force-share", no_argument, 0, 'U'},
2273305b4c60SDaniel P. Berrange             {"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS},
22748eaac025SMax Reitz             {"salvage", no_argument, 0, OPTION_SALVAGE},
2275168468feSDavid Edmondson             {"target-is-zero", no_argument, 0, OPTION_TARGET_IS_ZERO},
227615e39ad9SEric Blake             {"bitmaps", no_argument, 0, OPTION_BITMAPS},
2277955171e4SEric Blake             {"skip-broken-bitmaps", no_argument, 0, OPTION_SKIP_BROKEN},
22783babeb15SDaniel P. Berrange             {0, 0, 0, 0}
22793babeb15SDaniel P. Berrange         };
22801899bf47SEric Blake         c = getopt_long(argc, argv, ":hf:O:B:CcF:o:l:S:pt:T:qnm:WUr:",
22813babeb15SDaniel P. Berrange                         long_options, NULL);
2282b8fb60daSJes Sorensen         if (c == -1) {
2283ea2384d3Sbellard             break;
2284b8fb60daSJes Sorensen         }
2285ea2384d3Sbellard         switch(c) {
2286c9192973SStefan Hajnoczi         case ':':
2287c9192973SStefan Hajnoczi             missing_argument(argv[optind - 1]);
2288c9192973SStefan Hajnoczi             break;
2289ef87394cSJes Sorensen         case '?':
2290c9192973SStefan Hajnoczi             unrecognized_option(argv[optind - 1]);
2291c9192973SStefan Hajnoczi             break;
2292ea2384d3Sbellard         case 'h':
2293ea2384d3Sbellard             help();
2294ea2384d3Sbellard             break;
2295ea2384d3Sbellard         case 'f':
2296ea2384d3Sbellard             fmt = optarg;
2297ea2384d3Sbellard             break;
2298ea2384d3Sbellard         case 'O':
2299ea2384d3Sbellard             out_fmt = optarg;
2300ea2384d3Sbellard             break;
2301f58c7b35Sths         case 'B':
2302f58c7b35Sths             out_baseimg = optarg;
2303f58c7b35Sths             break;
2304e11ce12fSFam Zheng         case 'C':
2305e11ce12fSFam Zheng             s.copy_range = true;
2306e11ce12fSFam Zheng             break;
2307ea2384d3Sbellard         case 'c':
23089fd77f99SPeter Lieven             s.compressed = true;
2309ea2384d3Sbellard             break;
23101899bf47SEric Blake         case 'F':
23111899bf47SEric Blake             backing_fmt = optarg;
23121899bf47SEric Blake             break;
2313efa84d43SKevin Wolf         case 'o':
23146d2b5cbaSMarkus Armbruster             if (accumulate_options(&options, optarg) < 0) {
231564bb01aaSKevin Wolf                 goto fail_getopt;
23162dc8328bSKevin Wolf             }
2317efa84d43SKevin Wolf             break;
2318ef80654dSWenchao Xia         case 'l':
2319ef80654dSWenchao Xia             if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
232070b94331SMarkus Armbruster                 sn_opts = qemu_opts_parse_noisily(&internal_snapshot_opts,
232170b94331SMarkus Armbruster                                                   optarg, false);
2322ef80654dSWenchao Xia                 if (!sn_opts) {
2323ef80654dSWenchao Xia                     error_report("Failed in parsing snapshot param '%s'",
2324ef80654dSWenchao Xia                                  optarg);
232564bb01aaSKevin Wolf                     goto fail_getopt;
2326ef80654dSWenchao Xia                 }
2327ef80654dSWenchao Xia             } else {
2328ef80654dSWenchao Xia                 snapshot_name = optarg;
2329ef80654dSWenchao Xia             }
2330ef80654dSWenchao Xia             break;
2331a22f123cSKevin Wolf         case 'S':
2332a22f123cSKevin Wolf         {
2333a22f123cSKevin Wolf             int64_t sval;
2334606caa0aSMarkus Armbruster 
233543d589b0SEyal Moscovici             sval = cvtnum("buffer size for sparse output", optarg);
233643d589b0SEyal Moscovici             if (sval < 0) {
233743d589b0SEyal Moscovici                 goto fail_getopt;
233843d589b0SEyal Moscovici             } else if (!QEMU_IS_ALIGNED(sval, BDRV_SECTOR_SIZE) ||
23396360ab27SPeter Lieven                 sval / BDRV_SECTOR_SIZE > MAX_BUF_SECTORS) {
23406360ab27SPeter Lieven                 error_report("Invalid buffer size for sparse output specified. "
23416360ab27SPeter Lieven                     "Valid sizes are multiples of %llu up to %llu. Select "
23426360ab27SPeter Lieven                     "0 to disable sparse detection (fully allocates output).",
23436360ab27SPeter Lieven                     BDRV_SECTOR_SIZE, MAX_BUF_SECTORS * BDRV_SECTOR_SIZE);
234464bb01aaSKevin Wolf                 goto fail_getopt;
2345a22f123cSKevin Wolf             }
2346a22f123cSKevin Wolf 
23479fd77f99SPeter Lieven             s.min_sparse = sval / BDRV_SECTOR_SIZE;
2348e11ce12fSFam Zheng             explict_min_sparse = true;
2349a22f123cSKevin Wolf             break;
2350a22f123cSKevin Wolf         }
23516b837bc4SJes Sorensen         case 'p':
23529fd77f99SPeter Lieven             progress = true;
23536b837bc4SJes Sorensen             break;
2354661a0f71SFederico Simoncelli         case 't':
2355661a0f71SFederico Simoncelli             cache = optarg;
2356661a0f71SFederico Simoncelli             break;
235740055951SMax Reitz         case 'T':
235840055951SMax Reitz             src_cache = optarg;
235940055951SMax Reitz             break;
2360f382d43aSMiroslav Rezanina         case 'q':
23613d96cb91SMax Reitz             s.quiet = true;
2362f382d43aSMiroslav Rezanina             break;
2363b2e10493SAlexandre Derumier         case 'n':
23649fd77f99SPeter Lieven             skip_create = true;
2365b2e10493SAlexandre Derumier             break;
23662d9187bcSPeter Lieven         case 'm':
23679fd77f99SPeter Lieven             if (qemu_strtol(optarg, NULL, 0, &s.num_coroutines) ||
23689fd77f99SPeter Lieven                 s.num_coroutines < 1 || s.num_coroutines > MAX_COROUTINES) {
23692d9187bcSPeter Lieven                 error_report("Invalid number of coroutines. Allowed number of"
23702d9187bcSPeter Lieven                              " coroutines is between 1 and %d", MAX_COROUTINES);
23712d9187bcSPeter Lieven                 goto fail_getopt;
23722d9187bcSPeter Lieven             }
23732d9187bcSPeter Lieven             break;
23742d9187bcSPeter Lieven         case 'W':
23759fd77f99SPeter Lieven             s.wr_in_order = false;
23762d9187bcSPeter Lieven             break;
2377335e9937SFam Zheng         case 'U':
2378335e9937SFam Zheng             force_share = true;
2379335e9937SFam Zheng             break;
23800c8c4895SZhengui         case 'r':
23810c8c4895SZhengui             rate_limit = cvtnum("rate limit", optarg);
23820c8c4895SZhengui             if (rate_limit < 0) {
23830c8c4895SZhengui                 goto fail_getopt;
23840c8c4895SZhengui             }
23850c8c4895SZhengui             break;
238699b1e646SKevin Wolf         case OPTION_OBJECT:
238799b1e646SKevin Wolf             user_creatable_process_cmdline(optarg);
23883babeb15SDaniel P. Berrange             break;
2389eb769f74SDaniel P. Berrange         case OPTION_IMAGE_OPTS:
2390eb769f74SDaniel P. Berrange             image_opts = true;
2391eb769f74SDaniel P. Berrange             break;
23928eaac025SMax Reitz         case OPTION_SALVAGE:
23938eaac025SMax Reitz             s.salvage = true;
23948eaac025SMax Reitz             break;
2395305b4c60SDaniel P. Berrange         case OPTION_TARGET_IMAGE_OPTS:
2396305b4c60SDaniel P. Berrange             tgt_image_opts = true;
2397305b4c60SDaniel P. Berrange             break;
2398168468feSDavid Edmondson         case OPTION_TARGET_IS_ZERO:
2399168468feSDavid Edmondson             /*
2400168468feSDavid Edmondson              * The user asserting that the target is blank has the
2401168468feSDavid Edmondson              * same effect as the target driver supporting zero
2402168468feSDavid Edmondson              * initialisation.
2403168468feSDavid Edmondson              */
2404168468feSDavid Edmondson             s.has_zero_init = true;
2405168468feSDavid Edmondson             break;
240615e39ad9SEric Blake         case OPTION_BITMAPS:
240715e39ad9SEric Blake             bitmaps = true;
240815e39ad9SEric Blake             break;
2409955171e4SEric Blake         case OPTION_SKIP_BROKEN:
2410955171e4SEric Blake             skip_broken = true;
2411955171e4SEric Blake             break;
24123babeb15SDaniel P. Berrange         }
24133babeb15SDaniel P. Berrange     }
24143babeb15SDaniel P. Berrange 
2415305b4c60SDaniel P. Berrange     if (!out_fmt && !tgt_image_opts) {
2416305b4c60SDaniel P. Berrange         out_fmt = "raw";
2417305b4c60SDaniel P. Berrange     }
2418305b4c60SDaniel P. Berrange 
2419955171e4SEric Blake     if (skip_broken && !bitmaps) {
2420955171e4SEric Blake         error_report("Use of --skip-broken-bitmaps requires --bitmaps");
2421955171e4SEric Blake         goto fail_getopt;
2422955171e4SEric Blake     }
2423955171e4SEric Blake 
2424e11ce12fSFam Zheng     if (s.compressed && s.copy_range) {
2425e11ce12fSFam Zheng         error_report("Cannot enable copy offloading when -c is used");
2426e11ce12fSFam Zheng         goto fail_getopt;
2427e11ce12fSFam Zheng     }
2428e11ce12fSFam Zheng 
2429e11ce12fSFam Zheng     if (explict_min_sparse && s.copy_range) {
2430e11ce12fSFam Zheng         error_report("Cannot enable copy offloading when -S is used");
2431e11ce12fSFam Zheng         goto fail_getopt;
2432e11ce12fSFam Zheng     }
2433e11ce12fSFam Zheng 
24348eaac025SMax Reitz     if (s.copy_range && s.salvage) {
24358eaac025SMax Reitz         error_report("Cannot use copy offloading in salvaging mode");
24368eaac025SMax Reitz         goto fail_getopt;
24378eaac025SMax Reitz     }
24388eaac025SMax Reitz 
2439305b4c60SDaniel P. Berrange     if (tgt_image_opts && !skip_create) {
2440305b4c60SDaniel P. Berrange         error_report("--target-image-opts requires use of -n flag");
2441305b4c60SDaniel P. Berrange         goto fail_getopt;
2442305b4c60SDaniel P. Berrange     }
2443305b4c60SDaniel P. Berrange 
2444ffd8e8ffSKevin Wolf     if (skip_create && options) {
244525956af3SEric Blake         error_report("-o has no effect when skipping image creation");
244625956af3SEric Blake         goto fail_getopt;
2447ffd8e8ffSKevin Wolf     }
2448ffd8e8ffSKevin Wolf 
2449168468feSDavid Edmondson     if (s.has_zero_init && !skip_create) {
2450168468feSDavid Edmondson         error_report("--target-is-zero requires use of -n flag");
2451168468feSDavid Edmondson         goto fail_getopt;
2452168468feSDavid Edmondson     }
2453168468feSDavid Edmondson 
24549fd77f99SPeter Lieven     s.src_num = argc - optind - 1;
24559fd77f99SPeter Lieven     out_filename = s.src_num >= 1 ? argv[argc - 1] : NULL;
24569fd77f99SPeter Lieven 
24579fd77f99SPeter Lieven     if (options && has_help_option(options)) {
2458305b4c60SDaniel P. Berrange         if (out_fmt) {
24599fd77f99SPeter Lieven             ret = print_block_option_help(out_filename, out_fmt);
24609fd77f99SPeter Lieven             goto fail_getopt;
2461305b4c60SDaniel P. Berrange         } else {
2462305b4c60SDaniel P. Berrange             error_report("Option help requires a format be specified");
2463305b4c60SDaniel P. Berrange             goto fail_getopt;
2464305b4c60SDaniel P. Berrange         }
24659fd77f99SPeter Lieven     }
24669fd77f99SPeter Lieven 
24679fd77f99SPeter Lieven     if (s.src_num < 1) {
24689fd77f99SPeter Lieven         error_report("Must specify image file name");
24699fd77f99SPeter Lieven         goto fail_getopt;
24709fd77f99SPeter Lieven     }
24719fd77f99SPeter Lieven 
24729fd77f99SPeter Lieven     /* ret is still -EINVAL until here */
24739fd77f99SPeter Lieven     ret = bdrv_parse_cache_mode(src_cache, &src_flags, &src_writethrough);
24749fd77f99SPeter Lieven     if (ret < 0) {
24759fd77f99SPeter Lieven         error_report("Invalid source cache option: %s", src_cache);
24762d9187bcSPeter Lieven         goto fail_getopt;
24772d9187bcSPeter Lieven     }
24782d9187bcSPeter Lieven 
247964bb01aaSKevin Wolf     /* Initialize before goto out */
24803d96cb91SMax Reitz     if (s.quiet) {
24819fd77f99SPeter Lieven         progress = false;
2482f382d43aSMiroslav Rezanina     }
248364bb01aaSKevin Wolf     qemu_progress_init(progress, 1.0);
24846b837bc4SJes Sorensen     qemu_progress_print(0, 100);
24856b837bc4SJes Sorensen 
24869fd77f99SPeter Lieven     s.src = g_new0(BlockBackend *, s.src_num);
24879fd77f99SPeter Lieven     s.src_sectors = g_new(int64_t, s.src_num);
2488af8d43d3SPeter Lieven     s.src_alignment = g_new(int, s.src_num);
2489926c2d23Sbalrog 
24909fd77f99SPeter Lieven     for (bs_i = 0; bs_i < s.src_num; bs_i++) {
2491af8d43d3SPeter Lieven         BlockDriverState *src_bs;
24929fd77f99SPeter Lieven         s.src[bs_i] = img_open(image_opts, argv[optind + bs_i],
24933d96cb91SMax Reitz                                fmt, src_flags, src_writethrough, s.quiet,
2494335e9937SFam Zheng                                force_share);
24959fd77f99SPeter Lieven         if (!s.src[bs_i]) {
2496c2abccecSMORITA Kazutaka             ret = -1;
2497c2abccecSMORITA Kazutaka             goto out;
2498c2abccecSMORITA Kazutaka         }
24999fd77f99SPeter Lieven         s.src_sectors[bs_i] = blk_nb_sectors(s.src[bs_i]);
25009fd77f99SPeter Lieven         if (s.src_sectors[bs_i] < 0) {
250152bf1e72SMarkus Armbruster             error_report("Could not get size of %s: %s",
25029fd77f99SPeter Lieven                          argv[optind + bs_i], strerror(-s.src_sectors[bs_i]));
250352bf1e72SMarkus Armbruster             ret = -1;
250452bf1e72SMarkus Armbruster             goto out;
250552bf1e72SMarkus Armbruster         }
2506af8d43d3SPeter Lieven         src_bs = blk_bs(s.src[bs_i]);
2507af8d43d3SPeter Lieven         s.src_alignment[bs_i] = DIV_ROUND_UP(src_bs->bl.request_alignment,
2508af8d43d3SPeter Lieven                                              BDRV_SECTOR_SIZE);
2509af8d43d3SPeter Lieven         if (!bdrv_get_info(src_bs, &bdi)) {
2510af8d43d3SPeter Lieven             s.src_alignment[bs_i] = MAX(s.src_alignment[bs_i],
2511af8d43d3SPeter Lieven                                         bdi.cluster_size / BDRV_SECTOR_SIZE);
2512af8d43d3SPeter Lieven         }
25139fd77f99SPeter Lieven         s.total_sectors += s.src_sectors[bs_i];
2514926c2d23Sbalrog     }
2515ea2384d3Sbellard 
2516ef80654dSWenchao Xia     if (sn_opts) {
25179fd77f99SPeter Lieven         bdrv_snapshot_load_tmp(blk_bs(s.src[0]),
2518ef80654dSWenchao Xia                                qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID),
2519ef80654dSWenchao Xia                                qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME),
2520ef80654dSWenchao Xia                                &local_err);
2521ef80654dSWenchao Xia     } else if (snapshot_name != NULL) {
25229fd77f99SPeter Lieven         if (s.src_num > 1) {
25236daf194dSMarkus Armbruster             error_report("No support for concatenating multiple snapshot");
252451ef6727Sedison             ret = -1;
252551ef6727Sedison             goto out;
252651ef6727Sedison         }
25277b4c4781SWenchao Xia 
25289fd77f99SPeter Lieven         bdrv_snapshot_load_tmp_by_id_or_name(blk_bs(s.src[0]), snapshot_name,
25299fd77f99SPeter Lieven                                              &local_err);
2530ef80654dSWenchao Xia     }
253184d18f06SMarkus Armbruster     if (local_err) {
2532c29b77f9SMarkus Armbruster         error_reportf_err(local_err, "Failed to load snapshot: ");
253351ef6727Sedison         ret = -1;
253451ef6727Sedison         goto out;
253551ef6727Sedison     }
253651ef6727Sedison 
2537305b4c60SDaniel P. Berrange     if (!skip_create) {
2538efa84d43SKevin Wolf         /* Find driver and parse its options */
2539ea2384d3Sbellard         drv = bdrv_find_format(out_fmt);
2540c2abccecSMORITA Kazutaka         if (!drv) {
254115654a6dSJes Sorensen             error_report("Unknown file format '%s'", out_fmt);
2542c2abccecSMORITA Kazutaka             ret = -1;
2543c2abccecSMORITA Kazutaka             goto out;
2544c2abccecSMORITA Kazutaka         }
2545926c2d23Sbalrog 
2546b65a5e12SMax Reitz         proto_drv = bdrv_find_protocol(out_filename, true, &local_err);
2547c2abccecSMORITA Kazutaka         if (!proto_drv) {
25482867ce4aSMarkus Armbruster             error_report_err(local_err);
2549c2abccecSMORITA Kazutaka             ret = -1;
2550c2abccecSMORITA Kazutaka             goto out;
2551c2abccecSMORITA Kazutaka         }
2552b50cbabcSMORITA Kazutaka 
2553f75613cfSMax Reitz         if (!drv->create_opts) {
2554f75613cfSMax Reitz             error_report("Format driver '%s' does not support image creation",
2555f75613cfSMax Reitz                          drv->format_name);
2556f75613cfSMax Reitz             ret = -1;
2557f75613cfSMax Reitz             goto out;
2558f75613cfSMax Reitz         }
2559f75613cfSMax Reitz 
2560f75613cfSMax Reitz         if (!proto_drv->create_opts) {
2561f75613cfSMax Reitz             error_report("Protocol driver '%s' does not support image creation",
2562f75613cfSMax Reitz                          proto_drv->format_name);
2563f75613cfSMax Reitz             ret = -1;
2564f75613cfSMax Reitz             goto out;
2565f75613cfSMax Reitz         }
2566f75613cfSMax Reitz 
2567c282e1fdSChunyan Liu         create_opts = qemu_opts_append(create_opts, drv->create_opts);
2568c282e1fdSChunyan Liu         create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
2569db08adf5SKevin Wolf 
257083d0521aSChunyan Liu         opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
2571dc523cd3SMarkus Armbruster         if (options) {
2572235e59cfSMarkus Armbruster             if (!qemu_opts_do_parse(opts, options, NULL, &local_err)) {
257397a2ca7aSMarkus Armbruster                 error_report_err(local_err);
2574c2abccecSMORITA Kazutaka                 ret = -1;
2575c2abccecSMORITA Kazutaka                 goto out;
2576efa84d43SKevin Wolf             }
2577dc523cd3SMarkus Armbruster         }
2578efa84d43SKevin Wolf 
2579c075c42fSYi Li         qemu_opt_set_number(opts, BLOCK_OPT_SIZE,
2580c075c42fSYi Li                             s.total_sectors * BDRV_SECTOR_SIZE, &error_abort);
25811899bf47SEric Blake         ret = add_old_style_options(out_fmt, opts, out_baseimg, backing_fmt);
2582c2abccecSMORITA Kazutaka         if (ret < 0) {
2583c2abccecSMORITA Kazutaka             goto out;
2584c2abccecSMORITA Kazutaka         }
25852e024cdeSMax Reitz     }
2586efa84d43SKevin Wolf 
2587a18953fbSKevin Wolf     /* Get backing file name if -o backing_file was used */
258883d0521aSChunyan Liu     out_baseimg_param = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
2589a18953fbSKevin Wolf     if (out_baseimg_param) {
259083d0521aSChunyan Liu         out_baseimg = out_baseimg_param;
2591a18953fbSKevin Wolf     }
25929fd77f99SPeter Lieven     s.target_has_backing = (bool) out_baseimg;
2593a18953fbSKevin Wolf 
2594168468feSDavid Edmondson     if (s.has_zero_init && s.target_has_backing) {
2595168468feSDavid Edmondson         error_report("Cannot use --target-is-zero when the destination "
2596168468feSDavid Edmondson                      "image has a backing file");
2597168468feSDavid Edmondson         goto out;
2598168468feSDavid Edmondson     }
2599168468feSDavid Edmondson 
260048758a84SMax Reitz     if (s.src_num > 1 && out_baseimg) {
260148758a84SMax Reitz         error_report("Having a backing file for the target makes no sense when "
260248758a84SMax Reitz                      "concatenating multiple input images");
260348758a84SMax Reitz         ret = -1;
260448758a84SMax Reitz         goto out;
260548758a84SMax Reitz     }
260648758a84SMax Reitz 
2607d9f059aaSEric Blake     if (out_baseimg_param) {
2608d9f059aaSEric Blake         if (!qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT)) {
2609497a30dbSEric Blake             error_report("Use of backing file requires explicit "
2610d9f059aaSEric Blake                          "backing format");
2611497a30dbSEric Blake             ret = -1;
2612497a30dbSEric Blake             goto out;
2613d9f059aaSEric Blake         }
2614d9f059aaSEric Blake     }
2615d9f059aaSEric Blake 
2616efa84d43SKevin Wolf     /* Check if compression is supported */
26179fd77f99SPeter Lieven     if (s.compressed) {
261883d0521aSChunyan Liu         bool encryption =
261983d0521aSChunyan Liu             qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, false);
26200cb8d47bSDaniel P. Berrange         const char *encryptfmt =
26210cb8d47bSDaniel P. Berrange             qemu_opt_get(opts, BLOCK_OPT_ENCRYPT_FORMAT);
262283d0521aSChunyan Liu         const char *preallocation =
262383d0521aSChunyan Liu             qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
2624efa84d43SKevin Wolf 
2625ac850bf0SVladimir Sementsov-Ogievskiy         if (drv && !block_driver_can_compress(drv)) {
262615654a6dSJes Sorensen             error_report("Compression not supported for this file format");
2627c2abccecSMORITA Kazutaka             ret = -1;
2628c2abccecSMORITA Kazutaka             goto out;
2629efa84d43SKevin Wolf         }
2630efa84d43SKevin Wolf 
26310cb8d47bSDaniel P. Berrange         if (encryption || encryptfmt) {
263215654a6dSJes Sorensen             error_report("Compression and encryption not supported at "
263315654a6dSJes Sorensen                          "the same time");
2634c2abccecSMORITA Kazutaka             ret = -1;
2635c2abccecSMORITA Kazutaka             goto out;
2636efa84d43SKevin Wolf         }
263741521fa4SKevin Wolf 
263883d0521aSChunyan Liu         if (preallocation
263983d0521aSChunyan Liu             && strcmp(preallocation, "off"))
264041521fa4SKevin Wolf         {
264141521fa4SKevin Wolf             error_report("Compression and preallocation not supported at "
264241521fa4SKevin Wolf                          "the same time");
264341521fa4SKevin Wolf             ret = -1;
264441521fa4SKevin Wolf             goto out;
264541521fa4SKevin Wolf         }
2646efa84d43SKevin Wolf     }
2647efa84d43SKevin Wolf 
264815e39ad9SEric Blake     /* Determine if bitmaps need copying */
264915e39ad9SEric Blake     if (bitmaps) {
265015e39ad9SEric Blake         if (s.src_num > 1) {
265115e39ad9SEric Blake             error_report("Copying bitmaps only possible with single source");
265215e39ad9SEric Blake             ret = -1;
265315e39ad9SEric Blake             goto out;
265415e39ad9SEric Blake         }
2655955171e4SEric Blake         ret = convert_check_bitmaps(blk_bs(s.src[0]), skip_broken);
265674a4320fSEric Blake         if (ret < 0) {
265715e39ad9SEric Blake             goto out;
265815e39ad9SEric Blake         }
265915e39ad9SEric Blake     }
266015e39ad9SEric Blake 
26618d65a3ccSDaniel P. Berrangé     /*
26628d65a3ccSDaniel P. Berrangé      * The later open call will need any decryption secrets, and
26638d65a3ccSDaniel P. Berrangé      * bdrv_create() will purge "opts", so extract them now before
26648d65a3ccSDaniel P. Berrangé      * they are lost.
26658d65a3ccSDaniel P. Berrangé      */
26668d65a3ccSDaniel P. Berrangé     if (!skip_create) {
26678d65a3ccSDaniel P. Berrangé         open_opts = qdict_new();
26688d65a3ccSDaniel P. Berrangé         qemu_opt_foreach(opts, img_add_key_secrets, open_opts, &error_abort);
26698d65a3ccSDaniel P. Berrangé 
2670efa84d43SKevin Wolf         /* Create the new image */
2671c282e1fdSChunyan Liu         ret = bdrv_create(drv, out_filename, opts, &local_err);
2672ea2384d3Sbellard         if (ret < 0) {
2673c29b77f9SMarkus Armbruster             error_reportf_err(local_err, "%s: error while converting %s: ",
2674c29b77f9SMarkus Armbruster                               out_filename, out_fmt);
2675c2abccecSMORITA Kazutaka             goto out;
2676ea2384d3Sbellard         }
2677b2e10493SAlexandre Derumier     }
2678ea2384d3Sbellard 
26794d7c487eSMax Reitz     s.target_is_new = !skip_create;
26804d7c487eSMax Reitz 
26819fd77f99SPeter Lieven     flags = s.min_sparse ? (BDRV_O_RDWR | BDRV_O_UNMAP) : BDRV_O_RDWR;
2682ce099547SKevin Wolf     ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
2683661a0f71SFederico Simoncelli     if (ret < 0) {
2684661a0f71SFederico Simoncelli         error_report("Invalid cache option: %s", cache);
2685bb9cd2eeSMarkus Armbruster         goto out;
2686661a0f71SFederico Simoncelli     }
2687661a0f71SFederico Simoncelli 
2688a1c62436SHanna Reitz     if (flags & BDRV_O_NOCACHE) {
2689a1c62436SHanna Reitz         /*
2690a1c62436SHanna Reitz          * If we open the target with O_DIRECT, it may be necessary to
2691a1c62436SHanna Reitz          * extend its size to align to the physical sector size.
2692a1c62436SHanna Reitz          */
2693a1c62436SHanna Reitz         flags |= BDRV_O_RESIZE;
2694a1c62436SHanna Reitz     }
2695a1c62436SHanna Reitz 
2696305b4c60SDaniel P. Berrange     if (skip_create) {
2697305b4c60SDaniel P. Berrange         s.target = img_open(tgt_image_opts, out_filename, out_fmt,
26983d96cb91SMax Reitz                             flags, writethrough, s.quiet, false);
2699305b4c60SDaniel P. Berrange     } else {
2700305b4c60SDaniel P. Berrange         /* TODO ultimately we should allow --target-image-opts
2701305b4c60SDaniel P. Berrange          * to be used even when -n is not given.
2702305b4c60SDaniel P. Berrange          * That has to wait for bdrv_create to be improved
2703305b4c60SDaniel P. Berrange          * to allow filenames in option syntax
2704eb769f74SDaniel P. Berrange          */
27058d65a3ccSDaniel P. Berrangé         s.target = img_open_file(out_filename, open_opts, out_fmt,
27063d96cb91SMax Reitz                                  flags, writethrough, s.quiet, false);
27078d65a3ccSDaniel P. Berrangé         open_opts = NULL; /* blk_new_open will have freed it */
2708305b4c60SDaniel P. Berrange     }
27099fd77f99SPeter Lieven     if (!s.target) {
2710c2abccecSMORITA Kazutaka         ret = -1;
2711c2abccecSMORITA Kazutaka         goto out;
2712c2abccecSMORITA Kazutaka     }
27139fd77f99SPeter Lieven     out_bs = blk_bs(s.target);
2714ea2384d3Sbellard 
271515e39ad9SEric Blake     if (bitmaps && !bdrv_supports_persistent_dirty_bitmap(out_bs)) {
271615e39ad9SEric Blake         error_report("Format driver '%s' does not support bitmaps",
271715e39ad9SEric Blake                      out_bs->drv->format_name);
271815e39ad9SEric Blake         ret = -1;
271915e39ad9SEric Blake         goto out;
272015e39ad9SEric Blake     }
272115e39ad9SEric Blake 
2722ac850bf0SVladimir Sementsov-Ogievskiy     if (s.compressed && !block_driver_can_compress(out_bs->drv)) {
2723305b4c60SDaniel P. Berrange         error_report("Compression not supported for this file format");
2724305b4c60SDaniel P. Berrange         ret = -1;
2725305b4c60SDaniel P. Berrange         goto out;
2726305b4c60SDaniel P. Berrange     }
2727305b4c60SDaniel P. Berrange 
27285def6b80SEric Blake     /* increase bufsectors from the default 4096 (2M) if opt_transfer
27296360ab27SPeter Lieven      * or discard_alignment of the out_bs is greater. Limit to
27306360ab27SPeter Lieven      * MAX_BUF_SECTORS as maximum which is currently 32768 (16MB). */
27316360ab27SPeter Lieven     s.buf_sectors = MIN(MAX_BUF_SECTORS,
27329fd77f99SPeter Lieven                         MAX(s.buf_sectors,
27335def6b80SEric Blake                             MAX(out_bs->bl.opt_transfer >> BDRV_SECTOR_BITS,
2734b9f7855aSEric Blake                                 out_bs->bl.pdiscard_alignment >>
2735b9f7855aSEric Blake                                 BDRV_SECTOR_BITS)));
2736f2521c90SPeter Lieven 
27378dcd3c9bSPeter Lieven     /* try to align the write requests to the destination to avoid unnecessary
27388dcd3c9bSPeter Lieven      * RMW cycles. */
27398dcd3c9bSPeter Lieven     s.alignment = MAX(pow2floor(s.min_sparse),
27408dcd3c9bSPeter Lieven                       DIV_ROUND_UP(out_bs->bl.request_alignment,
27418dcd3c9bSPeter Lieven                                    BDRV_SECTOR_SIZE));
27428dcd3c9bSPeter Lieven     assert(is_power_of_2(s.alignment));
27438dcd3c9bSPeter Lieven 
2744b2e10493SAlexandre Derumier     if (skip_create) {
27459fd77f99SPeter Lieven         int64_t output_sectors = blk_nb_sectors(s.target);
274643716fa8SMarkus Armbruster         if (output_sectors < 0) {
2747eec5eb42SGonglei             error_report("unable to get output image length: %s",
274843716fa8SMarkus Armbruster                          strerror(-output_sectors));
2749b2e10493SAlexandre Derumier             ret = -1;
2750b2e10493SAlexandre Derumier             goto out;
27519fd77f99SPeter Lieven         } else if (output_sectors < s.total_sectors) {
2752b2e10493SAlexandre Derumier             error_report("output file is smaller than input file");
2753b2e10493SAlexandre Derumier             ret = -1;
2754b2e10493SAlexandre Derumier             goto out;
2755b2e10493SAlexandre Derumier         }
2756b2e10493SAlexandre Derumier     }
2757b2e10493SAlexandre Derumier 
2758c69291e7SMax Reitz     if (s.target_has_backing && s.target_is_new) {
2759351c8effSMax Reitz         /* Errors are treated as "backing length unknown" (which means
2760351c8effSMax Reitz          * s.target_backing_sectors has to be negative, which it will
2761351c8effSMax Reitz          * be automatically).  The backing file length is used only
2762351c8effSMax Reitz          * for optimizations, so such a case is not fatal. */
2763ad74751fSKevin Wolf         bdrv_graph_rdlock_main_loop();
27644a2061e6SMax Reitz         s.target_backing_sectors =
27654a2061e6SMax Reitz             bdrv_nb_sectors(bdrv_backing_chain_next(out_bs));
2766ad74751fSKevin Wolf         bdrv_graph_rdunlock_main_loop();
2767351c8effSMax Reitz     } else {
2768351c8effSMax Reitz         s.target_backing_sectors = -1;
2769351c8effSMax Reitz     }
2770351c8effSMax Reitz 
2771c2abccecSMORITA Kazutaka     ret = bdrv_get_info(out_bs, &bdi);
2772c2abccecSMORITA Kazutaka     if (ret < 0) {
27739fd77f99SPeter Lieven         if (s.compressed) {
277415654a6dSJes Sorensen             error_report("could not get block driver info");
2775c2abccecSMORITA Kazutaka             goto out;
2776c2abccecSMORITA Kazutaka         }
277724f833cdSPeter Lieven     } else {
27789fd77f99SPeter Lieven         s.compressed = s.compressed || bdi.needs_compressed_writes;
27799fd77f99SPeter Lieven         s.cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE;
278024f833cdSPeter Lieven     }
278124f833cdSPeter Lieven 
27820c8c4895SZhengui     if (rate_limit) {
27830c8c4895SZhengui         set_rate_limit(s.target, rate_limit);
27840c8c4895SZhengui     }
27850c8c4895SZhengui 
27869fd77f99SPeter Lieven     ret = convert_do_copy(&s);
278715e39ad9SEric Blake 
278815e39ad9SEric Blake     /* Now copy the bitmaps */
278915e39ad9SEric Blake     if (bitmaps && ret == 0) {
2790955171e4SEric Blake         ret = convert_copy_bitmaps(blk_bs(s.src[0]), out_bs, skip_broken);
279115e39ad9SEric Blake     }
279215e39ad9SEric Blake 
2793c2abccecSMORITA Kazutaka out:
279413c28af8SPeter Lieven     if (!ret) {
279513c28af8SPeter Lieven         qemu_progress_print(100, 0);
279613c28af8SPeter Lieven     }
27976b837bc4SJes Sorensen     qemu_progress_end();
279883d0521aSChunyan Liu     qemu_opts_del(opts);
279983d0521aSChunyan Liu     qemu_opts_free(create_opts);
28008d65a3ccSDaniel P. Berrangé     qobject_unref(open_opts);
28019fd77f99SPeter Lieven     blk_unref(s.target);
28029fd77f99SPeter Lieven     if (s.src) {
28039fd77f99SPeter Lieven         for (bs_i = 0; bs_i < s.src_num; bs_i++) {
28049fd77f99SPeter Lieven             blk_unref(s.src[bs_i]);
280526f54e9aSMarkus Armbruster         }
28069fd77f99SPeter Lieven         g_free(s.src);
280726f54e9aSMarkus Armbruster     }
28089fd77f99SPeter Lieven     g_free(s.src_sectors);
2809af8d43d3SPeter Lieven     g_free(s.src_alignment);
281064bb01aaSKevin Wolf fail_getopt:
28116aec830eSTuguoyi     qemu_opts_del(sn_opts);
281264bb01aaSKevin Wolf     g_free(options);
281364bb01aaSKevin Wolf 
28149fd77f99SPeter Lieven     return !!ret;
2815ea2384d3Sbellard }
2816ea2384d3Sbellard 
281757d1a2b6Sbellard 
dump_snapshots(BlockDriverState * bs)2818faea38e7Sbellard static void dump_snapshots(BlockDriverState *bs)
2819faea38e7Sbellard {
2820faea38e7Sbellard     QEMUSnapshotInfo *sn_tab, *sn;
2821faea38e7Sbellard     int nb_sns, i;
2822faea38e7Sbellard 
2823faea38e7Sbellard     nb_sns = bdrv_snapshot_list(bs, &sn_tab);
2824faea38e7Sbellard     if (nb_sns <= 0)
2825faea38e7Sbellard         return;
2826faea38e7Sbellard     printf("Snapshot list:\n");
2827e1ce7d74SMarkus Armbruster     bdrv_snapshot_dump(NULL);
28285b917044SWenchao Xia     printf("\n");
2829faea38e7Sbellard     for(i = 0; i < nb_sns; i++) {
2830faea38e7Sbellard         sn = &sn_tab[i];
2831e1ce7d74SMarkus Armbruster         bdrv_snapshot_dump(sn);
28325b917044SWenchao Xia         printf("\n");
2833faea38e7Sbellard     }
28347267c094SAnthony Liguori     g_free(sn_tab);
2835faea38e7Sbellard }
2836faea38e7Sbellard 
dump_json_block_graph_info_list(BlockGraphInfoList * list)2837c04d0ab0SHanna Reitz static void dump_json_block_graph_info_list(BlockGraphInfoList *list)
28389699bf0dSStefan Hajnoczi {
2839eab3a467SMarkus Armbruster     GString *str;
28409699bf0dSStefan Hajnoczi     QObject *obj;
28417d5e199aSDaniel P. Berrange     Visitor *v = qobject_output_visitor_new(&obj);
28423b098d56SEric Blake 
2843c04d0ab0SHanna Reitz     visit_type_BlockGraphInfoList(v, NULL, &list, &error_abort);
28443b098d56SEric Blake     visit_complete(v, &obj);
28456589f459SMarkus Armbruster     str = qobject_to_json_pretty(obj, true);
28469699bf0dSStefan Hajnoczi     assert(str != NULL);
2847eab3a467SMarkus Armbruster     printf("%s\n", str->str);
2848cb3e7f08SMarc-André Lureau     qobject_unref(obj);
28493b098d56SEric Blake     visit_free(v);
2850eab3a467SMarkus Armbruster     g_string_free(str, true);
28519699bf0dSStefan Hajnoczi }
28529699bf0dSStefan Hajnoczi 
dump_json_block_graph_info(BlockGraphInfo * info)2853c04d0ab0SHanna Reitz static void dump_json_block_graph_info(BlockGraphInfo *info)
2854c054b3fdSBenoît Canet {
2855eab3a467SMarkus Armbruster     GString *str;
2856c054b3fdSBenoît Canet     QObject *obj;
28577d5e199aSDaniel P. Berrange     Visitor *v = qobject_output_visitor_new(&obj);
28583b098d56SEric Blake 
2859c04d0ab0SHanna Reitz     visit_type_BlockGraphInfo(v, NULL, &info, &error_abort);
28603b098d56SEric Blake     visit_complete(v, &obj);
28616589f459SMarkus Armbruster     str = qobject_to_json_pretty(obj, true);
2862c054b3fdSBenoît Canet     assert(str != NULL);
2863eab3a467SMarkus Armbruster     printf("%s\n", str->str);
2864cb3e7f08SMarc-André Lureau     qobject_unref(obj);
28653b098d56SEric Blake     visit_free(v);
2866eab3a467SMarkus Armbruster     g_string_free(str, true);
2867c054b3fdSBenoît Canet }
2868c054b3fdSBenoît Canet 
dump_human_image_info(BlockGraphInfo * info,int indentation,const char * path)2869c04d0ab0SHanna Reitz static void dump_human_image_info(BlockGraphInfo *info, int indentation,
2870c04d0ab0SHanna Reitz                                   const char *path)
28719699bf0dSStefan Hajnoczi {
2872c04d0ab0SHanna Reitz     BlockChildInfoList *children_list;
2873c04d0ab0SHanna Reitz 
2874d570177bSHanna Reitz     bdrv_node_info_dump(qapi_BlockGraphInfo_base(info), indentation,
2875d570177bSHanna Reitz                         info->children == NULL);
2876c04d0ab0SHanna Reitz 
2877c04d0ab0SHanna Reitz     for (children_list = info->children; children_list;
2878c04d0ab0SHanna Reitz          children_list = children_list->next)
2879c04d0ab0SHanna Reitz     {
2880c04d0ab0SHanna Reitz         BlockChildInfo *child = children_list->value;
2881c04d0ab0SHanna Reitz         g_autofree char *child_path = NULL;
2882c04d0ab0SHanna Reitz 
2883c04d0ab0SHanna Reitz         printf("%*sChild node '%s%s':\n",
2884c04d0ab0SHanna Reitz                indentation * 4, "", path, child->name);
2885c04d0ab0SHanna Reitz         child_path = g_strdup_printf("%s%s/", path, child->name);
2886c04d0ab0SHanna Reitz         dump_human_image_info(child->info, indentation + 1, child_path);
2887c04d0ab0SHanna Reitz     }
2888c04d0ab0SHanna Reitz }
2889c04d0ab0SHanna Reitz 
dump_human_image_info_list(BlockGraphInfoList * list)2890c04d0ab0SHanna Reitz static void dump_human_image_info_list(BlockGraphInfoList *list)
2891c04d0ab0SHanna Reitz {
2892c04d0ab0SHanna Reitz     BlockGraphInfoList *elem;
28939699bf0dSStefan Hajnoczi     bool delim = false;
28949699bf0dSStefan Hajnoczi 
28959699bf0dSStefan Hajnoczi     for (elem = list; elem; elem = elem->next) {
28969699bf0dSStefan Hajnoczi         if (delim) {
28979699bf0dSStefan Hajnoczi             printf("\n");
28989699bf0dSStefan Hajnoczi         }
28999699bf0dSStefan Hajnoczi         delim = true;
29009699bf0dSStefan Hajnoczi 
2901c04d0ab0SHanna Reitz         dump_human_image_info(elem->value, 0, "/");
29029699bf0dSStefan Hajnoczi     }
29039699bf0dSStefan Hajnoczi }
29049699bf0dSStefan Hajnoczi 
str_equal_func(gconstpointer a,gconstpointer b)29059699bf0dSStefan Hajnoczi static gboolean str_equal_func(gconstpointer a, gconstpointer b)
29069699bf0dSStefan Hajnoczi {
29079699bf0dSStefan Hajnoczi     return strcmp(a, b) == 0;
29089699bf0dSStefan Hajnoczi }
29099699bf0dSStefan Hajnoczi 
29109699bf0dSStefan Hajnoczi /**
2911c04d0ab0SHanna Reitz  * Open an image file chain and return an BlockGraphInfoList
29129699bf0dSStefan Hajnoczi  *
29139699bf0dSStefan Hajnoczi  * @filename: topmost image filename
29149699bf0dSStefan Hajnoczi  * @fmt: topmost image format (may be NULL to autodetect)
29159699bf0dSStefan Hajnoczi  * @chain: true  - enumerate entire backing file chain
29169699bf0dSStefan Hajnoczi  *         false - only topmost image file
29179699bf0dSStefan Hajnoczi  *
2918b1f4cd15SHanna Reitz  * Returns a list of BlockNodeInfo objects or NULL if there was an error
2919b1f4cd15SHanna Reitz  * opening an image file.  If there was an error a message will have been
2920b1f4cd15SHanna Reitz  * printed to stderr.
29219699bf0dSStefan Hajnoczi  */
collect_image_info_list(bool image_opts,const char * filename,const char * fmt,bool chain,bool force_share)2922c04d0ab0SHanna Reitz static BlockGraphInfoList *collect_image_info_list(bool image_opts,
2923eb769f74SDaniel P. Berrange                                                    const char *filename,
29249699bf0dSStefan Hajnoczi                                                    const char *fmt,
2925335e9937SFam Zheng                                                    bool chain, bool force_share)
29269699bf0dSStefan Hajnoczi {
2927c04d0ab0SHanna Reitz     BlockGraphInfoList *head = NULL;
2928c04d0ab0SHanna Reitz     BlockGraphInfoList **tail = &head;
29299699bf0dSStefan Hajnoczi     GHashTable *filenames;
293043526ec8SWenchao Xia     Error *err = NULL;
29319699bf0dSStefan Hajnoczi 
29329699bf0dSStefan Hajnoczi     filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
29339699bf0dSStefan Hajnoczi 
29349699bf0dSStefan Hajnoczi     while (filename) {
293526f54e9aSMarkus Armbruster         BlockBackend *blk;
29369699bf0dSStefan Hajnoczi         BlockDriverState *bs;
2937c04d0ab0SHanna Reitz         BlockGraphInfo *info;
29389699bf0dSStefan Hajnoczi 
29399699bf0dSStefan Hajnoczi         if (g_hash_table_lookup_extended(filenames, filename, NULL, NULL)) {
29409699bf0dSStefan Hajnoczi             error_report("Backing file '%s' creates an infinite loop.",
29419699bf0dSStefan Hajnoczi                          filename);
29429699bf0dSStefan Hajnoczi             goto err;
29439699bf0dSStefan Hajnoczi         }
29449699bf0dSStefan Hajnoczi         g_hash_table_insert(filenames, (gpointer)filename, NULL);
29459699bf0dSStefan Hajnoczi 
2946efaa7c4eSMax Reitz         blk = img_open(image_opts, filename, fmt,
2947335e9937SFam Zheng                        BDRV_O_NO_BACKING | BDRV_O_NO_IO, false, false,
2948335e9937SFam Zheng                        force_share);
29497e7d56d9SMarkus Armbruster         if (!blk) {
29509699bf0dSStefan Hajnoczi             goto err;
29519699bf0dSStefan Hajnoczi         }
29527e7d56d9SMarkus Armbruster         bs = blk_bs(blk);
29539699bf0dSStefan Hajnoczi 
2954c04d0ab0SHanna Reitz         /*
2955c04d0ab0SHanna Reitz          * Note that the returned BlockGraphInfo object will not have
2956c04d0ab0SHanna Reitz          * information about this image's backing node, because we have opened
2957c04d0ab0SHanna Reitz          * it with BDRV_O_NO_BACKING.  Printing this object will therefore not
2958c04d0ab0SHanna Reitz          * duplicate the backing chain information that we obtain by walking
2959c04d0ab0SHanna Reitz          * the chain manually here.
2960c04d0ab0SHanna Reitz          */
29613db0c8b2SKevin Wolf         bdrv_graph_rdlock_main_loop();
2962c04d0ab0SHanna Reitz         bdrv_query_block_graph_info(bs, &info, &err);
29633db0c8b2SKevin Wolf         bdrv_graph_rdunlock_main_loop();
29643db0c8b2SKevin Wolf 
296584d18f06SMarkus Armbruster         if (err) {
2966565f65d2SMarkus Armbruster             error_report_err(err);
296726f54e9aSMarkus Armbruster             blk_unref(blk);
296843526ec8SWenchao Xia             goto err;
2969fb0ed453SWenchao Xia         }
29709699bf0dSStefan Hajnoczi 
2971c3033fd3SEric Blake         QAPI_LIST_APPEND(tail, info);
29729699bf0dSStefan Hajnoczi 
297326f54e9aSMarkus Armbruster         blk_unref(blk);
29749699bf0dSStefan Hajnoczi 
29750da7d13aSStefan Hajnoczi         /* Clear parameters that only apply to the topmost image */
29769699bf0dSStefan Hajnoczi         filename = fmt = NULL;
29770da7d13aSStefan Hajnoczi         image_opts = false;
29780da7d13aSStefan Hajnoczi 
29799699bf0dSStefan Hajnoczi         if (chain) {
298054fde4ffSMarkus Armbruster             if (info->full_backing_filename) {
29819699bf0dSStefan Hajnoczi                 filename = info->full_backing_filename;
298254fde4ffSMarkus Armbruster             } else if (info->backing_filename) {
298392d617abSJohn Snow                 error_report("Could not determine absolute backing filename,"
298492d617abSJohn Snow                              " but backing filename '%s' present",
298592d617abSJohn Snow                              info->backing_filename);
298692d617abSJohn Snow                 goto err;
29879699bf0dSStefan Hajnoczi             }
298854fde4ffSMarkus Armbruster             if (info->backing_filename_format) {
29899699bf0dSStefan Hajnoczi                 fmt = info->backing_filename_format;
29909699bf0dSStefan Hajnoczi             }
29919699bf0dSStefan Hajnoczi         }
29929699bf0dSStefan Hajnoczi     }
29939699bf0dSStefan Hajnoczi     g_hash_table_destroy(filenames);
29949699bf0dSStefan Hajnoczi     return head;
29959699bf0dSStefan Hajnoczi 
29969699bf0dSStefan Hajnoczi err:
2997c04d0ab0SHanna Reitz     qapi_free_BlockGraphInfoList(head);
29989699bf0dSStefan Hajnoczi     g_hash_table_destroy(filenames);
29999699bf0dSStefan Hajnoczi     return NULL;
30009699bf0dSStefan Hajnoczi }
30019699bf0dSStefan Hajnoczi 
img_info(int argc,char ** argv)3002c054b3fdSBenoît Canet static int img_info(int argc, char **argv)
3003c054b3fdSBenoît Canet {
3004c054b3fdSBenoît Canet     int c;
3005c054b3fdSBenoît Canet     OutputFormat output_format = OFORMAT_HUMAN;
30069699bf0dSStefan Hajnoczi     bool chain = false;
3007c054b3fdSBenoît Canet     const char *filename, *fmt, *output;
3008c04d0ab0SHanna Reitz     BlockGraphInfoList *list;
3009eb769f74SDaniel P. Berrange     bool image_opts = false;
3010335e9937SFam Zheng     bool force_share = false;
3011c054b3fdSBenoît Canet 
3012ea2384d3Sbellard     fmt = NULL;
3013c054b3fdSBenoît Canet     output = NULL;
3014ea2384d3Sbellard     for(;;) {
3015c054b3fdSBenoît Canet         int option_index = 0;
3016c054b3fdSBenoît Canet         static const struct option long_options[] = {
3017c054b3fdSBenoît Canet             {"help", no_argument, 0, 'h'},
3018c054b3fdSBenoît Canet             {"format", required_argument, 0, 'f'},
3019c054b3fdSBenoît Canet             {"output", required_argument, 0, OPTION_OUTPUT},
30209699bf0dSStefan Hajnoczi             {"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN},
30213babeb15SDaniel P. Berrange             {"object", required_argument, 0, OPTION_OBJECT},
3022eb769f74SDaniel P. Berrange             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
3023335e9937SFam Zheng             {"force-share", no_argument, 0, 'U'},
3024c054b3fdSBenoît Canet             {0, 0, 0, 0}
3025c054b3fdSBenoît Canet         };
3026335e9937SFam Zheng         c = getopt_long(argc, argv, ":f:hU",
3027c054b3fdSBenoît Canet                         long_options, &option_index);
3028b8fb60daSJes Sorensen         if (c == -1) {
3029ea2384d3Sbellard             break;
3030b8fb60daSJes Sorensen         }
3031ea2384d3Sbellard         switch(c) {
3032c9192973SStefan Hajnoczi         case ':':
3033c9192973SStefan Hajnoczi             missing_argument(argv[optind - 1]);
3034c9192973SStefan Hajnoczi             break;
3035ef87394cSJes Sorensen         case '?':
3036c9192973SStefan Hajnoczi             unrecognized_option(argv[optind - 1]);
3037c9192973SStefan Hajnoczi             break;
3038ea2384d3Sbellard         case 'h':
3039ea2384d3Sbellard             help();
3040ea2384d3Sbellard             break;
3041ea2384d3Sbellard         case 'f':
3042ea2384d3Sbellard             fmt = optarg;
3043ea2384d3Sbellard             break;
3044335e9937SFam Zheng         case 'U':
3045335e9937SFam Zheng             force_share = true;
3046335e9937SFam Zheng             break;
3047c054b3fdSBenoît Canet         case OPTION_OUTPUT:
3048c054b3fdSBenoît Canet             output = optarg;
3049c054b3fdSBenoît Canet             break;
30509699bf0dSStefan Hajnoczi         case OPTION_BACKING_CHAIN:
30519699bf0dSStefan Hajnoczi             chain = true;
30529699bf0dSStefan Hajnoczi             break;
305399b1e646SKevin Wolf         case OPTION_OBJECT:
305499b1e646SKevin Wolf             user_creatable_process_cmdline(optarg);
305599b1e646SKevin Wolf             break;
3056eb769f74SDaniel P. Berrange         case OPTION_IMAGE_OPTS:
3057eb769f74SDaniel P. Berrange             image_opts = true;
3058eb769f74SDaniel P. Berrange             break;
3059ea2384d3Sbellard         }
3060ea2384d3Sbellard     }
3061fc11eb26SKevin Wolf     if (optind != argc - 1) {
3062ac1307abSFam Zheng         error_exit("Expecting one image file name");
3063b8fb60daSJes Sorensen     }
3064ea2384d3Sbellard     filename = argv[optind++];
3065ea2384d3Sbellard 
3066c054b3fdSBenoît Canet     if (output && !strcmp(output, "json")) {
3067c054b3fdSBenoît Canet         output_format = OFORMAT_JSON;
3068c054b3fdSBenoît Canet     } else if (output && !strcmp(output, "human")) {
3069c054b3fdSBenoît Canet         output_format = OFORMAT_HUMAN;
3070c054b3fdSBenoît Canet     } else if (output) {
3071c054b3fdSBenoît Canet         error_report("--output must be used with human or json as argument.");
3072c054b3fdSBenoît Canet         return 1;
3073c054b3fdSBenoît Canet     }
3074c054b3fdSBenoît Canet 
3075335e9937SFam Zheng     list = collect_image_info_list(image_opts, filename, fmt, chain,
3076335e9937SFam Zheng                                    force_share);
30779699bf0dSStefan Hajnoczi     if (!list) {
3078c2abccecSMORITA Kazutaka         return 1;
3079c2abccecSMORITA Kazutaka     }
3080c054b3fdSBenoît Canet 
3081c054b3fdSBenoît Canet     switch (output_format) {
3082c054b3fdSBenoît Canet     case OFORMAT_HUMAN:
30839699bf0dSStefan Hajnoczi         dump_human_image_info_list(list);
3084c054b3fdSBenoît Canet         break;
3085c054b3fdSBenoît Canet     case OFORMAT_JSON:
30869699bf0dSStefan Hajnoczi         if (chain) {
3087c04d0ab0SHanna Reitz             dump_json_block_graph_info_list(list);
30889699bf0dSStefan Hajnoczi         } else {
3089c04d0ab0SHanna Reitz             dump_json_block_graph_info(list->value);
30909699bf0dSStefan Hajnoczi         }
3091c054b3fdSBenoît Canet         break;
3092c054b3fdSBenoît Canet     }
3093c054b3fdSBenoît Canet 
3094c04d0ab0SHanna Reitz     qapi_free_BlockGraphInfoList(list);
3095ea2384d3Sbellard     return 0;
3096ea2384d3Sbellard }
3097ea2384d3Sbellard 
dump_map_entry(OutputFormat output_format,MapEntry * e,MapEntry * next)309830065d14SEric Blake static int dump_map_entry(OutputFormat output_format, MapEntry *e,
30994c93a13bSPaolo Bonzini                           MapEntry *next)
31004c93a13bSPaolo Bonzini {
31014c93a13bSPaolo Bonzini     switch (output_format) {
31024c93a13bSPaolo Bonzini     case OFORMAT_HUMAN:
310316b0d555SFam Zheng         if (e->data && !e->has_offset) {
31044c93a13bSPaolo Bonzini             error_report("File contains external, encrypted or compressed clusters.");
310530065d14SEric Blake             return -1;
31064c93a13bSPaolo Bonzini         }
310716b0d555SFam Zheng         if (e->data && !e->zero) {
31084c93a13bSPaolo Bonzini             printf("%#-16"PRIx64"%#-16"PRIx64"%#-16"PRIx64"%s\n",
310916b0d555SFam Zheng                    e->start, e->length,
311016b0d555SFam Zheng                    e->has_offset ? e->offset : 0,
311154fde4ffSMarkus Armbruster                    e->filename ?: "");
31124c93a13bSPaolo Bonzini         }
31134c93a13bSPaolo Bonzini         /* This format ignores the distinction between 0, ZERO and ZERO|DATA.
31144c93a13bSPaolo Bonzini          * Modify the flags here to allow more coalescing.
31154c93a13bSPaolo Bonzini          */
311616b0d555SFam Zheng         if (next && (!next->data || next->zero)) {
311716b0d555SFam Zheng             next->data = false;
311816b0d555SFam Zheng             next->zero = true;
31194c93a13bSPaolo Bonzini         }
31204c93a13bSPaolo Bonzini         break;
31214c93a13bSPaolo Bonzini     case OFORMAT_JSON:
3122e46c0b18SEyal Moscovici         printf("{ \"start\": %"PRId64", \"length\": %"PRId64","
31238417e137SEric Blake                " \"depth\": %"PRId64", \"present\": %s, \"zero\": %s,"
312452b10c9cSAndrey Drobyshev via                " \"data\": %s, \"compressed\": %s",
312552b10c9cSAndrey Drobyshev via                e->start, e->length, e->depth,
31268417e137SEric Blake                e->present ? "true" : "false",
312716b0d555SFam Zheng                e->zero ? "true" : "false",
312852b10c9cSAndrey Drobyshev via                e->data ? "true" : "false",
312952b10c9cSAndrey Drobyshev via                e->compressed ? "true" : "false");
313016b0d555SFam Zheng         if (e->has_offset) {
3131c745bfb4SPaolo Bonzini             printf(", \"offset\": %"PRId64"", e->offset);
31324c93a13bSPaolo Bonzini         }
31334c93a13bSPaolo Bonzini         putchar('}');
31344c93a13bSPaolo Bonzini 
3135e46c0b18SEyal Moscovici         if (next) {
3136e46c0b18SEyal Moscovici             puts(",");
31374c93a13bSPaolo Bonzini         }
31384c93a13bSPaolo Bonzini         break;
31394c93a13bSPaolo Bonzini     }
314030065d14SEric Blake     return 0;
31414c93a13bSPaolo Bonzini }
31424c93a13bSPaolo Bonzini 
get_block_status(BlockDriverState * bs,int64_t offset,int64_t bytes,MapEntry * e)31435e344dd8SEric Blake static int get_block_status(BlockDriverState *bs, int64_t offset,
31445e344dd8SEric Blake                             int64_t bytes, MapEntry *e)
31454c93a13bSPaolo Bonzini {
3146237d78f8SEric Blake     int ret;
31474c93a13bSPaolo Bonzini     int depth;
314867a0fd2aSFam Zheng     BlockDriverState *file;
31492875645bSJohn Snow     bool has_offset;
3150237d78f8SEric Blake     int64_t map;
3151f30c66baSMax Reitz     char *filename = NULL;
31524c93a13bSPaolo Bonzini 
3153ad74751fSKevin Wolf     GLOBAL_STATE_CODE();
3154ad74751fSKevin Wolf     GRAPH_RDLOCK_GUARD_MAINLOOP();
3155ad74751fSKevin Wolf 
31564c93a13bSPaolo Bonzini     /* As an optimization, we could cache the current range of unallocated
31574c93a13bSPaolo Bonzini      * clusters in each file of the chain, and avoid querying the same
31584c93a13bSPaolo Bonzini      * range repeatedly.
31594c93a13bSPaolo Bonzini      */
31604c93a13bSPaolo Bonzini 
31614c93a13bSPaolo Bonzini     depth = 0;
31624c93a13bSPaolo Bonzini     for (;;) {
31634a2061e6SMax Reitz         bs = bdrv_skip_filters(bs);
3164237d78f8SEric Blake         ret = bdrv_block_status(bs, offset, bytes, &bytes, &map, &file);
31654c93a13bSPaolo Bonzini         if (ret < 0) {
31664c93a13bSPaolo Bonzini             return ret;
31674c93a13bSPaolo Bonzini         }
3168237d78f8SEric Blake         assert(bytes);
31694c93a13bSPaolo Bonzini         if (ret & (BDRV_BLOCK_ZERO|BDRV_BLOCK_DATA)) {
31704c93a13bSPaolo Bonzini             break;
31714c93a13bSPaolo Bonzini         }
31724a2061e6SMax Reitz         bs = bdrv_cow_bs(bs);
31734c93a13bSPaolo Bonzini         if (bs == NULL) {
31744c93a13bSPaolo Bonzini             ret = 0;
31754c93a13bSPaolo Bonzini             break;
31764c93a13bSPaolo Bonzini         }
31774c93a13bSPaolo Bonzini 
31784c93a13bSPaolo Bonzini         depth++;
31794c93a13bSPaolo Bonzini     }
31804c93a13bSPaolo Bonzini 
31812875645bSJohn Snow     has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID);
31822875645bSJohn Snow 
3183f30c66baSMax Reitz     if (file && has_offset) {
3184f30c66baSMax Reitz         bdrv_refresh_filename(file);
3185f30c66baSMax Reitz         filename = file->filename;
3186f30c66baSMax Reitz     }
3187f30c66baSMax Reitz 
31882875645bSJohn Snow     *e = (MapEntry) {
31895e344dd8SEric Blake         .start = offset,
3190237d78f8SEric Blake         .length = bytes,
31912875645bSJohn Snow         .data = !!(ret & BDRV_BLOCK_DATA),
31922875645bSJohn Snow         .zero = !!(ret & BDRV_BLOCK_ZERO),
319352b10c9cSAndrey Drobyshev via         .compressed = !!(ret & BDRV_BLOCK_COMPRESSED),
3194237d78f8SEric Blake         .offset = map,
31952875645bSJohn Snow         .has_offset = has_offset,
31962875645bSJohn Snow         .depth = depth,
31978417e137SEric Blake         .present = !!(ret & BDRV_BLOCK_ALLOCATED),
3198f30c66baSMax Reitz         .filename = filename,
31992875645bSJohn Snow     };
32002875645bSJohn Snow 
32014c93a13bSPaolo Bonzini     return 0;
32024c93a13bSPaolo Bonzini }
32034c93a13bSPaolo Bonzini 
entry_mergeable(const MapEntry * curr,const MapEntry * next)320416b0d555SFam Zheng static inline bool entry_mergeable(const MapEntry *curr, const MapEntry *next)
320516b0d555SFam Zheng {
320616b0d555SFam Zheng     if (curr->length == 0) {
320716b0d555SFam Zheng         return false;
320816b0d555SFam Zheng     }
320916b0d555SFam Zheng     if (curr->zero != next->zero ||
321016b0d555SFam Zheng         curr->data != next->data ||
321152b10c9cSAndrey Drobyshev via         curr->compressed != next->compressed ||
321216b0d555SFam Zheng         curr->depth != next->depth ||
32138417e137SEric Blake         curr->present != next->present ||
321454fde4ffSMarkus Armbruster         !curr->filename != !next->filename ||
321516b0d555SFam Zheng         curr->has_offset != next->has_offset) {
321616b0d555SFam Zheng         return false;
321716b0d555SFam Zheng     }
321854fde4ffSMarkus Armbruster     if (curr->filename && strcmp(curr->filename, next->filename)) {
321916b0d555SFam Zheng         return false;
322016b0d555SFam Zheng     }
322116b0d555SFam Zheng     if (curr->has_offset && curr->offset + curr->length != next->offset) {
322216b0d555SFam Zheng         return false;
322316b0d555SFam Zheng     }
322416b0d555SFam Zheng     return true;
322516b0d555SFam Zheng }
322616b0d555SFam Zheng 
img_map(int argc,char ** argv)32274c93a13bSPaolo Bonzini static int img_map(int argc, char **argv)
32284c93a13bSPaolo Bonzini {
32294c93a13bSPaolo Bonzini     int c;
32304c93a13bSPaolo Bonzini     OutputFormat output_format = OFORMAT_HUMAN;
323126f54e9aSMarkus Armbruster     BlockBackend *blk;
32324c93a13bSPaolo Bonzini     BlockDriverState *bs;
32334c93a13bSPaolo Bonzini     const char *filename, *fmt, *output;
32344c93a13bSPaolo Bonzini     int64_t length;
32354c93a13bSPaolo Bonzini     MapEntry curr = { .length = 0 }, next;
32364c93a13bSPaolo Bonzini     int ret = 0;
3237eb769f74SDaniel P. Berrange     bool image_opts = false;
3238335e9937SFam Zheng     bool force_share = false;
3239c0469496SEyal Moscovici     int64_t start_offset = 0;
3240c0469496SEyal Moscovici     int64_t max_length = -1;
32414c93a13bSPaolo Bonzini 
32424c93a13bSPaolo Bonzini     fmt = NULL;
32434c93a13bSPaolo Bonzini     output = NULL;
32444c93a13bSPaolo Bonzini     for (;;) {
32454c93a13bSPaolo Bonzini         int option_index = 0;
32464c93a13bSPaolo Bonzini         static const struct option long_options[] = {
32474c93a13bSPaolo Bonzini             {"help", no_argument, 0, 'h'},
32484c93a13bSPaolo Bonzini             {"format", required_argument, 0, 'f'},
32494c93a13bSPaolo Bonzini             {"output", required_argument, 0, OPTION_OUTPUT},
32503babeb15SDaniel P. Berrange             {"object", required_argument, 0, OPTION_OBJECT},
3251eb769f74SDaniel P. Berrange             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
3252335e9937SFam Zheng             {"force-share", no_argument, 0, 'U'},
3253c0469496SEyal Moscovici             {"start-offset", required_argument, 0, 's'},
3254c0469496SEyal Moscovici             {"max-length", required_argument, 0, 'l'},
32554c93a13bSPaolo Bonzini             {0, 0, 0, 0}
32564c93a13bSPaolo Bonzini         };
3257c0469496SEyal Moscovici         c = getopt_long(argc, argv, ":f:s:l:hU",
32584c93a13bSPaolo Bonzini                         long_options, &option_index);
32594c93a13bSPaolo Bonzini         if (c == -1) {
32604c93a13bSPaolo Bonzini             break;
32614c93a13bSPaolo Bonzini         }
32624c93a13bSPaolo Bonzini         switch (c) {
3263c9192973SStefan Hajnoczi         case ':':
3264c9192973SStefan Hajnoczi             missing_argument(argv[optind - 1]);
3265c9192973SStefan Hajnoczi             break;
32664c93a13bSPaolo Bonzini         case '?':
3267c9192973SStefan Hajnoczi             unrecognized_option(argv[optind - 1]);
3268c9192973SStefan Hajnoczi             break;
32694c93a13bSPaolo Bonzini         case 'h':
32704c93a13bSPaolo Bonzini             help();
32714c93a13bSPaolo Bonzini             break;
32724c93a13bSPaolo Bonzini         case 'f':
32734c93a13bSPaolo Bonzini             fmt = optarg;
32744c93a13bSPaolo Bonzini             break;
3275335e9937SFam Zheng         case 'U':
3276335e9937SFam Zheng             force_share = true;
3277335e9937SFam Zheng             break;
32784c93a13bSPaolo Bonzini         case OPTION_OUTPUT:
32794c93a13bSPaolo Bonzini             output = optarg;
32804c93a13bSPaolo Bonzini             break;
3281c0469496SEyal Moscovici         case 's':
3282c0469496SEyal Moscovici             start_offset = cvtnum("start offset", optarg);
3283c0469496SEyal Moscovici             if (start_offset < 0) {
3284c0469496SEyal Moscovici                 return 1;
3285c0469496SEyal Moscovici             }
3286c0469496SEyal Moscovici             break;
3287c0469496SEyal Moscovici         case 'l':
3288c0469496SEyal Moscovici             max_length = cvtnum("max length", optarg);
3289c0469496SEyal Moscovici             if (max_length < 0) {
3290c0469496SEyal Moscovici                 return 1;
3291c0469496SEyal Moscovici             }
3292c0469496SEyal Moscovici             break;
329399b1e646SKevin Wolf         case OPTION_OBJECT:
329499b1e646SKevin Wolf             user_creatable_process_cmdline(optarg);
329599b1e646SKevin Wolf             break;
3296eb769f74SDaniel P. Berrange         case OPTION_IMAGE_OPTS:
3297eb769f74SDaniel P. Berrange             image_opts = true;
3298eb769f74SDaniel P. Berrange             break;
32994c93a13bSPaolo Bonzini         }
33004c93a13bSPaolo Bonzini     }
3301ac1307abSFam Zheng     if (optind != argc - 1) {
3302ac1307abSFam Zheng         error_exit("Expecting one image file name");
33034c93a13bSPaolo Bonzini     }
3304ac1307abSFam Zheng     filename = argv[optind];
33054c93a13bSPaolo Bonzini 
33064c93a13bSPaolo Bonzini     if (output && !strcmp(output, "json")) {
33074c93a13bSPaolo Bonzini         output_format = OFORMAT_JSON;
33084c93a13bSPaolo Bonzini     } else if (output && !strcmp(output, "human")) {
33094c93a13bSPaolo Bonzini         output_format = OFORMAT_HUMAN;
33104c93a13bSPaolo Bonzini     } else if (output) {
33114c93a13bSPaolo Bonzini         error_report("--output must be used with human or json as argument.");
33124c93a13bSPaolo Bonzini         return 1;
33134c93a13bSPaolo Bonzini     }
33144c93a13bSPaolo Bonzini 
3315335e9937SFam Zheng     blk = img_open(image_opts, filename, fmt, 0, false, false, force_share);
33167e7d56d9SMarkus Armbruster     if (!blk) {
33177e7d56d9SMarkus Armbruster         return 1;
33184c93a13bSPaolo Bonzini     }
33197e7d56d9SMarkus Armbruster     bs = blk_bs(blk);
33204c93a13bSPaolo Bonzini 
33214c93a13bSPaolo Bonzini     if (output_format == OFORMAT_HUMAN) {
33224c93a13bSPaolo Bonzini         printf("%-16s%-16s%-16s%s\n", "Offset", "Length", "Mapped to", "File");
3323e46c0b18SEyal Moscovici     } else if (output_format == OFORMAT_JSON) {
3324e46c0b18SEyal Moscovici         putchar('[');
33254c93a13bSPaolo Bonzini     }
33264c93a13bSPaolo Bonzini 
3327f1d3cd79SMax Reitz     length = blk_getlength(blk);
33288f282e83SEyal Moscovici     if (length < 0) {
33298f282e83SEyal Moscovici         error_report("Failed to get size for '%s'", filename);
33308f282e83SEyal Moscovici         return 1;
33318f282e83SEyal Moscovici     }
3332c0469496SEyal Moscovici     if (max_length != -1) {
3333c0469496SEyal Moscovici         length = MIN(start_offset + max_length, length);
3334c0469496SEyal Moscovici     }
33358f282e83SEyal Moscovici 
3336c0469496SEyal Moscovici     curr.start = start_offset;
33374c93a13bSPaolo Bonzini     while (curr.start + curr.length < length) {
33385e344dd8SEric Blake         int64_t offset = curr.start + curr.length;
3339d0ceea88SKevin Wolf         int64_t n = length - offset;
33404c93a13bSPaolo Bonzini 
33415e344dd8SEric Blake         ret = get_block_status(bs, offset, n, &next);
33424c93a13bSPaolo Bonzini         if (ret < 0) {
33434c93a13bSPaolo Bonzini             error_report("Could not read file metadata: %s", strerror(-ret));
33444c93a13bSPaolo Bonzini             goto out;
33454c93a13bSPaolo Bonzini         }
33464c93a13bSPaolo Bonzini 
334716b0d555SFam Zheng         if (entry_mergeable(&curr, &next)) {
33484c93a13bSPaolo Bonzini             curr.length += next.length;
33494c93a13bSPaolo Bonzini             continue;
33504c93a13bSPaolo Bonzini         }
33514c93a13bSPaolo Bonzini 
33524c93a13bSPaolo Bonzini         if (curr.length > 0) {
335330065d14SEric Blake             ret = dump_map_entry(output_format, &curr, &next);
335430065d14SEric Blake             if (ret < 0) {
335530065d14SEric Blake                 goto out;
335630065d14SEric Blake             }
33574c93a13bSPaolo Bonzini         }
33584c93a13bSPaolo Bonzini         curr = next;
33594c93a13bSPaolo Bonzini     }
33604c93a13bSPaolo Bonzini 
336130065d14SEric Blake     ret = dump_map_entry(output_format, &curr, NULL);
3362e46c0b18SEyal Moscovici     if (output_format == OFORMAT_JSON) {
3363e46c0b18SEyal Moscovici         puts("]");
3364e46c0b18SEyal Moscovici     }
33654c93a13bSPaolo Bonzini 
33664c93a13bSPaolo Bonzini out:
336726f54e9aSMarkus Armbruster     blk_unref(blk);
33684c93a13bSPaolo Bonzini     return ret < 0;
33694c93a13bSPaolo Bonzini }
33704c93a13bSPaolo Bonzini 
3371f7b4a940Saliguori #define SNAPSHOT_LIST   1
3372f7b4a940Saliguori #define SNAPSHOT_CREATE 2
3373f7b4a940Saliguori #define SNAPSHOT_APPLY  3
3374f7b4a940Saliguori #define SNAPSHOT_DELETE 4
3375f7b4a940Saliguori 
img_snapshot(int argc,char ** argv)3376153859beSStuart Brady static int img_snapshot(int argc, char **argv)
3377f7b4a940Saliguori {
337826f54e9aSMarkus Armbruster     BlockBackend *blk;
3379f7b4a940Saliguori     BlockDriverState *bs;
3380f7b4a940Saliguori     QEMUSnapshotInfo sn;
3381f7b4a940Saliguori     char *filename, *snapshot_name = NULL;
3382c2abccecSMORITA Kazutaka     int c, ret = 0, bdrv_oflags;
3383f7b4a940Saliguori     int action = 0;
3384f382d43aSMiroslav Rezanina     bool quiet = false;
3385a89d89d3SWenchao Xia     Error *err = NULL;
3386eb769f74SDaniel P. Berrange     bool image_opts = false;
3387335e9937SFam Zheng     bool force_share = false;
3388f793dde0SMarc-André Lureau     int64_t rt;
3389f7b4a940Saliguori 
3390ce099547SKevin Wolf     bdrv_oflags = BDRV_O_RDWR;
3391f7b4a940Saliguori     /* Parse commandline parameters */
3392f7b4a940Saliguori     for(;;) {
33933babeb15SDaniel P. Berrange         static const struct option long_options[] = {
33943babeb15SDaniel P. Berrange             {"help", no_argument, 0, 'h'},
33953babeb15SDaniel P. Berrange             {"object", required_argument, 0, OPTION_OBJECT},
3396eb769f74SDaniel P. Berrange             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
3397335e9937SFam Zheng             {"force-share", no_argument, 0, 'U'},
33983babeb15SDaniel P. Berrange             {0, 0, 0, 0}
33993babeb15SDaniel P. Berrange         };
3400335e9937SFam Zheng         c = getopt_long(argc, argv, ":la:c:d:hqU",
34013babeb15SDaniel P. Berrange                         long_options, NULL);
3402b8fb60daSJes Sorensen         if (c == -1) {
3403f7b4a940Saliguori             break;
3404b8fb60daSJes Sorensen         }
3405f7b4a940Saliguori         switch(c) {
3406c9192973SStefan Hajnoczi         case ':':
3407c9192973SStefan Hajnoczi             missing_argument(argv[optind - 1]);
3408c9192973SStefan Hajnoczi             break;
3409ef87394cSJes Sorensen         case '?':
3410c9192973SStefan Hajnoczi             unrecognized_option(argv[optind - 1]);
3411c9192973SStefan Hajnoczi             break;
3412f7b4a940Saliguori         case 'h':
3413f7b4a940Saliguori             help();
3414153859beSStuart Brady             return 0;
3415f7b4a940Saliguori         case 'l':
3416f7b4a940Saliguori             if (action) {
3417ac1307abSFam Zheng                 error_exit("Cannot mix '-l', '-a', '-c', '-d'");
3418153859beSStuart Brady                 return 0;
3419f7b4a940Saliguori             }
3420f7b4a940Saliguori             action = SNAPSHOT_LIST;
3421f5edb014SNaphtali Sprei             bdrv_oflags &= ~BDRV_O_RDWR; /* no need for RW */
3422f7b4a940Saliguori             break;
3423f7b4a940Saliguori         case 'a':
3424f7b4a940Saliguori             if (action) {
3425ac1307abSFam Zheng                 error_exit("Cannot mix '-l', '-a', '-c', '-d'");
3426153859beSStuart Brady                 return 0;
3427f7b4a940Saliguori             }
3428f7b4a940Saliguori             action = SNAPSHOT_APPLY;
3429f7b4a940Saliguori             snapshot_name = optarg;
3430f7b4a940Saliguori             break;
3431f7b4a940Saliguori         case 'c':
3432f7b4a940Saliguori             if (action) {
3433ac1307abSFam Zheng                 error_exit("Cannot mix '-l', '-a', '-c', '-d'");
3434153859beSStuart Brady                 return 0;
3435f7b4a940Saliguori             }
3436f7b4a940Saliguori             action = SNAPSHOT_CREATE;
3437f7b4a940Saliguori             snapshot_name = optarg;
3438f7b4a940Saliguori             break;
3439f7b4a940Saliguori         case 'd':
3440f7b4a940Saliguori             if (action) {
3441ac1307abSFam Zheng                 error_exit("Cannot mix '-l', '-a', '-c', '-d'");
3442153859beSStuart Brady                 return 0;
3443f7b4a940Saliguori             }
3444f7b4a940Saliguori             action = SNAPSHOT_DELETE;
3445f7b4a940Saliguori             snapshot_name = optarg;
3446f7b4a940Saliguori             break;
3447f382d43aSMiroslav Rezanina         case 'q':
3448f382d43aSMiroslav Rezanina             quiet = true;
3449f382d43aSMiroslav Rezanina             break;
3450335e9937SFam Zheng         case 'U':
3451335e9937SFam Zheng             force_share = true;
3452335e9937SFam Zheng             break;
345399b1e646SKevin Wolf         case OPTION_OBJECT:
345499b1e646SKevin Wolf             user_creatable_process_cmdline(optarg);
345599b1e646SKevin Wolf             break;
3456eb769f74SDaniel P. Berrange         case OPTION_IMAGE_OPTS:
3457eb769f74SDaniel P. Berrange             image_opts = true;
3458eb769f74SDaniel P. Berrange             break;
3459f7b4a940Saliguori         }
3460f7b4a940Saliguori     }
3461f7b4a940Saliguori 
3462fc11eb26SKevin Wolf     if (optind != argc - 1) {
3463ac1307abSFam Zheng         error_exit("Expecting one image file name");
3464b8fb60daSJes Sorensen     }
3465f7b4a940Saliguori     filename = argv[optind++];
3466f7b4a940Saliguori 
3467f7b4a940Saliguori     /* Open the image */
3468335e9937SFam Zheng     blk = img_open(image_opts, filename, NULL, bdrv_oflags, false, quiet,
3469335e9937SFam Zheng                    force_share);
34707e7d56d9SMarkus Armbruster     if (!blk) {
34717e7d56d9SMarkus Armbruster         return 1;
3472c2abccecSMORITA Kazutaka     }
34737e7d56d9SMarkus Armbruster     bs = blk_bs(blk);
3474f7b4a940Saliguori 
3475f7b4a940Saliguori     /* Perform the requested action */
3476f7b4a940Saliguori     switch(action) {
3477f7b4a940Saliguori     case SNAPSHOT_LIST:
3478f7b4a940Saliguori         dump_snapshots(bs);
3479f7b4a940Saliguori         break;
3480f7b4a940Saliguori 
3481f7b4a940Saliguori     case SNAPSHOT_CREATE:
3482f7b4a940Saliguori         memset(&sn, 0, sizeof(sn));
3483f7b4a940Saliguori         pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
3484f7b4a940Saliguori 
3485f793dde0SMarc-André Lureau         rt = g_get_real_time();
3486f793dde0SMarc-André Lureau         sn.date_sec = rt / G_USEC_PER_SEC;
3487f793dde0SMarc-André Lureau         sn.date_nsec = (rt % G_USEC_PER_SEC) * 1000;
3488f7b4a940Saliguori 
3489a32e7818SKevin Wolf         bdrv_graph_rdlock_main_loop();
3490f7b4a940Saliguori         ret = bdrv_snapshot_create(bs, &sn);
3491a32e7818SKevin Wolf         bdrv_graph_rdunlock_main_loop();
3492a32e7818SKevin Wolf 
3493b8fb60daSJes Sorensen         if (ret) {
3494b0a6620aSMichael Tokarev             error_report("Could not create snapshot '%s': %s",
3495b0a6620aSMichael Tokarev                 snapshot_name, strerror(-ret));
3496b8fb60daSJes Sorensen         }
3497f7b4a940Saliguori         break;
3498f7b4a940Saliguori 
3499f7b4a940Saliguori     case SNAPSHOT_APPLY:
35000b62bcbcSKevin Wolf         ret = bdrv_snapshot_goto(bs, snapshot_name, &err);
3501b8fb60daSJes Sorensen         if (ret) {
35020b62bcbcSKevin Wolf             error_reportf_err(err, "Could not apply snapshot '%s': ",
35030b62bcbcSKevin Wolf                               snapshot_name);
3504b8fb60daSJes Sorensen         }
3505f7b4a940Saliguori         break;
3506f7b4a940Saliguori 
3507f7b4a940Saliguori     case SNAPSHOT_DELETE:
3508a32e7818SKevin Wolf         bdrv_graph_rdlock_main_loop();
35098c04093cSDaniel Henrique Barboza         ret = bdrv_snapshot_find(bs, &sn, snapshot_name);
35108c04093cSDaniel Henrique Barboza         if (ret < 0) {
35118c04093cSDaniel Henrique Barboza             error_report("Could not delete snapshot '%s': snapshot not "
35128c04093cSDaniel Henrique Barboza                          "found", snapshot_name);
35138c04093cSDaniel Henrique Barboza             ret = 1;
35148c04093cSDaniel Henrique Barboza         } else {
35158c04093cSDaniel Henrique Barboza             ret = bdrv_snapshot_delete(bs, sn.id_str, sn.name, &err);
35168c04093cSDaniel Henrique Barboza             if (ret < 0) {
3517c29b77f9SMarkus Armbruster                 error_reportf_err(err, "Could not delete snapshot '%s': ",
3518c29b77f9SMarkus Armbruster                                   snapshot_name);
3519a89d89d3SWenchao Xia                 ret = 1;
3520b8fb60daSJes Sorensen             }
35218c04093cSDaniel Henrique Barboza         }
3522a32e7818SKevin Wolf         bdrv_graph_rdunlock_main_loop();
3523f7b4a940Saliguori         break;
3524f7b4a940Saliguori     }
3525f7b4a940Saliguori 
3526f7b4a940Saliguori     /* Cleanup */
352726f54e9aSMarkus Armbruster     blk_unref(blk);
3528c2abccecSMORITA Kazutaka     if (ret) {
3529c2abccecSMORITA Kazutaka         return 1;
3530c2abccecSMORITA Kazutaka     }
3531153859beSStuart Brady     return 0;
3532f7b4a940Saliguori }
3533f7b4a940Saliguori 
img_rebase(int argc,char ** argv)35343e85c6fdSKevin Wolf static int img_rebase(int argc, char **argv)
35353e85c6fdSKevin Wolf {
353626f54e9aSMarkus Armbruster     BlockBackend *blk = NULL, *blk_old_backing = NULL, *blk_new_backing = NULL;
3537396374caSPaolo Bonzini     uint8_t *buf_old = NULL;
3538396374caSPaolo Bonzini     uint8_t *buf_new = NULL;
3539863cc78fSSam Eiderman     BlockDriverState *bs = NULL, *prefix_chain_bs = NULL;
3540*78a9c76eSKevin Wolf     BlockDriverState *unfiltered_bs, *unfiltered_bs_cow;
354112df580bSAndrey Drobyshev     BlockDriverInfo bdi = {0};
35423e85c6fdSKevin Wolf     char *filename;
354340055951SMax Reitz     const char *fmt, *cache, *src_cache, *out_basefmt, *out_baseimg;
354440055951SMax Reitz     int c, flags, src_flags, ret;
354526ea2789SAndrey Drobyshev     BdrvRequestFlags write_flags = 0;
3546ce099547SKevin Wolf     bool writethrough, src_writethrough;
35473e85c6fdSKevin Wolf     int unsafe = 0;
3548335e9937SFam Zheng     bool force_share = false;
35496b837bc4SJes Sorensen     int progress = 0;
3550f382d43aSMiroslav Rezanina     bool quiet = false;
355126ea2789SAndrey Drobyshev     bool compress = false;
355234b5d2c6SMax Reitz     Error *local_err = NULL;
3553eb769f74SDaniel P. Berrange     bool image_opts = false;
355412df580bSAndrey Drobyshev     int64_t write_align;
35553e85c6fdSKevin Wolf 
35563e85c6fdSKevin Wolf     /* Parse commandline parameters */
3557e53dbee0SKevin Wolf     fmt = NULL;
3558661a0f71SFederico Simoncelli     cache = BDRV_DEFAULT_CACHE;
355940055951SMax Reitz     src_cache = BDRV_DEFAULT_CACHE;
35603e85c6fdSKevin Wolf     out_baseimg = NULL;
35613e85c6fdSKevin Wolf     out_basefmt = NULL;
35623e85c6fdSKevin Wolf     for(;;) {
35633babeb15SDaniel P. Berrange         static const struct option long_options[] = {
35643babeb15SDaniel P. Berrange             {"help", no_argument, 0, 'h'},
35653babeb15SDaniel P. Berrange             {"object", required_argument, 0, OPTION_OBJECT},
3566eb769f74SDaniel P. Berrange             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
3567335e9937SFam Zheng             {"force-share", no_argument, 0, 'U'},
356826ea2789SAndrey Drobyshev             {"compress", no_argument, 0, 'c'},
35693babeb15SDaniel P. Berrange             {0, 0, 0, 0}
35703babeb15SDaniel P. Berrange         };
357126ea2789SAndrey Drobyshev         c = getopt_long(argc, argv, ":hf:F:b:upt:T:qUc",
35723babeb15SDaniel P. Berrange                         long_options, NULL);
3573b8fb60daSJes Sorensen         if (c == -1) {
35743e85c6fdSKevin Wolf             break;
3575b8fb60daSJes Sorensen         }
35763e85c6fdSKevin Wolf         switch(c) {
3577c9192973SStefan Hajnoczi         case ':':
3578c9192973SStefan Hajnoczi             missing_argument(argv[optind - 1]);
3579c9192973SStefan Hajnoczi             break;
3580ef87394cSJes Sorensen         case '?':
3581c9192973SStefan Hajnoczi             unrecognized_option(argv[optind - 1]);
3582c9192973SStefan Hajnoczi             break;
35833e85c6fdSKevin Wolf         case 'h':
35843e85c6fdSKevin Wolf             help();
35853e85c6fdSKevin Wolf             return 0;
3586e53dbee0SKevin Wolf         case 'f':
3587e53dbee0SKevin Wolf             fmt = optarg;
3588e53dbee0SKevin Wolf             break;
35893e85c6fdSKevin Wolf         case 'F':
35903e85c6fdSKevin Wolf             out_basefmt = optarg;
35913e85c6fdSKevin Wolf             break;
35923e85c6fdSKevin Wolf         case 'b':
35933e85c6fdSKevin Wolf             out_baseimg = optarg;
35943e85c6fdSKevin Wolf             break;
35953e85c6fdSKevin Wolf         case 'u':
35963e85c6fdSKevin Wolf             unsafe = 1;
35973e85c6fdSKevin Wolf             break;
35986b837bc4SJes Sorensen         case 'p':
35996b837bc4SJes Sorensen             progress = 1;
36006b837bc4SJes Sorensen             break;
3601661a0f71SFederico Simoncelli         case 't':
3602661a0f71SFederico Simoncelli             cache = optarg;
3603661a0f71SFederico Simoncelli             break;
360440055951SMax Reitz         case 'T':
360540055951SMax Reitz             src_cache = optarg;
360640055951SMax Reitz             break;
3607f382d43aSMiroslav Rezanina         case 'q':
3608f382d43aSMiroslav Rezanina             quiet = true;
3609f382d43aSMiroslav Rezanina             break;
361099b1e646SKevin Wolf         case OPTION_OBJECT:
361199b1e646SKevin Wolf             user_creatable_process_cmdline(optarg);
361299b1e646SKevin Wolf             break;
3613eb769f74SDaniel P. Berrange         case OPTION_IMAGE_OPTS:
3614eb769f74SDaniel P. Berrange             image_opts = true;
3615eb769f74SDaniel P. Berrange             break;
3616335e9937SFam Zheng         case 'U':
3617335e9937SFam Zheng             force_share = true;
3618335e9937SFam Zheng             break;
361926ea2789SAndrey Drobyshev         case 'c':
362026ea2789SAndrey Drobyshev             compress = true;
362126ea2789SAndrey Drobyshev             break;
36223e85c6fdSKevin Wolf         }
36233e85c6fdSKevin Wolf     }
36243e85c6fdSKevin Wolf 
3625f382d43aSMiroslav Rezanina     if (quiet) {
3626f382d43aSMiroslav Rezanina         progress = 0;
3627f382d43aSMiroslav Rezanina     }
3628f382d43aSMiroslav Rezanina 
3629ac1307abSFam Zheng     if (optind != argc - 1) {
3630ac1307abSFam Zheng         error_exit("Expecting one image file name");
3631ac1307abSFam Zheng     }
3632ac1307abSFam Zheng     if (!unsafe && !out_baseimg) {
3633ac1307abSFam Zheng         error_exit("Must specify backing file (-b) or use unsafe mode (-u)");
3634b8fb60daSJes Sorensen     }
36353e85c6fdSKevin Wolf     filename = argv[optind++];
36363e85c6fdSKevin Wolf 
36376b837bc4SJes Sorensen     qemu_progress_init(progress, 2.0);
36386b837bc4SJes Sorensen     qemu_progress_print(0, 100);
36396b837bc4SJes Sorensen 
3640661a0f71SFederico Simoncelli     flags = BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
3641ce099547SKevin Wolf     ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
3642661a0f71SFederico Simoncelli     if (ret < 0) {
3643661a0f71SFederico Simoncelli         error_report("Invalid cache option: %s", cache);
364440ed35a3SStefan Hajnoczi         goto out;
3645661a0f71SFederico Simoncelli     }
3646661a0f71SFederico Simoncelli 
3647ce099547SKevin Wolf     src_flags = 0;
3648ce099547SKevin Wolf     ret = bdrv_parse_cache_mode(src_cache, &src_flags, &src_writethrough);
364940055951SMax Reitz     if (ret < 0) {
365040055951SMax Reitz         error_report("Invalid source cache option: %s", src_cache);
365140ed35a3SStefan Hajnoczi         goto out;
365240055951SMax Reitz     }
365340055951SMax Reitz 
3654ce099547SKevin Wolf     /* The source files are opened read-only, don't care about WCE */
3655ce099547SKevin Wolf     assert((src_flags & BDRV_O_RDWR) == 0);
3656ce099547SKevin Wolf     (void) src_writethrough;
3657ce099547SKevin Wolf 
36583e85c6fdSKevin Wolf     /*
36593e85c6fdSKevin Wolf      * Open the images.
36603e85c6fdSKevin Wolf      *
36613e85c6fdSKevin Wolf      * Ignore the old backing file for unsafe rebase in case we want to correct
36623e85c6fdSKevin Wolf      * the reference to a renamed or moved backing file.
36633e85c6fdSKevin Wolf      */
3664335e9937SFam Zheng     blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet,
3665335e9937SFam Zheng                    false);
36667e7d56d9SMarkus Armbruster     if (!blk) {
366740ed35a3SStefan Hajnoczi         ret = -1;
366840ed35a3SStefan Hajnoczi         goto out;
3669c2abccecSMORITA Kazutaka     }
36707e7d56d9SMarkus Armbruster     bs = blk_bs(blk);
36713e85c6fdSKevin Wolf 
3672ad74751fSKevin Wolf     bdrv_graph_rdlock_main_loop();
36734a2061e6SMax Reitz     unfiltered_bs = bdrv_skip_filters(bs);
3674*78a9c76eSKevin Wolf     unfiltered_bs_cow = bdrv_cow_bs(unfiltered_bs);
3675ad74751fSKevin Wolf     bdrv_graph_rdunlock_main_loop();
36764a2061e6SMax Reitz 
367726ea2789SAndrey Drobyshev     if (compress && !block_driver_can_compress(unfiltered_bs->drv)) {
367826ea2789SAndrey Drobyshev         error_report("Compression not supported for this file format");
367926ea2789SAndrey Drobyshev         ret = -1;
368026ea2789SAndrey Drobyshev         goto out;
368126ea2789SAndrey Drobyshev     } else if (compress) {
368226ea2789SAndrey Drobyshev         write_flags |= BDRV_REQ_WRITE_COMPRESSED;
368326ea2789SAndrey Drobyshev     }
368426ea2789SAndrey Drobyshev 
36853e85c6fdSKevin Wolf     if (out_basefmt != NULL) {
3686644483d9SMax Reitz         if (bdrv_find_format(out_basefmt) == NULL) {
368715654a6dSJes Sorensen             error_report("Invalid format name: '%s'", out_basefmt);
3688c2abccecSMORITA Kazutaka             ret = -1;
3689c2abccecSMORITA Kazutaka             goto out;
36903e85c6fdSKevin Wolf         }
36913e85c6fdSKevin Wolf     }
36923e85c6fdSKevin Wolf 
369312df580bSAndrey Drobyshev     /*
369426ea2789SAndrey Drobyshev      * We need overlay subcluster size (or cluster size in case writes are
369526ea2789SAndrey Drobyshev      * compressed) to make sure write requests are aligned.
369612df580bSAndrey Drobyshev      */
369712df580bSAndrey Drobyshev     ret = bdrv_get_info(unfiltered_bs, &bdi);
369812df580bSAndrey Drobyshev     if (ret < 0) {
369912df580bSAndrey Drobyshev         error_report("could not get block driver info");
370012df580bSAndrey Drobyshev         goto out;
370112df580bSAndrey Drobyshev     } else if (bdi.subcluster_size == 0) {
370226ea2789SAndrey Drobyshev         bdi.cluster_size = bdi.subcluster_size = 1;
370312df580bSAndrey Drobyshev     }
370412df580bSAndrey Drobyshev 
370526ea2789SAndrey Drobyshev     write_align = compress ? bdi.cluster_size : bdi.subcluster_size;
370612df580bSAndrey Drobyshev 
37073e85c6fdSKevin Wolf     /* For safe rebasing we need to compare old and new backing file */
370840ed35a3SStefan Hajnoczi     if (!unsafe) {
3709644483d9SMax Reitz         QDict *options = NULL;
3710*78a9c76eSKevin Wolf         BlockDriverState *base_bs;
3711*78a9c76eSKevin Wolf 
3712*78a9c76eSKevin Wolf         bdrv_graph_rdlock_main_loop();
3713*78a9c76eSKevin Wolf         base_bs = bdrv_cow_bs(unfiltered_bs);
3714*78a9c76eSKevin Wolf         bdrv_graph_rdunlock_main_loop();
37153e85c6fdSKevin Wolf 
37164ebe0617SSam Eiderman         if (base_bs) {
3717d861ab3aSKevin Wolf             blk_old_backing = blk_new(qemu_get_aio_context(),
3718d861ab3aSKevin Wolf                                       BLK_PERM_CONSISTENT_READ,
37194ebe0617SSam Eiderman                                       BLK_PERM_ALL);
37204ebe0617SSam Eiderman             ret = blk_insert_bs(blk_old_backing, base_bs,
37214ebe0617SSam Eiderman                                 &local_err);
37224ebe0617SSam Eiderman             if (ret < 0) {
3723c29b77f9SMarkus Armbruster                 error_reportf_err(local_err,
37244ebe0617SSam Eiderman                                   "Could not reuse old backing file '%s': ",
37254ebe0617SSam Eiderman                                   base_bs->filename);
3726c2abccecSMORITA Kazutaka                 goto out;
37273e85c6fdSKevin Wolf             }
372835ddd930SMax Reitz         } else {
372935ddd930SMax Reitz             blk_old_backing = NULL;
373035ddd930SMax Reitz         }
3731644483d9SMax Reitz 
3732a616673dSAlex Bligh         if (out_baseimg[0]) {
3733d16699b6SMax Reitz             const char *overlay_filename;
3734d16699b6SMax Reitz             char *out_real_path;
3735d16699b6SMax Reitz 
3736644483d9SMax Reitz             options = qdict_new();
3737335e9937SFam Zheng             if (out_basefmt) {
373846f5ac20SEric Blake                 qdict_put_str(options, "driver", out_basefmt);
3739335e9937SFam Zheng             }
3740335e9937SFam Zheng             if (force_share) {
3741335e9937SFam Zheng                 qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true);
3742644483d9SMax Reitz             }
3743644483d9SMax Reitz 
3744b7cfc7d5SKevin Wolf             bdrv_graph_rdlock_main_loop();
3745f30c66baSMax Reitz             bdrv_refresh_filename(bs);
3746b7cfc7d5SKevin Wolf             bdrv_graph_rdunlock_main_loop();
3747d16699b6SMax Reitz             overlay_filename = bs->exact_filename[0] ? bs->exact_filename
3748d16699b6SMax Reitz                                                      : bs->filename;
3749645ae7d8SMax Reitz             out_real_path =
3750d16699b6SMax Reitz                 bdrv_get_full_backing_filename_from_filename(overlay_filename,
3751d16699b6SMax Reitz                                                              out_baseimg,
3752d16699b6SMax Reitz                                                              &local_err);
3753d16699b6SMax Reitz             if (local_err) {
3754f22356d9SMax Reitz                 qobject_unref(options);
3755d16699b6SMax Reitz                 error_reportf_err(local_err,
3756d16699b6SMax Reitz                                   "Could not resolve backing filename: ");
3757d16699b6SMax Reitz                 ret = -1;
3758d16699b6SMax Reitz                 goto out;
3759d16699b6SMax Reitz             }
3760d16699b6SMax Reitz 
3761863cc78fSSam Eiderman             /*
3762863cc78fSSam Eiderman              * Find out whether we rebase an image on top of a previous image
3763863cc78fSSam Eiderman              * in its chain.
3764863cc78fSSam Eiderman              */
3765863cc78fSSam Eiderman             prefix_chain_bs = bdrv_find_backing_image(bs, out_real_path);
3766330c7295SSam Eiderman             if (prefix_chain_bs) {
3767f22356d9SMax Reitz                 qobject_unref(options);
3768330c7295SSam Eiderman                 g_free(out_real_path);
3769f22356d9SMax Reitz 
3770d861ab3aSKevin Wolf                 blk_new_backing = blk_new(qemu_get_aio_context(),
3771d861ab3aSKevin Wolf                                           BLK_PERM_CONSISTENT_READ,
3772330c7295SSam Eiderman                                           BLK_PERM_ALL);
3773330c7295SSam Eiderman                 ret = blk_insert_bs(blk_new_backing, prefix_chain_bs,
3774330c7295SSam Eiderman                                     &local_err);
3775330c7295SSam Eiderman                 if (ret < 0) {
3776330c7295SSam Eiderman                     error_reportf_err(local_err,
3777330c7295SSam Eiderman                                       "Could not reuse backing file '%s': ",
3778330c7295SSam Eiderman                                       out_baseimg);
3779330c7295SSam Eiderman                     goto out;
3780330c7295SSam Eiderman                 }
3781330c7295SSam Eiderman             } else {
3782d16699b6SMax Reitz                 blk_new_backing = blk_new_open(out_real_path, NULL,
3783644483d9SMax Reitz                                                options, src_flags, &local_err);
3784d16699b6SMax Reitz                 g_free(out_real_path);
3785644483d9SMax Reitz                 if (!blk_new_backing) {
3786c29b77f9SMarkus Armbruster                     error_reportf_err(local_err,
3787c29b77f9SMarkus Armbruster                                       "Could not open new backing file '%s': ",
3788c29b77f9SMarkus Armbruster                                       out_baseimg);
3789e84a0dd5SXu Tian                     ret = -1;
3790c2abccecSMORITA Kazutaka                     goto out;
37913e85c6fdSKevin Wolf                 }
37923e85c6fdSKevin Wolf             }
3793a616673dSAlex Bligh         }
3794330c7295SSam Eiderman     }
37953e85c6fdSKevin Wolf 
37963e85c6fdSKevin Wolf     /*
37973e85c6fdSKevin Wolf      * Check each unallocated cluster in the COW file. If it is unallocated,
37983e85c6fdSKevin Wolf      * accesses go to the backing file. We must therefore compare this cluster
37993e85c6fdSKevin Wolf      * in the old and new backing file, and if they differ we need to copy it
38003e85c6fdSKevin Wolf      * from the old backing file into the COW file.
38013e85c6fdSKevin Wolf      *
38023e85c6fdSKevin Wolf      * If qemu-img crashes during this step, no harm is done. The content of
38033e85c6fdSKevin Wolf      * the image is the same as the original one at any time.
38043e85c6fdSKevin Wolf      */
38053e85c6fdSKevin Wolf     if (!unsafe) {
380641536287SEric Blake         int64_t size;
380735ddd930SMax Reitz         int64_t old_backing_size = 0;
380841536287SEric Blake         int64_t new_backing_size = 0;
380941536287SEric Blake         uint64_t offset;
381012df580bSAndrey Drobyshev         int64_t n, n_old = 0, n_new = 0;
38111f710495SKevin Wolf         float local_progress = 0;
3812d6771bfaSTeLeMan 
3813ce8b8f9fSAndrey Drobyshev         if (blk_old_backing && bdrv_opt_mem_align(blk_bs(blk_old_backing)) >
3814ce8b8f9fSAndrey Drobyshev             bdrv_opt_mem_align(blk_bs(blk))) {
3815ce8b8f9fSAndrey Drobyshev             buf_old = blk_blockalign(blk_old_backing, IO_BUF_SIZE);
3816ce8b8f9fSAndrey Drobyshev         } else {
3817f1d3cd79SMax Reitz             buf_old = blk_blockalign(blk, IO_BUF_SIZE);
3818ce8b8f9fSAndrey Drobyshev         }
3819ce8b8f9fSAndrey Drobyshev         buf_new = blk_blockalign(blk_new_backing, IO_BUF_SIZE);
38203e85c6fdSKevin Wolf 
382141536287SEric Blake         size = blk_getlength(blk);
382241536287SEric Blake         if (size < 0) {
382352bf1e72SMarkus Armbruster             error_report("Could not get size of '%s': %s",
382441536287SEric Blake                          filename, strerror(-size));
382552bf1e72SMarkus Armbruster             ret = -1;
382652bf1e72SMarkus Armbruster             goto out;
382752bf1e72SMarkus Armbruster         }
382835ddd930SMax Reitz         if (blk_old_backing) {
382941536287SEric Blake             old_backing_size = blk_getlength(blk_old_backing);
383041536287SEric Blake             if (old_backing_size < 0) {
38319a29e18fSJeff Cody                 char backing_name[PATH_MAX];
383252bf1e72SMarkus Armbruster 
383335ddd930SMax Reitz                 bdrv_get_backing_filename(bs, backing_name,
383435ddd930SMax Reitz                                           sizeof(backing_name));
383552bf1e72SMarkus Armbruster                 error_report("Could not get size of '%s': %s",
383641536287SEric Blake                              backing_name, strerror(-old_backing_size));
383752bf1e72SMarkus Armbruster                 ret = -1;
383852bf1e72SMarkus Armbruster                 goto out;
383952bf1e72SMarkus Armbruster             }
384035ddd930SMax Reitz         }
3841f1d3cd79SMax Reitz         if (blk_new_backing) {
384241536287SEric Blake             new_backing_size = blk_getlength(blk_new_backing);
384341536287SEric Blake             if (new_backing_size < 0) {
384452bf1e72SMarkus Armbruster                 error_report("Could not get size of '%s': %s",
384541536287SEric Blake                              out_baseimg, strerror(-new_backing_size));
384652bf1e72SMarkus Armbruster                 ret = -1;
384752bf1e72SMarkus Armbruster                 goto out;
384852bf1e72SMarkus Armbruster             }
3849a616673dSAlex Bligh         }
38503e85c6fdSKevin Wolf 
385141536287SEric Blake         if (size != 0) {
385241536287SEric Blake             local_progress = (float)100 / (size / MIN(size, IO_BUF_SIZE));
38531f710495SKevin Wolf         }
38541f710495SKevin Wolf 
385541536287SEric Blake         for (offset = 0; offset < size; offset += n) {
385612df580bSAndrey Drobyshev             bool old_backing_eof = false;
385712df580bSAndrey Drobyshev             int64_t n_alloc;
38581c6e8779SMax Reitz 
385941536287SEric Blake             /* How many bytes can we handle with the next read? */
386041536287SEric Blake             n = MIN(IO_BUF_SIZE, size - offset);
38613e85c6fdSKevin Wolf 
38623e85c6fdSKevin Wolf             /* If the cluster is allocated, we don't need to take action */
38634a2061e6SMax Reitz             ret = bdrv_is_allocated(unfiltered_bs, offset, n, &n);
3864d663640cSPaolo Bonzini             if (ret < 0) {
3865d663640cSPaolo Bonzini                 error_report("error while reading image metadata: %s",
3866d663640cSPaolo Bonzini                              strerror(-ret));
3867d663640cSPaolo Bonzini                 goto out;
3868d663640cSPaolo Bonzini             }
3869cc60e327SKevin Wolf             if (ret) {
38703e85c6fdSKevin Wolf                 continue;
38713e85c6fdSKevin Wolf             }
38723e85c6fdSKevin Wolf 
3873863cc78fSSam Eiderman             if (prefix_chain_bs) {
38748b097fd6SAndrey Drobyshev                 uint64_t bytes = n;
38758b097fd6SAndrey Drobyshev 
3876863cc78fSSam Eiderman                 /*
3877863cc78fSSam Eiderman                  * If cluster wasn't changed since prefix_chain, we don't need
3878863cc78fSSam Eiderman                  * to take action
3879863cc78fSSam Eiderman                  */
3880*78a9c76eSKevin Wolf                 ret = bdrv_is_allocated_above(unfiltered_bs_cow,
38814a2061e6SMax Reitz                                               prefix_chain_bs, false,
38824a2061e6SMax Reitz                                               offset, n, &n);
3883863cc78fSSam Eiderman                 if (ret < 0) {
3884863cc78fSSam Eiderman                     error_report("error while reading image metadata: %s",
3885863cc78fSSam Eiderman                                  strerror(-ret));
3886863cc78fSSam Eiderman                     goto out;
3887863cc78fSSam Eiderman                 }
38888b097fd6SAndrey Drobyshev                 if (!ret && n) {
3889863cc78fSSam Eiderman                     continue;
3890863cc78fSSam Eiderman                 }
38918b097fd6SAndrey Drobyshev                 if (!n) {
38928b097fd6SAndrey Drobyshev                     /*
38938b097fd6SAndrey Drobyshev                      * If we've reached EOF of the old backing, it means that
38948b097fd6SAndrey Drobyshev                      * offsets beyond the old backing size were read as zeroes.
38958b097fd6SAndrey Drobyshev                      * Now we will need to explicitly zero the cluster in
38968b097fd6SAndrey Drobyshev                      * order to preserve that state after the rebase.
38978b097fd6SAndrey Drobyshev                      */
38988b097fd6SAndrey Drobyshev                     n = bytes;
38998b097fd6SAndrey Drobyshev                 }
3900863cc78fSSam Eiderman             }
3901863cc78fSSam Eiderman 
390287a1b3e3SKevin Wolf             /*
390312df580bSAndrey Drobyshev              * At this point we know that the region [offset; offset + n)
390412df580bSAndrey Drobyshev              * is unallocated within the target image.  This region might be
390512df580bSAndrey Drobyshev              * unaligned to the target image's (sub)cluster boundaries, as
390612df580bSAndrey Drobyshev              * old backing may have smaller clusters (or have subclusters).
390712df580bSAndrey Drobyshev              * We extend it to the aligned boundaries to avoid CoW on
390812df580bSAndrey Drobyshev              * partial writes in blk_pwrite(),
390912df580bSAndrey Drobyshev              */
391012df580bSAndrey Drobyshev             n += offset - QEMU_ALIGN_DOWN(offset, write_align);
391112df580bSAndrey Drobyshev             offset = QEMU_ALIGN_DOWN(offset, write_align);
391212df580bSAndrey Drobyshev             n += QEMU_ALIGN_UP(offset + n, write_align) - (offset + n);
391312df580bSAndrey Drobyshev             n = MIN(n, size - offset);
391412df580bSAndrey Drobyshev             assert(!bdrv_is_allocated(unfiltered_bs, offset, n, &n_alloc) &&
391512df580bSAndrey Drobyshev                    n_alloc == n);
391612df580bSAndrey Drobyshev 
391712df580bSAndrey Drobyshev             /*
391812df580bSAndrey Drobyshev              * Much like with the target image, we'll try to read as much
391912df580bSAndrey Drobyshev              * of the old and new backings as we can.
392012df580bSAndrey Drobyshev              */
392112df580bSAndrey Drobyshev             n_old = MIN(n, MAX(0, old_backing_size - (int64_t) offset));
392212df580bSAndrey Drobyshev             n_new = MIN(n, MAX(0, new_backing_size - (int64_t) offset));
392312df580bSAndrey Drobyshev 
392412df580bSAndrey Drobyshev             /*
392587a1b3e3SKevin Wolf              * Read old and new backing file and take into consideration that
392687a1b3e3SKevin Wolf              * backing files may be smaller than the COW image.
392787a1b3e3SKevin Wolf              */
392812df580bSAndrey Drobyshev             memset(buf_old + n_old, 0, n - n_old);
392912df580bSAndrey Drobyshev             if (!n_old) {
393012df580bSAndrey Drobyshev                 old_backing_eof = true;
393187a1b3e3SKevin Wolf             } else {
393212df580bSAndrey Drobyshev                 ret = blk_pread(blk_old_backing, offset, n_old, buf_old, 0);
3933c2abccecSMORITA Kazutaka                 if (ret < 0) {
393415654a6dSJes Sorensen                     error_report("error while reading from old backing file");
3935c2abccecSMORITA Kazutaka                     goto out;
39363e85c6fdSKevin Wolf                 }
393787a1b3e3SKevin Wolf             }
393887a1b3e3SKevin Wolf 
393912df580bSAndrey Drobyshev             memset(buf_new + n_new, 0, n - n_new);
394012df580bSAndrey Drobyshev             if (n_new) {
394112df580bSAndrey Drobyshev                 ret = blk_pread(blk_new_backing, offset, n_new, buf_new, 0);
3942c2abccecSMORITA Kazutaka                 if (ret < 0) {
394315654a6dSJes Sorensen                     error_report("error while reading from new backing file");
3944c2abccecSMORITA Kazutaka                     goto out;
39453e85c6fdSKevin Wolf                 }
394687a1b3e3SKevin Wolf             }
39473e85c6fdSKevin Wolf 
39483e85c6fdSKevin Wolf             /* If they differ, we need to write to the COW file */
39493e85c6fdSKevin Wolf             uint64_t written = 0;
39503e85c6fdSKevin Wolf 
395141536287SEric Blake             while (written < n) {
3952dc61cd3bSEric Blake                 int64_t pnum;
39533e85c6fdSKevin Wolf 
395441536287SEric Blake                 if (compare_buffers(buf_old + written, buf_new + written,
395512df580bSAndrey Drobyshev                                     n - written, write_align, &pnum))
39563e85c6fdSKevin Wolf                 {
395712df580bSAndrey Drobyshev                     if (old_backing_eof) {
39581c6e8779SMax Reitz                         ret = blk_pwrite_zeroes(blk, offset + written, pnum, 0);
39591c6e8779SMax Reitz                     } else {
396012df580bSAndrey Drobyshev                         assert(written + pnum <= IO_BUF_SIZE);
3961a9262f55SAlberto Faria                         ret = blk_pwrite(blk, offset + written, pnum,
396226ea2789SAndrey Drobyshev                                          buf_old + written, write_flags);
39631c6e8779SMax Reitz                     }
39643e85c6fdSKevin Wolf                     if (ret < 0) {
396515654a6dSJes Sorensen                         error_report("Error while writing to COW image: %s",
39663e85c6fdSKevin Wolf                             strerror(-ret));
3967c2abccecSMORITA Kazutaka                         goto out;
39683e85c6fdSKevin Wolf                     }
39693e85c6fdSKevin Wolf                 }
39703e85c6fdSKevin Wolf 
39713e85c6fdSKevin Wolf                 written += pnum;
397212df580bSAndrey Drobyshev                 if (offset + written >= old_backing_size) {
397312df580bSAndrey Drobyshev                     old_backing_eof = true;
397412df580bSAndrey Drobyshev                 }
39753e85c6fdSKevin Wolf             }
39766b837bc4SJes Sorensen             qemu_progress_print(local_progress, 100);
39773e85c6fdSKevin Wolf         }
39783e85c6fdSKevin Wolf     }
39793e85c6fdSKevin Wolf 
39803e85c6fdSKevin Wolf     /*
39813e85c6fdSKevin Wolf      * Change the backing file. All clusters that are different from the old
39823e85c6fdSKevin Wolf      * backing file are overwritten in the COW file now, so the visible content
39833e85c6fdSKevin Wolf      * doesn't change when we switch the backing file.
39843e85c6fdSKevin Wolf      */
3985a616673dSAlex Bligh     if (out_baseimg && *out_baseimg) {
39864a2061e6SMax Reitz         ret = bdrv_change_backing_file(unfiltered_bs, out_baseimg, out_basefmt,
39874a2061e6SMax Reitz                                        true);
3988a616673dSAlex Bligh     } else {
39894a2061e6SMax Reitz         ret = bdrv_change_backing_file(unfiltered_bs, NULL, NULL, false);
3990a616673dSAlex Bligh     }
3991a616673dSAlex Bligh 
39923e85c6fdSKevin Wolf     if (ret == -ENOSPC) {
399315654a6dSJes Sorensen         error_report("Could not change the backing file to '%s': No "
399415654a6dSJes Sorensen                      "space left in the file header", out_baseimg);
3995a7cd44beSEric Blake     } else if (ret == -EINVAL && out_baseimg && !out_basefmt) {
3996a7cd44beSEric Blake         error_report("Could not change the backing file to '%s': backing "
3997a7cd44beSEric Blake                      "format must be specified", out_baseimg);
39983e85c6fdSKevin Wolf     } else if (ret < 0) {
399915654a6dSJes Sorensen         error_report("Could not change the backing file to '%s': %s",
40003e85c6fdSKevin Wolf             out_baseimg, strerror(-ret));
40013e85c6fdSKevin Wolf     }
40023e85c6fdSKevin Wolf 
40036b837bc4SJes Sorensen     qemu_progress_print(100, 0);
40043e85c6fdSKevin Wolf     /*
40053e85c6fdSKevin Wolf      * TODO At this point it is possible to check if any clusters that are
40063e85c6fdSKevin Wolf      * allocated in the COW file are the same in the backing file. If so, they
40073e85c6fdSKevin Wolf      * could be dropped from the COW file. Don't do this before switching the
40083e85c6fdSKevin Wolf      * backing file, in case of a crash this would lead to corruption.
40093e85c6fdSKevin Wolf      */
4010c2abccecSMORITA Kazutaka out:
40116b837bc4SJes Sorensen     qemu_progress_end();
40123e85c6fdSKevin Wolf     /* Cleanup */
40133e85c6fdSKevin Wolf     if (!unsafe) {
401426f54e9aSMarkus Armbruster         blk_unref(blk_old_backing);
401526f54e9aSMarkus Armbruster         blk_unref(blk_new_backing);
4016eb863addSKevin Wolf     }
4017396374caSPaolo Bonzini     qemu_vfree(buf_old);
4018396374caSPaolo Bonzini     qemu_vfree(buf_new);
40193e85c6fdSKevin Wolf 
402026f54e9aSMarkus Armbruster     blk_unref(blk);
4021c2abccecSMORITA Kazutaka     if (ret) {
4022c2abccecSMORITA Kazutaka         return 1;
4023c2abccecSMORITA Kazutaka     }
40243e85c6fdSKevin Wolf     return 0;
40253e85c6fdSKevin Wolf }
40263e85c6fdSKevin Wolf 
img_resize(int argc,char ** argv)4027ae6b0ed6SStefan Hajnoczi static int img_resize(int argc, char **argv)
4028ae6b0ed6SStefan Hajnoczi {
40296750e795SMarkus Armbruster     Error *err = NULL;
4030ae6b0ed6SStefan Hajnoczi     int c, ret, relative;
4031ae6b0ed6SStefan Hajnoczi     const char *filename, *fmt, *size;
403209c5c6deSMax Reitz     int64_t n, total_size, current_size;
4033f382d43aSMiroslav Rezanina     bool quiet = false;
403426f54e9aSMarkus Armbruster     BlockBackend *blk = NULL;
4035dc5f690bSMax Reitz     PreallocMode prealloc = PREALLOC_MODE_OFF;
403620caf0f7SDong Xu Wang     QemuOpts *param;
40373babeb15SDaniel P. Berrange 
403820caf0f7SDong Xu Wang     static QemuOptsList resize_options = {
403920caf0f7SDong Xu Wang         .name = "resize_options",
404020caf0f7SDong Xu Wang         .head = QTAILQ_HEAD_INITIALIZER(resize_options.head),
404120caf0f7SDong Xu Wang         .desc = {
4042ae6b0ed6SStefan Hajnoczi             {
4043ae6b0ed6SStefan Hajnoczi                 .name = BLOCK_OPT_SIZE,
404420caf0f7SDong Xu Wang                 .type = QEMU_OPT_SIZE,
4045ae6b0ed6SStefan Hajnoczi                 .help = "Virtual disk size"
404620caf0f7SDong Xu Wang             }, {
404720caf0f7SDong Xu Wang                 /* end of list */
404820caf0f7SDong Xu Wang             }
4049ae6b0ed6SStefan Hajnoczi         },
4050ae6b0ed6SStefan Hajnoczi     };
4051eb769f74SDaniel P. Berrange     bool image_opts = false;
40524ffca890SPavel Butsykin     bool shrink = false;
4053ae6b0ed6SStefan Hajnoczi 
4054e80fec7fSKevin Wolf     /* Remove size from argv manually so that negative numbers are not treated
4055e80fec7fSKevin Wolf      * as options by getopt. */
4056e80fec7fSKevin Wolf     if (argc < 3) {
4057ac1307abSFam Zheng         error_exit("Not enough arguments");
4058e80fec7fSKevin Wolf         return 1;
4059e80fec7fSKevin Wolf     }
4060e80fec7fSKevin Wolf 
4061e80fec7fSKevin Wolf     size = argv[--argc];
4062e80fec7fSKevin Wolf 
4063e80fec7fSKevin Wolf     /* Parse getopt arguments */
4064ae6b0ed6SStefan Hajnoczi     fmt = NULL;
4065ae6b0ed6SStefan Hajnoczi     for(;;) {
40663babeb15SDaniel P. Berrange         static const struct option long_options[] = {
40673babeb15SDaniel P. Berrange             {"help", no_argument, 0, 'h'},
40683babeb15SDaniel P. Berrange             {"object", required_argument, 0, OPTION_OBJECT},
4069eb769f74SDaniel P. Berrange             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
4070dc5f690bSMax Reitz             {"preallocation", required_argument, 0, OPTION_PREALLOCATION},
40714ffca890SPavel Butsykin             {"shrink", no_argument, 0, OPTION_SHRINK},
40723babeb15SDaniel P. Berrange             {0, 0, 0, 0}
40733babeb15SDaniel P. Berrange         };
4074c9192973SStefan Hajnoczi         c = getopt_long(argc, argv, ":f:hq",
40753babeb15SDaniel P. Berrange                         long_options, NULL);
4076ae6b0ed6SStefan Hajnoczi         if (c == -1) {
4077ae6b0ed6SStefan Hajnoczi             break;
4078ae6b0ed6SStefan Hajnoczi         }
4079ae6b0ed6SStefan Hajnoczi         switch(c) {
4080c9192973SStefan Hajnoczi         case ':':
4081c9192973SStefan Hajnoczi             missing_argument(argv[optind - 1]);
4082c9192973SStefan Hajnoczi             break;
4083ef87394cSJes Sorensen         case '?':
4084c9192973SStefan Hajnoczi             unrecognized_option(argv[optind - 1]);
4085c9192973SStefan Hajnoczi             break;
4086ae6b0ed6SStefan Hajnoczi         case 'h':
4087ae6b0ed6SStefan Hajnoczi             help();
4088ae6b0ed6SStefan Hajnoczi             break;
4089ae6b0ed6SStefan Hajnoczi         case 'f':
4090ae6b0ed6SStefan Hajnoczi             fmt = optarg;
4091ae6b0ed6SStefan Hajnoczi             break;
4092f382d43aSMiroslav Rezanina         case 'q':
4093f382d43aSMiroslav Rezanina             quiet = true;
4094f382d43aSMiroslav Rezanina             break;
409599b1e646SKevin Wolf         case OPTION_OBJECT:
409699b1e646SKevin Wolf             user_creatable_process_cmdline(optarg);
409799b1e646SKevin Wolf             break;
4098eb769f74SDaniel P. Berrange         case OPTION_IMAGE_OPTS:
4099eb769f74SDaniel P. Berrange             image_opts = true;
4100eb769f74SDaniel P. Berrange             break;
4101dc5f690bSMax Reitz         case OPTION_PREALLOCATION:
4102f7abe0ecSMarc-André Lureau             prealloc = qapi_enum_parse(&PreallocMode_lookup, optarg,
410306c60b6cSMarkus Armbruster                                        PREALLOC_MODE__MAX, NULL);
4104dc5f690bSMax Reitz             if (prealloc == PREALLOC_MODE__MAX) {
4105dc5f690bSMax Reitz                 error_report("Invalid preallocation mode '%s'", optarg);
4106dc5f690bSMax Reitz                 return 1;
4107dc5f690bSMax Reitz             }
4108dc5f690bSMax Reitz             break;
41094ffca890SPavel Butsykin         case OPTION_SHRINK:
41104ffca890SPavel Butsykin             shrink = true;
41114ffca890SPavel Butsykin             break;
4112ae6b0ed6SStefan Hajnoczi         }
4113ae6b0ed6SStefan Hajnoczi     }
4114fc11eb26SKevin Wolf     if (optind != argc - 1) {
4115be8fbd47SMax Reitz         error_exit("Expecting image file name and size");
4116ae6b0ed6SStefan Hajnoczi     }
4117ae6b0ed6SStefan Hajnoczi     filename = argv[optind++];
4118ae6b0ed6SStefan Hajnoczi 
4119ae6b0ed6SStefan Hajnoczi     /* Choose grow, shrink, or absolute resize mode */
4120ae6b0ed6SStefan Hajnoczi     switch (size[0]) {
4121ae6b0ed6SStefan Hajnoczi     case '+':
4122ae6b0ed6SStefan Hajnoczi         relative = 1;
4123ae6b0ed6SStefan Hajnoczi         size++;
4124ae6b0ed6SStefan Hajnoczi         break;
4125ae6b0ed6SStefan Hajnoczi     case '-':
4126ae6b0ed6SStefan Hajnoczi         relative = -1;
4127ae6b0ed6SStefan Hajnoczi         size++;
4128ae6b0ed6SStefan Hajnoczi         break;
4129ae6b0ed6SStefan Hajnoczi     default:
4130ae6b0ed6SStefan Hajnoczi         relative = 0;
4131ae6b0ed6SStefan Hajnoczi         break;
4132ae6b0ed6SStefan Hajnoczi     }
4133ae6b0ed6SStefan Hajnoczi 
4134ae6b0ed6SStefan Hajnoczi     /* Parse size */
413587ea75d5SPeter Crosthwaite     param = qemu_opts_create(&resize_options, NULL, 0, &error_abort);
4136235e59cfSMarkus Armbruster     if (!qemu_opt_set(param, BLOCK_OPT_SIZE, size, &err)) {
41376750e795SMarkus Armbruster         error_report_err(err);
41382a81998aSJes Sorensen         ret = -1;
413920caf0f7SDong Xu Wang         qemu_opts_del(param);
41402a81998aSJes Sorensen         goto out;
4141ae6b0ed6SStefan Hajnoczi     }
414220caf0f7SDong Xu Wang     n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
414320caf0f7SDong Xu Wang     qemu_opts_del(param);
4144ae6b0ed6SStefan Hajnoczi 
4145efaa7c4eSMax Reitz     blk = img_open(image_opts, filename, fmt,
4146335e9937SFam Zheng                    BDRV_O_RDWR | BDRV_O_RESIZE, false, quiet,
4147335e9937SFam Zheng                    false);
41487e7d56d9SMarkus Armbruster     if (!blk) {
41492a81998aSJes Sorensen         ret = -1;
41502a81998aSJes Sorensen         goto out;
4151c2abccecSMORITA Kazutaka     }
4152ae6b0ed6SStefan Hajnoczi 
4153dc5f690bSMax Reitz     current_size = blk_getlength(blk);
4154dc5f690bSMax Reitz     if (current_size < 0) {
4155dc5f690bSMax Reitz         error_report("Failed to inquire current image length: %s",
4156dc5f690bSMax Reitz                      strerror(-current_size));
4157dc5f690bSMax Reitz         ret = -1;
4158dc5f690bSMax Reitz         goto out;
4159dc5f690bSMax Reitz     }
4160dc5f690bSMax Reitz 
4161ae6b0ed6SStefan Hajnoczi     if (relative) {
4162dc5f690bSMax Reitz         total_size = current_size + n * relative;
4163ae6b0ed6SStefan Hajnoczi     } else {
4164ae6b0ed6SStefan Hajnoczi         total_size = n;
4165ae6b0ed6SStefan Hajnoczi     }
4166ae6b0ed6SStefan Hajnoczi     if (total_size <= 0) {
416715654a6dSJes Sorensen         error_report("New image size must be positive");
4168c2abccecSMORITA Kazutaka         ret = -1;
4169c2abccecSMORITA Kazutaka         goto out;
4170ae6b0ed6SStefan Hajnoczi     }
4171ae6b0ed6SStefan Hajnoczi 
4172dc5f690bSMax Reitz     if (total_size <= current_size && prealloc != PREALLOC_MODE_OFF) {
4173dc5f690bSMax Reitz         error_report("Preallocation can only be used for growing images");
4174dc5f690bSMax Reitz         ret = -1;
4175dc5f690bSMax Reitz         goto out;
4176dc5f690bSMax Reitz     }
4177dc5f690bSMax Reitz 
41784ffca890SPavel Butsykin     if (total_size < current_size && !shrink) {
41791c404d75SKevin Wolf         error_report("Use the --shrink option to perform a shrink operation.");
41804ffca890SPavel Butsykin         warn_report("Shrinking an image will delete all data beyond the "
41814ffca890SPavel Butsykin                     "shrunken image's end. Before performing such an "
41824ffca890SPavel Butsykin                     "operation, make sure there is no important data there.");
41834ffca890SPavel Butsykin         ret = -1;
41844ffca890SPavel Butsykin         goto out;
41854ffca890SPavel Butsykin     }
41864ffca890SPavel Butsykin 
4187e8d04f92SMax Reitz     /*
4188e8d04f92SMax Reitz      * The user expects the image to have the desired size after
4189e8d04f92SMax Reitz      * resizing, so pass @exact=true.  It is of no use to report
4190e8d04f92SMax Reitz      * success when the image has not actually been resized.
4191e8d04f92SMax Reitz      */
41928c6242b6SKevin Wolf     ret = blk_truncate(blk, total_size, true, prealloc, 0, &err);
419309c5c6deSMax Reitz     if (!ret) {
41945279b303SMax Reitz         qprintf(quiet, "Image resized.\n");
419509c5c6deSMax Reitz     } else {
419609c5c6deSMax Reitz         error_report_err(err);
419709c5c6deSMax Reitz     }
4198c2abccecSMORITA Kazutaka out:
419926f54e9aSMarkus Armbruster     blk_unref(blk);
4200c2abccecSMORITA Kazutaka     if (ret) {
4201c2abccecSMORITA Kazutaka         return 1;
4202c2abccecSMORITA Kazutaka     }
4203ae6b0ed6SStefan Hajnoczi     return 0;
4204ae6b0ed6SStefan Hajnoczi }
4205ae6b0ed6SStefan Hajnoczi 
amend_status_cb(BlockDriverState * bs,int64_t offset,int64_t total_work_size,void * opaque)420676a3a34dSMax Reitz static void amend_status_cb(BlockDriverState *bs,
42078b13976dSMax Reitz                             int64_t offset, int64_t total_work_size,
42088b13976dSMax Reitz                             void *opaque)
420976a3a34dSMax Reitz {
421076a3a34dSMax Reitz     qemu_progress_print(100.f * offset / total_work_size, 0);
421176a3a34dSMax Reitz }
421276a3a34dSMax Reitz 
print_amend_option_help(const char * format)421351641351SMax Reitz static int print_amend_option_help(const char *format)
421451641351SMax Reitz {
421551641351SMax Reitz     BlockDriver *drv;
421651641351SMax Reitz 
4217bd131d67SKevin Wolf     GRAPH_RDLOCK_GUARD_MAINLOOP();
4218bd131d67SKevin Wolf 
421951641351SMax Reitz     /* Find driver and parse its options */
422051641351SMax Reitz     drv = bdrv_find_format(format);
422151641351SMax Reitz     if (!drv) {
422251641351SMax Reitz         error_report("Unknown file format '%s'", format);
422351641351SMax Reitz         return 1;
422451641351SMax Reitz     }
422551641351SMax Reitz 
422651641351SMax Reitz     if (!drv->bdrv_amend_options) {
422751641351SMax Reitz         error_report("Format driver '%s' does not support option amendment",
422851641351SMax Reitz                      format);
422951641351SMax Reitz         return 1;
423051641351SMax Reitz     }
423151641351SMax Reitz 
4232df373fb0SMaxim Levitsky     /* Every driver supporting amendment must have amend_opts */
4233df373fb0SMaxim Levitsky     assert(drv->amend_opts);
423451641351SMax Reitz 
42350b6786a9SMaxim Levitsky     printf("Amend options for '%s':\n", format);
4236df373fb0SMaxim Levitsky     qemu_opts_print_help(drv->amend_opts, false);
423751641351SMax Reitz     return 0;
423851641351SMax Reitz }
423951641351SMax Reitz 
img_amend(int argc,char ** argv)42406f176b48SMax Reitz static int img_amend(int argc, char **argv)
42416f176b48SMax Reitz {
4242dc523cd3SMarkus Armbruster     Error *err = NULL;
42436f176b48SMax Reitz     int c, ret = 0;
42446f176b48SMax Reitz     char *options = NULL;
4245df373fb0SMaxim Levitsky     QemuOptsList *amend_opts = NULL;
424683d0521aSChunyan Liu     QemuOpts *opts = NULL;
4247bd39e6edSMax Reitz     const char *fmt = NULL, *filename, *cache;
4248bd39e6edSMax Reitz     int flags;
4249ce099547SKevin Wolf     bool writethrough;
425076a3a34dSMax Reitz     bool quiet = false, progress = false;
425126f54e9aSMarkus Armbruster     BlockBackend *blk = NULL;
42526f176b48SMax Reitz     BlockDriverState *bs = NULL;
4253eb769f74SDaniel P. Berrange     bool image_opts = false;
4254a3579bfaSMaxim Levitsky     bool force = false;
42556f176b48SMax Reitz 
4256bd39e6edSMax Reitz     cache = BDRV_DEFAULT_CACHE;
42576f176b48SMax Reitz     for (;;) {
42583babeb15SDaniel P. Berrange         static const struct option long_options[] = {
42593babeb15SDaniel P. Berrange             {"help", no_argument, 0, 'h'},
42603babeb15SDaniel P. Berrange             {"object", required_argument, 0, OPTION_OBJECT},
4261eb769f74SDaniel P. Berrange             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
4262a3579bfaSMaxim Levitsky             {"force", no_argument, 0, OPTION_FORCE},
42633babeb15SDaniel P. Berrange             {0, 0, 0, 0}
42643babeb15SDaniel P. Berrange         };
4265c9192973SStefan Hajnoczi         c = getopt_long(argc, argv, ":ho:f:t:pq",
42663babeb15SDaniel P. Berrange                         long_options, NULL);
42676f176b48SMax Reitz         if (c == -1) {
42686f176b48SMax Reitz             break;
42696f176b48SMax Reitz         }
42706f176b48SMax Reitz 
42716f176b48SMax Reitz         switch (c) {
4272c9192973SStefan Hajnoczi         case ':':
4273c9192973SStefan Hajnoczi             missing_argument(argv[optind - 1]);
4274c9192973SStefan Hajnoczi             break;
42756f176b48SMax Reitz         case '?':
4276c9192973SStefan Hajnoczi             unrecognized_option(argv[optind - 1]);
4277c9192973SStefan Hajnoczi             break;
4278c9192973SStefan Hajnoczi         case 'h':
42796f176b48SMax Reitz             help();
42806f176b48SMax Reitz             break;
42816f176b48SMax Reitz         case 'o':
42826d2b5cbaSMarkus Armbruster             if (accumulate_options(&options, optarg) < 0) {
4283626f84f3SKevin Wolf                 ret = -1;
4284e814dffcSMax Reitz                 goto out_no_progress;
4285626f84f3SKevin Wolf             }
42866f176b48SMax Reitz             break;
42876f176b48SMax Reitz         case 'f':
42886f176b48SMax Reitz             fmt = optarg;
42896f176b48SMax Reitz             break;
4290bd39e6edSMax Reitz         case 't':
4291bd39e6edSMax Reitz             cache = optarg;
4292bd39e6edSMax Reitz             break;
429376a3a34dSMax Reitz         case 'p':
429476a3a34dSMax Reitz             progress = true;
429576a3a34dSMax Reitz             break;
42966f176b48SMax Reitz         case 'q':
42976f176b48SMax Reitz             quiet = true;
42986f176b48SMax Reitz             break;
42993babeb15SDaniel P. Berrange         case OPTION_OBJECT:
430099b1e646SKevin Wolf             user_creatable_process_cmdline(optarg);
43013babeb15SDaniel P. Berrange             break;
4302eb769f74SDaniel P. Berrange         case OPTION_IMAGE_OPTS:
4303eb769f74SDaniel P. Berrange             image_opts = true;
4304eb769f74SDaniel P. Berrange             break;
4305a3579bfaSMaxim Levitsky         case OPTION_FORCE:
4306a3579bfaSMaxim Levitsky             force = true;
4307a3579bfaSMaxim Levitsky             break;
43086f176b48SMax Reitz         }
43096f176b48SMax Reitz     }
43106f176b48SMax Reitz 
43116f176b48SMax Reitz     if (!options) {
4312ac1307abSFam Zheng         error_exit("Must specify options (-o)");
43136f176b48SMax Reitz     }
43146f176b48SMax Reitz 
431576a3a34dSMax Reitz     if (quiet) {
431676a3a34dSMax Reitz         progress = false;
431776a3a34dSMax Reitz     }
431876a3a34dSMax Reitz     qemu_progress_init(progress, 1.0);
431976a3a34dSMax Reitz 
4320a283cb6eSKevin Wolf     filename = (optind == argc - 1) ? argv[argc - 1] : NULL;
4321a283cb6eSKevin Wolf     if (fmt && has_help_option(options)) {
4322a283cb6eSKevin Wolf         /* If a format is explicitly specified (and possibly no filename is
4323a283cb6eSKevin Wolf          * given), print option help here */
432451641351SMax Reitz         ret = print_amend_option_help(fmt);
4325a283cb6eSKevin Wolf         goto out;
4326a283cb6eSKevin Wolf     }
4327a283cb6eSKevin Wolf 
4328a283cb6eSKevin Wolf     if (optind != argc - 1) {
4329b2f27e44SMax Reitz         error_report("Expecting one image file name");
4330b2f27e44SMax Reitz         ret = -1;
4331b2f27e44SMax Reitz         goto out;
4332a283cb6eSKevin Wolf     }
43336f176b48SMax Reitz 
4334ce099547SKevin Wolf     flags = BDRV_O_RDWR;
4335ce099547SKevin Wolf     ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
4336bd39e6edSMax Reitz     if (ret < 0) {
4337bd39e6edSMax Reitz         error_report("Invalid cache option: %s", cache);
4338bd39e6edSMax Reitz         goto out;
4339bd39e6edSMax Reitz     }
4340bd39e6edSMax Reitz 
4341335e9937SFam Zheng     blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet,
4342335e9937SFam Zheng                    false);
43437e7d56d9SMarkus Armbruster     if (!blk) {
43446f176b48SMax Reitz         ret = -1;
43456f176b48SMax Reitz         goto out;
43466f176b48SMax Reitz     }
43477e7d56d9SMarkus Armbruster     bs = blk_bs(blk);
43486f176b48SMax Reitz 
43496f176b48SMax Reitz     fmt = bs->drv->format_name;
43506f176b48SMax Reitz 
4351626f84f3SKevin Wolf     if (has_help_option(options)) {
4352a283cb6eSKevin Wolf         /* If the format was auto-detected, print option help here */
435351641351SMax Reitz         ret = print_amend_option_help(fmt);
43546f176b48SMax Reitz         goto out;
43556f176b48SMax Reitz     }
43566f176b48SMax Reitz 
4357bd131d67SKevin Wolf     bdrv_graph_rdlock_main_loop();
43581f996683SMax Reitz     if (!bs->drv->bdrv_amend_options) {
43591f996683SMax Reitz         error_report("Format driver '%s' does not support option amendment",
4360b2439d26SMax Reitz                      fmt);
4361bd131d67SKevin Wolf         bdrv_graph_rdunlock_main_loop();
4362b2439d26SMax Reitz         ret = -1;
4363b2439d26SMax Reitz         goto out;
4364b2439d26SMax Reitz     }
4365b2439d26SMax Reitz 
4366df373fb0SMaxim Levitsky     /* Every driver supporting amendment must have amend_opts */
4367df373fb0SMaxim Levitsky     assert(bs->drv->amend_opts);
43681f996683SMax Reitz 
4369df373fb0SMaxim Levitsky     amend_opts = qemu_opts_append(amend_opts, bs->drv->amend_opts);
4370df373fb0SMaxim Levitsky     opts = qemu_opts_create(amend_opts, NULL, 0, &error_abort);
4371235e59cfSMarkus Armbruster     if (!qemu_opts_do_parse(opts, options, NULL, &err)) {
43720b6786a9SMaxim Levitsky         /* Try to parse options using the create options */
43730b6786a9SMaxim Levitsky         amend_opts = qemu_opts_append(amend_opts, bs->drv->create_opts);
43740b6786a9SMaxim Levitsky         qemu_opts_del(opts);
43750b6786a9SMaxim Levitsky         opts = qemu_opts_create(amend_opts, NULL, 0, &error_abort);
43769e194e06SMarkus Armbruster         if (qemu_opts_do_parse(opts, options, NULL, NULL)) {
43770b6786a9SMaxim Levitsky             error_append_hint(&err,
43780b6786a9SMaxim Levitsky                               "This option is only supported for image creation\n");
43790b6786a9SMaxim Levitsky         }
43800b6786a9SMaxim Levitsky 
4381bd131d67SKevin Wolf         bdrv_graph_rdunlock_main_loop();
438297a2ca7aSMarkus Armbruster         error_report_err(err);
43836f176b48SMax Reitz         ret = -1;
43846f176b48SMax Reitz         goto out;
43856f176b48SMax Reitz     }
43866f176b48SMax Reitz 
438776a3a34dSMax Reitz     /* In case the driver does not call amend_status_cb() */
438876a3a34dSMax Reitz     qemu_progress_print(0.f, 0);
4389a3579bfaSMaxim Levitsky     ret = bdrv_amend_options(bs, opts, &amend_status_cb, NULL, force, &err);
439076a3a34dSMax Reitz     qemu_progress_print(100.f, 0);
4391bd131d67SKevin Wolf     bdrv_graph_rdunlock_main_loop();
4392bd131d67SKevin Wolf 
43936f176b48SMax Reitz     if (ret < 0) {
4394d1402b50SMax Reitz         error_report_err(err);
43956f176b48SMax Reitz         goto out;
43966f176b48SMax Reitz     }
43976f176b48SMax Reitz 
43986f176b48SMax Reitz out:
439976a3a34dSMax Reitz     qemu_progress_end();
440076a3a34dSMax Reitz 
4401e814dffcSMax Reitz out_no_progress:
440226f54e9aSMarkus Armbruster     blk_unref(blk);
440383d0521aSChunyan Liu     qemu_opts_del(opts);
4404df373fb0SMaxim Levitsky     qemu_opts_free(amend_opts);
4405626f84f3SKevin Wolf     g_free(options);
4406626f84f3SKevin Wolf 
44076f176b48SMax Reitz     if (ret) {
44086f176b48SMax Reitz         return 1;
44096f176b48SMax Reitz     }
44106f176b48SMax Reitz     return 0;
44116f176b48SMax Reitz }
44126f176b48SMax Reitz 
4413b6133b8cSKevin Wolf typedef struct BenchData {
4414b6133b8cSKevin Wolf     BlockBackend *blk;
4415b6133b8cSKevin Wolf     uint64_t image_size;
4416b6495fa8SKevin Wolf     bool write;
4417b6133b8cSKevin Wolf     int bufsize;
441883de9be0SKevin Wolf     int step;
4419b6133b8cSKevin Wolf     int nrreq;
4420b6133b8cSKevin Wolf     int n;
442155d539c8SKevin Wolf     int flush_interval;
442255d539c8SKevin Wolf     bool drain_on_flush;
4423b6133b8cSKevin Wolf     uint8_t *buf;
4424b6133b8cSKevin Wolf     QEMUIOVector *qiov;
4425b6133b8cSKevin Wolf 
4426b6133b8cSKevin Wolf     int in_flight;
442755d539c8SKevin Wolf     bool in_flush;
4428b6133b8cSKevin Wolf     uint64_t offset;
4429b6133b8cSKevin Wolf } BenchData;
4430b6133b8cSKevin Wolf 
bench_undrained_flush_cb(void * opaque,int ret)443155d539c8SKevin Wolf static void bench_undrained_flush_cb(void *opaque, int ret)
443255d539c8SKevin Wolf {
443355d539c8SKevin Wolf     if (ret < 0) {
4434df3c286cSMarkus Armbruster         error_report("Failed flush request: %s", strerror(-ret));
443555d539c8SKevin Wolf         exit(EXIT_FAILURE);
443655d539c8SKevin Wolf     }
443755d539c8SKevin Wolf }
443855d539c8SKevin Wolf 
bench_cb(void * opaque,int ret)4439b6133b8cSKevin Wolf static void bench_cb(void *opaque, int ret)
4440b6133b8cSKevin Wolf {
4441b6133b8cSKevin Wolf     BenchData *b = opaque;
4442b6133b8cSKevin Wolf     BlockAIOCB *acb;
4443b6133b8cSKevin Wolf 
4444b6133b8cSKevin Wolf     if (ret < 0) {
4445df3c286cSMarkus Armbruster         error_report("Failed request: %s", strerror(-ret));
4446b6133b8cSKevin Wolf         exit(EXIT_FAILURE);
4447b6133b8cSKevin Wolf     }
444855d539c8SKevin Wolf 
444955d539c8SKevin Wolf     if (b->in_flush) {
445055d539c8SKevin Wolf         /* Just finished a flush with drained queue: Start next requests */
445155d539c8SKevin Wolf         assert(b->in_flight == 0);
445255d539c8SKevin Wolf         b->in_flush = false;
445355d539c8SKevin Wolf     } else if (b->in_flight > 0) {
445455d539c8SKevin Wolf         int remaining = b->n - b->in_flight;
445555d539c8SKevin Wolf 
4456b6133b8cSKevin Wolf         b->n--;
4457b6133b8cSKevin Wolf         b->in_flight--;
445855d539c8SKevin Wolf 
445955d539c8SKevin Wolf         /* Time for flush? Drain queue if requested, then flush */
446055d539c8SKevin Wolf         if (b->flush_interval && remaining % b->flush_interval == 0) {
446155d539c8SKevin Wolf             if (!b->in_flight || !b->drain_on_flush) {
446255d539c8SKevin Wolf                 BlockCompletionFunc *cb;
446355d539c8SKevin Wolf 
446455d539c8SKevin Wolf                 if (b->drain_on_flush) {
446555d539c8SKevin Wolf                     b->in_flush = true;
446655d539c8SKevin Wolf                     cb = bench_cb;
446755d539c8SKevin Wolf                 } else {
446855d539c8SKevin Wolf                     cb = bench_undrained_flush_cb;
446955d539c8SKevin Wolf                 }
447055d539c8SKevin Wolf 
447155d539c8SKevin Wolf                 acb = blk_aio_flush(b->blk, cb, b);
447255d539c8SKevin Wolf                 if (!acb) {
447355d539c8SKevin Wolf                     error_report("Failed to issue flush request");
447455d539c8SKevin Wolf                     exit(EXIT_FAILURE);
447555d539c8SKevin Wolf                 }
447655d539c8SKevin Wolf             }
447755d539c8SKevin Wolf             if (b->drain_on_flush) {
447855d539c8SKevin Wolf                 return;
447955d539c8SKevin Wolf             }
448055d539c8SKevin Wolf         }
4481b6133b8cSKevin Wolf     }
4482b6133b8cSKevin Wolf 
4483b6133b8cSKevin Wolf     while (b->n > b->in_flight && b->in_flight < b->nrreq) {
44844baaa8c3SPaolo Bonzini         int64_t offset = b->offset;
44854baaa8c3SPaolo Bonzini         /* blk_aio_* might look for completed I/Os and kick bench_cb
44864baaa8c3SPaolo Bonzini          * again, so make sure this operation is counted by in_flight
44874baaa8c3SPaolo Bonzini          * and b->offset is ready for the next submission.
44884baaa8c3SPaolo Bonzini          */
44894baaa8c3SPaolo Bonzini         b->in_flight++;
44904baaa8c3SPaolo Bonzini         b->offset += b->step;
44914baaa8c3SPaolo Bonzini         b->offset %= b->image_size;
4492b6495fa8SKevin Wolf         if (b->write) {
44934baaa8c3SPaolo Bonzini             acb = blk_aio_pwritev(b->blk, offset, b->qiov, 0, bench_cb, b);
4494b6495fa8SKevin Wolf         } else {
44954baaa8c3SPaolo Bonzini             acb = blk_aio_preadv(b->blk, offset, b->qiov, 0, bench_cb, b);
4496b6495fa8SKevin Wolf         }
4497b6133b8cSKevin Wolf         if (!acb) {
4498b6133b8cSKevin Wolf             error_report("Failed to issue request");
4499b6133b8cSKevin Wolf             exit(EXIT_FAILURE);
4500b6133b8cSKevin Wolf         }
4501b6133b8cSKevin Wolf     }
4502b6133b8cSKevin Wolf }
4503b6133b8cSKevin Wolf 
img_bench(int argc,char ** argv)4504b6133b8cSKevin Wolf static int img_bench(int argc, char **argv)
4505b6133b8cSKevin Wolf {
4506b6133b8cSKevin Wolf     int c, ret = 0;
4507b6133b8cSKevin Wolf     const char *fmt = NULL, *filename;
4508b6133b8cSKevin Wolf     bool quiet = false;
4509b6133b8cSKevin Wolf     bool image_opts = false;
4510b6495fa8SKevin Wolf     bool is_write = false;
4511b6133b8cSKevin Wolf     int count = 75000;
4512b6133b8cSKevin Wolf     int depth = 64;
4513d3199a31SKevin Wolf     int64_t offset = 0;
4514b6133b8cSKevin Wolf     size_t bufsize = 4096;
4515b6495fa8SKevin Wolf     int pattern = 0;
451683de9be0SKevin Wolf     size_t step = 0;
451755d539c8SKevin Wolf     int flush_interval = 0;
451855d539c8SKevin Wolf     bool drain_on_flush = true;
4519b6133b8cSKevin Wolf     int64_t image_size;
4520b6133b8cSKevin Wolf     BlockBackend *blk = NULL;
4521b6133b8cSKevin Wolf     BenchData data = {};
4522b6133b8cSKevin Wolf     int flags = 0;
4523604e8613SKevin Wolf     bool writethrough = false;
4524b6133b8cSKevin Wolf     struct timeval t1, t2;
4525b6133b8cSKevin Wolf     int i;
4526335e9937SFam Zheng     bool force_share = false;
45274f384011SStefan Hajnoczi     size_t buf_size = 0;
4528b6133b8cSKevin Wolf 
4529b6133b8cSKevin Wolf     for (;;) {
4530b6133b8cSKevin Wolf         static const struct option long_options[] = {
4531b6133b8cSKevin Wolf             {"help", no_argument, 0, 'h'},
453255d539c8SKevin Wolf             {"flush-interval", required_argument, 0, OPTION_FLUSH_INTERVAL},
4533b6133b8cSKevin Wolf             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
4534b6495fa8SKevin Wolf             {"pattern", required_argument, 0, OPTION_PATTERN},
453555d539c8SKevin Wolf             {"no-drain", no_argument, 0, OPTION_NO_DRAIN},
4536335e9937SFam Zheng             {"force-share", no_argument, 0, 'U'},
4537b6133b8cSKevin Wolf             {0, 0, 0, 0}
4538b6133b8cSKevin Wolf         };
4539cdd26774SAarushi Mehta         c = getopt_long(argc, argv, ":hc:d:f:ni:o:qs:S:t:wU", long_options,
4540cdd26774SAarushi Mehta                         NULL);
4541b6133b8cSKevin Wolf         if (c == -1) {
4542b6133b8cSKevin Wolf             break;
4543b6133b8cSKevin Wolf         }
4544b6133b8cSKevin Wolf 
4545b6133b8cSKevin Wolf         switch (c) {
4546c9192973SStefan Hajnoczi         case ':':
4547c9192973SStefan Hajnoczi             missing_argument(argv[optind - 1]);
4548c9192973SStefan Hajnoczi             break;
4549b6133b8cSKevin Wolf         case '?':
4550c9192973SStefan Hajnoczi             unrecognized_option(argv[optind - 1]);
4551c9192973SStefan Hajnoczi             break;
4552c9192973SStefan Hajnoczi         case 'h':
4553b6133b8cSKevin Wolf             help();
4554b6133b8cSKevin Wolf             break;
4555b6133b8cSKevin Wolf         case 'c':
4556b6133b8cSKevin Wolf         {
45578b3c6792SPeter Maydell             unsigned long res;
45588b3c6792SPeter Maydell 
45598b3c6792SPeter Maydell             if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > INT_MAX) {
4560b6133b8cSKevin Wolf                 error_report("Invalid request count specified");
4561b6133b8cSKevin Wolf                 return 1;
4562b6133b8cSKevin Wolf             }
45638b3c6792SPeter Maydell             count = res;
4564b6133b8cSKevin Wolf             break;
4565b6133b8cSKevin Wolf         }
4566b6133b8cSKevin Wolf         case 'd':
4567b6133b8cSKevin Wolf         {
45688b3c6792SPeter Maydell             unsigned long res;
45698b3c6792SPeter Maydell 
45708b3c6792SPeter Maydell             if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > INT_MAX) {
4571b6133b8cSKevin Wolf                 error_report("Invalid queue depth specified");
4572b6133b8cSKevin Wolf                 return 1;
4573b6133b8cSKevin Wolf             }
45748b3c6792SPeter Maydell             depth = res;
4575b6133b8cSKevin Wolf             break;
4576b6133b8cSKevin Wolf         }
4577b6133b8cSKevin Wolf         case 'f':
4578b6133b8cSKevin Wolf             fmt = optarg;
4579b6133b8cSKevin Wolf             break;
4580b6133b8cSKevin Wolf         case 'n':
4581b6133b8cSKevin Wolf             flags |= BDRV_O_NATIVE_AIO;
4582b6133b8cSKevin Wolf             break;
4583cdd26774SAarushi Mehta         case 'i':
4584cdd26774SAarushi Mehta             ret = bdrv_parse_aio(optarg, &flags);
4585cdd26774SAarushi Mehta             if (ret < 0) {
4586cdd26774SAarushi Mehta                 error_report("Invalid aio option: %s", optarg);
4587cdd26774SAarushi Mehta                 ret = -1;
4588cdd26774SAarushi Mehta                 goto out;
4589cdd26774SAarushi Mehta             }
4590cdd26774SAarushi Mehta             break;
4591d3199a31SKevin Wolf         case 'o':
4592d3199a31SKevin Wolf         {
459343d589b0SEyal Moscovici             offset = cvtnum("offset", optarg);
4594606caa0aSMarkus Armbruster             if (offset < 0) {
4595d3199a31SKevin Wolf                 return 1;
4596d3199a31SKevin Wolf             }
4597d3199a31SKevin Wolf             break;
4598d3199a31SKevin Wolf         }
4599d3199a31SKevin Wolf             break;
4600b6133b8cSKevin Wolf         case 'q':
4601b6133b8cSKevin Wolf             quiet = true;
4602b6133b8cSKevin Wolf             break;
4603b6133b8cSKevin Wolf         case 's':
4604b6133b8cSKevin Wolf         {
4605b6133b8cSKevin Wolf             int64_t sval;
4606b6133b8cSKevin Wolf 
460743d589b0SEyal Moscovici             sval = cvtnum_full("buffer size", optarg, 0, INT_MAX);
460843d589b0SEyal Moscovici             if (sval < 0) {
4609b6133b8cSKevin Wolf                 return 1;
4610b6133b8cSKevin Wolf             }
4611b6133b8cSKevin Wolf 
4612b6133b8cSKevin Wolf             bufsize = sval;
4613b6133b8cSKevin Wolf             break;
4614b6133b8cSKevin Wolf         }
461583de9be0SKevin Wolf         case 'S':
461683de9be0SKevin Wolf         {
461783de9be0SKevin Wolf             int64_t sval;
461883de9be0SKevin Wolf 
461943d589b0SEyal Moscovici             sval = cvtnum_full("step_size", optarg, 0, INT_MAX);
462043d589b0SEyal Moscovici             if (sval < 0) {
462183de9be0SKevin Wolf                 return 1;
462283de9be0SKevin Wolf             }
462383de9be0SKevin Wolf 
462483de9be0SKevin Wolf             step = sval;
462583de9be0SKevin Wolf             break;
462683de9be0SKevin Wolf         }
4627b6133b8cSKevin Wolf         case 't':
4628b6133b8cSKevin Wolf             ret = bdrv_parse_cache_mode(optarg, &flags, &writethrough);
4629b6133b8cSKevin Wolf             if (ret < 0) {
4630b6133b8cSKevin Wolf                 error_report("Invalid cache mode");
4631b6133b8cSKevin Wolf                 ret = -1;
4632b6133b8cSKevin Wolf                 goto out;
4633b6133b8cSKevin Wolf             }
4634b6133b8cSKevin Wolf             break;
4635b6495fa8SKevin Wolf         case 'w':
4636b6495fa8SKevin Wolf             flags |= BDRV_O_RDWR;
4637b6495fa8SKevin Wolf             is_write = true;
4638b6495fa8SKevin Wolf             break;
4639335e9937SFam Zheng         case 'U':
4640335e9937SFam Zheng             force_share = true;
4641335e9937SFam Zheng             break;
4642b6495fa8SKevin Wolf         case OPTION_PATTERN:
4643b6495fa8SKevin Wolf         {
46448b3c6792SPeter Maydell             unsigned long res;
46458b3c6792SPeter Maydell 
46468b3c6792SPeter Maydell             if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > 0xff) {
4647b6495fa8SKevin Wolf                 error_report("Invalid pattern byte specified");
4648b6495fa8SKevin Wolf                 return 1;
4649b6495fa8SKevin Wolf             }
46508b3c6792SPeter Maydell             pattern = res;
4651b6495fa8SKevin Wolf             break;
4652b6495fa8SKevin Wolf         }
465355d539c8SKevin Wolf         case OPTION_FLUSH_INTERVAL:
465455d539c8SKevin Wolf         {
46558b3c6792SPeter Maydell             unsigned long res;
46568b3c6792SPeter Maydell 
46578b3c6792SPeter Maydell             if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > INT_MAX) {
465855d539c8SKevin Wolf                 error_report("Invalid flush interval specified");
465955d539c8SKevin Wolf                 return 1;
466055d539c8SKevin Wolf             }
46618b3c6792SPeter Maydell             flush_interval = res;
466255d539c8SKevin Wolf             break;
466355d539c8SKevin Wolf         }
466455d539c8SKevin Wolf         case OPTION_NO_DRAIN:
466555d539c8SKevin Wolf             drain_on_flush = false;
466655d539c8SKevin Wolf             break;
4667b6133b8cSKevin Wolf         case OPTION_IMAGE_OPTS:
4668b6133b8cSKevin Wolf             image_opts = true;
4669b6133b8cSKevin Wolf             break;
4670b6133b8cSKevin Wolf         }
4671b6133b8cSKevin Wolf     }
4672b6133b8cSKevin Wolf 
4673b6133b8cSKevin Wolf     if (optind != argc - 1) {
4674b6133b8cSKevin Wolf         error_exit("Expecting one image file name");
4675b6133b8cSKevin Wolf     }
4676b6133b8cSKevin Wolf     filename = argv[argc - 1];
4677b6133b8cSKevin Wolf 
467855d539c8SKevin Wolf     if (!is_write && flush_interval) {
467955d539c8SKevin Wolf         error_report("--flush-interval is only available in write tests");
468055d539c8SKevin Wolf         ret = -1;
468155d539c8SKevin Wolf         goto out;
468255d539c8SKevin Wolf     }
468355d539c8SKevin Wolf     if (flush_interval && flush_interval < depth) {
468455d539c8SKevin Wolf         error_report("Flush interval can't be smaller than depth");
468555d539c8SKevin Wolf         ret = -1;
468655d539c8SKevin Wolf         goto out;
468755d539c8SKevin Wolf     }
468855d539c8SKevin Wolf 
4689335e9937SFam Zheng     blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet,
4690335e9937SFam Zheng                    force_share);
4691b6133b8cSKevin Wolf     if (!blk) {
4692b6133b8cSKevin Wolf         ret = -1;
4693b6133b8cSKevin Wolf         goto out;
4694b6133b8cSKevin Wolf     }
4695b6133b8cSKevin Wolf 
4696b6133b8cSKevin Wolf     image_size = blk_getlength(blk);
4697b6133b8cSKevin Wolf     if (image_size < 0) {
4698b6133b8cSKevin Wolf         ret = image_size;
4699b6133b8cSKevin Wolf         goto out;
4700b6133b8cSKevin Wolf     }
4701b6133b8cSKevin Wolf 
4702b6133b8cSKevin Wolf     data = (BenchData) {
4703b6133b8cSKevin Wolf         .blk            = blk,
4704b6133b8cSKevin Wolf         .image_size     = image_size,
4705b6133b8cSKevin Wolf         .bufsize        = bufsize,
470683de9be0SKevin Wolf         .step           = step ?: bufsize,
4707b6133b8cSKevin Wolf         .nrreq          = depth,
4708b6133b8cSKevin Wolf         .n              = count,
4709d3199a31SKevin Wolf         .offset         = offset,
4710b6495fa8SKevin Wolf         .write          = is_write,
471155d539c8SKevin Wolf         .flush_interval = flush_interval,
471255d539c8SKevin Wolf         .drain_on_flush = drain_on_flush,
4713b6133b8cSKevin Wolf     };
4714d3199a31SKevin Wolf     printf("Sending %d %s requests, %d bytes each, %d in parallel "
471583de9be0SKevin Wolf            "(starting at offset %" PRId64 ", step size %d)\n",
4716d3199a31SKevin Wolf            data.n, data.write ? "write" : "read", data.bufsize, data.nrreq,
471783de9be0SKevin Wolf            data.offset, data.step);
471855d539c8SKevin Wolf     if (flush_interval) {
471955d539c8SKevin Wolf         printf("Sending flush every %d requests\n", flush_interval);
472055d539c8SKevin Wolf     }
4721b6133b8cSKevin Wolf 
472279d46583SFam Zheng     buf_size = data.nrreq * data.bufsize;
472379d46583SFam Zheng     data.buf = blk_blockalign(blk, buf_size);
4724b6495fa8SKevin Wolf     memset(data.buf, pattern, data.nrreq * data.bufsize);
4725b6495fa8SKevin Wolf 
4726f4ec04baSStefan Hajnoczi     blk_register_buf(blk, data.buf, buf_size, &error_fatal);
472779d46583SFam Zheng 
4728b6133b8cSKevin Wolf     data.qiov = g_new(QEMUIOVector, data.nrreq);
4729b6133b8cSKevin Wolf     for (i = 0; i < data.nrreq; i++) {
4730b6133b8cSKevin Wolf         qemu_iovec_init(&data.qiov[i], 1);
4731b6133b8cSKevin Wolf         qemu_iovec_add(&data.qiov[i],
4732b6133b8cSKevin Wolf                        data.buf + i * data.bufsize, data.bufsize);
4733b6133b8cSKevin Wolf     }
4734b6133b8cSKevin Wolf 
4735b6133b8cSKevin Wolf     gettimeofday(&t1, NULL);
4736b6133b8cSKevin Wolf     bench_cb(&data, 0);
4737b6133b8cSKevin Wolf 
4738b6133b8cSKevin Wolf     while (data.n > 0) {
4739b6133b8cSKevin Wolf         main_loop_wait(false);
4740b6133b8cSKevin Wolf     }
4741b6133b8cSKevin Wolf     gettimeofday(&t2, NULL);
4742b6133b8cSKevin Wolf 
4743b6133b8cSKevin Wolf     printf("Run completed in %3.3f seconds.\n",
4744b6133b8cSKevin Wolf            (t2.tv_sec - t1.tv_sec)
4745b6133b8cSKevin Wolf            + ((double)(t2.tv_usec - t1.tv_usec) / 1000000));
4746b6133b8cSKevin Wolf 
4747b6133b8cSKevin Wolf out:
474879d46583SFam Zheng     if (data.buf) {
47494f384011SStefan Hajnoczi         blk_unregister_buf(blk, data.buf, buf_size);
475079d46583SFam Zheng     }
4751b6133b8cSKevin Wolf     qemu_vfree(data.buf);
4752b6133b8cSKevin Wolf     blk_unref(blk);
4753b6133b8cSKevin Wolf 
4754b6133b8cSKevin Wolf     if (ret) {
4755b6133b8cSKevin Wolf         return 1;
4756b6133b8cSKevin Wolf     }
4757b6133b8cSKevin Wolf     return 0;
4758b6133b8cSKevin Wolf }
4759b6133b8cSKevin Wolf 
47603b51ab4bSEric Blake enum ImgBitmapAct {
47613b51ab4bSEric Blake     BITMAP_ADD,
47623b51ab4bSEric Blake     BITMAP_REMOVE,
47633b51ab4bSEric Blake     BITMAP_CLEAR,
47643b51ab4bSEric Blake     BITMAP_ENABLE,
47653b51ab4bSEric Blake     BITMAP_DISABLE,
47663b51ab4bSEric Blake     BITMAP_MERGE,
47673b51ab4bSEric Blake };
47683b51ab4bSEric Blake typedef struct ImgBitmapAction {
47693b51ab4bSEric Blake     enum ImgBitmapAct act;
47703b51ab4bSEric Blake     const char *src; /* only used for merge */
47713b51ab4bSEric Blake     QSIMPLEQ_ENTRY(ImgBitmapAction) next;
47723b51ab4bSEric Blake } ImgBitmapAction;
47733b51ab4bSEric Blake 
img_bitmap(int argc,char ** argv)47743b51ab4bSEric Blake static int img_bitmap(int argc, char **argv)
47753b51ab4bSEric Blake {
47763b51ab4bSEric Blake     Error *err = NULL;
47773b51ab4bSEric Blake     int c, ret = 1;
47783b51ab4bSEric Blake     QemuOpts *opts = NULL;
47793b51ab4bSEric Blake     const char *fmt = NULL, *src_fmt = NULL, *src_filename = NULL;
47803b51ab4bSEric Blake     const char *filename, *bitmap;
47813b51ab4bSEric Blake     BlockBackend *blk = NULL, *src = NULL;
47823b51ab4bSEric Blake     BlockDriverState *bs = NULL, *src_bs = NULL;
47833b51ab4bSEric Blake     bool image_opts = false;
47843b51ab4bSEric Blake     int64_t granularity = 0;
47853b51ab4bSEric Blake     bool add = false, merge = false;
47863b51ab4bSEric Blake     QSIMPLEQ_HEAD(, ImgBitmapAction) actions;
47873b51ab4bSEric Blake     ImgBitmapAction *act, *act_next;
47883b51ab4bSEric Blake     const char *op;
4789c5e47711SKevin Wolf     int inactivate_ret;
47903b51ab4bSEric Blake 
47913b51ab4bSEric Blake     QSIMPLEQ_INIT(&actions);
47923b51ab4bSEric Blake 
47933b51ab4bSEric Blake     for (;;) {
47943b51ab4bSEric Blake         static const struct option long_options[] = {
47953b51ab4bSEric Blake             {"help", no_argument, 0, 'h'},
47963b51ab4bSEric Blake             {"object", required_argument, 0, OPTION_OBJECT},
47973b51ab4bSEric Blake             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
47983b51ab4bSEric Blake             {"add", no_argument, 0, OPTION_ADD},
47993b51ab4bSEric Blake             {"remove", no_argument, 0, OPTION_REMOVE},
48003b51ab4bSEric Blake             {"clear", no_argument, 0, OPTION_CLEAR},
48013b51ab4bSEric Blake             {"enable", no_argument, 0, OPTION_ENABLE},
48023b51ab4bSEric Blake             {"disable", no_argument, 0, OPTION_DISABLE},
48033b51ab4bSEric Blake             {"merge", required_argument, 0, OPTION_MERGE},
48043b51ab4bSEric Blake             {"granularity", required_argument, 0, 'g'},
48053b51ab4bSEric Blake             {"source-file", required_argument, 0, 'b'},
48063b51ab4bSEric Blake             {"source-format", required_argument, 0, 'F'},
48073b51ab4bSEric Blake             {0, 0, 0, 0}
48083b51ab4bSEric Blake         };
48093b51ab4bSEric Blake         c = getopt_long(argc, argv, ":b:f:F:g:h", long_options, NULL);
48103b51ab4bSEric Blake         if (c == -1) {
48113b51ab4bSEric Blake             break;
48123b51ab4bSEric Blake         }
48133b51ab4bSEric Blake 
48143b51ab4bSEric Blake         switch (c) {
48153b51ab4bSEric Blake         case ':':
48163b51ab4bSEric Blake             missing_argument(argv[optind - 1]);
48173b51ab4bSEric Blake             break;
48183b51ab4bSEric Blake         case '?':
48193b51ab4bSEric Blake             unrecognized_option(argv[optind - 1]);
48203b51ab4bSEric Blake             break;
48213b51ab4bSEric Blake         case 'h':
48223b51ab4bSEric Blake             help();
48233b51ab4bSEric Blake             break;
48243b51ab4bSEric Blake         case 'b':
48253b51ab4bSEric Blake             src_filename = optarg;
48263b51ab4bSEric Blake             break;
48273b51ab4bSEric Blake         case 'f':
48283b51ab4bSEric Blake             fmt = optarg;
48293b51ab4bSEric Blake             break;
48303b51ab4bSEric Blake         case 'F':
48313b51ab4bSEric Blake             src_fmt = optarg;
48323b51ab4bSEric Blake             break;
48333b51ab4bSEric Blake         case 'g':
48343b51ab4bSEric Blake             granularity = cvtnum("granularity", optarg);
48353b51ab4bSEric Blake             if (granularity < 0) {
48363b51ab4bSEric Blake                 return 1;
48373b51ab4bSEric Blake             }
48383b51ab4bSEric Blake             break;
48393b51ab4bSEric Blake         case OPTION_ADD:
48403b51ab4bSEric Blake             act = g_new0(ImgBitmapAction, 1);
48413b51ab4bSEric Blake             act->act = BITMAP_ADD;
48423b51ab4bSEric Blake             QSIMPLEQ_INSERT_TAIL(&actions, act, next);
48433b51ab4bSEric Blake             add = true;
48443b51ab4bSEric Blake             break;
48453b51ab4bSEric Blake         case OPTION_REMOVE:
48463b51ab4bSEric Blake             act = g_new0(ImgBitmapAction, 1);
48473b51ab4bSEric Blake             act->act = BITMAP_REMOVE;
48483b51ab4bSEric Blake             QSIMPLEQ_INSERT_TAIL(&actions, act, next);
48493b51ab4bSEric Blake             break;
48503b51ab4bSEric Blake         case OPTION_CLEAR:
48513b51ab4bSEric Blake             act = g_new0(ImgBitmapAction, 1);
48523b51ab4bSEric Blake             act->act = BITMAP_CLEAR;
48533b51ab4bSEric Blake             QSIMPLEQ_INSERT_TAIL(&actions, act, next);
48543b51ab4bSEric Blake             break;
48553b51ab4bSEric Blake         case OPTION_ENABLE:
48563b51ab4bSEric Blake             act = g_new0(ImgBitmapAction, 1);
48573b51ab4bSEric Blake             act->act = BITMAP_ENABLE;
48583b51ab4bSEric Blake             QSIMPLEQ_INSERT_TAIL(&actions, act, next);
48593b51ab4bSEric Blake             break;
48603b51ab4bSEric Blake         case OPTION_DISABLE:
48613b51ab4bSEric Blake             act = g_new0(ImgBitmapAction, 1);
48623b51ab4bSEric Blake             act->act = BITMAP_DISABLE;
48633b51ab4bSEric Blake             QSIMPLEQ_INSERT_TAIL(&actions, act, next);
48643b51ab4bSEric Blake             break;
48653b51ab4bSEric Blake         case OPTION_MERGE:
48663b51ab4bSEric Blake             act = g_new0(ImgBitmapAction, 1);
48673b51ab4bSEric Blake             act->act = BITMAP_MERGE;
48683b51ab4bSEric Blake             act->src = optarg;
48693b51ab4bSEric Blake             QSIMPLEQ_INSERT_TAIL(&actions, act, next);
48703b51ab4bSEric Blake             merge = true;
48713b51ab4bSEric Blake             break;
48723b51ab4bSEric Blake         case OPTION_OBJECT:
487399b1e646SKevin Wolf             user_creatable_process_cmdline(optarg);
48743b51ab4bSEric Blake             break;
48753b51ab4bSEric Blake         case OPTION_IMAGE_OPTS:
48763b51ab4bSEric Blake             image_opts = true;
48773b51ab4bSEric Blake             break;
48783b51ab4bSEric Blake         }
48793b51ab4bSEric Blake     }
48803b51ab4bSEric Blake 
48813b51ab4bSEric Blake     if (QSIMPLEQ_EMPTY(&actions)) {
48823b51ab4bSEric Blake         error_report("Need at least one of --add, --remove, --clear, "
48833b51ab4bSEric Blake                      "--enable, --disable, or --merge");
48843b51ab4bSEric Blake         goto out;
48853b51ab4bSEric Blake     }
48863b51ab4bSEric Blake 
48873b51ab4bSEric Blake     if (granularity && !add) {
48883b51ab4bSEric Blake         error_report("granularity only supported with --add");
48893b51ab4bSEric Blake         goto out;
48903b51ab4bSEric Blake     }
48913b51ab4bSEric Blake     if (src_fmt && !src_filename) {
48923b51ab4bSEric Blake         error_report("-F only supported with -b");
48933b51ab4bSEric Blake         goto out;
48943b51ab4bSEric Blake     }
48953b51ab4bSEric Blake     if (src_filename && !merge) {
48963b51ab4bSEric Blake         error_report("Merge bitmap source file only supported with "
48973b51ab4bSEric Blake                      "--merge");
48983b51ab4bSEric Blake         goto out;
48993b51ab4bSEric Blake     }
49003b51ab4bSEric Blake 
49013b51ab4bSEric Blake     if (optind != argc - 2) {
49023b51ab4bSEric Blake         error_report("Expecting filename and bitmap name");
49033b51ab4bSEric Blake         goto out;
49043b51ab4bSEric Blake     }
49053b51ab4bSEric Blake 
49063b51ab4bSEric Blake     filename = argv[optind];
49073b51ab4bSEric Blake     bitmap = argv[optind + 1];
49083b51ab4bSEric Blake 
490914f16bf9SEric Blake     /*
491014f16bf9SEric Blake      * No need to open backing chains; we will be manipulating bitmaps
491114f16bf9SEric Blake      * directly in this image without reference to image contents.
491214f16bf9SEric Blake      */
491314f16bf9SEric Blake     blk = img_open(image_opts, filename, fmt, BDRV_O_RDWR | BDRV_O_NO_BACKING,
491414f16bf9SEric Blake                    false, false, false);
49153b51ab4bSEric Blake     if (!blk) {
49163b51ab4bSEric Blake         goto out;
49173b51ab4bSEric Blake     }
49183b51ab4bSEric Blake     bs = blk_bs(blk);
49193b51ab4bSEric Blake     if (src_filename) {
492014f16bf9SEric Blake         src = img_open(false, src_filename, src_fmt, BDRV_O_NO_BACKING,
492114f16bf9SEric Blake                        false, false, false);
49223b51ab4bSEric Blake         if (!src) {
49233b51ab4bSEric Blake             goto out;
49243b51ab4bSEric Blake         }
49253b51ab4bSEric Blake         src_bs = blk_bs(src);
49263b51ab4bSEric Blake     } else {
49273b51ab4bSEric Blake         src_bs = bs;
49283b51ab4bSEric Blake     }
49293b51ab4bSEric Blake 
49303b51ab4bSEric Blake     QSIMPLEQ_FOREACH_SAFE(act, &actions, next, act_next) {
49313b51ab4bSEric Blake         switch (act->act) {
49323b51ab4bSEric Blake         case BITMAP_ADD:
49333b51ab4bSEric Blake             qmp_block_dirty_bitmap_add(bs->node_name, bitmap,
49343b51ab4bSEric Blake                                        !!granularity, granularity, true, true,
49353b51ab4bSEric Blake                                        false, false, &err);
49363b51ab4bSEric Blake             op = "add";
49373b51ab4bSEric Blake             break;
49383b51ab4bSEric Blake         case BITMAP_REMOVE:
49393b51ab4bSEric Blake             qmp_block_dirty_bitmap_remove(bs->node_name, bitmap, &err);
49403b51ab4bSEric Blake             op = "remove";
49413b51ab4bSEric Blake             break;
49423b51ab4bSEric Blake         case BITMAP_CLEAR:
49433b51ab4bSEric Blake             qmp_block_dirty_bitmap_clear(bs->node_name, bitmap, &err);
49443b51ab4bSEric Blake             op = "clear";
49453b51ab4bSEric Blake             break;
49463b51ab4bSEric Blake         case BITMAP_ENABLE:
49473b51ab4bSEric Blake             qmp_block_dirty_bitmap_enable(bs->node_name, bitmap, &err);
49483b51ab4bSEric Blake             op = "enable";
49493b51ab4bSEric Blake             break;
49503b51ab4bSEric Blake         case BITMAP_DISABLE:
49513b51ab4bSEric Blake             qmp_block_dirty_bitmap_disable(bs->node_name, bitmap, &err);
49523b51ab4bSEric Blake             op = "disable";
49533b51ab4bSEric Blake             break;
49546c729dd8SEric Blake         case BITMAP_MERGE:
49556c729dd8SEric Blake             do_dirty_bitmap_merge(bs->node_name, bitmap, src_bs->node_name,
49566c729dd8SEric Blake                                   act->src, &err);
49573b51ab4bSEric Blake             op = "merge";
49583b51ab4bSEric Blake             break;
49593b51ab4bSEric Blake         default:
49603b51ab4bSEric Blake             g_assert_not_reached();
49613b51ab4bSEric Blake         }
49623b51ab4bSEric Blake 
49633b51ab4bSEric Blake         if (err) {
49643b51ab4bSEric Blake             error_reportf_err(err, "Operation %s on bitmap %s failed: ",
49653b51ab4bSEric Blake                               op, bitmap);
49663b51ab4bSEric Blake             goto out;
49673b51ab4bSEric Blake         }
49683b51ab4bSEric Blake         g_free(act);
49693b51ab4bSEric Blake     }
49703b51ab4bSEric Blake 
49713b51ab4bSEric Blake     ret = 0;
49723b51ab4bSEric Blake 
49733b51ab4bSEric Blake  out:
4974c5e47711SKevin Wolf     /*
4975c5e47711SKevin Wolf      * Manually inactivate the images first because this way we can know whether
4976c5e47711SKevin Wolf      * an error occurred. blk_unref() doesn't tell us about failures.
4977c5e47711SKevin Wolf      */
4978c5e47711SKevin Wolf     inactivate_ret = bdrv_inactivate_all();
4979c5e47711SKevin Wolf     if (inactivate_ret < 0) {
4980c5e47711SKevin Wolf         error_report("Error while closing the image: %s", strerror(-inactivate_ret));
4981c5e47711SKevin Wolf         ret = 1;
4982c5e47711SKevin Wolf     }
4983c5e47711SKevin Wolf 
49843b51ab4bSEric Blake     blk_unref(src);
49853b51ab4bSEric Blake     blk_unref(blk);
49863b51ab4bSEric Blake     qemu_opts_del(opts);
49873b51ab4bSEric Blake     return ret;
49883b51ab4bSEric Blake }
49893b51ab4bSEric Blake 
499086ce1f6eSReda Sallahi #define C_BS      01
499186ce1f6eSReda Sallahi #define C_COUNT   02
499286ce1f6eSReda Sallahi #define C_IF      04
499386ce1f6eSReda Sallahi #define C_OF      010
4994f7c15533SReda Sallahi #define C_SKIP    020
499586ce1f6eSReda Sallahi 
499686ce1f6eSReda Sallahi struct DdInfo {
499786ce1f6eSReda Sallahi     unsigned int flags;
499886ce1f6eSReda Sallahi     int64_t count;
499986ce1f6eSReda Sallahi };
500086ce1f6eSReda Sallahi 
500186ce1f6eSReda Sallahi struct DdIo {
500286ce1f6eSReda Sallahi     int bsz;    /* Block size */
500386ce1f6eSReda Sallahi     char *filename;
500486ce1f6eSReda Sallahi     uint8_t *buf;
5005f7c15533SReda Sallahi     int64_t offset;
500686ce1f6eSReda Sallahi };
500786ce1f6eSReda Sallahi 
500886ce1f6eSReda Sallahi struct DdOpts {
500986ce1f6eSReda Sallahi     const char *name;
501086ce1f6eSReda Sallahi     int (*f)(const char *, struct DdIo *, struct DdIo *, struct DdInfo *);
501186ce1f6eSReda Sallahi     unsigned int flag;
501286ce1f6eSReda Sallahi };
501386ce1f6eSReda Sallahi 
img_dd_bs(const char * arg,struct DdIo * in,struct DdIo * out,struct DdInfo * dd)501486ce1f6eSReda Sallahi static int img_dd_bs(const char *arg,
501586ce1f6eSReda Sallahi                      struct DdIo *in, struct DdIo *out,
501686ce1f6eSReda Sallahi                      struct DdInfo *dd)
501786ce1f6eSReda Sallahi {
501886ce1f6eSReda Sallahi     int64_t res;
501986ce1f6eSReda Sallahi 
502043d589b0SEyal Moscovici     res = cvtnum_full("bs", arg, 1, INT_MAX);
502186ce1f6eSReda Sallahi 
502243d589b0SEyal Moscovici     if (res < 0) {
502386ce1f6eSReda Sallahi         return 1;
502486ce1f6eSReda Sallahi     }
502586ce1f6eSReda Sallahi     in->bsz = out->bsz = res;
502686ce1f6eSReda Sallahi 
502786ce1f6eSReda Sallahi     return 0;
502886ce1f6eSReda Sallahi }
502986ce1f6eSReda Sallahi 
img_dd_count(const char * arg,struct DdIo * in,struct DdIo * out,struct DdInfo * dd)503086ce1f6eSReda Sallahi static int img_dd_count(const char *arg,
503186ce1f6eSReda Sallahi                         struct DdIo *in, struct DdIo *out,
503286ce1f6eSReda Sallahi                         struct DdInfo *dd)
503386ce1f6eSReda Sallahi {
503443d589b0SEyal Moscovici     dd->count = cvtnum("count", arg);
503586ce1f6eSReda Sallahi 
5036606caa0aSMarkus Armbruster     if (dd->count < 0) {
503786ce1f6eSReda Sallahi         return 1;
503886ce1f6eSReda Sallahi     }
503986ce1f6eSReda Sallahi 
504086ce1f6eSReda Sallahi     return 0;
504186ce1f6eSReda Sallahi }
504286ce1f6eSReda Sallahi 
img_dd_if(const char * arg,struct DdIo * in,struct DdIo * out,struct DdInfo * dd)504386ce1f6eSReda Sallahi static int img_dd_if(const char *arg,
504486ce1f6eSReda Sallahi                      struct DdIo *in, struct DdIo *out,
504586ce1f6eSReda Sallahi                      struct DdInfo *dd)
504686ce1f6eSReda Sallahi {
504786ce1f6eSReda Sallahi     in->filename = g_strdup(arg);
504886ce1f6eSReda Sallahi 
504986ce1f6eSReda Sallahi     return 0;
505086ce1f6eSReda Sallahi }
505186ce1f6eSReda Sallahi 
img_dd_of(const char * arg,struct DdIo * in,struct DdIo * out,struct DdInfo * dd)505286ce1f6eSReda Sallahi static int img_dd_of(const char *arg,
505386ce1f6eSReda Sallahi                      struct DdIo *in, struct DdIo *out,
505486ce1f6eSReda Sallahi                      struct DdInfo *dd)
505586ce1f6eSReda Sallahi {
505686ce1f6eSReda Sallahi     out->filename = g_strdup(arg);
505786ce1f6eSReda Sallahi 
505886ce1f6eSReda Sallahi     return 0;
505986ce1f6eSReda Sallahi }
506086ce1f6eSReda Sallahi 
img_dd_skip(const char * arg,struct DdIo * in,struct DdIo * out,struct DdInfo * dd)5061f7c15533SReda Sallahi static int img_dd_skip(const char *arg,
5062f7c15533SReda Sallahi                        struct DdIo *in, struct DdIo *out,
5063f7c15533SReda Sallahi                        struct DdInfo *dd)
5064f7c15533SReda Sallahi {
506543d589b0SEyal Moscovici     in->offset = cvtnum("skip", arg);
5066f7c15533SReda Sallahi 
5067606caa0aSMarkus Armbruster     if (in->offset < 0) {
5068f7c15533SReda Sallahi         return 1;
5069f7c15533SReda Sallahi     }
5070f7c15533SReda Sallahi 
5071f7c15533SReda Sallahi     return 0;
5072f7c15533SReda Sallahi }
5073f7c15533SReda Sallahi 
img_dd(int argc,char ** argv)507486ce1f6eSReda Sallahi static int img_dd(int argc, char **argv)
507586ce1f6eSReda Sallahi {
507686ce1f6eSReda Sallahi     int ret = 0;
507786ce1f6eSReda Sallahi     char *arg = NULL;
507886ce1f6eSReda Sallahi     char *tmp;
507986ce1f6eSReda Sallahi     BlockDriver *drv = NULL, *proto_drv = NULL;
508086ce1f6eSReda Sallahi     BlockBackend *blk1 = NULL, *blk2 = NULL;
508186ce1f6eSReda Sallahi     QemuOpts *opts = NULL;
508286ce1f6eSReda Sallahi     QemuOptsList *create_opts = NULL;
508386ce1f6eSReda Sallahi     Error *local_err = NULL;
508486ce1f6eSReda Sallahi     bool image_opts = false;
508586ce1f6eSReda Sallahi     int c, i;
508686ce1f6eSReda Sallahi     const char *out_fmt = "raw";
508786ce1f6eSReda Sallahi     const char *fmt = NULL;
508886ce1f6eSReda Sallahi     int64_t size = 0;
50890f48c47cSMiroslav Rezanina     int64_t out_pos, in_pos;
5090335e9937SFam Zheng     bool force_share = false;
509186ce1f6eSReda Sallahi     struct DdInfo dd = {
509286ce1f6eSReda Sallahi         .flags = 0,
509386ce1f6eSReda Sallahi         .count = 0,
509486ce1f6eSReda Sallahi     };
509586ce1f6eSReda Sallahi     struct DdIo in = {
509686ce1f6eSReda Sallahi         .bsz = 512, /* Block size is by default 512 bytes */
509786ce1f6eSReda Sallahi         .filename = NULL,
5098f7c15533SReda Sallahi         .buf = NULL,
5099f7c15533SReda Sallahi         .offset = 0
510086ce1f6eSReda Sallahi     };
510186ce1f6eSReda Sallahi     struct DdIo out = {
510286ce1f6eSReda Sallahi         .bsz = 512,
510386ce1f6eSReda Sallahi         .filename = NULL,
5104f7c15533SReda Sallahi         .buf = NULL,
5105f7c15533SReda Sallahi         .offset = 0
510686ce1f6eSReda Sallahi     };
510786ce1f6eSReda Sallahi 
510886ce1f6eSReda Sallahi     const struct DdOpts options[] = {
510986ce1f6eSReda Sallahi         { "bs", img_dd_bs, C_BS },
511086ce1f6eSReda Sallahi         { "count", img_dd_count, C_COUNT },
511186ce1f6eSReda Sallahi         { "if", img_dd_if, C_IF },
511286ce1f6eSReda Sallahi         { "of", img_dd_of, C_OF },
5113f7c15533SReda Sallahi         { "skip", img_dd_skip, C_SKIP },
511486ce1f6eSReda Sallahi         { NULL, NULL, 0 }
511586ce1f6eSReda Sallahi     };
511686ce1f6eSReda Sallahi     const struct option long_options[] = {
511786ce1f6eSReda Sallahi         { "help", no_argument, 0, 'h'},
511883d4bf94SDaniel P. Berrange         { "object", required_argument, 0, OPTION_OBJECT},
511986ce1f6eSReda Sallahi         { "image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
5120335e9937SFam Zheng         { "force-share", no_argument, 0, 'U'},
512186ce1f6eSReda Sallahi         { 0, 0, 0, 0 }
512286ce1f6eSReda Sallahi     };
512386ce1f6eSReda Sallahi 
5124335e9937SFam Zheng     while ((c = getopt_long(argc, argv, ":hf:O:U", long_options, NULL))) {
512586ce1f6eSReda Sallahi         if (c == EOF) {
512686ce1f6eSReda Sallahi             break;
512786ce1f6eSReda Sallahi         }
512886ce1f6eSReda Sallahi         switch (c) {
512986ce1f6eSReda Sallahi         case 'O':
513086ce1f6eSReda Sallahi             out_fmt = optarg;
513186ce1f6eSReda Sallahi             break;
513286ce1f6eSReda Sallahi         case 'f':
513386ce1f6eSReda Sallahi             fmt = optarg;
513486ce1f6eSReda Sallahi             break;
5135c9192973SStefan Hajnoczi         case ':':
5136c9192973SStefan Hajnoczi             missing_argument(argv[optind - 1]);
5137c9192973SStefan Hajnoczi             break;
513886ce1f6eSReda Sallahi         case '?':
5139c9192973SStefan Hajnoczi             unrecognized_option(argv[optind - 1]);
5140c9192973SStefan Hajnoczi             break;
514186ce1f6eSReda Sallahi         case 'h':
514286ce1f6eSReda Sallahi             help();
514386ce1f6eSReda Sallahi             break;
5144335e9937SFam Zheng         case 'U':
5145335e9937SFam Zheng             force_share = true;
5146335e9937SFam Zheng             break;
51472a245709SStefan Hajnoczi         case OPTION_OBJECT:
514899b1e646SKevin Wolf             user_creatable_process_cmdline(optarg);
51492a245709SStefan Hajnoczi             break;
515086ce1f6eSReda Sallahi         case OPTION_IMAGE_OPTS:
515186ce1f6eSReda Sallahi             image_opts = true;
515286ce1f6eSReda Sallahi             break;
515386ce1f6eSReda Sallahi         }
515486ce1f6eSReda Sallahi     }
515586ce1f6eSReda Sallahi 
515686ce1f6eSReda Sallahi     for (i = optind; i < argc; i++) {
515786ce1f6eSReda Sallahi         int j;
515886ce1f6eSReda Sallahi         arg = g_strdup(argv[i]);
515986ce1f6eSReda Sallahi 
516086ce1f6eSReda Sallahi         tmp = strchr(arg, '=');
516186ce1f6eSReda Sallahi         if (tmp == NULL) {
516286ce1f6eSReda Sallahi             error_report("unrecognized operand %s", arg);
516386ce1f6eSReda Sallahi             ret = -1;
516486ce1f6eSReda Sallahi             goto out;
516586ce1f6eSReda Sallahi         }
516686ce1f6eSReda Sallahi 
516786ce1f6eSReda Sallahi         *tmp++ = '\0';
516886ce1f6eSReda Sallahi 
516986ce1f6eSReda Sallahi         for (j = 0; options[j].name != NULL; j++) {
517086ce1f6eSReda Sallahi             if (!strcmp(arg, options[j].name)) {
517186ce1f6eSReda Sallahi                 break;
517286ce1f6eSReda Sallahi             }
517386ce1f6eSReda Sallahi         }
517486ce1f6eSReda Sallahi         if (options[j].name == NULL) {
517586ce1f6eSReda Sallahi             error_report("unrecognized operand %s", arg);
517686ce1f6eSReda Sallahi             ret = -1;
517786ce1f6eSReda Sallahi             goto out;
517886ce1f6eSReda Sallahi         }
517986ce1f6eSReda Sallahi 
518086ce1f6eSReda Sallahi         if (options[j].f(tmp, &in, &out, &dd) != 0) {
518186ce1f6eSReda Sallahi             ret = -1;
518286ce1f6eSReda Sallahi             goto out;
518386ce1f6eSReda Sallahi         }
518486ce1f6eSReda Sallahi         dd.flags |= options[j].flag;
518586ce1f6eSReda Sallahi         g_free(arg);
518686ce1f6eSReda Sallahi         arg = NULL;
518786ce1f6eSReda Sallahi     }
518886ce1f6eSReda Sallahi 
518986ce1f6eSReda Sallahi     if (!(dd.flags & C_IF && dd.flags & C_OF)) {
519086ce1f6eSReda Sallahi         error_report("Must specify both input and output files");
519186ce1f6eSReda Sallahi         ret = -1;
519286ce1f6eSReda Sallahi         goto out;
519386ce1f6eSReda Sallahi     }
519483d4bf94SDaniel P. Berrange 
5195335e9937SFam Zheng     blk1 = img_open(image_opts, in.filename, fmt, 0, false, false,
5196335e9937SFam Zheng                     force_share);
519786ce1f6eSReda Sallahi 
519886ce1f6eSReda Sallahi     if (!blk1) {
519986ce1f6eSReda Sallahi         ret = -1;
520086ce1f6eSReda Sallahi         goto out;
520186ce1f6eSReda Sallahi     }
520286ce1f6eSReda Sallahi 
520386ce1f6eSReda Sallahi     drv = bdrv_find_format(out_fmt);
520486ce1f6eSReda Sallahi     if (!drv) {
520586ce1f6eSReda Sallahi         error_report("Unknown file format");
520686ce1f6eSReda Sallahi         ret = -1;
520786ce1f6eSReda Sallahi         goto out;
520886ce1f6eSReda Sallahi     }
520986ce1f6eSReda Sallahi     proto_drv = bdrv_find_protocol(out.filename, true, &local_err);
521086ce1f6eSReda Sallahi 
521186ce1f6eSReda Sallahi     if (!proto_drv) {
521286ce1f6eSReda Sallahi         error_report_err(local_err);
521386ce1f6eSReda Sallahi         ret = -1;
521486ce1f6eSReda Sallahi         goto out;
521586ce1f6eSReda Sallahi     }
521686ce1f6eSReda Sallahi     if (!drv->create_opts) {
521786ce1f6eSReda Sallahi         error_report("Format driver '%s' does not support image creation",
521886ce1f6eSReda Sallahi                      drv->format_name);
521986ce1f6eSReda Sallahi         ret = -1;
522086ce1f6eSReda Sallahi         goto out;
522186ce1f6eSReda Sallahi     }
522286ce1f6eSReda Sallahi     if (!proto_drv->create_opts) {
522386ce1f6eSReda Sallahi         error_report("Protocol driver '%s' does not support image creation",
522486ce1f6eSReda Sallahi                      proto_drv->format_name);
522586ce1f6eSReda Sallahi         ret = -1;
522686ce1f6eSReda Sallahi         goto out;
522786ce1f6eSReda Sallahi     }
522886ce1f6eSReda Sallahi     create_opts = qemu_opts_append(create_opts, drv->create_opts);
522986ce1f6eSReda Sallahi     create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
523086ce1f6eSReda Sallahi 
523186ce1f6eSReda Sallahi     opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
523286ce1f6eSReda Sallahi 
523386ce1f6eSReda Sallahi     size = blk_getlength(blk1);
523486ce1f6eSReda Sallahi     if (size < 0) {
523586ce1f6eSReda Sallahi         error_report("Failed to get size for '%s'", in.filename);
523686ce1f6eSReda Sallahi         ret = -1;
523786ce1f6eSReda Sallahi         goto out;
523886ce1f6eSReda Sallahi     }
523986ce1f6eSReda Sallahi 
524086ce1f6eSReda Sallahi     if (dd.flags & C_COUNT && dd.count <= INT64_MAX / in.bsz &&
524186ce1f6eSReda Sallahi         dd.count * in.bsz < size) {
524286ce1f6eSReda Sallahi         size = dd.count * in.bsz;
524386ce1f6eSReda Sallahi     }
524486ce1f6eSReda Sallahi 
5245f7c15533SReda Sallahi     /* Overflow means the specified offset is beyond input image's size */
5246f7c15533SReda Sallahi     if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz ||
5247f7c15533SReda Sallahi                               size < in.bsz * in.offset)) {
5248f7c15533SReda Sallahi         qemu_opt_set_number(opts, BLOCK_OPT_SIZE, 0, &error_abort);
5249f7c15533SReda Sallahi     } else {
5250f7c15533SReda Sallahi         qemu_opt_set_number(opts, BLOCK_OPT_SIZE,
5251f7c15533SReda Sallahi                             size - in.bsz * in.offset, &error_abort);
5252f7c15533SReda Sallahi     }
525386ce1f6eSReda Sallahi 
525486ce1f6eSReda Sallahi     ret = bdrv_create(drv, out.filename, opts, &local_err);
525586ce1f6eSReda Sallahi     if (ret < 0) {
525686ce1f6eSReda Sallahi         error_reportf_err(local_err,
525786ce1f6eSReda Sallahi                           "%s: error while creating output image: ",
525886ce1f6eSReda Sallahi                           out.filename);
525986ce1f6eSReda Sallahi         ret = -1;
526086ce1f6eSReda Sallahi         goto out;
526186ce1f6eSReda Sallahi     }
526286ce1f6eSReda Sallahi 
5263ea204ddaSDaniel P. Berrange     /* TODO, we can't honour --image-opts for the target,
5264ea204ddaSDaniel P. Berrange      * since it needs to be given in a format compatible
5265ea204ddaSDaniel P. Berrange      * with the bdrv_create() call above which does not
5266ea204ddaSDaniel P. Berrange      * support image-opts style.
5267ea204ddaSDaniel P. Berrange      */
526829cf9336SDaniel P. Berrange     blk2 = img_open_file(out.filename, NULL, out_fmt, BDRV_O_RDWR,
5269335e9937SFam Zheng                          false, false, false);
527086ce1f6eSReda Sallahi 
527186ce1f6eSReda Sallahi     if (!blk2) {
527286ce1f6eSReda Sallahi         ret = -1;
527386ce1f6eSReda Sallahi         goto out;
527486ce1f6eSReda Sallahi     }
527586ce1f6eSReda Sallahi 
5276f7c15533SReda Sallahi     if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz ||
5277f7c15533SReda Sallahi                               size < in.offset * in.bsz)) {
5278f7c15533SReda Sallahi         /* We give a warning if the skip option is bigger than the input
5279f7c15533SReda Sallahi          * size and create an empty output disk image (i.e. like dd(1)).
5280f7c15533SReda Sallahi          */
5281f7c15533SReda Sallahi         error_report("%s: cannot skip to specified offset", in.filename);
5282f7c15533SReda Sallahi         in_pos = size;
5283f7c15533SReda Sallahi     } else {
5284f7c15533SReda Sallahi         in_pos = in.offset * in.bsz;
5285f7c15533SReda Sallahi     }
5286f7c15533SReda Sallahi 
528786ce1f6eSReda Sallahi     in.buf = g_new(uint8_t, in.bsz);
528886ce1f6eSReda Sallahi 
52890f48c47cSMiroslav Rezanina     for (out_pos = 0; in_pos < size; ) {
5290bf5b16faSAlberto Faria         int bytes = (in_pos + in.bsz > size) ? size - in_pos : in.bsz;
529186ce1f6eSReda Sallahi 
5292a9262f55SAlberto Faria         ret = blk_pread(blk1, in_pos, bytes, in.buf, 0);
5293bf5b16faSAlberto Faria         if (ret < 0) {
529486ce1f6eSReda Sallahi             error_report("error while reading from input image file: %s",
5295bf5b16faSAlberto Faria                          strerror(-ret));
529686ce1f6eSReda Sallahi             goto out;
529786ce1f6eSReda Sallahi         }
5298bf5b16faSAlberto Faria         in_pos += bytes;
529986ce1f6eSReda Sallahi 
5300a9262f55SAlberto Faria         ret = blk_pwrite(blk2, out_pos, bytes, in.buf, 0);
5301bf5b16faSAlberto Faria         if (ret < 0) {
530286ce1f6eSReda Sallahi             error_report("error while writing to output image file: %s",
5303bf5b16faSAlberto Faria                          strerror(-ret));
530486ce1f6eSReda Sallahi             goto out;
530586ce1f6eSReda Sallahi         }
5306bf5b16faSAlberto Faria         out_pos += bytes;
530786ce1f6eSReda Sallahi     }
530886ce1f6eSReda Sallahi 
530986ce1f6eSReda Sallahi out:
531086ce1f6eSReda Sallahi     g_free(arg);
531186ce1f6eSReda Sallahi     qemu_opts_del(opts);
531286ce1f6eSReda Sallahi     qemu_opts_free(create_opts);
531386ce1f6eSReda Sallahi     blk_unref(blk1);
531486ce1f6eSReda Sallahi     blk_unref(blk2);
531586ce1f6eSReda Sallahi     g_free(in.filename);
531686ce1f6eSReda Sallahi     g_free(out.filename);
531786ce1f6eSReda Sallahi     g_free(in.buf);
531886ce1f6eSReda Sallahi     g_free(out.buf);
531986ce1f6eSReda Sallahi 
532086ce1f6eSReda Sallahi     if (ret) {
532186ce1f6eSReda Sallahi         return 1;
532286ce1f6eSReda Sallahi     }
532386ce1f6eSReda Sallahi     return 0;
532486ce1f6eSReda Sallahi }
532586ce1f6eSReda Sallahi 
dump_json_block_measure_info(BlockMeasureInfo * info)5326fd03c2b8SStefan Hajnoczi static void dump_json_block_measure_info(BlockMeasureInfo *info)
5327fd03c2b8SStefan Hajnoczi {
5328eab3a467SMarkus Armbruster     GString *str;
5329fd03c2b8SStefan Hajnoczi     QObject *obj;
5330fd03c2b8SStefan Hajnoczi     Visitor *v = qobject_output_visitor_new(&obj);
5331fd03c2b8SStefan Hajnoczi 
5332fd03c2b8SStefan Hajnoczi     visit_type_BlockMeasureInfo(v, NULL, &info, &error_abort);
5333fd03c2b8SStefan Hajnoczi     visit_complete(v, &obj);
53346589f459SMarkus Armbruster     str = qobject_to_json_pretty(obj, true);
5335fd03c2b8SStefan Hajnoczi     assert(str != NULL);
5336eab3a467SMarkus Armbruster     printf("%s\n", str->str);
5337cb3e7f08SMarc-André Lureau     qobject_unref(obj);
5338fd03c2b8SStefan Hajnoczi     visit_free(v);
5339eab3a467SMarkus Armbruster     g_string_free(str, true);
5340fd03c2b8SStefan Hajnoczi }
5341fd03c2b8SStefan Hajnoczi 
img_measure(int argc,char ** argv)5342fd03c2b8SStefan Hajnoczi static int img_measure(int argc, char **argv)
5343fd03c2b8SStefan Hajnoczi {
5344fd03c2b8SStefan Hajnoczi     static const struct option long_options[] = {
5345fd03c2b8SStefan Hajnoczi         {"help", no_argument, 0, 'h'},
5346fd03c2b8SStefan Hajnoczi         {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
5347fd03c2b8SStefan Hajnoczi         {"object", required_argument, 0, OPTION_OBJECT},
5348fd03c2b8SStefan Hajnoczi         {"output", required_argument, 0, OPTION_OUTPUT},
5349fd03c2b8SStefan Hajnoczi         {"size", required_argument, 0, OPTION_SIZE},
5350fd03c2b8SStefan Hajnoczi         {"force-share", no_argument, 0, 'U'},
5351fd03c2b8SStefan Hajnoczi         {0, 0, 0, 0}
5352fd03c2b8SStefan Hajnoczi     };
5353fd03c2b8SStefan Hajnoczi     OutputFormat output_format = OFORMAT_HUMAN;
5354fd03c2b8SStefan Hajnoczi     BlockBackend *in_blk = NULL;
5355fd03c2b8SStefan Hajnoczi     BlockDriver *drv;
5356fd03c2b8SStefan Hajnoczi     const char *filename = NULL;
5357fd03c2b8SStefan Hajnoczi     const char *fmt = NULL;
5358fd03c2b8SStefan Hajnoczi     const char *out_fmt = "raw";
5359fd03c2b8SStefan Hajnoczi     char *options = NULL;
5360fd03c2b8SStefan Hajnoczi     char *snapshot_name = NULL;
5361fd03c2b8SStefan Hajnoczi     bool force_share = false;
5362fd03c2b8SStefan Hajnoczi     QemuOpts *opts = NULL;
5363fd03c2b8SStefan Hajnoczi     QemuOpts *object_opts = NULL;
5364fd03c2b8SStefan Hajnoczi     QemuOpts *sn_opts = NULL;
5365fd03c2b8SStefan Hajnoczi     QemuOptsList *create_opts = NULL;
5366fd03c2b8SStefan Hajnoczi     bool image_opts = false;
5367fd03c2b8SStefan Hajnoczi     uint64_t img_size = UINT64_MAX;
5368fd03c2b8SStefan Hajnoczi     BlockMeasureInfo *info = NULL;
5369fd03c2b8SStefan Hajnoczi     Error *local_err = NULL;
5370fd03c2b8SStefan Hajnoczi     int ret = 1;
5371fd03c2b8SStefan Hajnoczi     int c;
5372fd03c2b8SStefan Hajnoczi 
5373fd03c2b8SStefan Hajnoczi     while ((c = getopt_long(argc, argv, "hf:O:o:l:U",
5374fd03c2b8SStefan Hajnoczi                             long_options, NULL)) != -1) {
5375fd03c2b8SStefan Hajnoczi         switch (c) {
5376fd03c2b8SStefan Hajnoczi         case '?':
5377fd03c2b8SStefan Hajnoczi         case 'h':
5378fd03c2b8SStefan Hajnoczi             help();
5379fd03c2b8SStefan Hajnoczi             break;
5380fd03c2b8SStefan Hajnoczi         case 'f':
5381fd03c2b8SStefan Hajnoczi             fmt = optarg;
5382fd03c2b8SStefan Hajnoczi             break;
5383fd03c2b8SStefan Hajnoczi         case 'O':
5384fd03c2b8SStefan Hajnoczi             out_fmt = optarg;
5385fd03c2b8SStefan Hajnoczi             break;
5386fd03c2b8SStefan Hajnoczi         case 'o':
53876d2b5cbaSMarkus Armbruster             if (accumulate_options(&options, optarg) < 0) {
5388fd03c2b8SStefan Hajnoczi                 goto out;
5389fd03c2b8SStefan Hajnoczi             }
5390fd03c2b8SStefan Hajnoczi             break;
5391fd03c2b8SStefan Hajnoczi         case 'l':
5392fd03c2b8SStefan Hajnoczi             if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
5393fd03c2b8SStefan Hajnoczi                 sn_opts = qemu_opts_parse_noisily(&internal_snapshot_opts,
5394fd03c2b8SStefan Hajnoczi                                                   optarg, false);
5395fd03c2b8SStefan Hajnoczi                 if (!sn_opts) {
5396fd03c2b8SStefan Hajnoczi                     error_report("Failed in parsing snapshot param '%s'",
5397fd03c2b8SStefan Hajnoczi                                  optarg);
5398fd03c2b8SStefan Hajnoczi                     goto out;
5399fd03c2b8SStefan Hajnoczi                 }
5400fd03c2b8SStefan Hajnoczi             } else {
5401fd03c2b8SStefan Hajnoczi                 snapshot_name = optarg;
5402fd03c2b8SStefan Hajnoczi             }
5403fd03c2b8SStefan Hajnoczi             break;
5404fd03c2b8SStefan Hajnoczi         case 'U':
5405fd03c2b8SStefan Hajnoczi             force_share = true;
5406fd03c2b8SStefan Hajnoczi             break;
5407fd03c2b8SStefan Hajnoczi         case OPTION_OBJECT:
540899b1e646SKevin Wolf             user_creatable_process_cmdline(optarg);
5409fd03c2b8SStefan Hajnoczi             break;
5410fd03c2b8SStefan Hajnoczi         case OPTION_IMAGE_OPTS:
5411fd03c2b8SStefan Hajnoczi             image_opts = true;
5412fd03c2b8SStefan Hajnoczi             break;
5413fd03c2b8SStefan Hajnoczi         case OPTION_OUTPUT:
5414fd03c2b8SStefan Hajnoczi             if (!strcmp(optarg, "json")) {
5415fd03c2b8SStefan Hajnoczi                 output_format = OFORMAT_JSON;
5416fd03c2b8SStefan Hajnoczi             } else if (!strcmp(optarg, "human")) {
5417fd03c2b8SStefan Hajnoczi                 output_format = OFORMAT_HUMAN;
5418fd03c2b8SStefan Hajnoczi             } else {
5419fd03c2b8SStefan Hajnoczi                 error_report("--output must be used with human or json "
5420fd03c2b8SStefan Hajnoczi                              "as argument.");
5421fd03c2b8SStefan Hajnoczi                 goto out;
5422fd03c2b8SStefan Hajnoczi             }
5423fd03c2b8SStefan Hajnoczi             break;
5424fd03c2b8SStefan Hajnoczi         case OPTION_SIZE:
5425fd03c2b8SStefan Hajnoczi         {
5426fd03c2b8SStefan Hajnoczi             int64_t sval;
5427fd03c2b8SStefan Hajnoczi 
542843d589b0SEyal Moscovici             sval = cvtnum("image size", optarg);
5429fd03c2b8SStefan Hajnoczi             if (sval < 0) {
5430fd03c2b8SStefan Hajnoczi                 goto out;
5431fd03c2b8SStefan Hajnoczi             }
5432fd03c2b8SStefan Hajnoczi             img_size = (uint64_t)sval;
5433fd03c2b8SStefan Hajnoczi         }
5434fd03c2b8SStefan Hajnoczi         break;
5435fd03c2b8SStefan Hajnoczi         }
5436fd03c2b8SStefan Hajnoczi     }
5437fd03c2b8SStefan Hajnoczi 
5438fd03c2b8SStefan Hajnoczi     if (argc - optind > 1) {
5439fd03c2b8SStefan Hajnoczi         error_report("At most one filename argument is allowed.");
5440fd03c2b8SStefan Hajnoczi         goto out;
5441fd03c2b8SStefan Hajnoczi     } else if (argc - optind == 1) {
5442fd03c2b8SStefan Hajnoczi         filename = argv[optind];
5443fd03c2b8SStefan Hajnoczi     }
5444fd03c2b8SStefan Hajnoczi 
5445c3673dcfSStefan Hajnoczi     if (!filename && (image_opts || fmt || snapshot_name || sn_opts)) {
5446c3673dcfSStefan Hajnoczi         error_report("--image-opts, -f, and -l require a filename argument.");
5447fd03c2b8SStefan Hajnoczi         goto out;
5448fd03c2b8SStefan Hajnoczi     }
5449fd03c2b8SStefan Hajnoczi     if (filename && img_size != UINT64_MAX) {
5450fd03c2b8SStefan Hajnoczi         error_report("--size N cannot be used together with a filename.");
5451fd03c2b8SStefan Hajnoczi         goto out;
5452fd03c2b8SStefan Hajnoczi     }
5453fd03c2b8SStefan Hajnoczi     if (!filename && img_size == UINT64_MAX) {
5454fd03c2b8SStefan Hajnoczi         error_report("Either --size N or one filename must be specified.");
5455fd03c2b8SStefan Hajnoczi         goto out;
5456fd03c2b8SStefan Hajnoczi     }
5457fd03c2b8SStefan Hajnoczi 
5458fd03c2b8SStefan Hajnoczi     if (filename) {
5459fd03c2b8SStefan Hajnoczi         in_blk = img_open(image_opts, filename, fmt, 0,
5460fd03c2b8SStefan Hajnoczi                           false, false, force_share);
5461fd03c2b8SStefan Hajnoczi         if (!in_blk) {
5462fd03c2b8SStefan Hajnoczi             goto out;
5463fd03c2b8SStefan Hajnoczi         }
5464fd03c2b8SStefan Hajnoczi 
5465fd03c2b8SStefan Hajnoczi         if (sn_opts) {
5466fd03c2b8SStefan Hajnoczi             bdrv_snapshot_load_tmp(blk_bs(in_blk),
5467fd03c2b8SStefan Hajnoczi                     qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID),
5468fd03c2b8SStefan Hajnoczi                     qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME),
5469fd03c2b8SStefan Hajnoczi                     &local_err);
5470fd03c2b8SStefan Hajnoczi         } else if (snapshot_name != NULL) {
5471fd03c2b8SStefan Hajnoczi             bdrv_snapshot_load_tmp_by_id_or_name(blk_bs(in_blk),
5472fd03c2b8SStefan Hajnoczi                     snapshot_name, &local_err);
5473fd03c2b8SStefan Hajnoczi         }
5474fd03c2b8SStefan Hajnoczi         if (local_err) {
5475fd03c2b8SStefan Hajnoczi             error_reportf_err(local_err, "Failed to load snapshot: ");
5476fd03c2b8SStefan Hajnoczi             goto out;
5477fd03c2b8SStefan Hajnoczi         }
5478fd03c2b8SStefan Hajnoczi     }
5479fd03c2b8SStefan Hajnoczi 
5480fd03c2b8SStefan Hajnoczi     drv = bdrv_find_format(out_fmt);
5481fd03c2b8SStefan Hajnoczi     if (!drv) {
5482fd03c2b8SStefan Hajnoczi         error_report("Unknown file format '%s'", out_fmt);
5483fd03c2b8SStefan Hajnoczi         goto out;
5484fd03c2b8SStefan Hajnoczi     }
5485fd03c2b8SStefan Hajnoczi     if (!drv->create_opts) {
5486fd03c2b8SStefan Hajnoczi         error_report("Format driver '%s' does not support image creation",
5487fd03c2b8SStefan Hajnoczi                      drv->format_name);
5488fd03c2b8SStefan Hajnoczi         goto out;
5489fd03c2b8SStefan Hajnoczi     }
5490fd03c2b8SStefan Hajnoczi 
5491fd03c2b8SStefan Hajnoczi     create_opts = qemu_opts_append(create_opts, drv->create_opts);
5492fd03c2b8SStefan Hajnoczi     create_opts = qemu_opts_append(create_opts, bdrv_file.create_opts);
5493fd03c2b8SStefan Hajnoczi     opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
5494fd03c2b8SStefan Hajnoczi     if (options) {
5495235e59cfSMarkus Armbruster         if (!qemu_opts_do_parse(opts, options, NULL, &local_err)) {
5496fd03c2b8SStefan Hajnoczi             error_report_err(local_err);
5497fd03c2b8SStefan Hajnoczi             error_report("Invalid options for file format '%s'", out_fmt);
5498fd03c2b8SStefan Hajnoczi             goto out;
5499fd03c2b8SStefan Hajnoczi         }
5500fd03c2b8SStefan Hajnoczi     }
5501fd03c2b8SStefan Hajnoczi     if (img_size != UINT64_MAX) {
5502fd03c2b8SStefan Hajnoczi         qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size, &error_abort);
5503fd03c2b8SStefan Hajnoczi     }
5504fd03c2b8SStefan Hajnoczi 
5505fd03c2b8SStefan Hajnoczi     info = bdrv_measure(drv, opts, in_blk ? blk_bs(in_blk) : NULL, &local_err);
5506fd03c2b8SStefan Hajnoczi     if (local_err) {
5507fd03c2b8SStefan Hajnoczi         error_report_err(local_err);
5508fd03c2b8SStefan Hajnoczi         goto out;
5509fd03c2b8SStefan Hajnoczi     }
5510fd03c2b8SStefan Hajnoczi 
5511fd03c2b8SStefan Hajnoczi     if (output_format == OFORMAT_HUMAN) {
5512fd03c2b8SStefan Hajnoczi         printf("required size: %" PRIu64 "\n", info->required);
5513fd03c2b8SStefan Hajnoczi         printf("fully allocated size: %" PRIu64 "\n", info->fully_allocated);
55145d72c68bSEric Blake         if (info->has_bitmaps) {
55155d72c68bSEric Blake             printf("bitmaps size: %" PRIu64 "\n", info->bitmaps);
55165d72c68bSEric Blake         }
5517fd03c2b8SStefan Hajnoczi     } else {
5518fd03c2b8SStefan Hajnoczi         dump_json_block_measure_info(info);
5519fd03c2b8SStefan Hajnoczi     }
5520fd03c2b8SStefan Hajnoczi 
5521fd03c2b8SStefan Hajnoczi     ret = 0;
5522fd03c2b8SStefan Hajnoczi 
5523fd03c2b8SStefan Hajnoczi out:
5524fd03c2b8SStefan Hajnoczi     qapi_free_BlockMeasureInfo(info);
5525fd03c2b8SStefan Hajnoczi     qemu_opts_del(object_opts);
5526fd03c2b8SStefan Hajnoczi     qemu_opts_del(opts);
5527fd03c2b8SStefan Hajnoczi     qemu_opts_del(sn_opts);
5528fd03c2b8SStefan Hajnoczi     qemu_opts_free(create_opts);
5529fd03c2b8SStefan Hajnoczi     g_free(options);
5530fd03c2b8SStefan Hajnoczi     blk_unref(in_blk);
5531fd03c2b8SStefan Hajnoczi     return ret;
5532fd03c2b8SStefan Hajnoczi }
5533b6133b8cSKevin Wolf 
5534c227f099SAnthony Liguori static const img_cmd_t img_cmds[] = {
5535153859beSStuart Brady #define DEF(option, callback, arg_string)        \
5536153859beSStuart Brady     { option, callback },
5537153859beSStuart Brady #include "qemu-img-cmds.h"
5538153859beSStuart Brady #undef DEF
5539153859beSStuart Brady     { NULL, NULL, },
5540153859beSStuart Brady };
5541153859beSStuart Brady 
main(int argc,char ** argv)5542ea2384d3Sbellard int main(int argc, char **argv)
5543ea2384d3Sbellard {
5544c227f099SAnthony Liguori     const img_cmd_t *cmd;
5545153859beSStuart Brady     const char *cmdname;
55467db1689cSJeff Cody     int c;
55477db1689cSJeff Cody     static const struct option long_options[] = {
55487db1689cSJeff Cody         {"help", no_argument, 0, 'h'},
554910985131SDenis V. Lunev         {"version", no_argument, 0, 'V'},
555006a1e0c1SDenis V. Lunev         {"trace", required_argument, NULL, 'T'},
55517db1689cSJeff Cody         {0, 0, 0, 0}
55527db1689cSJeff Cody     };
5553ea2384d3Sbellard 
5554526eda14SMORITA Kazutaka #ifdef CONFIG_POSIX
5555526eda14SMORITA Kazutaka     signal(SIGPIPE, SIG_IGN);
5556526eda14SMORITA Kazutaka #endif
5557526eda14SMORITA Kazutaka 
555898c5d2e7SDaniel P. Berrangé     socket_init();
5559f5852efaSChristophe Fergeau     error_init(argv[0]);
5560fe4db84dSDaniel P. Berrange     module_call_init(MODULE_INIT_TRACE);
556110f5bff6SFam Zheng     qemu_init_exec_dir(argv[0]);
556253f76e58SKevin Wolf 
5563f9734d5dSMarkus Armbruster     qemu_init_main_loop(&error_fatal);
55642f78e491SChrysostomos Nanakos 
5565e8f2d272SEduardo Habkost     qcrypto_init(&error_fatal);
5566c2297088SDaniel P. Berrange 
5567064097d9SDaniel P. Berrange     module_call_init(MODULE_INIT_QOM);
5568ea2384d3Sbellard     bdrv_init();
5569ac1307abSFam Zheng     if (argc < 2) {
5570ac1307abSFam Zheng         error_exit("Not enough arguments");
5571ac1307abSFam Zheng     }
5572153859beSStuart Brady 
5573eb769f74SDaniel P. Berrange     qemu_add_opts(&qemu_source_opts);
557406a1e0c1SDenis V. Lunev     qemu_add_opts(&qemu_trace_opts);
55753babeb15SDaniel P. Berrange 
5576c9192973SStefan Hajnoczi     while ((c = getopt_long(argc, argv, "+:hVT:", long_options, NULL)) != -1) {
557710985131SDenis V. Lunev         switch (c) {
5578c9192973SStefan Hajnoczi         case ':':
5579c9192973SStefan Hajnoczi             missing_argument(argv[optind - 1]);
5580c9192973SStefan Hajnoczi             return 0;
55814581c16fSStefan Hajnoczi         case '?':
5582c9192973SStefan Hajnoczi             unrecognized_option(argv[optind - 1]);
5583c9192973SStefan Hajnoczi             return 0;
5584c9192973SStefan Hajnoczi         case 'h':
558510985131SDenis V. Lunev             help();
558610985131SDenis V. Lunev             return 0;
558710985131SDenis V. Lunev         case 'V':
558810985131SDenis V. Lunev             printf(QEMU_IMG_VERSION);
558910985131SDenis V. Lunev             return 0;
559006a1e0c1SDenis V. Lunev         case 'T':
559192eecfffSPaolo Bonzini             trace_opt_parse(optarg);
559206a1e0c1SDenis V. Lunev             break;
559310985131SDenis V. Lunev         }
559410985131SDenis V. Lunev     }
559510985131SDenis V. Lunev 
559610985131SDenis V. Lunev     cmdname = argv[optind];
559710985131SDenis V. Lunev 
559810985131SDenis V. Lunev     /* reset getopt_long scanning */
559910985131SDenis V. Lunev     argc -= optind;
560010985131SDenis V. Lunev     if (argc < 1) {
560110985131SDenis V. Lunev         return 0;
560210985131SDenis V. Lunev     }
560310985131SDenis V. Lunev     argv += optind;
5604d339d766SRichard W.M. Jones     qemu_reset_optind();
560510985131SDenis V. Lunev 
560606a1e0c1SDenis V. Lunev     if (!trace_init_backends()) {
560706a1e0c1SDenis V. Lunev         exit(1);
560806a1e0c1SDenis V. Lunev     }
560992eecfffSPaolo Bonzini     trace_init_file();
5610c5955f4fSRichard Henderson     qemu_set_log(LOG_TRACE, &error_fatal);
561106a1e0c1SDenis V. Lunev 
5612153859beSStuart Brady     /* find the command */
5613153859beSStuart Brady     for (cmd = img_cmds; cmd->name != NULL; cmd++) {
5614153859beSStuart Brady         if (!strcmp(cmdname, cmd->name)) {
561510985131SDenis V. Lunev             return cmd->handler(argc, argv);
5616ea2384d3Sbellard         }
5617153859beSStuart Brady     }
5618153859beSStuart Brady 
5619153859beSStuart Brady     /* not found */
5620ac1307abSFam Zheng     error_exit("Command not found: %s", cmdname);
5621ea2384d3Sbellard }
5622