xref: /openbmc/qemu/blockdev.c (revision 94d16a640a1058653327392e08c6d39eeba1e499)
1666daa68SMarkus Armbruster /*
2666daa68SMarkus Armbruster  * QEMU host block devices
3666daa68SMarkus Armbruster  *
4666daa68SMarkus Armbruster  * Copyright (c) 2003-2008 Fabrice Bellard
5666daa68SMarkus Armbruster  *
6666daa68SMarkus Armbruster  * This work is licensed under the terms of the GNU GPL, version 2 or
7666daa68SMarkus Armbruster  * later.  See the COPYING file in the top-level directory.
83618a094SMarkus Armbruster  *
93618a094SMarkus Armbruster  * This file incorporates work covered by the following copyright and
103618a094SMarkus Armbruster  * permission notice:
113618a094SMarkus Armbruster  *
123618a094SMarkus Armbruster  * Copyright (c) 2003-2008 Fabrice Bellard
133618a094SMarkus Armbruster  *
143618a094SMarkus Armbruster  * Permission is hereby granted, free of charge, to any person obtaining a copy
153618a094SMarkus Armbruster  * of this software and associated documentation files (the "Software"), to deal
163618a094SMarkus Armbruster  * in the Software without restriction, including without limitation the rights
173618a094SMarkus Armbruster  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
183618a094SMarkus Armbruster  * copies of the Software, and to permit persons to whom the Software is
193618a094SMarkus Armbruster  * furnished to do so, subject to the following conditions:
203618a094SMarkus Armbruster  *
213618a094SMarkus Armbruster  * The above copyright notice and this permission notice shall be included in
223618a094SMarkus Armbruster  * all copies or substantial portions of the Software.
233618a094SMarkus Armbruster  *
243618a094SMarkus Armbruster  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
253618a094SMarkus Armbruster  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
263618a094SMarkus Armbruster  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
273618a094SMarkus Armbruster  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
283618a094SMarkus Armbruster  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
293618a094SMarkus Armbruster  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
303618a094SMarkus Armbruster  * THE SOFTWARE.
31666daa68SMarkus Armbruster  */
32666daa68SMarkus Armbruster 
3326f54e9aSMarkus Armbruster #include "sysemu/block-backend.h"
349c17d615SPaolo Bonzini #include "sysemu/blockdev.h"
350d09e41aSPaolo Bonzini #include "hw/block/block.h"
36737e150eSPaolo Bonzini #include "block/blockjob.h"
3776f4afb4SAlberto Garcia #include "block/throttle-groups.h"
3883c9089eSPaolo Bonzini #include "monitor/monitor.h"
39d49b6836SMarkus Armbruster #include "qemu/error-report.h"
401de7afc9SPaolo Bonzini #include "qemu/option.h"
411de7afc9SPaolo Bonzini #include "qemu/config-file.h"
427b1b5d19SPaolo Bonzini #include "qapi/qmp/types.h"
43d26c9a15SKevin Wolf #include "qapi-visit.h"
44cc7a8ea7SMarkus Armbruster #include "qapi/qmp/qerror.h"
45d26c9a15SKevin Wolf #include "qapi/qmp-output-visitor.h"
469e7dac7cSPeter Lieven #include "qapi/util.h"
479c17d615SPaolo Bonzini #include "sysemu/sysemu.h"
48737e150eSPaolo Bonzini #include "block/block_int.h"
49a4dea8a9SLuiz Capitulino #include "qmp-commands.h"
5012bd451fSStefan Hajnoczi #include "trace.h"
519c17d615SPaolo Bonzini #include "sysemu/arch_init.h"
52666daa68SMarkus Armbruster 
531960966dSMarkus Armbruster static const char *const if_name[IF_COUNT] = {
541960966dSMarkus Armbruster     [IF_NONE] = "none",
551960966dSMarkus Armbruster     [IF_IDE] = "ide",
561960966dSMarkus Armbruster     [IF_SCSI] = "scsi",
571960966dSMarkus Armbruster     [IF_FLOPPY] = "floppy",
581960966dSMarkus Armbruster     [IF_PFLASH] = "pflash",
591960966dSMarkus Armbruster     [IF_MTD] = "mtd",
601960966dSMarkus Armbruster     [IF_SD] = "sd",
611960966dSMarkus Armbruster     [IF_VIRTIO] = "virtio",
621960966dSMarkus Armbruster     [IF_XEN] = "xen",
631960966dSMarkus Armbruster };
641960966dSMarkus Armbruster 
6521dff8cfSJohn Snow static int if_max_devs[IF_COUNT] = {
6627d6bf40SMarkus Armbruster     /*
6727d6bf40SMarkus Armbruster      * Do not change these numbers!  They govern how drive option
6827d6bf40SMarkus Armbruster      * index maps to unit and bus.  That mapping is ABI.
6927d6bf40SMarkus Armbruster      *
7027d6bf40SMarkus Armbruster      * All controllers used to imlement if=T drives need to support
7127d6bf40SMarkus Armbruster      * if_max_devs[T] units, for any T with if_max_devs[T] != 0.
7227d6bf40SMarkus Armbruster      * Otherwise, some index values map to "impossible" bus, unit
7327d6bf40SMarkus Armbruster      * values.
7427d6bf40SMarkus Armbruster      *
7527d6bf40SMarkus Armbruster      * For instance, if you change [IF_SCSI] to 255, -drive
7627d6bf40SMarkus Armbruster      * if=scsi,index=12 no longer means bus=1,unit=5, but
7727d6bf40SMarkus Armbruster      * bus=0,unit=12.  With an lsi53c895a controller (7 units max),
7827d6bf40SMarkus Armbruster      * the drive can't be set up.  Regression.
7927d6bf40SMarkus Armbruster      */
8027d6bf40SMarkus Armbruster     [IF_IDE] = 2,
8127d6bf40SMarkus Armbruster     [IF_SCSI] = 7,
821960966dSMarkus Armbruster };
831960966dSMarkus Armbruster 
8421dff8cfSJohn Snow /**
8521dff8cfSJohn Snow  * Boards may call this to offer board-by-board overrides
8621dff8cfSJohn Snow  * of the default, global values.
8721dff8cfSJohn Snow  */
8821dff8cfSJohn Snow void override_max_devs(BlockInterfaceType type, int max_devs)
8921dff8cfSJohn Snow {
9018e46a03SMarkus Armbruster     BlockBackend *blk;
9121dff8cfSJohn Snow     DriveInfo *dinfo;
9221dff8cfSJohn Snow 
9321dff8cfSJohn Snow     if (max_devs <= 0) {
9421dff8cfSJohn Snow         return;
9521dff8cfSJohn Snow     }
9621dff8cfSJohn Snow 
9718e46a03SMarkus Armbruster     for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
9818e46a03SMarkus Armbruster         dinfo = blk_legacy_dinfo(blk);
9921dff8cfSJohn Snow         if (dinfo->type == type) {
10021dff8cfSJohn Snow             fprintf(stderr, "Cannot override units-per-bus property of"
10121dff8cfSJohn Snow                     " the %s interface, because a drive of that type has"
10221dff8cfSJohn Snow                     " already been added.\n", if_name[type]);
10321dff8cfSJohn Snow             g_assert_not_reached();
10421dff8cfSJohn Snow         }
10521dff8cfSJohn Snow     }
10621dff8cfSJohn Snow 
10721dff8cfSJohn Snow     if_max_devs[type] = max_devs;
10821dff8cfSJohn Snow }
10921dff8cfSJohn Snow 
11014bafc54SMarkus Armbruster /*
11114bafc54SMarkus Armbruster  * We automatically delete the drive when a device using it gets
11214bafc54SMarkus Armbruster  * unplugged.  Questionable feature, but we can't just drop it.
11314bafc54SMarkus Armbruster  * Device models call blockdev_mark_auto_del() to schedule the
11414bafc54SMarkus Armbruster  * automatic deletion, and generic qdev code calls blockdev_auto_del()
11514bafc54SMarkus Armbruster  * when deletion is actually safe.
11614bafc54SMarkus Armbruster  */
1174be74634SMarkus Armbruster void blockdev_mark_auto_del(BlockBackend *blk)
11814bafc54SMarkus Armbruster {
11918e46a03SMarkus Armbruster     DriveInfo *dinfo = blk_legacy_dinfo(blk);
1204be74634SMarkus Armbruster     BlockDriverState *bs = blk_bs(blk);
12191fddb0dSStefan Hajnoczi     AioContext *aio_context;
12214bafc54SMarkus Armbruster 
12326f8b3a8SMarkus Armbruster     if (!dinfo) {
1242d246f01SKevin Wolf         return;
1252d246f01SKevin Wolf     }
1262d246f01SKevin Wolf 
1275433c24fSMax Reitz     if (bs) {
12891fddb0dSStefan Hajnoczi         aio_context = bdrv_get_aio_context(bs);
12991fddb0dSStefan Hajnoczi         aio_context_acquire(aio_context);
13091fddb0dSStefan Hajnoczi 
13112bde0eeSPaolo Bonzini         if (bs->job) {
13212bde0eeSPaolo Bonzini             block_job_cancel(bs->job);
13312bde0eeSPaolo Bonzini         }
13491fddb0dSStefan Hajnoczi 
13591fddb0dSStefan Hajnoczi         aio_context_release(aio_context);
1365433c24fSMax Reitz     }
13791fddb0dSStefan Hajnoczi 
13814bafc54SMarkus Armbruster     dinfo->auto_del = 1;
13914bafc54SMarkus Armbruster }
14014bafc54SMarkus Armbruster 
1414be74634SMarkus Armbruster void blockdev_auto_del(BlockBackend *blk)
14214bafc54SMarkus Armbruster {
14318e46a03SMarkus Armbruster     DriveInfo *dinfo = blk_legacy_dinfo(blk);
14414bafc54SMarkus Armbruster 
1450fc0f1faSRyan Harper     if (dinfo && dinfo->auto_del) {
146b9fe8a7aSMarkus Armbruster         blk_unref(blk);
14714bafc54SMarkus Armbruster     }
14814bafc54SMarkus Armbruster }
14914bafc54SMarkus Armbruster 
150d8f94e1bSJohn Snow /**
151d8f94e1bSJohn Snow  * Returns the current mapping of how many units per bus
152d8f94e1bSJohn Snow  * a particular interface can support.
153d8f94e1bSJohn Snow  *
154d8f94e1bSJohn Snow  *  A positive integer indicates n units per bus.
155d8f94e1bSJohn Snow  *  0 implies the mapping has not been established.
156d8f94e1bSJohn Snow  * -1 indicates an invalid BlockInterfaceType was given.
157d8f94e1bSJohn Snow  */
158d8f94e1bSJohn Snow int drive_get_max_devs(BlockInterfaceType type)
159d8f94e1bSJohn Snow {
160d8f94e1bSJohn Snow     if (type >= IF_IDE && type < IF_COUNT) {
161d8f94e1bSJohn Snow         return if_max_devs[type];
162d8f94e1bSJohn Snow     }
163d8f94e1bSJohn Snow 
164d8f94e1bSJohn Snow     return -1;
165d8f94e1bSJohn Snow }
166d8f94e1bSJohn Snow 
167505a7fb1SMarkus Armbruster static int drive_index_to_bus_id(BlockInterfaceType type, int index)
168505a7fb1SMarkus Armbruster {
169505a7fb1SMarkus Armbruster     int max_devs = if_max_devs[type];
170505a7fb1SMarkus Armbruster     return max_devs ? index / max_devs : 0;
171505a7fb1SMarkus Armbruster }
172505a7fb1SMarkus Armbruster 
173505a7fb1SMarkus Armbruster static int drive_index_to_unit_id(BlockInterfaceType type, int index)
174505a7fb1SMarkus Armbruster {
175505a7fb1SMarkus Armbruster     int max_devs = if_max_devs[type];
176505a7fb1SMarkus Armbruster     return max_devs ? index % max_devs : index;
177505a7fb1SMarkus Armbruster }
178505a7fb1SMarkus Armbruster 
1792292ddaeSMarkus Armbruster QemuOpts *drive_def(const char *optstr)
1802292ddaeSMarkus Armbruster {
18170b94331SMarkus Armbruster     return qemu_opts_parse_noisily(qemu_find_opts("drive"), optstr, false);
1822292ddaeSMarkus Armbruster }
1832292ddaeSMarkus Armbruster 
1842292ddaeSMarkus Armbruster QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
1855645b0f4SMarkus Armbruster                     const char *optstr)
186666daa68SMarkus Armbruster {
187666daa68SMarkus Armbruster     QemuOpts *opts;
188666daa68SMarkus Armbruster 
1892292ddaeSMarkus Armbruster     opts = drive_def(optstr);
190666daa68SMarkus Armbruster     if (!opts) {
191666daa68SMarkus Armbruster         return NULL;
192666daa68SMarkus Armbruster     }
1932292ddaeSMarkus Armbruster     if (type != IF_DEFAULT) {
194f43e47dbSMarkus Armbruster         qemu_opt_set(opts, "if", if_name[type], &error_abort);
1952292ddaeSMarkus Armbruster     }
1962292ddaeSMarkus Armbruster     if (index >= 0) {
197a8b18f8fSMarkus Armbruster         qemu_opt_set_number(opts, "index", index, &error_abort);
1982292ddaeSMarkus Armbruster     }
199666daa68SMarkus Armbruster     if (file)
200f43e47dbSMarkus Armbruster         qemu_opt_set(opts, "file", file, &error_abort);
201666daa68SMarkus Armbruster     return opts;
202666daa68SMarkus Armbruster }
203666daa68SMarkus Armbruster 
204666daa68SMarkus Armbruster DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
205666daa68SMarkus Armbruster {
20618e46a03SMarkus Armbruster     BlockBackend *blk;
207666daa68SMarkus Armbruster     DriveInfo *dinfo;
208666daa68SMarkus Armbruster 
20918e46a03SMarkus Armbruster     for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
21018e46a03SMarkus Armbruster         dinfo = blk_legacy_dinfo(blk);
21118e46a03SMarkus Armbruster         if (dinfo && dinfo->type == type
21218e46a03SMarkus Armbruster             && dinfo->bus == bus && dinfo->unit == unit) {
213666daa68SMarkus Armbruster             return dinfo;
214666daa68SMarkus Armbruster         }
21518e46a03SMarkus Armbruster     }
216666daa68SMarkus Armbruster 
217666daa68SMarkus Armbruster     return NULL;
218666daa68SMarkus Armbruster }
219666daa68SMarkus Armbruster 
220a66c9dc7SJohn Snow bool drive_check_orphaned(void)
221a66c9dc7SJohn Snow {
22218e46a03SMarkus Armbruster     BlockBackend *blk;
223a66c9dc7SJohn Snow     DriveInfo *dinfo;
224a66c9dc7SJohn Snow     bool rs = false;
225a66c9dc7SJohn Snow 
22618e46a03SMarkus Armbruster     for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
22718e46a03SMarkus Armbruster         dinfo = blk_legacy_dinfo(blk);
228a66c9dc7SJohn Snow         /* If dinfo->bdrv->dev is NULL, it has no device attached. */
229a66c9dc7SJohn Snow         /* Unless this is a default drive, this may be an oversight. */
230a7f53e26SMarkus Armbruster         if (!blk_get_attached_dev(blk) && !dinfo->is_default &&
231a66c9dc7SJohn Snow             dinfo->type != IF_NONE) {
232a66c9dc7SJohn Snow             fprintf(stderr, "Warning: Orphaned drive without device: "
233a66c9dc7SJohn Snow                     "id=%s,file=%s,if=%s,bus=%d,unit=%d\n",
2345433c24fSMax Reitz                     blk_name(blk), blk_bs(blk) ? blk_bs(blk)->filename : "",
2355433c24fSMax Reitz                     if_name[dinfo->type], dinfo->bus, dinfo->unit);
236a66c9dc7SJohn Snow             rs = true;
237a66c9dc7SJohn Snow         }
238a66c9dc7SJohn Snow     }
239a66c9dc7SJohn Snow 
240a66c9dc7SJohn Snow     return rs;
241a66c9dc7SJohn Snow }
242a66c9dc7SJohn Snow 
243f1bd51acSMarkus Armbruster DriveInfo *drive_get_by_index(BlockInterfaceType type, int index)
244f1bd51acSMarkus Armbruster {
245f1bd51acSMarkus Armbruster     return drive_get(type,
246f1bd51acSMarkus Armbruster                      drive_index_to_bus_id(type, index),
247f1bd51acSMarkus Armbruster                      drive_index_to_unit_id(type, index));
248f1bd51acSMarkus Armbruster }
249f1bd51acSMarkus Armbruster 
250666daa68SMarkus Armbruster int drive_get_max_bus(BlockInterfaceType type)
251666daa68SMarkus Armbruster {
252666daa68SMarkus Armbruster     int max_bus;
25318e46a03SMarkus Armbruster     BlockBackend *blk;
254666daa68SMarkus Armbruster     DriveInfo *dinfo;
255666daa68SMarkus Armbruster 
256666daa68SMarkus Armbruster     max_bus = -1;
25718e46a03SMarkus Armbruster     for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
25818e46a03SMarkus Armbruster         dinfo = blk_legacy_dinfo(blk);
25918e46a03SMarkus Armbruster         if (dinfo && dinfo->type == type && dinfo->bus > max_bus) {
260666daa68SMarkus Armbruster             max_bus = dinfo->bus;
261666daa68SMarkus Armbruster         }
26218e46a03SMarkus Armbruster     }
263666daa68SMarkus Armbruster     return max_bus;
264666daa68SMarkus Armbruster }
265666daa68SMarkus Armbruster 
26613839974SMarkus Armbruster /* Get a block device.  This should only be used for single-drive devices
26713839974SMarkus Armbruster    (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
26813839974SMarkus Armbruster    appropriate bus.  */
26913839974SMarkus Armbruster DriveInfo *drive_get_next(BlockInterfaceType type)
27013839974SMarkus Armbruster {
27113839974SMarkus Armbruster     static int next_block_unit[IF_COUNT];
27213839974SMarkus Armbruster 
27313839974SMarkus Armbruster     return drive_get(type, 0, next_block_unit[type]++);
27413839974SMarkus Armbruster }
27513839974SMarkus Armbruster 
276666daa68SMarkus Armbruster static void bdrv_format_print(void *opaque, const char *name)
277666daa68SMarkus Armbruster {
278807105a7SMarkus Armbruster     error_printf(" %s", name);
279666daa68SMarkus Armbruster }
280666daa68SMarkus Armbruster 
281aa398a5cSStefan Hajnoczi typedef struct {
282aa398a5cSStefan Hajnoczi     QEMUBH *bh;
283fa510ebfSFam Zheng     BlockDriverState *bs;
284fa510ebfSFam Zheng } BDRVPutRefBH;
285aa398a5cSStefan Hajnoczi 
286b681072dSKevin Wolf static int parse_block_error_action(const char *buf, bool is_read, Error **errp)
287666daa68SMarkus Armbruster {
288666daa68SMarkus Armbruster     if (!strcmp(buf, "ignore")) {
28992aa5c6dSPaolo Bonzini         return BLOCKDEV_ON_ERROR_IGNORE;
290666daa68SMarkus Armbruster     } else if (!is_read && !strcmp(buf, "enospc")) {
29192aa5c6dSPaolo Bonzini         return BLOCKDEV_ON_ERROR_ENOSPC;
292666daa68SMarkus Armbruster     } else if (!strcmp(buf, "stop")) {
29392aa5c6dSPaolo Bonzini         return BLOCKDEV_ON_ERROR_STOP;
294666daa68SMarkus Armbruster     } else if (!strcmp(buf, "report")) {
29592aa5c6dSPaolo Bonzini         return BLOCKDEV_ON_ERROR_REPORT;
296666daa68SMarkus Armbruster     } else {
297b681072dSKevin Wolf         error_setg(errp, "'%s' invalid %s error action",
298666daa68SMarkus Armbruster                    buf, is_read ? "read" : "write");
299666daa68SMarkus Armbruster         return -1;
300666daa68SMarkus Armbruster     }
301666daa68SMarkus Armbruster }
302666daa68SMarkus Armbruster 
303cc0681c4SBenoît Canet static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
3040563e191SZhi Yong Wu {
305cc0681c4SBenoît Canet     if (throttle_conflicting(cfg)) {
306cc0681c4SBenoît Canet         error_setg(errp, "bps/iops/max total values and read/write values"
307c546194fSStefan Hajnoczi                          " cannot be used at the same time");
3080563e191SZhi Yong Wu         return false;
3090563e191SZhi Yong Wu     }
3100563e191SZhi Yong Wu 
311cc0681c4SBenoît Canet     if (!throttle_is_valid(cfg)) {
312cc0681c4SBenoît Canet         error_setg(errp, "bps/iops/maxs values must be 0 or greater");
3137d81c141SStefan Hajnoczi         return false;
3147d81c141SStefan Hajnoczi     }
3157d81c141SStefan Hajnoczi 
316ee2bdc33SStefan Hajnoczi     if (throttle_max_is_missing_limit(cfg)) {
317ee2bdc33SStefan Hajnoczi         error_setg(errp, "bps_max/iops_max require corresponding"
318ee2bdc33SStefan Hajnoczi                          " bps/iops values");
319ee2bdc33SStefan Hajnoczi         return false;
320ee2bdc33SStefan Hajnoczi     }
321ee2bdc33SStefan Hajnoczi 
3220563e191SZhi Yong Wu     return true;
3230563e191SZhi Yong Wu }
3240563e191SZhi Yong Wu 
32533cb7dc8SKevin Wolf typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
32633cb7dc8SKevin Wolf 
327fbf8175eSMax Reitz /* All parameters but @opts are optional and may be set to NULL. */
328fbf8175eSMax Reitz static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags,
329fbf8175eSMax Reitz     const char **throttling_group, ThrottleConfig *throttle_cfg,
330fbf8175eSMax Reitz     BlockdevDetectZeroesOptions *detect_zeroes, Error **errp)
331fbf8175eSMax Reitz {
332fbf8175eSMax Reitz     const char *discard;
333fbf8175eSMax Reitz     Error *local_error = NULL;
334fbf8175eSMax Reitz     const char *aio;
335fbf8175eSMax Reitz 
336fbf8175eSMax Reitz     if (bdrv_flags) {
337fbf8175eSMax Reitz         if (!qemu_opt_get_bool(opts, "read-only", false)) {
338fbf8175eSMax Reitz             *bdrv_flags |= BDRV_O_RDWR;
339fbf8175eSMax Reitz         }
340fbf8175eSMax Reitz         if (qemu_opt_get_bool(opts, "copy-on-read", false)) {
341fbf8175eSMax Reitz             *bdrv_flags |= BDRV_O_COPY_ON_READ;
342fbf8175eSMax Reitz         }
343fbf8175eSMax Reitz 
344fbf8175eSMax Reitz         if ((discard = qemu_opt_get(opts, "discard")) != NULL) {
345fbf8175eSMax Reitz             if (bdrv_parse_discard_flags(discard, bdrv_flags) != 0) {
346fbf8175eSMax Reitz                 error_setg(errp, "Invalid discard option");
347fbf8175eSMax Reitz                 return;
348fbf8175eSMax Reitz             }
349fbf8175eSMax Reitz         }
350fbf8175eSMax Reitz 
351fbf8175eSMax Reitz         if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_WB, true)) {
352fbf8175eSMax Reitz             *bdrv_flags |= BDRV_O_CACHE_WB;
353fbf8175eSMax Reitz         }
354fbf8175eSMax Reitz         if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_DIRECT, false)) {
355fbf8175eSMax Reitz             *bdrv_flags |= BDRV_O_NOCACHE;
356fbf8175eSMax Reitz         }
357fbf8175eSMax Reitz         if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) {
358fbf8175eSMax Reitz             *bdrv_flags |= BDRV_O_NO_FLUSH;
359fbf8175eSMax Reitz         }
360fbf8175eSMax Reitz 
361fbf8175eSMax Reitz         if ((aio = qemu_opt_get(opts, "aio")) != NULL) {
362fbf8175eSMax Reitz             if (!strcmp(aio, "native")) {
363fbf8175eSMax Reitz                 *bdrv_flags |= BDRV_O_NATIVE_AIO;
364fbf8175eSMax Reitz             } else if (!strcmp(aio, "threads")) {
365fbf8175eSMax Reitz                 /* this is the default */
366fbf8175eSMax Reitz             } else {
367fbf8175eSMax Reitz                error_setg(errp, "invalid aio option");
368fbf8175eSMax Reitz                return;
369fbf8175eSMax Reitz             }
370fbf8175eSMax Reitz         }
371fbf8175eSMax Reitz     }
372fbf8175eSMax Reitz 
373fbf8175eSMax Reitz     /* disk I/O throttling */
374fbf8175eSMax Reitz     if (throttling_group) {
375fbf8175eSMax Reitz         *throttling_group = qemu_opt_get(opts, "throttling.group");
376fbf8175eSMax Reitz     }
377fbf8175eSMax Reitz 
378fbf8175eSMax Reitz     if (throttle_cfg) {
379fbf8175eSMax Reitz         memset(throttle_cfg, 0, sizeof(*throttle_cfg));
380fbf8175eSMax Reitz         throttle_cfg->buckets[THROTTLE_BPS_TOTAL].avg =
381fbf8175eSMax Reitz             qemu_opt_get_number(opts, "throttling.bps-total", 0);
382fbf8175eSMax Reitz         throttle_cfg->buckets[THROTTLE_BPS_READ].avg  =
383fbf8175eSMax Reitz             qemu_opt_get_number(opts, "throttling.bps-read", 0);
384fbf8175eSMax Reitz         throttle_cfg->buckets[THROTTLE_BPS_WRITE].avg =
385fbf8175eSMax Reitz             qemu_opt_get_number(opts, "throttling.bps-write", 0);
386fbf8175eSMax Reitz         throttle_cfg->buckets[THROTTLE_OPS_TOTAL].avg =
387fbf8175eSMax Reitz             qemu_opt_get_number(opts, "throttling.iops-total", 0);
388fbf8175eSMax Reitz         throttle_cfg->buckets[THROTTLE_OPS_READ].avg =
389fbf8175eSMax Reitz             qemu_opt_get_number(opts, "throttling.iops-read", 0);
390fbf8175eSMax Reitz         throttle_cfg->buckets[THROTTLE_OPS_WRITE].avg =
391fbf8175eSMax Reitz             qemu_opt_get_number(opts, "throttling.iops-write", 0);
392fbf8175eSMax Reitz 
393fbf8175eSMax Reitz         throttle_cfg->buckets[THROTTLE_BPS_TOTAL].max =
394fbf8175eSMax Reitz             qemu_opt_get_number(opts, "throttling.bps-total-max", 0);
395fbf8175eSMax Reitz         throttle_cfg->buckets[THROTTLE_BPS_READ].max  =
396fbf8175eSMax Reitz             qemu_opt_get_number(opts, "throttling.bps-read-max", 0);
397fbf8175eSMax Reitz         throttle_cfg->buckets[THROTTLE_BPS_WRITE].max =
398fbf8175eSMax Reitz             qemu_opt_get_number(opts, "throttling.bps-write-max", 0);
399fbf8175eSMax Reitz         throttle_cfg->buckets[THROTTLE_OPS_TOTAL].max =
400fbf8175eSMax Reitz             qemu_opt_get_number(opts, "throttling.iops-total-max", 0);
401fbf8175eSMax Reitz         throttle_cfg->buckets[THROTTLE_OPS_READ].max =
402fbf8175eSMax Reitz             qemu_opt_get_number(opts, "throttling.iops-read-max", 0);
403fbf8175eSMax Reitz         throttle_cfg->buckets[THROTTLE_OPS_WRITE].max =
404fbf8175eSMax Reitz             qemu_opt_get_number(opts, "throttling.iops-write-max", 0);
405fbf8175eSMax Reitz 
406fbf8175eSMax Reitz         throttle_cfg->op_size =
407fbf8175eSMax Reitz             qemu_opt_get_number(opts, "throttling.iops-size", 0);
408fbf8175eSMax Reitz 
409fbf8175eSMax Reitz         if (!check_throttle_config(throttle_cfg, errp)) {
410fbf8175eSMax Reitz             return;
411fbf8175eSMax Reitz         }
412fbf8175eSMax Reitz     }
413fbf8175eSMax Reitz 
414fbf8175eSMax Reitz     if (detect_zeroes) {
415fbf8175eSMax Reitz         *detect_zeroes =
416fbf8175eSMax Reitz             qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
417fbf8175eSMax Reitz                             qemu_opt_get(opts, "detect-zeroes"),
418fbf8175eSMax Reitz                             BLOCKDEV_DETECT_ZEROES_OPTIONS_MAX,
419fbf8175eSMax Reitz                             BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
420fbf8175eSMax Reitz                             &local_error);
421fbf8175eSMax Reitz         if (local_error) {
422fbf8175eSMax Reitz             error_propagate(errp, local_error);
423fbf8175eSMax Reitz             return;
424fbf8175eSMax Reitz         }
425fbf8175eSMax Reitz 
426fbf8175eSMax Reitz         if (bdrv_flags &&
427fbf8175eSMax Reitz             *detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP &&
428fbf8175eSMax Reitz             !(*bdrv_flags & BDRV_O_UNMAP))
429fbf8175eSMax Reitz         {
430fbf8175eSMax Reitz             error_setg(errp, "setting detect-zeroes to unmap is not allowed "
431fbf8175eSMax Reitz                              "without setting discard operation to unmap");
432fbf8175eSMax Reitz             return;
433fbf8175eSMax Reitz         }
434fbf8175eSMax Reitz     }
435fbf8175eSMax Reitz }
436fbf8175eSMax Reitz 
437f298d071SKevin Wolf /* Takes the ownership of bs_opts */
43818e46a03SMarkus Armbruster static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
439b681072dSKevin Wolf                                    Error **errp)
440666daa68SMarkus Armbruster {
441666daa68SMarkus Armbruster     const char *buf;
442666daa68SMarkus Armbruster     int bdrv_flags = 0;
443666daa68SMarkus Armbruster     int on_read_error, on_write_error;
44426f54e9aSMarkus Armbruster     BlockBackend *blk;
445a0f1eab1SMarkus Armbruster     BlockDriverState *bs;
446cc0681c4SBenoît Canet     ThrottleConfig cfg;
447666daa68SMarkus Armbruster     int snapshot = 0;
448c546194fSStefan Hajnoczi     Error *error = NULL;
4490006383eSKevin Wolf     QemuOpts *opts;
4500006383eSKevin Wolf     const char *id;
45174fe54f2SKevin Wolf     bool has_driver_specific_opts;
452fbf8175eSMax Reitz     BlockdevDetectZeroesOptions detect_zeroes =
453fbf8175eSMax Reitz         BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF;
454fbf8175eSMax Reitz     const char *throttling_group = NULL;
455666daa68SMarkus Armbruster 
456f298d071SKevin Wolf     /* Check common options by copying from bs_opts to opts, all other options
457f298d071SKevin Wolf      * stay in bs_opts for processing by bdrv_open(). */
458f298d071SKevin Wolf     id = qdict_get_try_str(bs_opts, "id");
4590006383eSKevin Wolf     opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error);
46084d18f06SMarkus Armbruster     if (error) {
461b681072dSKevin Wolf         error_propagate(errp, error);
4626376f952SMarkus Armbruster         goto err_no_opts;
4630006383eSKevin Wolf     }
4640006383eSKevin Wolf 
4650006383eSKevin Wolf     qemu_opts_absorb_qdict(opts, bs_opts, &error);
46684d18f06SMarkus Armbruster     if (error) {
467b681072dSKevin Wolf         error_propagate(errp, error);
468ec9c10d2SStefan Hajnoczi         goto early_err;
4690006383eSKevin Wolf     }
4700006383eSKevin Wolf 
4710006383eSKevin Wolf     if (id) {
4720006383eSKevin Wolf         qdict_del(bs_opts, "id");
4730006383eSKevin Wolf     }
4740006383eSKevin Wolf 
47574fe54f2SKevin Wolf     has_driver_specific_opts = !!qdict_size(bs_opts);
47674fe54f2SKevin Wolf 
477666daa68SMarkus Armbruster     /* extract parameters */
478666daa68SMarkus Armbruster     snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
479666daa68SMarkus Armbruster 
480fbf8175eSMax Reitz     extract_common_blockdev_options(opts, &bdrv_flags, &throttling_group, &cfg,
481fbf8175eSMax Reitz                                     &detect_zeroes, &error);
482fbf8175eSMax Reitz     if (error) {
483fbf8175eSMax Reitz         error_propagate(errp, error);
484ec9c10d2SStefan Hajnoczi         goto early_err;
485a9384affSPaolo Bonzini     }
486666daa68SMarkus Armbruster 
487666daa68SMarkus Armbruster     if ((buf = qemu_opt_get(opts, "format")) != NULL) {
488c8057f95SPeter Maydell         if (is_help_option(buf)) {
489807105a7SMarkus Armbruster             error_printf("Supported formats:");
490666daa68SMarkus Armbruster             bdrv_iterate_format(bdrv_format_print, NULL);
491807105a7SMarkus Armbruster             error_printf("\n");
492ec9c10d2SStefan Hajnoczi             goto early_err;
493666daa68SMarkus Armbruster         }
49474fe54f2SKevin Wolf 
495e4342ce5SMax Reitz         if (qdict_haskey(bs_opts, "driver")) {
496e4342ce5SMax Reitz             error_setg(errp, "Cannot specify both 'driver' and 'format'");
497ec9c10d2SStefan Hajnoczi             goto early_err;
4986db5f5d6SMike Qiu         }
499e4342ce5SMax Reitz         qdict_put(bs_opts, "driver", qstring_from_str(buf));
500666daa68SMarkus Armbruster     }
501666daa68SMarkus Armbruster 
50292aa5c6dSPaolo Bonzini     on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
503666daa68SMarkus Armbruster     if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
504b681072dSKevin Wolf         on_write_error = parse_block_error_action(buf, 0, &error);
50584d18f06SMarkus Armbruster         if (error) {
506b681072dSKevin Wolf             error_propagate(errp, error);
507ec9c10d2SStefan Hajnoczi             goto early_err;
508666daa68SMarkus Armbruster         }
509666daa68SMarkus Armbruster     }
510666daa68SMarkus Armbruster 
51192aa5c6dSPaolo Bonzini     on_read_error = BLOCKDEV_ON_ERROR_REPORT;
512666daa68SMarkus Armbruster     if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
513b681072dSKevin Wolf         on_read_error = parse_block_error_action(buf, 1, &error);
51484d18f06SMarkus Armbruster         if (error) {
515b681072dSKevin Wolf             error_propagate(errp, error);
516ec9c10d2SStefan Hajnoczi             goto early_err;
517666daa68SMarkus Armbruster         }
518666daa68SMarkus Armbruster     }
519666daa68SMarkus Armbruster 
520666daa68SMarkus Armbruster     if (snapshot) {
521666daa68SMarkus Armbruster         /* always use cache=unsafe with snapshot */
522666daa68SMarkus Armbruster         bdrv_flags &= ~BDRV_O_CACHE_MASK;
523666daa68SMarkus Armbruster         bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
524666daa68SMarkus Armbruster     }
525666daa68SMarkus Armbruster 
5265ec18f8cSMax Reitz     /* init */
5275ec18f8cSMax Reitz     if ((!file || !*file) && !has_driver_specific_opts) {
5285ec18f8cSMax Reitz         BlockBackendRootState *blk_rs;
5295ec18f8cSMax Reitz 
5305ec18f8cSMax Reitz         blk = blk_new(qemu_opts_id(opts), errp);
5315ec18f8cSMax Reitz         if (!blk) {
5325ec18f8cSMax Reitz             goto early_err;
5335ec18f8cSMax Reitz         }
5345ec18f8cSMax Reitz 
5355ec18f8cSMax Reitz         blk_rs = blk_get_root_state(blk);
5365ec18f8cSMax Reitz         blk_rs->open_flags    = bdrv_flags;
537fbf8175eSMax Reitz         blk_rs->read_only     = !(bdrv_flags & BDRV_O_RDWR);
5385ec18f8cSMax Reitz         blk_rs->detect_zeroes = detect_zeroes;
5395ec18f8cSMax Reitz 
5405ec18f8cSMax Reitz         if (throttle_enabled(&cfg)) {
5415ec18f8cSMax Reitz             if (!throttling_group) {
5425ec18f8cSMax Reitz                 throttling_group = blk_name(blk);
5435ec18f8cSMax Reitz             }
5445ec18f8cSMax Reitz             blk_rs->throttle_group = g_strdup(throttling_group);
5455ec18f8cSMax Reitz             blk_rs->throttle_state = throttle_group_incref(throttling_group);
5465ec18f8cSMax Reitz             blk_rs->throttle_state->cfg = cfg;
5475ec18f8cSMax Reitz         }
5485ec18f8cSMax Reitz 
5495ec18f8cSMax Reitz         QDECREF(bs_opts);
5505ec18f8cSMax Reitz     } else {
5515ec18f8cSMax Reitz         if (file && !*file) {
5525ec18f8cSMax Reitz             file = NULL;
5535ec18f8cSMax Reitz         }
5545ec18f8cSMax Reitz 
555e4342ce5SMax Reitz         blk = blk_new_open(qemu_opts_id(opts), file, NULL, bs_opts, bdrv_flags,
556e4342ce5SMax Reitz                            errp);
557e4342ce5SMax Reitz         if (!blk) {
558e4342ce5SMax Reitz             goto err_no_bs_opts;
559e4342ce5SMax Reitz         }
560e4342ce5SMax Reitz         bs = blk_bs(blk);
5610006383eSKevin Wolf 
562e4342ce5SMax Reitz         bs->detect_zeroes = detect_zeroes;
563e4342ce5SMax Reitz 
564e4342ce5SMax Reitz         /* disk I/O throttling */
565e4342ce5SMax Reitz         if (throttle_enabled(&cfg)) {
56676f4afb4SAlberto Garcia             if (!throttling_group) {
56776f4afb4SAlberto Garcia                 throttling_group = blk_name(blk);
56876f4afb4SAlberto Garcia             }
56976f4afb4SAlberto Garcia             bdrv_io_limits_enable(bs, throttling_group);
570e4342ce5SMax Reitz             bdrv_set_io_limits(bs, &cfg);
571666daa68SMarkus Armbruster         }
572666daa68SMarkus Armbruster 
573a0f1eab1SMarkus Armbruster         if (bdrv_key_required(bs)) {
574666daa68SMarkus Armbruster             autostart = 0;
575a0f1eab1SMarkus Armbruster         }
5765ec18f8cSMax Reitz     }
5775ec18f8cSMax Reitz 
5785ec18f8cSMax Reitz     blk_set_on_error(blk, on_read_error, on_write_error);
5790006383eSKevin Wolf 
580e4342ce5SMax Reitz err_no_bs_opts:
5810006383eSKevin Wolf     qemu_opts_del(opts);
58218e46a03SMarkus Armbruster     return blk;
583a9ae2bffSMarkus Armbruster 
584ec9c10d2SStefan Hajnoczi early_err:
585ec9c10d2SStefan Hajnoczi     qemu_opts_del(opts);
5866376f952SMarkus Armbruster err_no_opts:
5876376f952SMarkus Armbruster     QDECREF(bs_opts);
588a9ae2bffSMarkus Armbruster     return NULL;
589666daa68SMarkus Armbruster }
590666daa68SMarkus Armbruster 
591bd745e23SMax Reitz static QemuOptsList qemu_root_bds_opts;
592bd745e23SMax Reitz 
593bd745e23SMax Reitz /* Takes the ownership of bs_opts */
594bd745e23SMax Reitz static BlockDriverState *bds_tree_init(QDict *bs_opts, Error **errp)
595bd745e23SMax Reitz {
596bd745e23SMax Reitz     BlockDriverState *bs;
597bd745e23SMax Reitz     QemuOpts *opts;
598bd745e23SMax Reitz     Error *local_error = NULL;
599bd745e23SMax Reitz     BlockdevDetectZeroesOptions detect_zeroes;
600bd745e23SMax Reitz     int ret;
601bd745e23SMax Reitz     int bdrv_flags = 0;
602bd745e23SMax Reitz 
603bd745e23SMax Reitz     opts = qemu_opts_create(&qemu_root_bds_opts, NULL, 1, errp);
604bd745e23SMax Reitz     if (!opts) {
605bd745e23SMax Reitz         goto fail;
606bd745e23SMax Reitz     }
607bd745e23SMax Reitz 
608bd745e23SMax Reitz     qemu_opts_absorb_qdict(opts, bs_opts, &local_error);
609bd745e23SMax Reitz     if (local_error) {
610bd745e23SMax Reitz         error_propagate(errp, local_error);
611bd745e23SMax Reitz         goto fail;
612bd745e23SMax Reitz     }
613bd745e23SMax Reitz 
614bd745e23SMax Reitz     extract_common_blockdev_options(opts, &bdrv_flags, NULL, NULL,
615bd745e23SMax Reitz                                     &detect_zeroes, &local_error);
616bd745e23SMax Reitz     if (local_error) {
617bd745e23SMax Reitz         error_propagate(errp, local_error);
618bd745e23SMax Reitz         goto fail;
619bd745e23SMax Reitz     }
620bd745e23SMax Reitz 
621bd745e23SMax Reitz     bs = NULL;
622bd745e23SMax Reitz     ret = bdrv_open(&bs, NULL, NULL, bs_opts, bdrv_flags, errp);
623bd745e23SMax Reitz     if (ret < 0) {
624bd745e23SMax Reitz         goto fail_no_bs_opts;
625bd745e23SMax Reitz     }
626bd745e23SMax Reitz 
627bd745e23SMax Reitz     bs->detect_zeroes = detect_zeroes;
628bd745e23SMax Reitz 
629bd745e23SMax Reitz fail_no_bs_opts:
630bd745e23SMax Reitz     qemu_opts_del(opts);
631bd745e23SMax Reitz     return bs;
632bd745e23SMax Reitz 
633bd745e23SMax Reitz fail:
634bd745e23SMax Reitz     qemu_opts_del(opts);
635bd745e23SMax Reitz     QDECREF(bs_opts);
636bd745e23SMax Reitz     return NULL;
637bd745e23SMax Reitz }
638bd745e23SMax Reitz 
6395abbf0eeSKevin Wolf static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to,
6405abbf0eeSKevin Wolf                             Error **errp)
64157975222SKevin Wolf {
64257975222SKevin Wolf     const char *value;
64357975222SKevin Wolf 
64457975222SKevin Wolf     value = qemu_opt_get(opts, from);
64557975222SKevin Wolf     if (value) {
6465abbf0eeSKevin Wolf         if (qemu_opt_find(opts, to)) {
6475abbf0eeSKevin Wolf             error_setg(errp, "'%s' and its alias '%s' can't be used at the "
6485abbf0eeSKevin Wolf                        "same time", to, from);
6495abbf0eeSKevin Wolf             return;
6505abbf0eeSKevin Wolf         }
65120d6cd47SJun Li     }
65220d6cd47SJun Li 
65320d6cd47SJun Li     /* rename all items in opts */
65420d6cd47SJun Li     while ((value = qemu_opt_get(opts, from))) {
655f43e47dbSMarkus Armbruster         qemu_opt_set(opts, to, value, &error_abort);
65657975222SKevin Wolf         qemu_opt_unset(opts, from);
65757975222SKevin Wolf     }
65857975222SKevin Wolf }
65957975222SKevin Wolf 
66033cb7dc8SKevin Wolf QemuOptsList qemu_legacy_drive_opts = {
66133cb7dc8SKevin Wolf     .name = "drive",
66233cb7dc8SKevin Wolf     .head = QTAILQ_HEAD_INITIALIZER(qemu_legacy_drive_opts.head),
66333cb7dc8SKevin Wolf     .desc = {
66433cb7dc8SKevin Wolf         {
66587a899c5SKevin Wolf             .name = "bus",
66687a899c5SKevin Wolf             .type = QEMU_OPT_NUMBER,
66787a899c5SKevin Wolf             .help = "bus number",
66887a899c5SKevin Wolf         },{
66987a899c5SKevin Wolf             .name = "unit",
67087a899c5SKevin Wolf             .type = QEMU_OPT_NUMBER,
67187a899c5SKevin Wolf             .help = "unit number (i.e. lun for scsi)",
67287a899c5SKevin Wolf         },{
67387a899c5SKevin Wolf             .name = "index",
67487a899c5SKevin Wolf             .type = QEMU_OPT_NUMBER,
67587a899c5SKevin Wolf             .help = "index number",
67687a899c5SKevin Wolf         },{
67733cb7dc8SKevin Wolf             .name = "media",
67833cb7dc8SKevin Wolf             .type = QEMU_OPT_STRING,
67933cb7dc8SKevin Wolf             .help = "media type (disk, cdrom)",
680593d464bSKevin Wolf         },{
681593d464bSKevin Wolf             .name = "if",
682593d464bSKevin Wolf             .type = QEMU_OPT_STRING,
683593d464bSKevin Wolf             .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
684b41a7338SKevin Wolf         },{
685b41a7338SKevin Wolf             .name = "cyls",
686b41a7338SKevin Wolf             .type = QEMU_OPT_NUMBER,
687b41a7338SKevin Wolf             .help = "number of cylinders (ide disk geometry)",
688b41a7338SKevin Wolf         },{
689b41a7338SKevin Wolf             .name = "heads",
690b41a7338SKevin Wolf             .type = QEMU_OPT_NUMBER,
691b41a7338SKevin Wolf             .help = "number of heads (ide disk geometry)",
692b41a7338SKevin Wolf         },{
693b41a7338SKevin Wolf             .name = "secs",
694b41a7338SKevin Wolf             .type = QEMU_OPT_NUMBER,
695b41a7338SKevin Wolf             .help = "number of sectors (ide disk geometry)",
696b41a7338SKevin Wolf         },{
697b41a7338SKevin Wolf             .name = "trans",
698b41a7338SKevin Wolf             .type = QEMU_OPT_STRING,
699b41a7338SKevin Wolf             .help = "chs translation (auto, lba, none)",
70026929298SKevin Wolf         },{
70126929298SKevin Wolf             .name = "boot",
70226929298SKevin Wolf             .type = QEMU_OPT_BOOL,
70326929298SKevin Wolf             .help = "(deprecated, ignored)",
704394c7d4dSKevin Wolf         },{
705394c7d4dSKevin Wolf             .name = "addr",
706394c7d4dSKevin Wolf             .type = QEMU_OPT_STRING,
707394c7d4dSKevin Wolf             .help = "pci address (virtio only)",
708d095b465SMax Reitz         },{
709bcf83158SKevin Wolf             .name = "serial",
710bcf83158SKevin Wolf             .type = QEMU_OPT_STRING,
711bcf83158SKevin Wolf             .help = "disk serial number",
712bcf83158SKevin Wolf         },{
713d095b465SMax Reitz             .name = "file",
714d095b465SMax Reitz             .type = QEMU_OPT_STRING,
715d095b465SMax Reitz             .help = "file name",
71633cb7dc8SKevin Wolf         },
7170ebd24e0SKevin Wolf 
7180ebd24e0SKevin Wolf         /* Options that are passed on, but have special semantics with -drive */
7190ebd24e0SKevin Wolf         {
7200ebd24e0SKevin Wolf             .name = "read-only",
7210ebd24e0SKevin Wolf             .type = QEMU_OPT_BOOL,
7220ebd24e0SKevin Wolf             .help = "open drive file as read-only",
7230ebd24e0SKevin Wolf         },{
724ee13ed1cSKevin Wolf             .name = "rerror",
725ee13ed1cSKevin Wolf             .type = QEMU_OPT_STRING,
726ee13ed1cSKevin Wolf             .help = "read error action",
727ee13ed1cSKevin Wolf         },{
728ee13ed1cSKevin Wolf             .name = "werror",
729ee13ed1cSKevin Wolf             .type = QEMU_OPT_STRING,
730ee13ed1cSKevin Wolf             .help = "write error action",
731ee13ed1cSKevin Wolf         },{
7320ebd24e0SKevin Wolf             .name = "copy-on-read",
7330ebd24e0SKevin Wolf             .type = QEMU_OPT_BOOL,
7340ebd24e0SKevin Wolf             .help = "copy read data from backing file into image file",
7350ebd24e0SKevin Wolf         },
7360ebd24e0SKevin Wolf 
73733cb7dc8SKevin Wolf         { /* end of list */ }
73833cb7dc8SKevin Wolf     },
73933cb7dc8SKevin Wolf };
74033cb7dc8SKevin Wolf 
74160e19e06SMarkus Armbruster DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
74257975222SKevin Wolf {
74329c4e2b5SKevin Wolf     const char *value;
74418e46a03SMarkus Armbruster     BlockBackend *blk;
74533cb7dc8SKevin Wolf     DriveInfo *dinfo = NULL;
746f298d071SKevin Wolf     QDict *bs_opts;
74733cb7dc8SKevin Wolf     QemuOpts *legacy_opts;
74833cb7dc8SKevin Wolf     DriveMediaType media = MEDIA_DISK;
749593d464bSKevin Wolf     BlockInterfaceType type;
750b41a7338SKevin Wolf     int cyls, heads, secs, translation;
75187a899c5SKevin Wolf     int max_devs, bus_id, unit_id, index;
752394c7d4dSKevin Wolf     const char *devaddr;
753ee13ed1cSKevin Wolf     const char *werror, *rerror;
754a7fdbcf0SFam Zheng     bool read_only = false;
755a7fdbcf0SFam Zheng     bool copy_on_read;
756bcf83158SKevin Wolf     const char *serial;
757d095b465SMax Reitz     const char *filename;
75833cb7dc8SKevin Wolf     Error *local_err = NULL;
759247147fbSKevin Wolf     int i;
76029c4e2b5SKevin Wolf 
76157975222SKevin Wolf     /* Change legacy command line options into QMP ones */
762247147fbSKevin Wolf     static const struct {
763247147fbSKevin Wolf         const char *from;
764247147fbSKevin Wolf         const char *to;
765247147fbSKevin Wolf     } opt_renames[] = {
766247147fbSKevin Wolf         { "iops",           "throttling.iops-total" },
767247147fbSKevin Wolf         { "iops_rd",        "throttling.iops-read" },
768247147fbSKevin Wolf         { "iops_wr",        "throttling.iops-write" },
76957975222SKevin Wolf 
770247147fbSKevin Wolf         { "bps",            "throttling.bps-total" },
771247147fbSKevin Wolf         { "bps_rd",         "throttling.bps-read" },
772247147fbSKevin Wolf         { "bps_wr",         "throttling.bps-write" },
77357975222SKevin Wolf 
774247147fbSKevin Wolf         { "iops_max",       "throttling.iops-total-max" },
775247147fbSKevin Wolf         { "iops_rd_max",    "throttling.iops-read-max" },
776247147fbSKevin Wolf         { "iops_wr_max",    "throttling.iops-write-max" },
7773e9fab69SBenoît Canet 
778247147fbSKevin Wolf         { "bps_max",        "throttling.bps-total-max" },
779247147fbSKevin Wolf         { "bps_rd_max",     "throttling.bps-read-max" },
780247147fbSKevin Wolf         { "bps_wr_max",     "throttling.bps-write-max" },
7813e9fab69SBenoît Canet 
782247147fbSKevin Wolf         { "iops_size",      "throttling.iops-size" },
7832024c1dfSBenoît Canet 
78476f4afb4SAlberto Garcia         { "group",          "throttling.group" },
78576f4afb4SAlberto Garcia 
786247147fbSKevin Wolf         { "readonly",       "read-only" },
787247147fbSKevin Wolf     };
788247147fbSKevin Wolf 
789247147fbSKevin Wolf     for (i = 0; i < ARRAY_SIZE(opt_renames); i++) {
7905abbf0eeSKevin Wolf         qemu_opt_rename(all_opts, opt_renames[i].from, opt_renames[i].to,
7915abbf0eeSKevin Wolf                         &local_err);
7925abbf0eeSKevin Wolf         if (local_err) {
793565f65d2SMarkus Armbruster             error_report_err(local_err);
7945abbf0eeSKevin Wolf             return NULL;
7955abbf0eeSKevin Wolf         }
796247147fbSKevin Wolf     }
7970f227a94SKevin Wolf 
79829c4e2b5SKevin Wolf     value = qemu_opt_get(all_opts, "cache");
79929c4e2b5SKevin Wolf     if (value) {
80029c4e2b5SKevin Wolf         int flags = 0;
80129c4e2b5SKevin Wolf 
80229c4e2b5SKevin Wolf         if (bdrv_parse_cache_flags(value, &flags) != 0) {
80329c4e2b5SKevin Wolf             error_report("invalid cache option");
80429c4e2b5SKevin Wolf             return NULL;
80529c4e2b5SKevin Wolf         }
80629c4e2b5SKevin Wolf 
80729c4e2b5SKevin Wolf         /* Specific options take precedence */
80854861b92SKevin Wolf         if (!qemu_opt_get(all_opts, BDRV_OPT_CACHE_WB)) {
80954861b92SKevin Wolf             qemu_opt_set_bool(all_opts, BDRV_OPT_CACHE_WB,
810cccb7967SMarkus Armbruster                               !!(flags & BDRV_O_CACHE_WB), &error_abort);
81129c4e2b5SKevin Wolf         }
81254861b92SKevin Wolf         if (!qemu_opt_get(all_opts, BDRV_OPT_CACHE_DIRECT)) {
81354861b92SKevin Wolf             qemu_opt_set_bool(all_opts, BDRV_OPT_CACHE_DIRECT,
814cccb7967SMarkus Armbruster                               !!(flags & BDRV_O_NOCACHE), &error_abort);
81529c4e2b5SKevin Wolf         }
81654861b92SKevin Wolf         if (!qemu_opt_get(all_opts, BDRV_OPT_CACHE_NO_FLUSH)) {
81754861b92SKevin Wolf             qemu_opt_set_bool(all_opts, BDRV_OPT_CACHE_NO_FLUSH,
818cccb7967SMarkus Armbruster                               !!(flags & BDRV_O_NO_FLUSH), &error_abort);
81929c4e2b5SKevin Wolf         }
82029c4e2b5SKevin Wolf         qemu_opt_unset(all_opts, "cache");
82129c4e2b5SKevin Wolf     }
82229c4e2b5SKevin Wolf 
823f298d071SKevin Wolf     /* Get a QDict for processing the options */
824f298d071SKevin Wolf     bs_opts = qdict_new();
825f298d071SKevin Wolf     qemu_opts_to_qdict(all_opts, bs_opts);
826f298d071SKevin Wolf 
82787ea75d5SPeter Crosthwaite     legacy_opts = qemu_opts_create(&qemu_legacy_drive_opts, NULL, 0,
82887ea75d5SPeter Crosthwaite                                    &error_abort);
82933cb7dc8SKevin Wolf     qemu_opts_absorb_qdict(legacy_opts, bs_opts, &local_err);
83084d18f06SMarkus Armbruster     if (local_err) {
831565f65d2SMarkus Armbruster         error_report_err(local_err);
83233cb7dc8SKevin Wolf         goto fail;
83333cb7dc8SKevin Wolf     }
83433cb7dc8SKevin Wolf 
83526929298SKevin Wolf     /* Deprecated option boot=[on|off] */
83626929298SKevin Wolf     if (qemu_opt_get(legacy_opts, "boot") != NULL) {
83726929298SKevin Wolf         fprintf(stderr, "qemu-kvm: boot=on|off is deprecated and will be "
83826929298SKevin Wolf                 "ignored. Future versions will reject this parameter. Please "
83926929298SKevin Wolf                 "update your scripts.\n");
84026929298SKevin Wolf     }
84126929298SKevin Wolf 
84233cb7dc8SKevin Wolf     /* Media type */
84333cb7dc8SKevin Wolf     value = qemu_opt_get(legacy_opts, "media");
84433cb7dc8SKevin Wolf     if (value) {
84533cb7dc8SKevin Wolf         if (!strcmp(value, "disk")) {
84633cb7dc8SKevin Wolf             media = MEDIA_DISK;
84733cb7dc8SKevin Wolf         } else if (!strcmp(value, "cdrom")) {
84833cb7dc8SKevin Wolf             media = MEDIA_CDROM;
849a7fdbcf0SFam Zheng             read_only = true;
85033cb7dc8SKevin Wolf         } else {
85133cb7dc8SKevin Wolf             error_report("'%s' invalid media", value);
85233cb7dc8SKevin Wolf             goto fail;
85333cb7dc8SKevin Wolf         }
85433cb7dc8SKevin Wolf     }
85533cb7dc8SKevin Wolf 
8560ebd24e0SKevin Wolf     /* copy-on-read is disabled with a warning for read-only devices */
857a7fdbcf0SFam Zheng     read_only |= qemu_opt_get_bool(legacy_opts, "read-only", false);
8580ebd24e0SKevin Wolf     copy_on_read = qemu_opt_get_bool(legacy_opts, "copy-on-read", false);
8590ebd24e0SKevin Wolf 
8600ebd24e0SKevin Wolf     if (read_only && copy_on_read) {
8610ebd24e0SKevin Wolf         error_report("warning: disabling copy-on-read on read-only drive");
8620ebd24e0SKevin Wolf         copy_on_read = false;
8630ebd24e0SKevin Wolf     }
8640ebd24e0SKevin Wolf 
8650ebd24e0SKevin Wolf     qdict_put(bs_opts, "read-only",
8660ebd24e0SKevin Wolf               qstring_from_str(read_only ? "on" : "off"));
8670ebd24e0SKevin Wolf     qdict_put(bs_opts, "copy-on-read",
8680ebd24e0SKevin Wolf               qstring_from_str(copy_on_read ? "on" :"off"));
8690ebd24e0SKevin Wolf 
870593d464bSKevin Wolf     /* Controller type */
871593d464bSKevin Wolf     value = qemu_opt_get(legacy_opts, "if");
872593d464bSKevin Wolf     if (value) {
873593d464bSKevin Wolf         for (type = 0;
874593d464bSKevin Wolf              type < IF_COUNT && strcmp(value, if_name[type]);
875593d464bSKevin Wolf              type++) {
876593d464bSKevin Wolf         }
877593d464bSKevin Wolf         if (type == IF_COUNT) {
878593d464bSKevin Wolf             error_report("unsupported bus type '%s'", value);
879593d464bSKevin Wolf             goto fail;
880593d464bSKevin Wolf         }
881593d464bSKevin Wolf     } else {
882593d464bSKevin Wolf         type = block_default_type;
883593d464bSKevin Wolf     }
884593d464bSKevin Wolf 
885b41a7338SKevin Wolf     /* Geometry */
886b41a7338SKevin Wolf     cyls  = qemu_opt_get_number(legacy_opts, "cyls", 0);
887b41a7338SKevin Wolf     heads = qemu_opt_get_number(legacy_opts, "heads", 0);
888b41a7338SKevin Wolf     secs  = qemu_opt_get_number(legacy_opts, "secs", 0);
889b41a7338SKevin Wolf 
890b41a7338SKevin Wolf     if (cyls || heads || secs) {
891b41a7338SKevin Wolf         if (cyls < 1) {
892b41a7338SKevin Wolf             error_report("invalid physical cyls number");
893b41a7338SKevin Wolf             goto fail;
894b41a7338SKevin Wolf         }
895b41a7338SKevin Wolf         if (heads < 1) {
896b41a7338SKevin Wolf             error_report("invalid physical heads number");
897b41a7338SKevin Wolf             goto fail;
898b41a7338SKevin Wolf         }
899b41a7338SKevin Wolf         if (secs < 1) {
900b41a7338SKevin Wolf             error_report("invalid physical secs number");
901b41a7338SKevin Wolf             goto fail;
902b41a7338SKevin Wolf         }
903b41a7338SKevin Wolf     }
904b41a7338SKevin Wolf 
905b41a7338SKevin Wolf     translation = BIOS_ATA_TRANSLATION_AUTO;
906b41a7338SKevin Wolf     value = qemu_opt_get(legacy_opts, "trans");
907b41a7338SKevin Wolf     if (value != NULL) {
908b41a7338SKevin Wolf         if (!cyls) {
909b41a7338SKevin Wolf             error_report("'%s' trans must be used with cyls, heads and secs",
910b41a7338SKevin Wolf                          value);
911b41a7338SKevin Wolf             goto fail;
912b41a7338SKevin Wolf         }
913b41a7338SKevin Wolf         if (!strcmp(value, "none")) {
914b41a7338SKevin Wolf             translation = BIOS_ATA_TRANSLATION_NONE;
915b41a7338SKevin Wolf         } else if (!strcmp(value, "lba")) {
916b41a7338SKevin Wolf             translation = BIOS_ATA_TRANSLATION_LBA;
917f31c41ffSPaolo Bonzini         } else if (!strcmp(value, "large")) {
918f31c41ffSPaolo Bonzini             translation = BIOS_ATA_TRANSLATION_LARGE;
919f31c41ffSPaolo Bonzini         } else if (!strcmp(value, "rechs")) {
920f31c41ffSPaolo Bonzini             translation = BIOS_ATA_TRANSLATION_RECHS;
921b41a7338SKevin Wolf         } else if (!strcmp(value, "auto")) {
922b41a7338SKevin Wolf             translation = BIOS_ATA_TRANSLATION_AUTO;
923b41a7338SKevin Wolf         } else {
924b41a7338SKevin Wolf             error_report("'%s' invalid translation type", value);
925b41a7338SKevin Wolf             goto fail;
926b41a7338SKevin Wolf         }
927b41a7338SKevin Wolf     }
928b41a7338SKevin Wolf 
929b41a7338SKevin Wolf     if (media == MEDIA_CDROM) {
930b41a7338SKevin Wolf         if (cyls || secs || heads) {
931b41a7338SKevin Wolf             error_report("CHS can't be set with media=cdrom");
932b41a7338SKevin Wolf             goto fail;
933b41a7338SKevin Wolf         }
934b41a7338SKevin Wolf     }
935b41a7338SKevin Wolf 
93687a899c5SKevin Wolf     /* Device address specified by bus/unit or index.
93787a899c5SKevin Wolf      * If none was specified, try to find the first free one. */
93887a899c5SKevin Wolf     bus_id  = qemu_opt_get_number(legacy_opts, "bus", 0);
93987a899c5SKevin Wolf     unit_id = qemu_opt_get_number(legacy_opts, "unit", -1);
94087a899c5SKevin Wolf     index   = qemu_opt_get_number(legacy_opts, "index", -1);
94187a899c5SKevin Wolf 
94287a899c5SKevin Wolf     max_devs = if_max_devs[type];
94387a899c5SKevin Wolf 
94487a899c5SKevin Wolf     if (index != -1) {
94587a899c5SKevin Wolf         if (bus_id != 0 || unit_id != -1) {
94687a899c5SKevin Wolf             error_report("index cannot be used with bus and unit");
94787a899c5SKevin Wolf             goto fail;
94887a899c5SKevin Wolf         }
94987a899c5SKevin Wolf         bus_id = drive_index_to_bus_id(type, index);
95087a899c5SKevin Wolf         unit_id = drive_index_to_unit_id(type, index);
95187a899c5SKevin Wolf     }
95287a899c5SKevin Wolf 
95387a899c5SKevin Wolf     if (unit_id == -1) {
95487a899c5SKevin Wolf        unit_id = 0;
95587a899c5SKevin Wolf        while (drive_get(type, bus_id, unit_id) != NULL) {
95687a899c5SKevin Wolf            unit_id++;
95787a899c5SKevin Wolf            if (max_devs && unit_id >= max_devs) {
95887a899c5SKevin Wolf                unit_id -= max_devs;
95987a899c5SKevin Wolf                bus_id++;
96087a899c5SKevin Wolf            }
96187a899c5SKevin Wolf        }
96287a899c5SKevin Wolf     }
96387a899c5SKevin Wolf 
96487a899c5SKevin Wolf     if (max_devs && unit_id >= max_devs) {
96587a899c5SKevin Wolf         error_report("unit %d too big (max is %d)", unit_id, max_devs - 1);
96687a899c5SKevin Wolf         goto fail;
96787a899c5SKevin Wolf     }
96887a899c5SKevin Wolf 
96987a899c5SKevin Wolf     if (drive_get(type, bus_id, unit_id) != NULL) {
97087a899c5SKevin Wolf         error_report("drive with bus=%d, unit=%d (index=%d) exists",
97187a899c5SKevin Wolf                      bus_id, unit_id, index);
97287a899c5SKevin Wolf         goto fail;
97387a899c5SKevin Wolf     }
97487a899c5SKevin Wolf 
975bcf83158SKevin Wolf     /* Serial number */
976bcf83158SKevin Wolf     serial = qemu_opt_get(legacy_opts, "serial");
977bcf83158SKevin Wolf 
97887a899c5SKevin Wolf     /* no id supplied -> create one */
97987a899c5SKevin Wolf     if (qemu_opts_id(all_opts) == NULL) {
98087a899c5SKevin Wolf         char *new_id;
98187a899c5SKevin Wolf         const char *mediastr = "";
98287a899c5SKevin Wolf         if (type == IF_IDE || type == IF_SCSI) {
98387a899c5SKevin Wolf             mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
98487a899c5SKevin Wolf         }
98587a899c5SKevin Wolf         if (max_devs) {
98687a899c5SKevin Wolf             new_id = g_strdup_printf("%s%i%s%i", if_name[type], bus_id,
98787a899c5SKevin Wolf                                      mediastr, unit_id);
98887a899c5SKevin Wolf         } else {
98987a899c5SKevin Wolf             new_id = g_strdup_printf("%s%s%i", if_name[type],
99087a899c5SKevin Wolf                                      mediastr, unit_id);
99187a899c5SKevin Wolf         }
99287a899c5SKevin Wolf         qdict_put(bs_opts, "id", qstring_from_str(new_id));
99387a899c5SKevin Wolf         g_free(new_id);
99487a899c5SKevin Wolf     }
99587a899c5SKevin Wolf 
996394c7d4dSKevin Wolf     /* Add virtio block device */
997394c7d4dSKevin Wolf     devaddr = qemu_opt_get(legacy_opts, "addr");
998394c7d4dSKevin Wolf     if (devaddr && type != IF_VIRTIO) {
999394c7d4dSKevin Wolf         error_report("addr is not supported by this bus type");
1000394c7d4dSKevin Wolf         goto fail;
1001394c7d4dSKevin Wolf     }
1002394c7d4dSKevin Wolf 
1003394c7d4dSKevin Wolf     if (type == IF_VIRTIO) {
1004394c7d4dSKevin Wolf         QemuOpts *devopts;
100587ea75d5SPeter Crosthwaite         devopts = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
100687ea75d5SPeter Crosthwaite                                    &error_abort);
1007394c7d4dSKevin Wolf         if (arch_type == QEMU_ARCH_S390X) {
10081f68f1d3SAlexander Graf             qemu_opt_set(devopts, "driver", "virtio-blk-ccw", &error_abort);
1009394c7d4dSKevin Wolf         } else {
1010f43e47dbSMarkus Armbruster             qemu_opt_set(devopts, "driver", "virtio-blk-pci", &error_abort);
1011394c7d4dSKevin Wolf         }
1012f43e47dbSMarkus Armbruster         qemu_opt_set(devopts, "drive", qdict_get_str(bs_opts, "id"),
1013f43e47dbSMarkus Armbruster                      &error_abort);
1014394c7d4dSKevin Wolf         if (devaddr) {
1015f43e47dbSMarkus Armbruster             qemu_opt_set(devopts, "addr", devaddr, &error_abort);
1016394c7d4dSKevin Wolf         }
1017394c7d4dSKevin Wolf     }
1018394c7d4dSKevin Wolf 
1019d095b465SMax Reitz     filename = qemu_opt_get(legacy_opts, "file");
1020d095b465SMax Reitz 
1021ee13ed1cSKevin Wolf     /* Check werror/rerror compatibility with if=... */
1022ee13ed1cSKevin Wolf     werror = qemu_opt_get(legacy_opts, "werror");
1023ee13ed1cSKevin Wolf     if (werror != NULL) {
1024ee13ed1cSKevin Wolf         if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO &&
1025ee13ed1cSKevin Wolf             type != IF_NONE) {
1026ee13ed1cSKevin Wolf             error_report("werror is not supported by this bus type");
1027ee13ed1cSKevin Wolf             goto fail;
1028ee13ed1cSKevin Wolf         }
1029ee13ed1cSKevin Wolf         qdict_put(bs_opts, "werror", qstring_from_str(werror));
1030ee13ed1cSKevin Wolf     }
1031ee13ed1cSKevin Wolf 
1032ee13ed1cSKevin Wolf     rerror = qemu_opt_get(legacy_opts, "rerror");
1033ee13ed1cSKevin Wolf     if (rerror != NULL) {
1034ee13ed1cSKevin Wolf         if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI &&
1035ee13ed1cSKevin Wolf             type != IF_NONE) {
1036ee13ed1cSKevin Wolf             error_report("rerror is not supported by this bus type");
1037ee13ed1cSKevin Wolf             goto fail;
1038ee13ed1cSKevin Wolf         }
1039ee13ed1cSKevin Wolf         qdict_put(bs_opts, "rerror", qstring_from_str(rerror));
1040ee13ed1cSKevin Wolf     }
1041ee13ed1cSKevin Wolf 
10422d246f01SKevin Wolf     /* Actual block device init: Functionality shared with blockdev-add */
104318e46a03SMarkus Armbruster     blk = blockdev_init(filename, bs_opts, &local_err);
10443cb0e25cSMarkus Armbruster     bs_opts = NULL;
104518e46a03SMarkus Armbruster     if (!blk) {
104684d18f06SMarkus Armbruster         if (local_err) {
1047565f65d2SMarkus Armbruster             error_report_err(local_err);
1048b681072dSKevin Wolf         }
10492d246f01SKevin Wolf         goto fail;
1050b681072dSKevin Wolf     } else {
105184d18f06SMarkus Armbruster         assert(!local_err);
10522d246f01SKevin Wolf     }
10532d246f01SKevin Wolf 
105426f8b3a8SMarkus Armbruster     /* Create legacy DriveInfo */
105526f8b3a8SMarkus Armbruster     dinfo = g_malloc0(sizeof(*dinfo));
1056f298d071SKevin Wolf     dinfo->opts = all_opts;
10572d246f01SKevin Wolf 
1058b41a7338SKevin Wolf     dinfo->cyls = cyls;
1059b41a7338SKevin Wolf     dinfo->heads = heads;
1060b41a7338SKevin Wolf     dinfo->secs = secs;
1061b41a7338SKevin Wolf     dinfo->trans = translation;
1062b41a7338SKevin Wolf 
1063ee13ed1cSKevin Wolf     dinfo->type = type;
106487a899c5SKevin Wolf     dinfo->bus = bus_id;
106587a899c5SKevin Wolf     dinfo->unit = unit_id;
1066394c7d4dSKevin Wolf     dinfo->devaddr = devaddr;
1067bcf83158SKevin Wolf     dinfo->serial = g_strdup(serial);
1068bcf83158SKevin Wolf 
106926f8b3a8SMarkus Armbruster     blk_set_legacy_dinfo(blk, dinfo);
107026f8b3a8SMarkus Armbruster 
1071e34ef046SKevin Wolf     switch(type) {
1072e34ef046SKevin Wolf     case IF_IDE:
1073e34ef046SKevin Wolf     case IF_SCSI:
1074e34ef046SKevin Wolf     case IF_XEN:
1075e34ef046SKevin Wolf     case IF_NONE:
1076e34ef046SKevin Wolf         dinfo->media_cd = media == MEDIA_CDROM;
1077e34ef046SKevin Wolf         break;
1078e34ef046SKevin Wolf     default:
1079e34ef046SKevin Wolf         break;
1080e34ef046SKevin Wolf     }
1081e34ef046SKevin Wolf 
10822d246f01SKevin Wolf fail:
108333cb7dc8SKevin Wolf     qemu_opts_del(legacy_opts);
10843cb0e25cSMarkus Armbruster     QDECREF(bs_opts);
10852d246f01SKevin Wolf     return dinfo;
108657975222SKevin Wolf }
108757975222SKevin Wolf 
10883e5a50d6SMarkus Armbruster void hmp_commit(Monitor *mon, const QDict *qdict)
1089666daa68SMarkus Armbruster {
1090666daa68SMarkus Armbruster     const char *device = qdict_get_str(qdict, "device");
1091a0e8544cSFam Zheng     BlockBackend *blk;
10922d3735d3SStefan Hajnoczi     int ret;
10932d3735d3SStefan Hajnoczi 
1094e8877497SStefan Hajnoczi     if (!strcmp(device, "all")) {
1095e8877497SStefan Hajnoczi         ret = bdrv_commit_all();
1096e8877497SStefan Hajnoczi     } else {
109784aa0140SStefan Hajnoczi         BlockDriverState *bs;
109884aa0140SStefan Hajnoczi         AioContext *aio_context;
109984aa0140SStefan Hajnoczi 
1100a0e8544cSFam Zheng         blk = blk_by_name(device);
1101a0e8544cSFam Zheng         if (!blk) {
110258513bdeSJeff Cody             monitor_printf(mon, "Device '%s' not found\n", device);
1103ac59eb95SMarkus Armbruster             return;
11046ab4b5abSMarkus Armbruster         }
11055433c24fSMax Reitz         if (!blk_is_available(blk)) {
11065433c24fSMax Reitz             monitor_printf(mon, "Device '%s' has no medium\n", device);
11075433c24fSMax Reitz             return;
11085433c24fSMax Reitz         }
110984aa0140SStefan Hajnoczi 
111084aa0140SStefan Hajnoczi         bs = blk_bs(blk);
111184aa0140SStefan Hajnoczi         aio_context = bdrv_get_aio_context(bs);
111284aa0140SStefan Hajnoczi         aio_context_acquire(aio_context);
111384aa0140SStefan Hajnoczi 
111484aa0140SStefan Hajnoczi         ret = bdrv_commit(bs);
111584aa0140SStefan Hajnoczi 
111684aa0140SStefan Hajnoczi         aio_context_release(aio_context);
11172d3735d3SStefan Hajnoczi     }
111858513bdeSJeff Cody     if (ret < 0) {
111958513bdeSJeff Cody         monitor_printf(mon, "'commit' error for '%s': %s\n", device,
112058513bdeSJeff Cody                        strerror(-ret));
1121666daa68SMarkus Armbruster     }
1122666daa68SMarkus Armbruster }
1123666daa68SMarkus Armbruster 
11246a8f9661SEric Blake static void blockdev_do_action(TransactionActionKind type, void *data,
11256a8f9661SEric Blake                                Error **errp)
11266cc2a415SPaolo Bonzini {
1127c8a83e85SKevin Wolf     TransactionAction action;
1128c8a83e85SKevin Wolf     TransactionActionList list;
11296cc2a415SPaolo Bonzini 
11306a8f9661SEric Blake     action.type = type;
11316a8f9661SEric Blake     action.u.data = data;
11326cc2a415SPaolo Bonzini     list.value = &action;
11336cc2a415SPaolo Bonzini     list.next = NULL;
1134*94d16a64SJohn Snow     qmp_transaction(&list, false, NULL, errp);
11356cc2a415SPaolo Bonzini }
11366cc2a415SPaolo Bonzini 
11370901f67eSBenoît Canet void qmp_blockdev_snapshot_sync(bool has_device, const char *device,
11380901f67eSBenoît Canet                                 bool has_node_name, const char *node_name,
11390901f67eSBenoît Canet                                 const char *snapshot_file,
11400901f67eSBenoît Canet                                 bool has_snapshot_node_name,
11410901f67eSBenoît Canet                                 const char *snapshot_node_name,
11426106e249SLuiz Capitulino                                 bool has_format, const char *format,
11430901f67eSBenoît Canet                                 bool has_mode, NewImageMode mode, Error **errp)
1144f8882568SJes Sorensen {
1145a911e6aeSAlberto Garcia     BlockdevSnapshotSync snapshot = {
11460901f67eSBenoît Canet         .has_device = has_device,
11476cc2a415SPaolo Bonzini         .device = (char *) device,
11480901f67eSBenoît Canet         .has_node_name = has_node_name,
11490901f67eSBenoît Canet         .node_name = (char *) node_name,
11506cc2a415SPaolo Bonzini         .snapshot_file = (char *) snapshot_file,
11510901f67eSBenoît Canet         .has_snapshot_node_name = has_snapshot_node_name,
11520901f67eSBenoît Canet         .snapshot_node_name = (char *) snapshot_node_name,
11536cc2a415SPaolo Bonzini         .has_format = has_format,
11546cc2a415SPaolo Bonzini         .format = (char *) format,
11556cc2a415SPaolo Bonzini         .has_mode = has_mode,
11566cc2a415SPaolo Bonzini         .mode = mode,
11576cc2a415SPaolo Bonzini     };
1158c8a83e85SKevin Wolf     blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC,
1159c8a83e85SKevin Wolf                        &snapshot, errp);
1160f8882568SJes Sorensen }
1161f8882568SJes Sorensen 
116243de7e2dSAlberto Garcia void qmp_blockdev_snapshot(const char *node, const char *overlay,
116343de7e2dSAlberto Garcia                            Error **errp)
116443de7e2dSAlberto Garcia {
116543de7e2dSAlberto Garcia     BlockdevSnapshot snapshot_data = {
116643de7e2dSAlberto Garcia         .node = (char *) node,
116743de7e2dSAlberto Garcia         .overlay = (char *) overlay
116843de7e2dSAlberto Garcia     };
116943de7e2dSAlberto Garcia 
117043de7e2dSAlberto Garcia     blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT,
117143de7e2dSAlberto Garcia                        &snapshot_data, errp);
117243de7e2dSAlberto Garcia }
117343de7e2dSAlberto Garcia 
1174f323bc9eSWenchao Xia void qmp_blockdev_snapshot_internal_sync(const char *device,
1175f323bc9eSWenchao Xia                                          const char *name,
1176f323bc9eSWenchao Xia                                          Error **errp)
1177f323bc9eSWenchao Xia {
1178f323bc9eSWenchao Xia     BlockdevSnapshotInternal snapshot = {
1179f323bc9eSWenchao Xia         .device = (char *) device,
1180f323bc9eSWenchao Xia         .name = (char *) name
1181f323bc9eSWenchao Xia     };
1182f323bc9eSWenchao Xia 
1183f323bc9eSWenchao Xia     blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC,
1184f323bc9eSWenchao Xia                        &snapshot, errp);
1185f323bc9eSWenchao Xia }
1186f323bc9eSWenchao Xia 
118744e3e053SWenchao Xia SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
118844e3e053SWenchao Xia                                                          bool has_id,
118944e3e053SWenchao Xia                                                          const char *id,
119044e3e053SWenchao Xia                                                          bool has_name,
119144e3e053SWenchao Xia                                                          const char *name,
119244e3e053SWenchao Xia                                                          Error **errp)
119344e3e053SWenchao Xia {
1194a0e8544cSFam Zheng     BlockDriverState *bs;
1195a0e8544cSFam Zheng     BlockBackend *blk;
11964ef3982aSStefan Hajnoczi     AioContext *aio_context;
119744e3e053SWenchao Xia     QEMUSnapshotInfo sn;
119844e3e053SWenchao Xia     Error *local_err = NULL;
119944e3e053SWenchao Xia     SnapshotInfo *info = NULL;
120044e3e053SWenchao Xia     int ret;
120144e3e053SWenchao Xia 
1202a0e8544cSFam Zheng     blk = blk_by_name(device);
1203a0e8544cSFam Zheng     if (!blk) {
120475158ebbSMarkus Armbruster         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
120575158ebbSMarkus Armbruster                   "Device '%s' not found", device);
120644e3e053SWenchao Xia         return NULL;
120744e3e053SWenchao Xia     }
12085433c24fSMax Reitz 
12095433c24fSMax Reitz     aio_context = blk_get_aio_context(blk);
12105433c24fSMax Reitz     aio_context_acquire(aio_context);
121144e3e053SWenchao Xia 
121244e3e053SWenchao Xia     if (!has_id) {
121344e3e053SWenchao Xia         id = NULL;
121444e3e053SWenchao Xia     }
121544e3e053SWenchao Xia 
121644e3e053SWenchao Xia     if (!has_name) {
121744e3e053SWenchao Xia         name = NULL;
121844e3e053SWenchao Xia     }
121944e3e053SWenchao Xia 
122044e3e053SWenchao Xia     if (!id && !name) {
122144e3e053SWenchao Xia         error_setg(errp, "Name or id must be provided");
12225433c24fSMax Reitz         goto out_aio_context;
122344e3e053SWenchao Xia     }
122444e3e053SWenchao Xia 
12255433c24fSMax Reitz     if (!blk_is_available(blk)) {
12265433c24fSMax Reitz         error_setg(errp, "Device '%s' has no medium", device);
12275433c24fSMax Reitz         goto out_aio_context;
12285433c24fSMax Reitz     }
12295433c24fSMax Reitz     bs = blk_bs(blk);
12304ef3982aSStefan Hajnoczi 
12310b928854SStefan Hajnoczi     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE, errp)) {
12320b928854SStefan Hajnoczi         goto out_aio_context;
12330b928854SStefan Hajnoczi     }
12340b928854SStefan Hajnoczi 
123544e3e053SWenchao Xia     ret = bdrv_snapshot_find_by_id_and_name(bs, id, name, &sn, &local_err);
123684d18f06SMarkus Armbruster     if (local_err) {
123744e3e053SWenchao Xia         error_propagate(errp, local_err);
12384ef3982aSStefan Hajnoczi         goto out_aio_context;
123944e3e053SWenchao Xia     }
124044e3e053SWenchao Xia     if (!ret) {
124144e3e053SWenchao Xia         error_setg(errp,
124244e3e053SWenchao Xia                    "Snapshot with id '%s' and name '%s' does not exist on "
124344e3e053SWenchao Xia                    "device '%s'",
124444e3e053SWenchao Xia                    STR_OR_NULL(id), STR_OR_NULL(name), device);
12454ef3982aSStefan Hajnoczi         goto out_aio_context;
124644e3e053SWenchao Xia     }
124744e3e053SWenchao Xia 
124844e3e053SWenchao Xia     bdrv_snapshot_delete(bs, id, name, &local_err);
124984d18f06SMarkus Armbruster     if (local_err) {
125044e3e053SWenchao Xia         error_propagate(errp, local_err);
12514ef3982aSStefan Hajnoczi         goto out_aio_context;
125244e3e053SWenchao Xia     }
125344e3e053SWenchao Xia 
12544ef3982aSStefan Hajnoczi     aio_context_release(aio_context);
12554ef3982aSStefan Hajnoczi 
12565839e53bSMarkus Armbruster     info = g_new0(SnapshotInfo, 1);
125744e3e053SWenchao Xia     info->id = g_strdup(sn.id_str);
125844e3e053SWenchao Xia     info->name = g_strdup(sn.name);
125944e3e053SWenchao Xia     info->date_nsec = sn.date_nsec;
126044e3e053SWenchao Xia     info->date_sec = sn.date_sec;
126144e3e053SWenchao Xia     info->vm_state_size = sn.vm_state_size;
126244e3e053SWenchao Xia     info->vm_clock_nsec = sn.vm_clock_nsec % 1000000000;
126344e3e053SWenchao Xia     info->vm_clock_sec = sn.vm_clock_nsec / 1000000000;
126444e3e053SWenchao Xia 
126544e3e053SWenchao Xia     return info;
12664ef3982aSStefan Hajnoczi 
12674ef3982aSStefan Hajnoczi out_aio_context:
12684ef3982aSStefan Hajnoczi     aio_context_release(aio_context);
12694ef3982aSStefan Hajnoczi     return NULL;
127044e3e053SWenchao Xia }
12718802d1fdSJeff Cody 
1272341ebc2fSJohn Snow /**
1273341ebc2fSJohn Snow  * block_dirty_bitmap_lookup:
1274341ebc2fSJohn Snow  * Return a dirty bitmap (if present), after validating
1275341ebc2fSJohn Snow  * the node reference and bitmap names.
1276341ebc2fSJohn Snow  *
1277341ebc2fSJohn Snow  * @node: The name of the BDS node to search for bitmaps
1278341ebc2fSJohn Snow  * @name: The name of the bitmap to search for
1279341ebc2fSJohn Snow  * @pbs: Output pointer for BDS lookup, if desired. Can be NULL.
1280341ebc2fSJohn Snow  * @paio: Output pointer for aio_context acquisition, if desired. Can be NULL.
1281341ebc2fSJohn Snow  * @errp: Output pointer for error information. Can be NULL.
1282341ebc2fSJohn Snow  *
1283341ebc2fSJohn Snow  * @return: A bitmap object on success, or NULL on failure.
1284341ebc2fSJohn Snow  */
1285341ebc2fSJohn Snow static BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
1286341ebc2fSJohn Snow                                                   const char *name,
1287341ebc2fSJohn Snow                                                   BlockDriverState **pbs,
1288341ebc2fSJohn Snow                                                   AioContext **paio,
1289341ebc2fSJohn Snow                                                   Error **errp)
1290341ebc2fSJohn Snow {
1291341ebc2fSJohn Snow     BlockDriverState *bs;
1292341ebc2fSJohn Snow     BdrvDirtyBitmap *bitmap;
1293341ebc2fSJohn Snow     AioContext *aio_context;
1294341ebc2fSJohn Snow 
1295341ebc2fSJohn Snow     if (!node) {
1296341ebc2fSJohn Snow         error_setg(errp, "Node cannot be NULL");
1297341ebc2fSJohn Snow         return NULL;
1298341ebc2fSJohn Snow     }
1299341ebc2fSJohn Snow     if (!name) {
1300341ebc2fSJohn Snow         error_setg(errp, "Bitmap name cannot be NULL");
1301341ebc2fSJohn Snow         return NULL;
1302341ebc2fSJohn Snow     }
1303341ebc2fSJohn Snow     bs = bdrv_lookup_bs(node, node, NULL);
1304341ebc2fSJohn Snow     if (!bs) {
1305341ebc2fSJohn Snow         error_setg(errp, "Node '%s' not found", node);
1306341ebc2fSJohn Snow         return NULL;
1307341ebc2fSJohn Snow     }
1308341ebc2fSJohn Snow 
1309341ebc2fSJohn Snow     aio_context = bdrv_get_aio_context(bs);
1310341ebc2fSJohn Snow     aio_context_acquire(aio_context);
1311341ebc2fSJohn Snow 
1312341ebc2fSJohn Snow     bitmap = bdrv_find_dirty_bitmap(bs, name);
1313341ebc2fSJohn Snow     if (!bitmap) {
1314341ebc2fSJohn Snow         error_setg(errp, "Dirty bitmap '%s' not found", name);
1315341ebc2fSJohn Snow         goto fail;
1316341ebc2fSJohn Snow     }
1317341ebc2fSJohn Snow 
1318341ebc2fSJohn Snow     if (pbs) {
1319341ebc2fSJohn Snow         *pbs = bs;
1320341ebc2fSJohn Snow     }
1321341ebc2fSJohn Snow     if (paio) {
1322341ebc2fSJohn Snow         *paio = aio_context;
1323341ebc2fSJohn Snow     } else {
1324341ebc2fSJohn Snow         aio_context_release(aio_context);
1325341ebc2fSJohn Snow     }
1326341ebc2fSJohn Snow 
1327341ebc2fSJohn Snow     return bitmap;
1328341ebc2fSJohn Snow 
1329341ebc2fSJohn Snow  fail:
1330341ebc2fSJohn Snow     aio_context_release(aio_context);
1331341ebc2fSJohn Snow     return NULL;
1332341ebc2fSJohn Snow }
1333341ebc2fSJohn Snow 
1334b756b9ceSStefan Hajnoczi /* New and old BlockDriverState structs for atomic group operations */
1335ba0c86a3SWenchao Xia 
133650f43f0fSJohn Snow typedef struct BlkActionState BlkActionState;
1337ba0c86a3SWenchao Xia 
133850f43f0fSJohn Snow /**
133950f43f0fSJohn Snow  * BlkActionOps:
134050f43f0fSJohn Snow  * Table of operations that define an Action.
134150f43f0fSJohn Snow  *
134250f43f0fSJohn Snow  * @instance_size: Size of state struct, in bytes.
134350f43f0fSJohn Snow  * @prepare: Prepare the work, must NOT be NULL.
134450f43f0fSJohn Snow  * @commit: Commit the changes, can be NULL.
134550f43f0fSJohn Snow  * @abort: Abort the changes on fail, can be NULL.
134650f43f0fSJohn Snow  * @clean: Clean up resources after all transaction actions have called
134750f43f0fSJohn Snow  *         commit() or abort(). Can be NULL.
134850f43f0fSJohn Snow  *
134950f43f0fSJohn Snow  * Only prepare() may fail. In a single transaction, only one of commit() or
135050f43f0fSJohn Snow  * abort() will be called. clean() will always be called if it is present.
1351ba0c86a3SWenchao Xia  */
135250f43f0fSJohn Snow typedef struct BlkActionOps {
135350f43f0fSJohn Snow     size_t instance_size;
135450f43f0fSJohn Snow     void (*prepare)(BlkActionState *common, Error **errp);
135550f43f0fSJohn Snow     void (*commit)(BlkActionState *common);
135650f43f0fSJohn Snow     void (*abort)(BlkActionState *common);
135750f43f0fSJohn Snow     void (*clean)(BlkActionState *common);
135850f43f0fSJohn Snow } BlkActionOps;
135950f43f0fSJohn Snow 
136050f43f0fSJohn Snow /**
136150f43f0fSJohn Snow  * BlkActionState:
136250f43f0fSJohn Snow  * Describes one Action's state within a Transaction.
136350f43f0fSJohn Snow  *
136450f43f0fSJohn Snow  * @action: QAPI-defined enum identifying which Action to perform.
136550f43f0fSJohn Snow  * @ops: Table of ActionOps this Action can perform.
1366*94d16a64SJohn Snow  * @block_job_txn: Transaction which this action belongs to.
136750f43f0fSJohn Snow  * @entry: List membership for all Actions in this Transaction.
136850f43f0fSJohn Snow  *
136950f43f0fSJohn Snow  * This structure must be arranged as first member in a subclassed type,
137050f43f0fSJohn Snow  * assuming that the compiler will also arrange it to the same offsets as the
137150f43f0fSJohn Snow  * base class.
137250f43f0fSJohn Snow  */
137350f43f0fSJohn Snow struct BlkActionState {
1374c8a83e85SKevin Wolf     TransactionAction *action;
137550f43f0fSJohn Snow     const BlkActionOps *ops;
1376*94d16a64SJohn Snow     BlockJobTxn *block_job_txn;
1377*94d16a64SJohn Snow     TransactionProperties *txn_props;
137850f43f0fSJohn Snow     QSIMPLEQ_ENTRY(BlkActionState) entry;
1379ba0c86a3SWenchao Xia };
1380ba0c86a3SWenchao Xia 
1381bbe86010SWenchao Xia /* internal snapshot private data */
1382bbe86010SWenchao Xia typedef struct InternalSnapshotState {
138350f43f0fSJohn Snow     BlkActionState common;
1384bbe86010SWenchao Xia     BlockDriverState *bs;
13855d6e96efSStefan Hajnoczi     AioContext *aio_context;
1386bbe86010SWenchao Xia     QEMUSnapshotInfo sn;
1387507306ccSFam Zheng     bool created;
1388bbe86010SWenchao Xia } InternalSnapshotState;
1389bbe86010SWenchao Xia 
1390*94d16a64SJohn Snow 
1391*94d16a64SJohn Snow static int action_check_completion_mode(BlkActionState *s, Error **errp)
1392*94d16a64SJohn Snow {
1393*94d16a64SJohn Snow     if (s->txn_props->completion_mode != ACTION_COMPLETION_MODE_INDIVIDUAL) {
1394*94d16a64SJohn Snow         error_setg(errp,
1395*94d16a64SJohn Snow                    "Action '%s' does not support Transaction property "
1396*94d16a64SJohn Snow                    "completion-mode = %s",
1397*94d16a64SJohn Snow                    TransactionActionKind_lookup[s->action->type],
1398*94d16a64SJohn Snow                    ActionCompletionMode_lookup[s->txn_props->completion_mode]);
1399*94d16a64SJohn Snow         return -1;
1400*94d16a64SJohn Snow     }
1401*94d16a64SJohn Snow     return 0;
1402*94d16a64SJohn Snow }
1403*94d16a64SJohn Snow 
140450f43f0fSJohn Snow static void internal_snapshot_prepare(BlkActionState *common,
1405bbe86010SWenchao Xia                                       Error **errp)
1406bbe86010SWenchao Xia {
1407f70edf99SMarkus Armbruster     Error *local_err = NULL;
1408bbe86010SWenchao Xia     const char *device;
1409bbe86010SWenchao Xia     const char *name;
1410a0e8544cSFam Zheng     BlockBackend *blk;
1411bbe86010SWenchao Xia     BlockDriverState *bs;
1412bbe86010SWenchao Xia     QEMUSnapshotInfo old_sn, *sn;
1413bbe86010SWenchao Xia     bool ret;
1414bbe86010SWenchao Xia     qemu_timeval tv;
1415bbe86010SWenchao Xia     BlockdevSnapshotInternal *internal;
1416bbe86010SWenchao Xia     InternalSnapshotState *state;
1417bbe86010SWenchao Xia     int ret1;
1418bbe86010SWenchao Xia 
14196a8f9661SEric Blake     g_assert(common->action->type ==
1420bbe86010SWenchao Xia              TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC);
14216a8f9661SEric Blake     internal = common->action->u.blockdev_snapshot_internal_sync;
1422bbe86010SWenchao Xia     state = DO_UPCAST(InternalSnapshotState, common, common);
1423bbe86010SWenchao Xia 
1424bbe86010SWenchao Xia     /* 1. parse input */
1425bbe86010SWenchao Xia     device = internal->device;
1426bbe86010SWenchao Xia     name = internal->name;
1427bbe86010SWenchao Xia 
1428bbe86010SWenchao Xia     /* 2. check for validation */
1429*94d16a64SJohn Snow     if (action_check_completion_mode(common, errp) < 0) {
1430*94d16a64SJohn Snow         return;
1431*94d16a64SJohn Snow     }
1432*94d16a64SJohn Snow 
1433a0e8544cSFam Zheng     blk = blk_by_name(device);
1434a0e8544cSFam Zheng     if (!blk) {
143575158ebbSMarkus Armbruster         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
143675158ebbSMarkus Armbruster                   "Device '%s' not found", device);
1437bbe86010SWenchao Xia         return;
1438bbe86010SWenchao Xia     }
1439bbe86010SWenchao Xia 
14405d6e96efSStefan Hajnoczi     /* AioContext is released in .clean() */
14415433c24fSMax Reitz     state->aio_context = blk_get_aio_context(blk);
14425d6e96efSStefan Hajnoczi     aio_context_acquire(state->aio_context);
14435d6e96efSStefan Hajnoczi 
14445433c24fSMax Reitz     if (!blk_is_available(blk)) {
1445c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
1446bbe86010SWenchao Xia         return;
1447bbe86010SWenchao Xia     }
14485433c24fSMax Reitz     bs = blk_bs(blk);
1449bbe86010SWenchao Xia 
1450507306ccSFam Zheng     state->bs = bs;
1451507306ccSFam Zheng     bdrv_drained_begin(bs);
1452507306ccSFam Zheng 
14533dc7ca3cSStefan Hajnoczi     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT, errp)) {
14543dc7ca3cSStefan Hajnoczi         return;
14553dc7ca3cSStefan Hajnoczi     }
14563dc7ca3cSStefan Hajnoczi 
1457bbe86010SWenchao Xia     if (bdrv_is_read_only(bs)) {
145881e5f78aSAlberto Garcia         error_setg(errp, "Device '%s' is read only", device);
1459bbe86010SWenchao Xia         return;
1460bbe86010SWenchao Xia     }
1461bbe86010SWenchao Xia 
1462bbe86010SWenchao Xia     if (!bdrv_can_snapshot(bs)) {
146381e5f78aSAlberto Garcia         error_setg(errp, "Block format '%s' used by device '%s' "
146481e5f78aSAlberto Garcia                    "does not support internal snapshots",
146581e5f78aSAlberto Garcia                    bs->drv->format_name, device);
1466bbe86010SWenchao Xia         return;
1467bbe86010SWenchao Xia     }
1468bbe86010SWenchao Xia 
1469bbe86010SWenchao Xia     if (!strlen(name)) {
1470bbe86010SWenchao Xia         error_setg(errp, "Name is empty");
1471bbe86010SWenchao Xia         return;
1472bbe86010SWenchao Xia     }
1473bbe86010SWenchao Xia 
1474bbe86010SWenchao Xia     /* check whether a snapshot with name exist */
1475f70edf99SMarkus Armbruster     ret = bdrv_snapshot_find_by_id_and_name(bs, NULL, name, &old_sn,
1476f70edf99SMarkus Armbruster                                             &local_err);
1477f70edf99SMarkus Armbruster     if (local_err) {
1478f70edf99SMarkus Armbruster         error_propagate(errp, local_err);
1479bbe86010SWenchao Xia         return;
1480bbe86010SWenchao Xia     } else if (ret) {
1481bbe86010SWenchao Xia         error_setg(errp,
1482bbe86010SWenchao Xia                    "Snapshot with name '%s' already exists on device '%s'",
1483bbe86010SWenchao Xia                    name, device);
1484bbe86010SWenchao Xia         return;
1485bbe86010SWenchao Xia     }
1486bbe86010SWenchao Xia 
1487bbe86010SWenchao Xia     /* 3. take the snapshot */
1488bbe86010SWenchao Xia     sn = &state->sn;
1489bbe86010SWenchao Xia     pstrcpy(sn->name, sizeof(sn->name), name);
1490bbe86010SWenchao Xia     qemu_gettimeofday(&tv);
1491bbe86010SWenchao Xia     sn->date_sec = tv.tv_sec;
1492bbe86010SWenchao Xia     sn->date_nsec = tv.tv_usec * 1000;
1493bbe86010SWenchao Xia     sn->vm_clock_nsec = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
1494bbe86010SWenchao Xia 
1495bbe86010SWenchao Xia     ret1 = bdrv_snapshot_create(bs, sn);
1496bbe86010SWenchao Xia     if (ret1 < 0) {
1497bbe86010SWenchao Xia         error_setg_errno(errp, -ret1,
1498bbe86010SWenchao Xia                          "Failed to create snapshot '%s' on device '%s'",
1499bbe86010SWenchao Xia                          name, device);
1500bbe86010SWenchao Xia         return;
1501bbe86010SWenchao Xia     }
1502bbe86010SWenchao Xia 
1503bbe86010SWenchao Xia     /* 4. succeed, mark a snapshot is created */
1504507306ccSFam Zheng     state->created = true;
1505bbe86010SWenchao Xia }
1506bbe86010SWenchao Xia 
150750f43f0fSJohn Snow static void internal_snapshot_abort(BlkActionState *common)
1508bbe86010SWenchao Xia {
1509bbe86010SWenchao Xia     InternalSnapshotState *state =
1510bbe86010SWenchao Xia                              DO_UPCAST(InternalSnapshotState, common, common);
1511bbe86010SWenchao Xia     BlockDriverState *bs = state->bs;
1512bbe86010SWenchao Xia     QEMUSnapshotInfo *sn = &state->sn;
1513bbe86010SWenchao Xia     Error *local_error = NULL;
1514bbe86010SWenchao Xia 
1515507306ccSFam Zheng     if (!state->created) {
1516bbe86010SWenchao Xia         return;
1517bbe86010SWenchao Xia     }
1518bbe86010SWenchao Xia 
1519bbe86010SWenchao Xia     if (bdrv_snapshot_delete(bs, sn->id_str, sn->name, &local_error) < 0) {
1520bbe86010SWenchao Xia         error_report("Failed to delete snapshot with id '%s' and name '%s' on "
1521bbe86010SWenchao Xia                      "device '%s' in abort: %s",
1522bbe86010SWenchao Xia                      sn->id_str,
1523bbe86010SWenchao Xia                      sn->name,
1524bbe86010SWenchao Xia                      bdrv_get_device_name(bs),
1525bbe86010SWenchao Xia                      error_get_pretty(local_error));
1526bbe86010SWenchao Xia         error_free(local_error);
1527bbe86010SWenchao Xia     }
1528bbe86010SWenchao Xia }
1529bbe86010SWenchao Xia 
153050f43f0fSJohn Snow static void internal_snapshot_clean(BlkActionState *common)
15315d6e96efSStefan Hajnoczi {
15325d6e96efSStefan Hajnoczi     InternalSnapshotState *state = DO_UPCAST(InternalSnapshotState,
15335d6e96efSStefan Hajnoczi                                              common, common);
15345d6e96efSStefan Hajnoczi 
15355d6e96efSStefan Hajnoczi     if (state->aio_context) {
1536507306ccSFam Zheng         if (state->bs) {
1537507306ccSFam Zheng             bdrv_drained_end(state->bs);
1538507306ccSFam Zheng         }
15395d6e96efSStefan Hajnoczi         aio_context_release(state->aio_context);
15405d6e96efSStefan Hajnoczi     }
15415d6e96efSStefan Hajnoczi }
15425d6e96efSStefan Hajnoczi 
1543ba0c86a3SWenchao Xia /* external snapshot private data */
1544ba5d6ab6SStefan Hajnoczi typedef struct ExternalSnapshotState {
154550f43f0fSJohn Snow     BlkActionState common;
15468802d1fdSJeff Cody     BlockDriverState *old_bs;
15478802d1fdSJeff Cody     BlockDriverState *new_bs;
15485d6e96efSStefan Hajnoczi     AioContext *aio_context;
1549ba5d6ab6SStefan Hajnoczi } ExternalSnapshotState;
15508802d1fdSJeff Cody 
155150f43f0fSJohn Snow static void external_snapshot_prepare(BlkActionState *common,
15529b9877eeSWenchao Xia                                       Error **errp)
15539b9877eeSWenchao Xia {
155443de7e2dSAlberto Garcia     int flags = 0, ret;
155543de7e2dSAlberto Garcia     QDict *options = NULL;
15569b9877eeSWenchao Xia     Error *local_err = NULL;
155743de7e2dSAlberto Garcia     /* Device and node name of the image to generate the snapshot from */
1558e2a31e87SWenchao Xia     const char *device;
15590901f67eSBenoît Canet     const char *node_name;
156043de7e2dSAlberto Garcia     /* Reference to the new image (for 'blockdev-snapshot') */
156143de7e2dSAlberto Garcia     const char *snapshot_ref;
156243de7e2dSAlberto Garcia     /* File name of the new image (for 'blockdev-snapshot-sync') */
1563e2a31e87SWenchao Xia     const char *new_image_file;
1564ba5d6ab6SStefan Hajnoczi     ExternalSnapshotState *state =
1565ba5d6ab6SStefan Hajnoczi                              DO_UPCAST(ExternalSnapshotState, common, common);
1566c8a83e85SKevin Wolf     TransactionAction *action = common->action;
15679b9877eeSWenchao Xia 
156843de7e2dSAlberto Garcia     /* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
156943de7e2dSAlberto Garcia      * purpose but a different set of parameters */
157043de7e2dSAlberto Garcia     switch (action->type) {
157143de7e2dSAlberto Garcia     case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT:
157243de7e2dSAlberto Garcia         {
157343de7e2dSAlberto Garcia             BlockdevSnapshot *s = action->u.blockdev_snapshot;
157443de7e2dSAlberto Garcia             device = s->node;
157543de7e2dSAlberto Garcia             node_name = s->node;
157643de7e2dSAlberto Garcia             new_image_file = NULL;
157743de7e2dSAlberto Garcia             snapshot_ref = s->overlay;
1578e2a31e87SWenchao Xia         }
157943de7e2dSAlberto Garcia         break;
158043de7e2dSAlberto Garcia     case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC:
158143de7e2dSAlberto Garcia         {
158243de7e2dSAlberto Garcia             BlockdevSnapshotSync *s = action->u.blockdev_snapshot_sync;
158343de7e2dSAlberto Garcia             device = s->has_device ? s->device : NULL;
158443de7e2dSAlberto Garcia             node_name = s->has_node_name ? s->node_name : NULL;
158543de7e2dSAlberto Garcia             new_image_file = s->snapshot_file;
158643de7e2dSAlberto Garcia             snapshot_ref = NULL;
158743de7e2dSAlberto Garcia         }
158843de7e2dSAlberto Garcia         break;
158943de7e2dSAlberto Garcia     default:
159043de7e2dSAlberto Garcia         g_assert_not_reached();
1591e2a31e87SWenchao Xia     }
1592e2a31e87SWenchao Xia 
1593e2a31e87SWenchao Xia     /* start processing */
1594*94d16a64SJohn Snow     if (action_check_completion_mode(common, errp) < 0) {
1595*94d16a64SJohn Snow         return;
1596*94d16a64SJohn Snow     }
1597*94d16a64SJohn Snow 
159843de7e2dSAlberto Garcia     state->old_bs = bdrv_lookup_bs(device, node_name, errp);
159943de7e2dSAlberto Garcia     if (!state->old_bs) {
16009b9877eeSWenchao Xia         return;
16019b9877eeSWenchao Xia     }
16029b9877eeSWenchao Xia 
16035d6e96efSStefan Hajnoczi     /* Acquire AioContext now so any threads operating on old_bs stop */
16045d6e96efSStefan Hajnoczi     state->aio_context = bdrv_get_aio_context(state->old_bs);
16055d6e96efSStefan Hajnoczi     aio_context_acquire(state->aio_context);
1606da763e83SFam Zheng     bdrv_drained_begin(state->old_bs);
16075d6e96efSStefan Hajnoczi 
1608ba5d6ab6SStefan Hajnoczi     if (!bdrv_is_inserted(state->old_bs)) {
1609c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
16109b9877eeSWenchao Xia         return;
16119b9877eeSWenchao Xia     }
16129b9877eeSWenchao Xia 
16133718d8abSFam Zheng     if (bdrv_op_is_blocked(state->old_bs,
16143718d8abSFam Zheng                            BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, errp)) {
16159b9877eeSWenchao Xia         return;
16169b9877eeSWenchao Xia     }
16179b9877eeSWenchao Xia 
1618ba5d6ab6SStefan Hajnoczi     if (!bdrv_is_read_only(state->old_bs)) {
1619ba5d6ab6SStefan Hajnoczi         if (bdrv_flush(state->old_bs)) {
1620c6bd8c70SMarkus Armbruster             error_setg(errp, QERR_IO_ERROR);
16219b9877eeSWenchao Xia             return;
16229b9877eeSWenchao Xia         }
16239b9877eeSWenchao Xia     }
16249b9877eeSWenchao Xia 
1625212a5a8fSBenoît Canet     if (!bdrv_is_first_non_filter(state->old_bs)) {
1626c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_FEATURE_DISABLED, "snapshot");
1627f6186f49SBenoît Canet         return;
1628f6186f49SBenoît Canet     }
1629f6186f49SBenoît Canet 
163043de7e2dSAlberto Garcia     if (action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC) {
163143de7e2dSAlberto Garcia         BlockdevSnapshotSync *s = action->u.blockdev_snapshot_sync;
163243de7e2dSAlberto Garcia         const char *format = s->has_format ? s->format : "qcow2";
163343de7e2dSAlberto Garcia         enum NewImageMode mode;
163443de7e2dSAlberto Garcia         const char *snapshot_node_name =
163543de7e2dSAlberto Garcia             s->has_snapshot_node_name ? s->snapshot_node_name : NULL;
163643de7e2dSAlberto Garcia 
163743de7e2dSAlberto Garcia         if (node_name && !snapshot_node_name) {
163843de7e2dSAlberto Garcia             error_setg(errp, "New snapshot node name missing");
163943de7e2dSAlberto Garcia             return;
164043de7e2dSAlberto Garcia         }
164143de7e2dSAlberto Garcia 
164243de7e2dSAlberto Garcia         if (snapshot_node_name &&
164343de7e2dSAlberto Garcia             bdrv_lookup_bs(snapshot_node_name, snapshot_node_name, NULL)) {
164443de7e2dSAlberto Garcia             error_setg(errp, "New snapshot node name already in use");
164543de7e2dSAlberto Garcia             return;
164643de7e2dSAlberto Garcia         }
164743de7e2dSAlberto Garcia 
1648ba5d6ab6SStefan Hajnoczi         flags = state->old_bs->open_flags;
16499b9877eeSWenchao Xia 
16509b9877eeSWenchao Xia         /* create new image w/backing file */
165143de7e2dSAlberto Garcia         mode = s->has_mode ? s->mode : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
16529b9877eeSWenchao Xia         if (mode != NEW_IMAGE_MODE_EXISTING) {
16539b9877eeSWenchao Xia             bdrv_img_create(new_image_file, format,
1654ba5d6ab6SStefan Hajnoczi                             state->old_bs->filename,
1655ba5d6ab6SStefan Hajnoczi                             state->old_bs->drv->format_name,
16569b9877eeSWenchao Xia                             NULL, -1, flags, &local_err, false);
165784d18f06SMarkus Armbruster             if (local_err) {
16589b9877eeSWenchao Xia                 error_propagate(errp, local_err);
16599b9877eeSWenchao Xia                 return;
16609b9877eeSWenchao Xia             }
16619b9877eeSWenchao Xia         }
16629b9877eeSWenchao Xia 
16630901f67eSBenoît Canet         options = qdict_new();
166443de7e2dSAlberto Garcia         if (s->has_snapshot_node_name) {
16650901f67eSBenoît Canet             qdict_put(options, "node-name",
16660901f67eSBenoît Canet                       qstring_from_str(snapshot_node_name));
16670901f67eSBenoît Canet         }
1668e6641719SMax Reitz         qdict_put(options, "driver", qstring_from_str(format));
16690901f67eSBenoît Canet 
167043de7e2dSAlberto Garcia         flags |= BDRV_O_NO_BACKING;
167143de7e2dSAlberto Garcia     }
167243de7e2dSAlberto Garcia 
1673f67503e5SMax Reitz     assert(state->new_bs == NULL);
167443de7e2dSAlberto Garcia     ret = bdrv_open(&state->new_bs, new_image_file, snapshot_ref, options,
167543de7e2dSAlberto Garcia                     flags, errp);
1676f67503e5SMax Reitz     /* We will manually add the backing_hd field to the bs later */
16779b9877eeSWenchao Xia     if (ret != 0) {
167843de7e2dSAlberto Garcia         return;
167943de7e2dSAlberto Garcia     }
168043de7e2dSAlberto Garcia 
168143de7e2dSAlberto Garcia     if (state->new_bs->blk != NULL) {
168243de7e2dSAlberto Garcia         error_setg(errp, "The snapshot is already in use by %s",
168343de7e2dSAlberto Garcia                    blk_name(state->new_bs->blk));
168443de7e2dSAlberto Garcia         return;
168543de7e2dSAlberto Garcia     }
168643de7e2dSAlberto Garcia 
168743de7e2dSAlberto Garcia     if (bdrv_op_is_blocked(state->new_bs, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
168843de7e2dSAlberto Garcia                            errp)) {
168943de7e2dSAlberto Garcia         return;
169043de7e2dSAlberto Garcia     }
169143de7e2dSAlberto Garcia 
169243de7e2dSAlberto Garcia     if (state->new_bs->backing != NULL) {
169343de7e2dSAlberto Garcia         error_setg(errp, "The snapshot already has a backing image");
169408b24cfeSAlberto Garcia         return;
169508b24cfeSAlberto Garcia     }
169608b24cfeSAlberto Garcia 
169708b24cfeSAlberto Garcia     if (!state->new_bs->drv->supports_backing) {
169808b24cfeSAlberto Garcia         error_setg(errp, "The snapshot does not support backing images");
16999b9877eeSWenchao Xia     }
17009b9877eeSWenchao Xia }
17019b9877eeSWenchao Xia 
170250f43f0fSJohn Snow static void external_snapshot_commit(BlkActionState *common)
17033b0047e8SWenchao Xia {
1704ba5d6ab6SStefan Hajnoczi     ExternalSnapshotState *state =
1705ba5d6ab6SStefan Hajnoczi                              DO_UPCAST(ExternalSnapshotState, common, common);
1706ba0c86a3SWenchao Xia 
17075d6e96efSStefan Hajnoczi     bdrv_set_aio_context(state->new_bs, state->aio_context);
17085d6e96efSStefan Hajnoczi 
1709ba5d6ab6SStefan Hajnoczi     /* This removes our old bs and adds the new bs */
1710ba5d6ab6SStefan Hajnoczi     bdrv_append(state->new_bs, state->old_bs);
17113b0047e8SWenchao Xia     /* We don't need (or want) to use the transactional
17123b0047e8SWenchao Xia      * bdrv_reopen_multiple() across all the entries at once, because we
17133b0047e8SWenchao Xia      * don't want to abort all of them if one of them fails the reopen */
1714dd62f1caSKevin Wolf     bdrv_reopen(state->old_bs, state->old_bs->open_flags & ~BDRV_O_RDWR,
17153b0047e8SWenchao Xia                 NULL);
17163b0047e8SWenchao Xia }
17173b0047e8SWenchao Xia 
171850f43f0fSJohn Snow static void external_snapshot_abort(BlkActionState *common)
171996b86bf7SWenchao Xia {
1720ba5d6ab6SStefan Hajnoczi     ExternalSnapshotState *state =
1721ba5d6ab6SStefan Hajnoczi                              DO_UPCAST(ExternalSnapshotState, common, common);
1722ba5d6ab6SStefan Hajnoczi     if (state->new_bs) {
17234f6fd349SFam Zheng         bdrv_unref(state->new_bs);
172496b86bf7SWenchao Xia     }
1725da763e83SFam Zheng }
1726da763e83SFam Zheng 
172750f43f0fSJohn Snow static void external_snapshot_clean(BlkActionState *common)
1728da763e83SFam Zheng {
1729da763e83SFam Zheng     ExternalSnapshotState *state =
1730da763e83SFam Zheng                              DO_UPCAST(ExternalSnapshotState, common, common);
17315d6e96efSStefan Hajnoczi     if (state->aio_context) {
1732da763e83SFam Zheng         bdrv_drained_end(state->old_bs);
17335d6e96efSStefan Hajnoczi         aio_context_release(state->aio_context);
17345d6e96efSStefan Hajnoczi     }
173596b86bf7SWenchao Xia }
173696b86bf7SWenchao Xia 
17373037f364SStefan Hajnoczi typedef struct DriveBackupState {
173850f43f0fSJohn Snow     BlkActionState common;
17393037f364SStefan Hajnoczi     BlockDriverState *bs;
17405d6e96efSStefan Hajnoczi     AioContext *aio_context;
17413037f364SStefan Hajnoczi     BlockJob *job;
17423037f364SStefan Hajnoczi } DriveBackupState;
17433037f364SStefan Hajnoczi 
174478f51fdeSJohn Snow static void do_drive_backup(const char *device, const char *target,
174578f51fdeSJohn Snow                             bool has_format, const char *format,
174678f51fdeSJohn Snow                             enum MirrorSyncMode sync,
174778f51fdeSJohn Snow                             bool has_mode, enum NewImageMode mode,
174878f51fdeSJohn Snow                             bool has_speed, int64_t speed,
174978f51fdeSJohn Snow                             bool has_bitmap, const char *bitmap,
175078f51fdeSJohn Snow                             bool has_on_source_error,
175178f51fdeSJohn Snow                             BlockdevOnError on_source_error,
175278f51fdeSJohn Snow                             bool has_on_target_error,
175378f51fdeSJohn Snow                             BlockdevOnError on_target_error,
175478f51fdeSJohn Snow                             BlockJobTxn *txn, Error **errp);
175578f51fdeSJohn Snow 
175650f43f0fSJohn Snow static void drive_backup_prepare(BlkActionState *common, Error **errp)
17573037f364SStefan Hajnoczi {
17583037f364SStefan Hajnoczi     DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
1759a0e8544cSFam Zheng     BlockBackend *blk;
17603037f364SStefan Hajnoczi     DriveBackup *backup;
17613037f364SStefan Hajnoczi     Error *local_err = NULL;
17623037f364SStefan Hajnoczi 
17636a8f9661SEric Blake     assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
17646a8f9661SEric Blake     backup = common->action->u.drive_backup;
17653037f364SStefan Hajnoczi 
1766a0e8544cSFam Zheng     blk = blk_by_name(backup->device);
1767a0e8544cSFam Zheng     if (!blk) {
176875158ebbSMarkus Armbruster         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
176975158ebbSMarkus Armbruster                   "Device '%s' not found", backup->device);
17705d6e96efSStefan Hajnoczi         return;
17715d6e96efSStefan Hajnoczi     }
17725d6e96efSStefan Hajnoczi 
17731fdd4b7bSFam Zheng     if (!blk_is_available(blk)) {
17741fdd4b7bSFam Zheng         error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, backup->device);
17751fdd4b7bSFam Zheng         return;
17761fdd4b7bSFam Zheng     }
17771fdd4b7bSFam Zheng 
17785d6e96efSStefan Hajnoczi     /* AioContext is released in .clean() */
17795433c24fSMax Reitz     state->aio_context = blk_get_aio_context(blk);
17805d6e96efSStefan Hajnoczi     aio_context_acquire(state->aio_context);
17811fdd4b7bSFam Zheng     bdrv_drained_begin(blk_bs(blk));
17821fdd4b7bSFam Zheng     state->bs = blk_bs(blk);
17835d6e96efSStefan Hajnoczi 
178478f51fdeSJohn Snow     do_drive_backup(backup->device, backup->target,
17853037f364SStefan Hajnoczi                     backup->has_format, backup->format,
1786b53169eaSStefan Hajnoczi                     backup->sync,
17873037f364SStefan Hajnoczi                     backup->has_mode, backup->mode,
17883037f364SStefan Hajnoczi                     backup->has_speed, backup->speed,
1789d58d8453SJohn Snow                     backup->has_bitmap, backup->bitmap,
17903037f364SStefan Hajnoczi                     backup->has_on_source_error, backup->on_source_error,
17913037f364SStefan Hajnoczi                     backup->has_on_target_error, backup->on_target_error,
1792*94d16a64SJohn Snow                     common->block_job_txn, &local_err);
179384d18f06SMarkus Armbruster     if (local_err) {
17943037f364SStefan Hajnoczi         error_propagate(errp, local_err);
17953037f364SStefan Hajnoczi         return;
17963037f364SStefan Hajnoczi     }
17973037f364SStefan Hajnoczi 
17983037f364SStefan Hajnoczi     state->job = state->bs->job;
17993037f364SStefan Hajnoczi }
18003037f364SStefan Hajnoczi 
180150f43f0fSJohn Snow static void drive_backup_abort(BlkActionState *common)
18023037f364SStefan Hajnoczi {
18033037f364SStefan Hajnoczi     DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
18043037f364SStefan Hajnoczi     BlockDriverState *bs = state->bs;
18053037f364SStefan Hajnoczi 
18063037f364SStefan Hajnoczi     /* Only cancel if it's the job we started */
18073037f364SStefan Hajnoczi     if (bs && bs->job && bs->job == state->job) {
18083037f364SStefan Hajnoczi         block_job_cancel_sync(bs->job);
18093037f364SStefan Hajnoczi     }
18103037f364SStefan Hajnoczi }
18113037f364SStefan Hajnoczi 
181250f43f0fSJohn Snow static void drive_backup_clean(BlkActionState *common)
18135d6e96efSStefan Hajnoczi {
18145d6e96efSStefan Hajnoczi     DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
18155d6e96efSStefan Hajnoczi 
18165d6e96efSStefan Hajnoczi     if (state->aio_context) {
18171fdd4b7bSFam Zheng         bdrv_drained_end(state->bs);
18185d6e96efSStefan Hajnoczi         aio_context_release(state->aio_context);
18195d6e96efSStefan Hajnoczi     }
18205d6e96efSStefan Hajnoczi }
18215d6e96efSStefan Hajnoczi 
1822bd8baecdSFam Zheng typedef struct BlockdevBackupState {
182350f43f0fSJohn Snow     BlkActionState common;
1824bd8baecdSFam Zheng     BlockDriverState *bs;
1825bd8baecdSFam Zheng     BlockJob *job;
1826bd8baecdSFam Zheng     AioContext *aio_context;
1827bd8baecdSFam Zheng } BlockdevBackupState;
1828bd8baecdSFam Zheng 
182978f51fdeSJohn Snow static void do_blockdev_backup(const char *device, const char *target,
183078f51fdeSJohn Snow                                enum MirrorSyncMode sync,
183178f51fdeSJohn Snow                                bool has_speed, int64_t speed,
183278f51fdeSJohn Snow                                bool has_on_source_error,
183378f51fdeSJohn Snow                                BlockdevOnError on_source_error,
183478f51fdeSJohn Snow                                bool has_on_target_error,
183578f51fdeSJohn Snow                                BlockdevOnError on_target_error,
183678f51fdeSJohn Snow                                BlockJobTxn *txn, Error **errp);
183778f51fdeSJohn Snow 
183850f43f0fSJohn Snow static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
1839bd8baecdSFam Zheng {
1840bd8baecdSFam Zheng     BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
1841bd8baecdSFam Zheng     BlockdevBackup *backup;
18425433c24fSMax Reitz     BlockBackend *blk, *target;
1843bd8baecdSFam Zheng     Error *local_err = NULL;
1844bd8baecdSFam Zheng 
18456a8f9661SEric Blake     assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
18466a8f9661SEric Blake     backup = common->action->u.blockdev_backup;
1847bd8baecdSFam Zheng 
1848a0e8544cSFam Zheng     blk = blk_by_name(backup->device);
1849a0e8544cSFam Zheng     if (!blk) {
18505b347c54SMarkus Armbruster         error_setg(errp, "Device '%s' not found", backup->device);
1851bd8baecdSFam Zheng         return;
1852bd8baecdSFam Zheng     }
1853bd8baecdSFam Zheng 
1854ff52bf36SFam Zheng     if (!blk_is_available(blk)) {
1855ff52bf36SFam Zheng         error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, backup->device);
1856ff52bf36SFam Zheng         return;
1857ff52bf36SFam Zheng     }
1858ff52bf36SFam Zheng 
18595433c24fSMax Reitz     target = blk_by_name(backup->target);
18605433c24fSMax Reitz     if (!target) {
18615b347c54SMarkus Armbruster         error_setg(errp, "Device '%s' not found", backup->target);
1862bd8baecdSFam Zheng         return;
1863bd8baecdSFam Zheng     }
1864bd8baecdSFam Zheng 
1865bd8baecdSFam Zheng     /* AioContext is released in .clean() */
18665433c24fSMax Reitz     state->aio_context = blk_get_aio_context(blk);
18675433c24fSMax Reitz     if (state->aio_context != blk_get_aio_context(target)) {
1868bd8baecdSFam Zheng         state->aio_context = NULL;
1869bd8baecdSFam Zheng         error_setg(errp, "Backup between two IO threads is not implemented");
1870bd8baecdSFam Zheng         return;
1871bd8baecdSFam Zheng     }
1872bd8baecdSFam Zheng     aio_context_acquire(state->aio_context);
1873ff52bf36SFam Zheng     state->bs = blk_bs(blk);
1874ff52bf36SFam Zheng     bdrv_drained_begin(state->bs);
1875bd8baecdSFam Zheng 
187678f51fdeSJohn Snow     do_blockdev_backup(backup->device, backup->target,
1877bd8baecdSFam Zheng                        backup->sync,
1878bd8baecdSFam Zheng                        backup->has_speed, backup->speed,
1879bd8baecdSFam Zheng                        backup->has_on_source_error, backup->on_source_error,
1880bd8baecdSFam Zheng                        backup->has_on_target_error, backup->on_target_error,
1881*94d16a64SJohn Snow                        common->block_job_txn, &local_err);
1882bd8baecdSFam Zheng     if (local_err) {
1883bd8baecdSFam Zheng         error_propagate(errp, local_err);
1884bd8baecdSFam Zheng         return;
1885bd8baecdSFam Zheng     }
1886bd8baecdSFam Zheng 
1887bd8baecdSFam Zheng     state->job = state->bs->job;
1888bd8baecdSFam Zheng }
1889bd8baecdSFam Zheng 
189050f43f0fSJohn Snow static void blockdev_backup_abort(BlkActionState *common)
1891bd8baecdSFam Zheng {
1892bd8baecdSFam Zheng     BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
1893bd8baecdSFam Zheng     BlockDriverState *bs = state->bs;
1894bd8baecdSFam Zheng 
1895bd8baecdSFam Zheng     /* Only cancel if it's the job we started */
1896bd8baecdSFam Zheng     if (bs && bs->job && bs->job == state->job) {
1897bd8baecdSFam Zheng         block_job_cancel_sync(bs->job);
1898bd8baecdSFam Zheng     }
1899bd8baecdSFam Zheng }
1900bd8baecdSFam Zheng 
190150f43f0fSJohn Snow static void blockdev_backup_clean(BlkActionState *common)
1902bd8baecdSFam Zheng {
1903bd8baecdSFam Zheng     BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
1904bd8baecdSFam Zheng 
1905bd8baecdSFam Zheng     if (state->aio_context) {
1906ff52bf36SFam Zheng         bdrv_drained_end(state->bs);
1907bd8baecdSFam Zheng         aio_context_release(state->aio_context);
1908bd8baecdSFam Zheng     }
1909bd8baecdSFam Zheng }
1910bd8baecdSFam Zheng 
1911df9a681dSFam Zheng typedef struct BlockDirtyBitmapState {
191250f43f0fSJohn Snow     BlkActionState common;
1913df9a681dSFam Zheng     BdrvDirtyBitmap *bitmap;
1914df9a681dSFam Zheng     BlockDriverState *bs;
1915df9a681dSFam Zheng     AioContext *aio_context;
1916df9a681dSFam Zheng     HBitmap *backup;
1917df9a681dSFam Zheng     bool prepared;
1918df9a681dSFam Zheng } BlockDirtyBitmapState;
1919df9a681dSFam Zheng 
192050f43f0fSJohn Snow static void block_dirty_bitmap_add_prepare(BlkActionState *common,
1921df9a681dSFam Zheng                                            Error **errp)
1922df9a681dSFam Zheng {
1923df9a681dSFam Zheng     Error *local_err = NULL;
1924df9a681dSFam Zheng     BlockDirtyBitmapAdd *action;
1925df9a681dSFam Zheng     BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
1926df9a681dSFam Zheng                                              common, common);
1927df9a681dSFam Zheng 
1928*94d16a64SJohn Snow     if (action_check_completion_mode(common, errp) < 0) {
1929*94d16a64SJohn Snow         return;
1930*94d16a64SJohn Snow     }
1931*94d16a64SJohn Snow 
193250f43f0fSJohn Snow     action = common->action->u.block_dirty_bitmap_add;
1933df9a681dSFam Zheng     /* AIO context taken and released within qmp_block_dirty_bitmap_add */
1934df9a681dSFam Zheng     qmp_block_dirty_bitmap_add(action->node, action->name,
1935df9a681dSFam Zheng                                action->has_granularity, action->granularity,
1936df9a681dSFam Zheng                                &local_err);
1937df9a681dSFam Zheng 
1938df9a681dSFam Zheng     if (!local_err) {
1939df9a681dSFam Zheng         state->prepared = true;
1940df9a681dSFam Zheng     } else {
1941df9a681dSFam Zheng         error_propagate(errp, local_err);
1942df9a681dSFam Zheng     }
1943df9a681dSFam Zheng }
1944df9a681dSFam Zheng 
194550f43f0fSJohn Snow static void block_dirty_bitmap_add_abort(BlkActionState *common)
1946df9a681dSFam Zheng {
1947df9a681dSFam Zheng     BlockDirtyBitmapAdd *action;
1948df9a681dSFam Zheng     BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
1949df9a681dSFam Zheng                                              common, common);
1950df9a681dSFam Zheng 
195150f43f0fSJohn Snow     action = common->action->u.block_dirty_bitmap_add;
1952df9a681dSFam Zheng     /* Should not be able to fail: IF the bitmap was added via .prepare(),
1953df9a681dSFam Zheng      * then the node reference and bitmap name must have been valid.
1954df9a681dSFam Zheng      */
1955df9a681dSFam Zheng     if (state->prepared) {
1956df9a681dSFam Zheng         qmp_block_dirty_bitmap_remove(action->node, action->name, &error_abort);
1957df9a681dSFam Zheng     }
1958df9a681dSFam Zheng }
1959df9a681dSFam Zheng 
196050f43f0fSJohn Snow static void block_dirty_bitmap_clear_prepare(BlkActionState *common,
1961df9a681dSFam Zheng                                              Error **errp)
1962df9a681dSFam Zheng {
1963df9a681dSFam Zheng     BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
1964df9a681dSFam Zheng                                              common, common);
1965df9a681dSFam Zheng     BlockDirtyBitmap *action;
1966df9a681dSFam Zheng 
1967*94d16a64SJohn Snow     if (action_check_completion_mode(common, errp) < 0) {
1968*94d16a64SJohn Snow         return;
1969*94d16a64SJohn Snow     }
1970*94d16a64SJohn Snow 
197150f43f0fSJohn Snow     action = common->action->u.block_dirty_bitmap_clear;
1972df9a681dSFam Zheng     state->bitmap = block_dirty_bitmap_lookup(action->node,
1973df9a681dSFam Zheng                                               action->name,
1974df9a681dSFam Zheng                                               &state->bs,
1975df9a681dSFam Zheng                                               &state->aio_context,
1976df9a681dSFam Zheng                                               errp);
1977df9a681dSFam Zheng     if (!state->bitmap) {
1978df9a681dSFam Zheng         return;
1979df9a681dSFam Zheng     }
1980df9a681dSFam Zheng 
1981df9a681dSFam Zheng     if (bdrv_dirty_bitmap_frozen(state->bitmap)) {
1982df9a681dSFam Zheng         error_setg(errp, "Cannot modify a frozen bitmap");
1983df9a681dSFam Zheng         return;
1984df9a681dSFam Zheng     } else if (!bdrv_dirty_bitmap_enabled(state->bitmap)) {
1985df9a681dSFam Zheng         error_setg(errp, "Cannot clear a disabled bitmap");
1986df9a681dSFam Zheng         return;
1987df9a681dSFam Zheng     }
1988df9a681dSFam Zheng 
1989df9a681dSFam Zheng     bdrv_clear_dirty_bitmap(state->bitmap, &state->backup);
1990df9a681dSFam Zheng     /* AioContext is released in .clean() */
1991df9a681dSFam Zheng }
1992df9a681dSFam Zheng 
199350f43f0fSJohn Snow static void block_dirty_bitmap_clear_abort(BlkActionState *common)
1994df9a681dSFam Zheng {
1995df9a681dSFam Zheng     BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
1996df9a681dSFam Zheng                                              common, common);
1997df9a681dSFam Zheng 
1998df9a681dSFam Zheng     bdrv_undo_clear_dirty_bitmap(state->bitmap, state->backup);
1999df9a681dSFam Zheng }
2000df9a681dSFam Zheng 
200150f43f0fSJohn Snow static void block_dirty_bitmap_clear_commit(BlkActionState *common)
2002df9a681dSFam Zheng {
2003df9a681dSFam Zheng     BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
2004df9a681dSFam Zheng                                              common, common);
2005df9a681dSFam Zheng 
2006df9a681dSFam Zheng     hbitmap_free(state->backup);
2007df9a681dSFam Zheng }
2008df9a681dSFam Zheng 
200950f43f0fSJohn Snow static void block_dirty_bitmap_clear_clean(BlkActionState *common)
2010df9a681dSFam Zheng {
2011df9a681dSFam Zheng     BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
2012df9a681dSFam Zheng                                              common, common);
2013df9a681dSFam Zheng 
2014df9a681dSFam Zheng     if (state->aio_context) {
2015df9a681dSFam Zheng         aio_context_release(state->aio_context);
2016df9a681dSFam Zheng     }
2017df9a681dSFam Zheng }
2018df9a681dSFam Zheng 
201950f43f0fSJohn Snow static void abort_prepare(BlkActionState *common, Error **errp)
202078b18b78SStefan Hajnoczi {
202178b18b78SStefan Hajnoczi     error_setg(errp, "Transaction aborted using Abort action");
202278b18b78SStefan Hajnoczi }
202378b18b78SStefan Hajnoczi 
202450f43f0fSJohn Snow static void abort_commit(BlkActionState *common)
202578b18b78SStefan Hajnoczi {
2026dfc6f865SStefan Weil     g_assert_not_reached(); /* this action never succeeds */
202778b18b78SStefan Hajnoczi }
202878b18b78SStefan Hajnoczi 
202950f43f0fSJohn Snow static const BlkActionOps actions[] = {
203043de7e2dSAlberto Garcia     [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT] = {
203143de7e2dSAlberto Garcia         .instance_size = sizeof(ExternalSnapshotState),
203243de7e2dSAlberto Garcia         .prepare  = external_snapshot_prepare,
203343de7e2dSAlberto Garcia         .commit   = external_snapshot_commit,
203443de7e2dSAlberto Garcia         .abort = external_snapshot_abort,
203543de7e2dSAlberto Garcia     },
2036c8a83e85SKevin Wolf     [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC] = {
2037ba5d6ab6SStefan Hajnoczi         .instance_size = sizeof(ExternalSnapshotState),
2038ba0c86a3SWenchao Xia         .prepare  = external_snapshot_prepare,
2039ba0c86a3SWenchao Xia         .commit   = external_snapshot_commit,
2040ba0c86a3SWenchao Xia         .abort = external_snapshot_abort,
2041da763e83SFam Zheng         .clean = external_snapshot_clean,
2042ba0c86a3SWenchao Xia     },
20433037f364SStefan Hajnoczi     [TRANSACTION_ACTION_KIND_DRIVE_BACKUP] = {
20443037f364SStefan Hajnoczi         .instance_size = sizeof(DriveBackupState),
20453037f364SStefan Hajnoczi         .prepare = drive_backup_prepare,
20463037f364SStefan Hajnoczi         .abort = drive_backup_abort,
20475d6e96efSStefan Hajnoczi         .clean = drive_backup_clean,
20483037f364SStefan Hajnoczi     },
2049bd8baecdSFam Zheng     [TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP] = {
2050bd8baecdSFam Zheng         .instance_size = sizeof(BlockdevBackupState),
2051bd8baecdSFam Zheng         .prepare = blockdev_backup_prepare,
2052bd8baecdSFam Zheng         .abort = blockdev_backup_abort,
2053bd8baecdSFam Zheng         .clean = blockdev_backup_clean,
2054bd8baecdSFam Zheng     },
205578b18b78SStefan Hajnoczi     [TRANSACTION_ACTION_KIND_ABORT] = {
205650f43f0fSJohn Snow         .instance_size = sizeof(BlkActionState),
205778b18b78SStefan Hajnoczi         .prepare = abort_prepare,
205878b18b78SStefan Hajnoczi         .commit = abort_commit,
205978b18b78SStefan Hajnoczi     },
2060bbe86010SWenchao Xia     [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC] = {
2061bbe86010SWenchao Xia         .instance_size = sizeof(InternalSnapshotState),
2062bbe86010SWenchao Xia         .prepare  = internal_snapshot_prepare,
2063bbe86010SWenchao Xia         .abort = internal_snapshot_abort,
20645d6e96efSStefan Hajnoczi         .clean = internal_snapshot_clean,
2065bbe86010SWenchao Xia     },
2066df9a681dSFam Zheng     [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_ADD] = {
2067df9a681dSFam Zheng         .instance_size = sizeof(BlockDirtyBitmapState),
2068df9a681dSFam Zheng         .prepare = block_dirty_bitmap_add_prepare,
2069df9a681dSFam Zheng         .abort = block_dirty_bitmap_add_abort,
2070df9a681dSFam Zheng     },
2071df9a681dSFam Zheng     [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_CLEAR] = {
2072df9a681dSFam Zheng         .instance_size = sizeof(BlockDirtyBitmapState),
2073df9a681dSFam Zheng         .prepare = block_dirty_bitmap_clear_prepare,
2074df9a681dSFam Zheng         .commit = block_dirty_bitmap_clear_commit,
2075df9a681dSFam Zheng         .abort = block_dirty_bitmap_clear_abort,
2076df9a681dSFam Zheng         .clean = block_dirty_bitmap_clear_clean,
2077df9a681dSFam Zheng     }
2078ba0c86a3SWenchao Xia };
2079ba0c86a3SWenchao Xia 
2080*94d16a64SJohn Snow /**
2081*94d16a64SJohn Snow  * Allocate a TransactionProperties structure if necessary, and fill
2082*94d16a64SJohn Snow  * that structure with desired defaults if they are unset.
2083*94d16a64SJohn Snow  */
2084*94d16a64SJohn Snow static TransactionProperties *get_transaction_properties(
2085*94d16a64SJohn Snow     TransactionProperties *props)
2086*94d16a64SJohn Snow {
2087*94d16a64SJohn Snow     if (!props) {
2088*94d16a64SJohn Snow         props = g_new0(TransactionProperties, 1);
2089*94d16a64SJohn Snow     }
2090*94d16a64SJohn Snow 
2091*94d16a64SJohn Snow     if (!props->has_completion_mode) {
2092*94d16a64SJohn Snow         props->has_completion_mode = true;
2093*94d16a64SJohn Snow         props->completion_mode = ACTION_COMPLETION_MODE_INDIVIDUAL;
2094*94d16a64SJohn Snow     }
2095*94d16a64SJohn Snow 
2096*94d16a64SJohn Snow     return props;
2097*94d16a64SJohn Snow }
2098*94d16a64SJohn Snow 
20998802d1fdSJeff Cody /*
2100b756b9ceSStefan Hajnoczi  * 'Atomic' group operations.  The operations are performed as a set, and if
2101b756b9ceSStefan Hajnoczi  * any fail then we roll back all operations in the group.
21028802d1fdSJeff Cody  */
2103*94d16a64SJohn Snow void qmp_transaction(TransactionActionList *dev_list,
2104*94d16a64SJohn Snow                      bool has_props,
2105*94d16a64SJohn Snow                      struct TransactionProperties *props,
2106*94d16a64SJohn Snow                      Error **errp)
21078802d1fdSJeff Cody {
2108c8a83e85SKevin Wolf     TransactionActionList *dev_entry = dev_list;
2109*94d16a64SJohn Snow     BlockJobTxn *block_job_txn = NULL;
211050f43f0fSJohn Snow     BlkActionState *state, *next;
211143e17041SLuiz Capitulino     Error *local_err = NULL;
21128802d1fdSJeff Cody 
211350f43f0fSJohn Snow     QSIMPLEQ_HEAD(snap_bdrv_states, BlkActionState) snap_bdrv_states;
21148802d1fdSJeff Cody     QSIMPLEQ_INIT(&snap_bdrv_states);
21158802d1fdSJeff Cody 
2116*94d16a64SJohn Snow     /* Does this transaction get canceled as a group on failure?
2117*94d16a64SJohn Snow      * If not, we don't really need to make a BlockJobTxn.
2118*94d16a64SJohn Snow      */
2119*94d16a64SJohn Snow     props = get_transaction_properties(props);
2120*94d16a64SJohn Snow     if (props->completion_mode != ACTION_COMPLETION_MODE_INDIVIDUAL) {
2121*94d16a64SJohn Snow         block_job_txn = block_job_txn_new();
2122*94d16a64SJohn Snow     }
2123*94d16a64SJohn Snow 
2124b756b9ceSStefan Hajnoczi     /* drain all i/o before any operations */
21258802d1fdSJeff Cody     bdrv_drain_all();
21268802d1fdSJeff Cody 
2127b756b9ceSStefan Hajnoczi     /* We don't do anything in this loop that commits us to the operations */
21288802d1fdSJeff Cody     while (NULL != dev_entry) {
2129c8a83e85SKevin Wolf         TransactionAction *dev_info = NULL;
213050f43f0fSJohn Snow         const BlkActionOps *ops;
213152e7c241SPaolo Bonzini 
21328802d1fdSJeff Cody         dev_info = dev_entry->value;
21338802d1fdSJeff Cody         dev_entry = dev_entry->next;
21348802d1fdSJeff Cody 
21356a8f9661SEric Blake         assert(dev_info->type < ARRAY_SIZE(actions));
2136ba0c86a3SWenchao Xia 
21376a8f9661SEric Blake         ops = &actions[dev_info->type];
2138aa3fe714SMax Reitz         assert(ops->instance_size > 0);
2139aa3fe714SMax Reitz 
2140ba5d6ab6SStefan Hajnoczi         state = g_malloc0(ops->instance_size);
2141ba5d6ab6SStefan Hajnoczi         state->ops = ops;
2142ba5d6ab6SStefan Hajnoczi         state->action = dev_info;
2143*94d16a64SJohn Snow         state->block_job_txn = block_job_txn;
2144*94d16a64SJohn Snow         state->txn_props = props;
2145ba5d6ab6SStefan Hajnoczi         QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, state, entry);
21468802d1fdSJeff Cody 
2147ba5d6ab6SStefan Hajnoczi         state->ops->prepare(state, &local_err);
214884d18f06SMarkus Armbruster         if (local_err) {
21499b9877eeSWenchao Xia             error_propagate(errp, local_err);
21509b9877eeSWenchao Xia             goto delete_and_fail;
21519b9877eeSWenchao Xia         }
215252e7c241SPaolo Bonzini     }
21538802d1fdSJeff Cody 
2154ba5d6ab6SStefan Hajnoczi     QSIMPLEQ_FOREACH(state, &snap_bdrv_states, entry) {
2155f9ea81e8SStefan Hajnoczi         if (state->ops->commit) {
2156ba5d6ab6SStefan Hajnoczi             state->ops->commit(state);
21578802d1fdSJeff Cody         }
2158f9ea81e8SStefan Hajnoczi     }
21598802d1fdSJeff Cody 
21608802d1fdSJeff Cody     /* success */
21618802d1fdSJeff Cody     goto exit;
21628802d1fdSJeff Cody 
21638802d1fdSJeff Cody delete_and_fail:
2164b756b9ceSStefan Hajnoczi     /* failure, and it is all-or-none; roll back all operations */
2165ba5d6ab6SStefan Hajnoczi     QSIMPLEQ_FOREACH(state, &snap_bdrv_states, entry) {
2166ba5d6ab6SStefan Hajnoczi         if (state->ops->abort) {
2167ba5d6ab6SStefan Hajnoczi             state->ops->abort(state);
2168ba0c86a3SWenchao Xia         }
21698802d1fdSJeff Cody     }
21708802d1fdSJeff Cody exit:
2171ba5d6ab6SStefan Hajnoczi     QSIMPLEQ_FOREACH_SAFE(state, &snap_bdrv_states, entry, next) {
2172ba5d6ab6SStefan Hajnoczi         if (state->ops->clean) {
2173ba5d6ab6SStefan Hajnoczi             state->ops->clean(state);
2174ba0c86a3SWenchao Xia         }
2175ba5d6ab6SStefan Hajnoczi         g_free(state);
21768802d1fdSJeff Cody     }
2177*94d16a64SJohn Snow     if (!has_props) {
2178*94d16a64SJohn Snow         qapi_free_TransactionProperties(props);
2179*94d16a64SJohn Snow     }
2180*94d16a64SJohn Snow     block_job_txn_unref(block_job_txn);
21818802d1fdSJeff Cody }
21828802d1fdSJeff Cody 
2183c245b6a3SLuiz Capitulino void qmp_eject(const char *device, bool has_force, bool force, Error **errp)
2184666daa68SMarkus Armbruster {
218538f54bd1SMax Reitz     Error *local_err = NULL;
2186666daa68SMarkus Armbruster 
218738f54bd1SMax Reitz     qmp_blockdev_open_tray(device, has_force, force, &local_err);
218838f54bd1SMax Reitz     if (local_err) {
218938f54bd1SMax Reitz         error_propagate(errp, local_err);
2190c245b6a3SLuiz Capitulino         return;
2191666daa68SMarkus Armbruster     }
219292d48558SLuiz Capitulino 
219338f54bd1SMax Reitz     qmp_blockdev_remove_medium(device, errp);
2194666daa68SMarkus Armbruster }
2195666daa68SMarkus Armbruster 
219612d3ba82SBenoît Canet void qmp_block_passwd(bool has_device, const char *device,
219712d3ba82SBenoît Canet                       bool has_node_name, const char *node_name,
219812d3ba82SBenoît Canet                       const char *password, Error **errp)
2199666daa68SMarkus Armbruster {
220012d3ba82SBenoît Canet     Error *local_err = NULL;
2201666daa68SMarkus Armbruster     BlockDriverState *bs;
2202e3442099SStefan Hajnoczi     AioContext *aio_context;
2203666daa68SMarkus Armbruster 
220412d3ba82SBenoît Canet     bs = bdrv_lookup_bs(has_device ? device : NULL,
220512d3ba82SBenoît Canet                         has_node_name ? node_name : NULL,
220612d3ba82SBenoît Canet                         &local_err);
220784d18f06SMarkus Armbruster     if (local_err) {
220812d3ba82SBenoît Canet         error_propagate(errp, local_err);
2209a4dea8a9SLuiz Capitulino         return;
2210666daa68SMarkus Armbruster     }
2211666daa68SMarkus Armbruster 
2212e3442099SStefan Hajnoczi     aio_context = bdrv_get_aio_context(bs);
2213e3442099SStefan Hajnoczi     aio_context_acquire(aio_context);
2214e3442099SStefan Hajnoczi 
22154d2855a3SMarkus Armbruster     bdrv_add_key(bs, password, errp);
2216666daa68SMarkus Armbruster 
2217e3442099SStefan Hajnoczi     aio_context_release(aio_context);
2218e3442099SStefan Hajnoczi }
2219e3442099SStefan Hajnoczi 
22207d8a9f71SMax Reitz void qmp_blockdev_open_tray(const char *device, bool has_force, bool force,
22217d8a9f71SMax Reitz                             Error **errp)
22227d8a9f71SMax Reitz {
22237d8a9f71SMax Reitz     BlockBackend *blk;
22247d8a9f71SMax Reitz     bool locked;
22257d8a9f71SMax Reitz 
22267d8a9f71SMax Reitz     if (!has_force) {
22277d8a9f71SMax Reitz         force = false;
22287d8a9f71SMax Reitz     }
22297d8a9f71SMax Reitz 
22307d8a9f71SMax Reitz     blk = blk_by_name(device);
22317d8a9f71SMax Reitz     if (!blk) {
22327d8a9f71SMax Reitz         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
22337d8a9f71SMax Reitz                   "Device '%s' not found", device);
22347d8a9f71SMax Reitz         return;
22357d8a9f71SMax Reitz     }
22367d8a9f71SMax Reitz 
22377d8a9f71SMax Reitz     if (!blk_dev_has_removable_media(blk)) {
22387d8a9f71SMax Reitz         error_setg(errp, "Device '%s' is not removable", device);
22397d8a9f71SMax Reitz         return;
22407d8a9f71SMax Reitz     }
22417d8a9f71SMax Reitz 
22427d8a9f71SMax Reitz     if (blk_dev_is_tray_open(blk)) {
22437d8a9f71SMax Reitz         return;
22447d8a9f71SMax Reitz     }
22457d8a9f71SMax Reitz 
22467d8a9f71SMax Reitz     locked = blk_dev_is_medium_locked(blk);
22477d8a9f71SMax Reitz     if (locked) {
22487d8a9f71SMax Reitz         blk_dev_eject_request(blk, force);
22497d8a9f71SMax Reitz     }
22507d8a9f71SMax Reitz 
22517d8a9f71SMax Reitz     if (!locked || force) {
22527d8a9f71SMax Reitz         blk_dev_change_media_cb(blk, false);
22537d8a9f71SMax Reitz     }
22547d8a9f71SMax Reitz }
22557d8a9f71SMax Reitz 
2256abaaf59dSMax Reitz void qmp_blockdev_close_tray(const char *device, Error **errp)
2257abaaf59dSMax Reitz {
2258abaaf59dSMax Reitz     BlockBackend *blk;
2259abaaf59dSMax Reitz 
2260abaaf59dSMax Reitz     blk = blk_by_name(device);
2261abaaf59dSMax Reitz     if (!blk) {
2262abaaf59dSMax Reitz         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
2263abaaf59dSMax Reitz                   "Device '%s' not found", device);
2264abaaf59dSMax Reitz         return;
2265abaaf59dSMax Reitz     }
2266abaaf59dSMax Reitz 
2267abaaf59dSMax Reitz     if (!blk_dev_has_removable_media(blk)) {
2268abaaf59dSMax Reitz         error_setg(errp, "Device '%s' is not removable", device);
2269abaaf59dSMax Reitz         return;
2270abaaf59dSMax Reitz     }
2271abaaf59dSMax Reitz 
2272abaaf59dSMax Reitz     if (!blk_dev_is_tray_open(blk)) {
2273abaaf59dSMax Reitz         return;
2274abaaf59dSMax Reitz     }
2275abaaf59dSMax Reitz 
2276abaaf59dSMax Reitz     blk_dev_change_media_cb(blk, true);
2277abaaf59dSMax Reitz }
2278abaaf59dSMax Reitz 
22792814f672SMax Reitz void qmp_blockdev_remove_medium(const char *device, Error **errp)
22802814f672SMax Reitz {
22812814f672SMax Reitz     BlockBackend *blk;
22822814f672SMax Reitz     BlockDriverState *bs;
22832814f672SMax Reitz     AioContext *aio_context;
22842814f672SMax Reitz     bool has_device;
22852814f672SMax Reitz 
22862814f672SMax Reitz     blk = blk_by_name(device);
22872814f672SMax Reitz     if (!blk) {
22882814f672SMax Reitz         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
22892814f672SMax Reitz                   "Device '%s' not found", device);
22902814f672SMax Reitz         return;
22912814f672SMax Reitz     }
22922814f672SMax Reitz 
22932814f672SMax Reitz     /* For BBs without a device, we can exchange the BDS tree at will */
22942814f672SMax Reitz     has_device = blk_get_attached_dev(blk);
22952814f672SMax Reitz 
22962814f672SMax Reitz     if (has_device && !blk_dev_has_removable_media(blk)) {
22972814f672SMax Reitz         error_setg(errp, "Device '%s' is not removable", device);
22982814f672SMax Reitz         return;
22992814f672SMax Reitz     }
23002814f672SMax Reitz 
23012814f672SMax Reitz     if (has_device && !blk_dev_is_tray_open(blk)) {
23022814f672SMax Reitz         error_setg(errp, "Tray of device '%s' is not open", device);
23032814f672SMax Reitz         return;
23042814f672SMax Reitz     }
23052814f672SMax Reitz 
23062814f672SMax Reitz     bs = blk_bs(blk);
23072814f672SMax Reitz     if (!bs) {
23082814f672SMax Reitz         return;
23092814f672SMax Reitz     }
23102814f672SMax Reitz 
23112814f672SMax Reitz     aio_context = bdrv_get_aio_context(bs);
23122814f672SMax Reitz     aio_context_acquire(aio_context);
23132814f672SMax Reitz 
23142814f672SMax Reitz     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
23152814f672SMax Reitz         goto out;
23162814f672SMax Reitz     }
23172814f672SMax Reitz 
23182814f672SMax Reitz     /* This follows the convention established by bdrv_make_anon() */
23192814f672SMax Reitz     if (bs->device_list.tqe_prev) {
23202814f672SMax Reitz         QTAILQ_REMOVE(&bdrv_states, bs, device_list);
23212814f672SMax Reitz         bs->device_list.tqe_prev = NULL;
23222814f672SMax Reitz     }
23232814f672SMax Reitz 
23242814f672SMax Reitz     blk_remove_bs(blk);
23252814f672SMax Reitz 
23262814f672SMax Reitz out:
23272814f672SMax Reitz     aio_context_release(aio_context);
23282814f672SMax Reitz }
23292814f672SMax Reitz 
2330d1299882SMax Reitz static void qmp_blockdev_insert_anon_medium(const char *device,
2331d1299882SMax Reitz                                             BlockDriverState *bs, Error **errp)
2332d1299882SMax Reitz {
2333d1299882SMax Reitz     BlockBackend *blk;
2334d1299882SMax Reitz     bool has_device;
2335d1299882SMax Reitz 
2336d1299882SMax Reitz     blk = blk_by_name(device);
2337d1299882SMax Reitz     if (!blk) {
2338d1299882SMax Reitz         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
2339d1299882SMax Reitz                   "Device '%s' not found", device);
2340d1299882SMax Reitz         return;
2341d1299882SMax Reitz     }
2342d1299882SMax Reitz 
2343d1299882SMax Reitz     /* For BBs without a device, we can exchange the BDS tree at will */
2344d1299882SMax Reitz     has_device = blk_get_attached_dev(blk);
2345d1299882SMax Reitz 
2346d1299882SMax Reitz     if (has_device && !blk_dev_has_removable_media(blk)) {
2347d1299882SMax Reitz         error_setg(errp, "Device '%s' is not removable", device);
2348d1299882SMax Reitz         return;
2349d1299882SMax Reitz     }
2350d1299882SMax Reitz 
2351d1299882SMax Reitz     if (has_device && !blk_dev_is_tray_open(blk)) {
2352d1299882SMax Reitz         error_setg(errp, "Tray of device '%s' is not open", device);
2353d1299882SMax Reitz         return;
2354d1299882SMax Reitz     }
2355d1299882SMax Reitz 
2356d1299882SMax Reitz     if (blk_bs(blk)) {
2357d1299882SMax Reitz         error_setg(errp, "There already is a medium in device '%s'", device);
2358d1299882SMax Reitz         return;
2359d1299882SMax Reitz     }
2360d1299882SMax Reitz 
2361d1299882SMax Reitz     blk_insert_bs(blk, bs);
2362d1299882SMax Reitz 
2363d1299882SMax Reitz     QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list);
2364d1299882SMax Reitz }
2365d1299882SMax Reitz 
2366d1299882SMax Reitz void qmp_blockdev_insert_medium(const char *device, const char *node_name,
2367d1299882SMax Reitz                                 Error **errp)
2368d1299882SMax Reitz {
2369d1299882SMax Reitz     BlockDriverState *bs;
2370d1299882SMax Reitz 
2371d1299882SMax Reitz     bs = bdrv_find_node(node_name);
2372d1299882SMax Reitz     if (!bs) {
2373d1299882SMax Reitz         error_setg(errp, "Node '%s' not found", node_name);
2374d1299882SMax Reitz         return;
2375d1299882SMax Reitz     }
2376d1299882SMax Reitz 
2377d1299882SMax Reitz     if (bs->blk) {
2378d1299882SMax Reitz         error_setg(errp, "Node '%s' is already in use by '%s'", node_name,
2379d1299882SMax Reitz                    blk_name(bs->blk));
2380d1299882SMax Reitz         return;
2381d1299882SMax Reitz     }
2382d1299882SMax Reitz 
2383d1299882SMax Reitz     qmp_blockdev_insert_anon_medium(device, bs, errp);
2384d1299882SMax Reitz }
2385d1299882SMax Reitz 
238624fb4133SMax Reitz void qmp_blockdev_change_medium(const char *device, const char *filename,
238724fb4133SMax Reitz                                 bool has_format, const char *format,
238839ff43d9SMax Reitz                                 bool has_read_only,
238939ff43d9SMax Reitz                                 BlockdevChangeReadOnlyMode read_only,
239024fb4133SMax Reitz                                 Error **errp)
2391de2c6c05SMax Reitz {
2392de2c6c05SMax Reitz     BlockBackend *blk;
2393de2c6c05SMax Reitz     BlockDriverState *medium_bs = NULL;
2394de2c6c05SMax Reitz     int bdrv_flags, ret;
2395de2c6c05SMax Reitz     QDict *options = NULL;
2396de2c6c05SMax Reitz     Error *err = NULL;
2397de2c6c05SMax Reitz 
2398de2c6c05SMax Reitz     blk = blk_by_name(device);
2399de2c6c05SMax Reitz     if (!blk) {
2400de2c6c05SMax Reitz         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
2401de2c6c05SMax Reitz                   "Device '%s' not found", device);
2402de2c6c05SMax Reitz         goto fail;
2403de2c6c05SMax Reitz     }
2404de2c6c05SMax Reitz 
2405de2c6c05SMax Reitz     if (blk_bs(blk)) {
2406de2c6c05SMax Reitz         blk_update_root_state(blk);
2407de2c6c05SMax Reitz     }
2408de2c6c05SMax Reitz 
2409de2c6c05SMax Reitz     bdrv_flags = blk_get_open_flags_from_root_state(blk);
2410de2c6c05SMax Reitz 
241139ff43d9SMax Reitz     if (!has_read_only) {
241239ff43d9SMax Reitz         read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
241339ff43d9SMax Reitz     }
241439ff43d9SMax Reitz 
241539ff43d9SMax Reitz     switch (read_only) {
241639ff43d9SMax Reitz     case BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN:
241739ff43d9SMax Reitz         break;
241839ff43d9SMax Reitz 
241939ff43d9SMax Reitz     case BLOCKDEV_CHANGE_READ_ONLY_MODE_READ_ONLY:
242039ff43d9SMax Reitz         bdrv_flags &= ~BDRV_O_RDWR;
242139ff43d9SMax Reitz         break;
242239ff43d9SMax Reitz 
242339ff43d9SMax Reitz     case BLOCKDEV_CHANGE_READ_ONLY_MODE_READ_WRITE:
242439ff43d9SMax Reitz         bdrv_flags |= BDRV_O_RDWR;
242539ff43d9SMax Reitz         break;
242639ff43d9SMax Reitz 
242739ff43d9SMax Reitz     default:
242839ff43d9SMax Reitz         abort();
242939ff43d9SMax Reitz     }
243039ff43d9SMax Reitz 
243124fb4133SMax Reitz     if (has_format) {
2432de2c6c05SMax Reitz         options = qdict_new();
2433de2c6c05SMax Reitz         qdict_put(options, "driver", qstring_from_str(format));
2434de2c6c05SMax Reitz     }
2435de2c6c05SMax Reitz 
2436de2c6c05SMax Reitz     assert(!medium_bs);
2437de2c6c05SMax Reitz     ret = bdrv_open(&medium_bs, filename, NULL, options, bdrv_flags, errp);
2438de2c6c05SMax Reitz     if (ret < 0) {
2439de2c6c05SMax Reitz         goto fail;
2440de2c6c05SMax Reitz     }
2441de2c6c05SMax Reitz 
2442de2c6c05SMax Reitz     blk_apply_root_state(blk, medium_bs);
2443de2c6c05SMax Reitz 
2444de2c6c05SMax Reitz     bdrv_add_key(medium_bs, NULL, &err);
2445de2c6c05SMax Reitz     if (err) {
2446de2c6c05SMax Reitz         error_propagate(errp, err);
2447de2c6c05SMax Reitz         goto fail;
2448de2c6c05SMax Reitz     }
2449de2c6c05SMax Reitz 
2450de2c6c05SMax Reitz     qmp_blockdev_open_tray(device, false, false, &err);
2451de2c6c05SMax Reitz     if (err) {
2452de2c6c05SMax Reitz         error_propagate(errp, err);
2453de2c6c05SMax Reitz         goto fail;
2454de2c6c05SMax Reitz     }
2455de2c6c05SMax Reitz 
2456de2c6c05SMax Reitz     qmp_blockdev_remove_medium(device, &err);
2457de2c6c05SMax Reitz     if (err) {
2458de2c6c05SMax Reitz         error_propagate(errp, err);
2459de2c6c05SMax Reitz         goto fail;
2460de2c6c05SMax Reitz     }
2461de2c6c05SMax Reitz 
2462de2c6c05SMax Reitz     qmp_blockdev_insert_anon_medium(device, medium_bs, &err);
2463de2c6c05SMax Reitz     if (err) {
2464de2c6c05SMax Reitz         error_propagate(errp, err);
2465de2c6c05SMax Reitz         goto fail;
2466de2c6c05SMax Reitz     }
2467de2c6c05SMax Reitz 
2468de2c6c05SMax Reitz     qmp_blockdev_close_tray(device, errp);
2469de2c6c05SMax Reitz 
2470de2c6c05SMax Reitz fail:
2471de2c6c05SMax Reitz     /* If the medium has been inserted, the device has its own reference, so
2472de2c6c05SMax Reitz      * ours must be relinquished; and if it has not been inserted successfully,
2473de2c6c05SMax Reitz      * the reference must be relinquished anyway */
2474de2c6c05SMax Reitz     bdrv_unref(medium_bs);
2475de2c6c05SMax Reitz }
2476de2c6c05SMax Reitz 
2477727f005eSZhi Yong Wu /* throttling disk I/O limits */
247880047da5SLuiz Capitulino void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
24793e9fab69SBenoît Canet                                int64_t bps_wr,
24803e9fab69SBenoît Canet                                int64_t iops,
24813e9fab69SBenoît Canet                                int64_t iops_rd,
24823e9fab69SBenoît Canet                                int64_t iops_wr,
24833e9fab69SBenoît Canet                                bool has_bps_max,
24843e9fab69SBenoît Canet                                int64_t bps_max,
24853e9fab69SBenoît Canet                                bool has_bps_rd_max,
24863e9fab69SBenoît Canet                                int64_t bps_rd_max,
24873e9fab69SBenoît Canet                                bool has_bps_wr_max,
24883e9fab69SBenoît Canet                                int64_t bps_wr_max,
24893e9fab69SBenoît Canet                                bool has_iops_max,
24903e9fab69SBenoît Canet                                int64_t iops_max,
24913e9fab69SBenoît Canet                                bool has_iops_rd_max,
24923e9fab69SBenoît Canet                                int64_t iops_rd_max,
24933e9fab69SBenoît Canet                                bool has_iops_wr_max,
24942024c1dfSBenoît Canet                                int64_t iops_wr_max,
24952024c1dfSBenoît Canet                                bool has_iops_size,
249676f4afb4SAlberto Garcia                                int64_t iops_size,
249776f4afb4SAlberto Garcia                                bool has_group,
249876f4afb4SAlberto Garcia                                const char *group, Error **errp)
2499727f005eSZhi Yong Wu {
2500cc0681c4SBenoît Canet     ThrottleConfig cfg;
2501727f005eSZhi Yong Wu     BlockDriverState *bs;
2502a0e8544cSFam Zheng     BlockBackend *blk;
2503b15446fdSStefan Hajnoczi     AioContext *aio_context;
2504727f005eSZhi Yong Wu 
2505a0e8544cSFam Zheng     blk = blk_by_name(device);
2506a0e8544cSFam Zheng     if (!blk) {
250775158ebbSMarkus Armbruster         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
250875158ebbSMarkus Armbruster                   "Device '%s' not found", device);
250980047da5SLuiz Capitulino         return;
2510727f005eSZhi Yong Wu     }
25115433c24fSMax Reitz 
25125433c24fSMax Reitz     aio_context = blk_get_aio_context(blk);
25135433c24fSMax Reitz     aio_context_acquire(aio_context);
25145433c24fSMax Reitz 
2515a0e8544cSFam Zheng     bs = blk_bs(blk);
25165433c24fSMax Reitz     if (!bs) {
25175433c24fSMax Reitz         error_setg(errp, "Device '%s' has no medium", device);
25185433c24fSMax Reitz         goto out;
25195433c24fSMax Reitz     }
2520727f005eSZhi Yong Wu 
2521cc0681c4SBenoît Canet     memset(&cfg, 0, sizeof(cfg));
2522cc0681c4SBenoît Canet     cfg.buckets[THROTTLE_BPS_TOTAL].avg = bps;
2523cc0681c4SBenoît Canet     cfg.buckets[THROTTLE_BPS_READ].avg  = bps_rd;
2524cc0681c4SBenoît Canet     cfg.buckets[THROTTLE_BPS_WRITE].avg = bps_wr;
2525727f005eSZhi Yong Wu 
2526cc0681c4SBenoît Canet     cfg.buckets[THROTTLE_OPS_TOTAL].avg = iops;
2527cc0681c4SBenoît Canet     cfg.buckets[THROTTLE_OPS_READ].avg  = iops_rd;
2528cc0681c4SBenoît Canet     cfg.buckets[THROTTLE_OPS_WRITE].avg = iops_wr;
2529cc0681c4SBenoît Canet 
25303e9fab69SBenoît Canet     if (has_bps_max) {
25313e9fab69SBenoît Canet         cfg.buckets[THROTTLE_BPS_TOTAL].max = bps_max;
25323e9fab69SBenoît Canet     }
25333e9fab69SBenoît Canet     if (has_bps_rd_max) {
25343e9fab69SBenoît Canet         cfg.buckets[THROTTLE_BPS_READ].max = bps_rd_max;
25353e9fab69SBenoît Canet     }
25363e9fab69SBenoît Canet     if (has_bps_wr_max) {
25373e9fab69SBenoît Canet         cfg.buckets[THROTTLE_BPS_WRITE].max = bps_wr_max;
25383e9fab69SBenoît Canet     }
25393e9fab69SBenoît Canet     if (has_iops_max) {
25403e9fab69SBenoît Canet         cfg.buckets[THROTTLE_OPS_TOTAL].max = iops_max;
25413e9fab69SBenoît Canet     }
25423e9fab69SBenoît Canet     if (has_iops_rd_max) {
25433e9fab69SBenoît Canet         cfg.buckets[THROTTLE_OPS_READ].max = iops_rd_max;
25443e9fab69SBenoît Canet     }
25453e9fab69SBenoît Canet     if (has_iops_wr_max) {
25463e9fab69SBenoît Canet         cfg.buckets[THROTTLE_OPS_WRITE].max = iops_wr_max;
25473e9fab69SBenoît Canet     }
2548cc0681c4SBenoît Canet 
25492024c1dfSBenoît Canet     if (has_iops_size) {
25502024c1dfSBenoît Canet         cfg.op_size = iops_size;
25512024c1dfSBenoît Canet     }
2552cc0681c4SBenoît Canet 
2553cc0681c4SBenoît Canet     if (!check_throttle_config(&cfg, errp)) {
25545433c24fSMax Reitz         goto out;
2555727f005eSZhi Yong Wu     }
2556727f005eSZhi Yong Wu 
255776f4afb4SAlberto Garcia     if (throttle_enabled(&cfg)) {
255876f4afb4SAlberto Garcia         /* Enable I/O limits if they're not enabled yet, otherwise
255976f4afb4SAlberto Garcia          * just update the throttling group. */
2560a0d64a61SAlberto Garcia         if (!bs->throttle_state) {
256176f4afb4SAlberto Garcia             bdrv_io_limits_enable(bs, has_group ? group : device);
256276f4afb4SAlberto Garcia         } else if (has_group) {
256376f4afb4SAlberto Garcia             bdrv_io_limits_update_group(bs, group);
2564727f005eSZhi Yong Wu         }
256576f4afb4SAlberto Garcia         /* Set the new throttling configuration */
2566cc0681c4SBenoît Canet         bdrv_set_io_limits(bs, &cfg);
2567a0d64a61SAlberto Garcia     } else if (bs->throttle_state) {
256876f4afb4SAlberto Garcia         /* If all throttling settings are set to 0, disable I/O limits */
256976f4afb4SAlberto Garcia         bdrv_io_limits_disable(bs);
2570727f005eSZhi Yong Wu     }
2571b15446fdSStefan Hajnoczi 
25725433c24fSMax Reitz out:
2573b15446fdSStefan Hajnoczi     aio_context_release(aio_context);
2574727f005eSZhi Yong Wu }
2575727f005eSZhi Yong Wu 
2576341ebc2fSJohn Snow void qmp_block_dirty_bitmap_add(const char *node, const char *name,
2577341ebc2fSJohn Snow                                 bool has_granularity, uint32_t granularity,
2578341ebc2fSJohn Snow                                 Error **errp)
2579341ebc2fSJohn Snow {
2580341ebc2fSJohn Snow     AioContext *aio_context;
2581341ebc2fSJohn Snow     BlockDriverState *bs;
2582341ebc2fSJohn Snow 
2583341ebc2fSJohn Snow     if (!name || name[0] == '\0') {
2584341ebc2fSJohn Snow         error_setg(errp, "Bitmap name cannot be empty");
2585341ebc2fSJohn Snow         return;
2586341ebc2fSJohn Snow     }
2587341ebc2fSJohn Snow 
2588341ebc2fSJohn Snow     bs = bdrv_lookup_bs(node, node, errp);
2589341ebc2fSJohn Snow     if (!bs) {
2590341ebc2fSJohn Snow         return;
2591341ebc2fSJohn Snow     }
2592341ebc2fSJohn Snow 
2593341ebc2fSJohn Snow     aio_context = bdrv_get_aio_context(bs);
2594341ebc2fSJohn Snow     aio_context_acquire(aio_context);
2595341ebc2fSJohn Snow 
2596341ebc2fSJohn Snow     if (has_granularity) {
2597341ebc2fSJohn Snow         if (granularity < 512 || !is_power_of_2(granularity)) {
2598341ebc2fSJohn Snow             error_setg(errp, "Granularity must be power of 2 "
2599341ebc2fSJohn Snow                              "and at least 512");
2600341ebc2fSJohn Snow             goto out;
2601341ebc2fSJohn Snow         }
2602341ebc2fSJohn Snow     } else {
2603341ebc2fSJohn Snow         /* Default to cluster size, if available: */
2604341ebc2fSJohn Snow         granularity = bdrv_get_default_bitmap_granularity(bs);
2605341ebc2fSJohn Snow     }
2606341ebc2fSJohn Snow 
2607341ebc2fSJohn Snow     bdrv_create_dirty_bitmap(bs, granularity, name, errp);
2608341ebc2fSJohn Snow 
2609341ebc2fSJohn Snow  out:
2610341ebc2fSJohn Snow     aio_context_release(aio_context);
2611341ebc2fSJohn Snow }
2612341ebc2fSJohn Snow 
2613341ebc2fSJohn Snow void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
2614341ebc2fSJohn Snow                                    Error **errp)
2615341ebc2fSJohn Snow {
2616341ebc2fSJohn Snow     AioContext *aio_context;
2617341ebc2fSJohn Snow     BlockDriverState *bs;
2618341ebc2fSJohn Snow     BdrvDirtyBitmap *bitmap;
2619341ebc2fSJohn Snow 
2620341ebc2fSJohn Snow     bitmap = block_dirty_bitmap_lookup(node, name, &bs, &aio_context, errp);
2621341ebc2fSJohn Snow     if (!bitmap || !bs) {
2622341ebc2fSJohn Snow         return;
2623341ebc2fSJohn Snow     }
2624341ebc2fSJohn Snow 
26259bd2b08fSJohn Snow     if (bdrv_dirty_bitmap_frozen(bitmap)) {
26269bd2b08fSJohn Snow         error_setg(errp,
26279bd2b08fSJohn Snow                    "Bitmap '%s' is currently frozen and cannot be removed",
26289bd2b08fSJohn Snow                    name);
26299bd2b08fSJohn Snow         goto out;
26309bd2b08fSJohn Snow     }
263120dca810SJohn Snow     bdrv_dirty_bitmap_make_anon(bitmap);
2632341ebc2fSJohn Snow     bdrv_release_dirty_bitmap(bs, bitmap);
2633341ebc2fSJohn Snow 
26349bd2b08fSJohn Snow  out:
2635341ebc2fSJohn Snow     aio_context_release(aio_context);
2636341ebc2fSJohn Snow }
2637341ebc2fSJohn Snow 
2638e74e6b78SJohn Snow /**
2639e74e6b78SJohn Snow  * Completely clear a bitmap, for the purposes of synchronizing a bitmap
2640e74e6b78SJohn Snow  * immediately after a full backup operation.
2641e74e6b78SJohn Snow  */
2642e74e6b78SJohn Snow void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
2643e74e6b78SJohn Snow                                   Error **errp)
2644e74e6b78SJohn Snow {
2645e74e6b78SJohn Snow     AioContext *aio_context;
2646e74e6b78SJohn Snow     BdrvDirtyBitmap *bitmap;
2647e74e6b78SJohn Snow     BlockDriverState *bs;
2648e74e6b78SJohn Snow 
2649e74e6b78SJohn Snow     bitmap = block_dirty_bitmap_lookup(node, name, &bs, &aio_context, errp);
2650e74e6b78SJohn Snow     if (!bitmap || !bs) {
2651e74e6b78SJohn Snow         return;
2652e74e6b78SJohn Snow     }
2653e74e6b78SJohn Snow 
2654e74e6b78SJohn Snow     if (bdrv_dirty_bitmap_frozen(bitmap)) {
2655e74e6b78SJohn Snow         error_setg(errp,
2656e74e6b78SJohn Snow                    "Bitmap '%s' is currently frozen and cannot be modified",
2657e74e6b78SJohn Snow                    name);
2658e74e6b78SJohn Snow         goto out;
2659e74e6b78SJohn Snow     } else if (!bdrv_dirty_bitmap_enabled(bitmap)) {
2660e74e6b78SJohn Snow         error_setg(errp,
2661e74e6b78SJohn Snow                    "Bitmap '%s' is currently disabled and cannot be cleared",
2662e74e6b78SJohn Snow                    name);
2663e74e6b78SJohn Snow         goto out;
2664e74e6b78SJohn Snow     }
2665e74e6b78SJohn Snow 
2666df9a681dSFam Zheng     bdrv_clear_dirty_bitmap(bitmap, NULL);
2667e74e6b78SJohn Snow 
2668e74e6b78SJohn Snow  out:
2669e74e6b78SJohn Snow     aio_context_release(aio_context);
2670e74e6b78SJohn Snow }
2671e74e6b78SJohn Snow 
2672072ebe6bSMarkus Armbruster void hmp_drive_del(Monitor *mon, const QDict *qdict)
26739063f814SRyan Harper {
26749063f814SRyan Harper     const char *id = qdict_get_str(qdict, "id");
26757e7d56d9SMarkus Armbruster     BlockBackend *blk;
26769063f814SRyan Harper     BlockDriverState *bs;
26778ad4202bSStefan Hajnoczi     AioContext *aio_context;
26783718d8abSFam Zheng     Error *local_err = NULL;
26799063f814SRyan Harper 
26807e7d56d9SMarkus Armbruster     blk = blk_by_name(id);
26817e7d56d9SMarkus Armbruster     if (!blk) {
2682b1422f20SMarkus Armbruster         error_report("Device '%s' not found", id);
2683072ebe6bSMarkus Armbruster         return;
26849063f814SRyan Harper     }
26858ad4202bSStefan Hajnoczi 
268626f8b3a8SMarkus Armbruster     if (!blk_legacy_dinfo(blk)) {
268748f364ddSMarkus Armbruster         error_report("Deleting device added with blockdev-add"
268848f364ddSMarkus Armbruster                      " is not supported");
2689072ebe6bSMarkus Armbruster         return;
269048f364ddSMarkus Armbruster     }
269148f364ddSMarkus Armbruster 
26925433c24fSMax Reitz     aio_context = blk_get_aio_context(blk);
26938ad4202bSStefan Hajnoczi     aio_context_acquire(aio_context);
26948ad4202bSStefan Hajnoczi 
26955433c24fSMax Reitz     bs = blk_bs(blk);
26965433c24fSMax Reitz     if (bs) {
26973718d8abSFam Zheng         if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) {
2698565f65d2SMarkus Armbruster             error_report_err(local_err);
26998ad4202bSStefan Hajnoczi             aio_context_release(aio_context);
2700072ebe6bSMarkus Armbruster             return;
27018591675fSMarcelo Tosatti         }
27029063f814SRyan Harper 
27039063f814SRyan Harper         bdrv_close(bs);
27045433c24fSMax Reitz     }
27059063f814SRyan Harper 
2706fa879d62SMarkus Armbruster     /* if we have a device attached to this BlockDriverState
2707d22b2f41SRyan Harper      * then we need to make the drive anonymous until the device
2708d22b2f41SRyan Harper      * can be removed.  If this is a drive with no device backing
2709d22b2f41SRyan Harper      * then we can just get rid of the block driver state right here.
2710d22b2f41SRyan Harper      */
2711a7f53e26SMarkus Armbruster     if (blk_get_attached_dev(blk)) {
27123e5a50d6SMarkus Armbruster         blk_hide_on_behalf_of_hmp_drive_del(blk);
2713293c51a6SStefan Hajnoczi         /* Further I/O must not pause the guest */
2714373340b2SMax Reitz         blk_set_on_error(blk, BLOCKDEV_ON_ERROR_REPORT,
2715293c51a6SStefan Hajnoczi                          BLOCKDEV_ON_ERROR_REPORT);
2716d22b2f41SRyan Harper     } else {
2717b9fe8a7aSMarkus Armbruster         blk_unref(blk);
2718d22b2f41SRyan Harper     }
27199063f814SRyan Harper 
27208ad4202bSStefan Hajnoczi     aio_context_release(aio_context);
27219063f814SRyan Harper }
27226d4a2b3aSChristoph Hellwig 
27233b1dbd11SBenoît Canet void qmp_block_resize(bool has_device, const char *device,
27243b1dbd11SBenoît Canet                       bool has_node_name, const char *node_name,
27253b1dbd11SBenoît Canet                       int64_t size, Error **errp)
27266d4a2b3aSChristoph Hellwig {
27273b1dbd11SBenoît Canet     Error *local_err = NULL;
27286d4a2b3aSChristoph Hellwig     BlockDriverState *bs;
2729927e0e76SStefan Hajnoczi     AioContext *aio_context;
27308732901eSKevin Wolf     int ret;
27316d4a2b3aSChristoph Hellwig 
27323b1dbd11SBenoît Canet     bs = bdrv_lookup_bs(has_device ? device : NULL,
27333b1dbd11SBenoît Canet                         has_node_name ? node_name : NULL,
27343b1dbd11SBenoît Canet                         &local_err);
273584d18f06SMarkus Armbruster     if (local_err) {
27363b1dbd11SBenoît Canet         error_propagate(errp, local_err);
27373b1dbd11SBenoît Canet         return;
27383b1dbd11SBenoît Canet     }
27393b1dbd11SBenoît Canet 
2740927e0e76SStefan Hajnoczi     aio_context = bdrv_get_aio_context(bs);
2741927e0e76SStefan Hajnoczi     aio_context_acquire(aio_context);
2742927e0e76SStefan Hajnoczi 
27433b1dbd11SBenoît Canet     if (!bdrv_is_first_non_filter(bs)) {
2744c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_FEATURE_DISABLED, "resize");
2745927e0e76SStefan Hajnoczi         goto out;
27466d4a2b3aSChristoph Hellwig     }
27476d4a2b3aSChristoph Hellwig 
27486d4a2b3aSChristoph Hellwig     if (size < 0) {
2749c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "size", "a >0 size");
2750927e0e76SStefan Hajnoczi         goto out;
27516d4a2b3aSChristoph Hellwig     }
27526d4a2b3aSChristoph Hellwig 
27539c75e168SJeff Cody     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_RESIZE, NULL)) {
2754c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_DEVICE_IN_USE, device);
2755927e0e76SStefan Hajnoczi         goto out;
27569c75e168SJeff Cody     }
27579c75e168SJeff Cody 
275892b7a08dSPeter Lieven     /* complete all in-flight operations before resizing the device */
275992b7a08dSPeter Lieven     bdrv_drain_all();
276092b7a08dSPeter Lieven 
27618732901eSKevin Wolf     ret = bdrv_truncate(bs, size);
27628732901eSKevin Wolf     switch (ret) {
2763939a1cc3SStefan Hajnoczi     case 0:
2764939a1cc3SStefan Hajnoczi         break;
2765939a1cc3SStefan Hajnoczi     case -ENOMEDIUM:
2766c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
2767939a1cc3SStefan Hajnoczi         break;
2768939a1cc3SStefan Hajnoczi     case -ENOTSUP:
2769c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_UNSUPPORTED);
2770939a1cc3SStefan Hajnoczi         break;
2771939a1cc3SStefan Hajnoczi     case -EACCES:
277281e5f78aSAlberto Garcia         error_setg(errp, "Device '%s' is read only", device);
2773939a1cc3SStefan Hajnoczi         break;
2774939a1cc3SStefan Hajnoczi     case -EBUSY:
2775c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_DEVICE_IN_USE, device);
2776939a1cc3SStefan Hajnoczi         break;
2777939a1cc3SStefan Hajnoczi     default:
27788732901eSKevin Wolf         error_setg_errno(errp, -ret, "Could not resize");
2779939a1cc3SStefan Hajnoczi         break;
27806d4a2b3aSChristoph Hellwig     }
2781927e0e76SStefan Hajnoczi 
2782927e0e76SStefan Hajnoczi out:
2783927e0e76SStefan Hajnoczi     aio_context_release(aio_context);
27846d4a2b3aSChristoph Hellwig }
278512bd451fSStefan Hajnoczi 
27869abf2dbaSJeff Cody static void block_job_cb(void *opaque, int ret)
278712bd451fSStefan Hajnoczi {
2788723c5d93SStefan Hajnoczi     /* Note that this function may be executed from another AioContext besides
2789723c5d93SStefan Hajnoczi      * the QEMU main loop.  If you need to access anything that assumes the
2790723c5d93SStefan Hajnoczi      * QEMU global mutex, use a BH or introduce a mutex.
2791723c5d93SStefan Hajnoczi      */
2792723c5d93SStefan Hajnoczi 
279312bd451fSStefan Hajnoczi     BlockDriverState *bs = opaque;
2794bcada37bSWenchao Xia     const char *msg = NULL;
279512bd451fSStefan Hajnoczi 
27969abf2dbaSJeff Cody     trace_block_job_cb(bs, bs->job, ret);
279712bd451fSStefan Hajnoczi 
279812bd451fSStefan Hajnoczi     assert(bs->job);
2799bcada37bSWenchao Xia 
280012bd451fSStefan Hajnoczi     if (ret < 0) {
2801bcada37bSWenchao Xia         msg = strerror(-ret);
280212bd451fSStefan Hajnoczi     }
280312bd451fSStefan Hajnoczi 
2804370521a1SStefan Hajnoczi     if (block_job_is_cancelled(bs->job)) {
2805bcada37bSWenchao Xia         block_job_event_cancelled(bs->job);
2806370521a1SStefan Hajnoczi     } else {
2807bcada37bSWenchao Xia         block_job_event_completed(bs->job, msg);
2808370521a1SStefan Hajnoczi     }
280912bd451fSStefan Hajnoczi }
281012bd451fSStefan Hajnoczi 
281113d8cc51SJeff Cody void qmp_block_stream(const char *device,
281213d8cc51SJeff Cody                       bool has_base, const char *base,
281313d8cc51SJeff Cody                       bool has_backing_file, const char *backing_file,
281413d8cc51SJeff Cody                       bool has_speed, int64_t speed,
28151d809098SPaolo Bonzini                       bool has_on_error, BlockdevOnError on_error,
28161d809098SPaolo Bonzini                       Error **errp)
281712bd451fSStefan Hajnoczi {
2818a0e8544cSFam Zheng     BlockBackend *blk;
281912bd451fSStefan Hajnoczi     BlockDriverState *bs;
2820c8c3080fSMarcelo Tosatti     BlockDriverState *base_bs = NULL;
2821f3e69bebSStefan Hajnoczi     AioContext *aio_context;
2822fd7f8c65SStefan Hajnoczi     Error *local_err = NULL;
282313d8cc51SJeff Cody     const char *base_name = NULL;
282412bd451fSStefan Hajnoczi 
28251d809098SPaolo Bonzini     if (!has_on_error) {
28261d809098SPaolo Bonzini         on_error = BLOCKDEV_ON_ERROR_REPORT;
28271d809098SPaolo Bonzini     }
28281d809098SPaolo Bonzini 
2829a0e8544cSFam Zheng     blk = blk_by_name(device);
2830a0e8544cSFam Zheng     if (!blk) {
283175158ebbSMarkus Armbruster         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
283275158ebbSMarkus Armbruster                   "Device '%s' not found", device);
283312bd451fSStefan Hajnoczi         return;
283412bd451fSStefan Hajnoczi     }
283512bd451fSStefan Hajnoczi 
28365433c24fSMax Reitz     aio_context = blk_get_aio_context(blk);
2837f3e69bebSStefan Hajnoczi     aio_context_acquire(aio_context);
2838f3e69bebSStefan Hajnoczi 
28395433c24fSMax Reitz     if (!blk_is_available(blk)) {
28405433c24fSMax Reitz         error_setg(errp, "Device '%s' has no medium", device);
28415433c24fSMax Reitz         goto out;
28425433c24fSMax Reitz     }
28435433c24fSMax Reitz     bs = blk_bs(blk);
28445433c24fSMax Reitz 
2845628ff683SFam Zheng     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_STREAM, errp)) {
2846f3e69bebSStefan Hajnoczi         goto out;
2847628ff683SFam Zheng     }
2848628ff683SFam Zheng 
284913d8cc51SJeff Cody     if (has_base) {
2850c8c3080fSMarcelo Tosatti         base_bs = bdrv_find_backing_image(bs, base);
2851c8c3080fSMarcelo Tosatti         if (base_bs == NULL) {
2852c6bd8c70SMarkus Armbruster             error_setg(errp, QERR_BASE_NOT_FOUND, base);
2853f3e69bebSStefan Hajnoczi             goto out;
285412bd451fSStefan Hajnoczi         }
2855f3e69bebSStefan Hajnoczi         assert(bdrv_get_aio_context(base_bs) == aio_context);
285613d8cc51SJeff Cody         base_name = base;
2857c8c3080fSMarcelo Tosatti     }
285812bd451fSStefan Hajnoczi 
285913d8cc51SJeff Cody     /* if we are streaming the entire chain, the result will have no backing
286013d8cc51SJeff Cody      * file, and specifying one is therefore an error */
286113d8cc51SJeff Cody     if (base_bs == NULL && has_backing_file) {
286213d8cc51SJeff Cody         error_setg(errp, "backing file specified, but streaming the "
286313d8cc51SJeff Cody                          "entire chain");
2864f3e69bebSStefan Hajnoczi         goto out;
286513d8cc51SJeff Cody     }
286613d8cc51SJeff Cody 
286713d8cc51SJeff Cody     /* backing_file string overrides base bs filename */
286813d8cc51SJeff Cody     base_name = has_backing_file ? backing_file : base_name;
286913d8cc51SJeff Cody 
287013d8cc51SJeff Cody     stream_start(bs, base_bs, base_name, has_speed ? speed : 0,
28711d809098SPaolo Bonzini                  on_error, block_job_cb, bs, &local_err);
287284d18f06SMarkus Armbruster     if (local_err) {
2873fd7f8c65SStefan Hajnoczi         error_propagate(errp, local_err);
2874f3e69bebSStefan Hajnoczi         goto out;
287512bd451fSStefan Hajnoczi     }
287612bd451fSStefan Hajnoczi 
287712bd451fSStefan Hajnoczi     trace_qmp_block_stream(bs, bs->job);
2878f3e69bebSStefan Hajnoczi 
2879f3e69bebSStefan Hajnoczi out:
2880f3e69bebSStefan Hajnoczi     aio_context_release(aio_context);
288112bd451fSStefan Hajnoczi }
28822d47c6e9SStefan Hajnoczi 
2883ed61fc10SJeff Cody void qmp_block_commit(const char *device,
28847676e2c5SJeff Cody                       bool has_base, const char *base,
28857676e2c5SJeff Cody                       bool has_top, const char *top,
288654e26900SJeff Cody                       bool has_backing_file, const char *backing_file,
2887ed61fc10SJeff Cody                       bool has_speed, int64_t speed,
2888ed61fc10SJeff Cody                       Error **errp)
2889ed61fc10SJeff Cody {
2890a0e8544cSFam Zheng     BlockBackend *blk;
2891ed61fc10SJeff Cody     BlockDriverState *bs;
2892ed61fc10SJeff Cody     BlockDriverState *base_bs, *top_bs;
28939e85cd5cSStefan Hajnoczi     AioContext *aio_context;
2894ed61fc10SJeff Cody     Error *local_err = NULL;
2895ed61fc10SJeff Cody     /* This will be part of the QMP command, if/when the
2896ed61fc10SJeff Cody      * BlockdevOnError change for blkmirror makes it in
2897ed61fc10SJeff Cody      */
289892aa5c6dSPaolo Bonzini     BlockdevOnError on_error = BLOCKDEV_ON_ERROR_REPORT;
2899ed61fc10SJeff Cody 
290054504663SMax Reitz     if (!has_speed) {
290154504663SMax Reitz         speed = 0;
290254504663SMax Reitz     }
290354504663SMax Reitz 
29047676e2c5SJeff Cody     /* Important Note:
29057676e2c5SJeff Cody      *  libvirt relies on the DeviceNotFound error class in order to probe for
29067676e2c5SJeff Cody      *  live commit feature versions; for this to work, we must make sure to
29077676e2c5SJeff Cody      *  perform the device lookup before any generic errors that may occur in a
29087676e2c5SJeff Cody      *  scenario in which all optional arguments are omitted. */
2909a0e8544cSFam Zheng     blk = blk_by_name(device);
2910a0e8544cSFam Zheng     if (!blk) {
291175158ebbSMarkus Armbruster         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
291275158ebbSMarkus Armbruster                   "Device '%s' not found", device);
2913ed61fc10SJeff Cody         return;
2914ed61fc10SJeff Cody     }
2915ed61fc10SJeff Cody 
29165433c24fSMax Reitz     aio_context = blk_get_aio_context(blk);
29179e85cd5cSStefan Hajnoczi     aio_context_acquire(aio_context);
29189e85cd5cSStefan Hajnoczi 
29195433c24fSMax Reitz     if (!blk_is_available(blk)) {
29205433c24fSMax Reitz         error_setg(errp, "Device '%s' has no medium", device);
29215433c24fSMax Reitz         goto out;
29225433c24fSMax Reitz     }
29235433c24fSMax Reitz     bs = blk_bs(blk);
29245433c24fSMax Reitz 
2925bb00021dSFam Zheng     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT_SOURCE, errp)) {
29269e85cd5cSStefan Hajnoczi         goto out;
2927628ff683SFam Zheng     }
2928628ff683SFam Zheng 
2929ed61fc10SJeff Cody     /* default top_bs is the active layer */
2930ed61fc10SJeff Cody     top_bs = bs;
2931ed61fc10SJeff Cody 
29327676e2c5SJeff Cody     if (has_top && top) {
2933ed61fc10SJeff Cody         if (strcmp(bs->filename, top) != 0) {
2934ed61fc10SJeff Cody             top_bs = bdrv_find_backing_image(bs, top);
2935ed61fc10SJeff Cody         }
2936ed61fc10SJeff Cody     }
2937ed61fc10SJeff Cody 
2938ed61fc10SJeff Cody     if (top_bs == NULL) {
2939ed61fc10SJeff Cody         error_setg(errp, "Top image file %s not found", top ? top : "NULL");
29409e85cd5cSStefan Hajnoczi         goto out;
2941ed61fc10SJeff Cody     }
2942ed61fc10SJeff Cody 
29439e85cd5cSStefan Hajnoczi     assert(bdrv_get_aio_context(top_bs) == aio_context);
29449e85cd5cSStefan Hajnoczi 
2945d5208c45SJeff Cody     if (has_base && base) {
2946d5208c45SJeff Cody         base_bs = bdrv_find_backing_image(top_bs, base);
2947d5208c45SJeff Cody     } else {
2948d5208c45SJeff Cody         base_bs = bdrv_find_base(top_bs);
2949d5208c45SJeff Cody     }
2950d5208c45SJeff Cody 
2951d5208c45SJeff Cody     if (base_bs == NULL) {
2952c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_BASE_NOT_FOUND, base ? base : "NULL");
29539e85cd5cSStefan Hajnoczi         goto out;
2954d5208c45SJeff Cody     }
2955d5208c45SJeff Cody 
29569e85cd5cSStefan Hajnoczi     assert(bdrv_get_aio_context(base_bs) == aio_context);
29579e85cd5cSStefan Hajnoczi 
2958bb00021dSFam Zheng     if (bdrv_op_is_blocked(base_bs, BLOCK_OP_TYPE_COMMIT_TARGET, errp)) {
2959bb00021dSFam Zheng         goto out;
2960bb00021dSFam Zheng     }
2961bb00021dSFam Zheng 
29627676e2c5SJeff Cody     /* Do not allow attempts to commit an image into itself */
29637676e2c5SJeff Cody     if (top_bs == base_bs) {
29647676e2c5SJeff Cody         error_setg(errp, "cannot commit an image into itself");
29659e85cd5cSStefan Hajnoczi         goto out;
29667676e2c5SJeff Cody     }
29677676e2c5SJeff Cody 
296820a63d2cSFam Zheng     if (top_bs == bs) {
296954e26900SJeff Cody         if (has_backing_file) {
297054e26900SJeff Cody             error_setg(errp, "'backing-file' specified,"
297154e26900SJeff Cody                              " but 'top' is the active layer");
29729e85cd5cSStefan Hajnoczi             goto out;
297354e26900SJeff Cody         }
297420a63d2cSFam Zheng         commit_active_start(bs, base_bs, speed, on_error, block_job_cb,
297520a63d2cSFam Zheng                             bs, &local_err);
297620a63d2cSFam Zheng     } else {
2977ed61fc10SJeff Cody         commit_start(bs, base_bs, top_bs, speed, on_error, block_job_cb, bs,
297854e26900SJeff Cody                      has_backing_file ? backing_file : NULL, &local_err);
297920a63d2cSFam Zheng     }
2980ed61fc10SJeff Cody     if (local_err != NULL) {
2981ed61fc10SJeff Cody         error_propagate(errp, local_err);
29829e85cd5cSStefan Hajnoczi         goto out;
2983ed61fc10SJeff Cody     }
29849e85cd5cSStefan Hajnoczi 
29859e85cd5cSStefan Hajnoczi out:
29869e85cd5cSStefan Hajnoczi     aio_context_release(aio_context);
2987ed61fc10SJeff Cody }
2988ed61fc10SJeff Cody 
298978f51fdeSJohn Snow static void do_drive_backup(const char *device, const char *target,
299099a9addfSStefan Hajnoczi                             bool has_format, const char *format,
2991b53169eaSStefan Hajnoczi                             enum MirrorSyncMode sync,
299299a9addfSStefan Hajnoczi                             bool has_mode, enum NewImageMode mode,
299399a9addfSStefan Hajnoczi                             bool has_speed, int64_t speed,
2994d58d8453SJohn Snow                             bool has_bitmap, const char *bitmap,
299578f51fdeSJohn Snow                             bool has_on_source_error,
299678f51fdeSJohn Snow                             BlockdevOnError on_source_error,
299778f51fdeSJohn Snow                             bool has_on_target_error,
299878f51fdeSJohn Snow                             BlockdevOnError on_target_error,
299978f51fdeSJohn Snow                             BlockJobTxn *txn, Error **errp)
300099a9addfSStefan Hajnoczi {
3001a0e8544cSFam Zheng     BlockBackend *blk;
300299a9addfSStefan Hajnoczi     BlockDriverState *bs;
300399a9addfSStefan Hajnoczi     BlockDriverState *target_bs;
3004fc5d3f84SIan Main     BlockDriverState *source = NULL;
3005d58d8453SJohn Snow     BdrvDirtyBitmap *bmap = NULL;
3006761731b1SStefan Hajnoczi     AioContext *aio_context;
3007e6641719SMax Reitz     QDict *options = NULL;
300899a9addfSStefan Hajnoczi     Error *local_err = NULL;
300999a9addfSStefan Hajnoczi     int flags;
301099a9addfSStefan Hajnoczi     int64_t size;
301199a9addfSStefan Hajnoczi     int ret;
301299a9addfSStefan Hajnoczi 
301399a9addfSStefan Hajnoczi     if (!has_speed) {
301499a9addfSStefan Hajnoczi         speed = 0;
301599a9addfSStefan Hajnoczi     }
301699a9addfSStefan Hajnoczi     if (!has_on_source_error) {
301799a9addfSStefan Hajnoczi         on_source_error = BLOCKDEV_ON_ERROR_REPORT;
301899a9addfSStefan Hajnoczi     }
301999a9addfSStefan Hajnoczi     if (!has_on_target_error) {
302099a9addfSStefan Hajnoczi         on_target_error = BLOCKDEV_ON_ERROR_REPORT;
302199a9addfSStefan Hajnoczi     }
302299a9addfSStefan Hajnoczi     if (!has_mode) {
302399a9addfSStefan Hajnoczi         mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
302499a9addfSStefan Hajnoczi     }
302599a9addfSStefan Hajnoczi 
3026a0e8544cSFam Zheng     blk = blk_by_name(device);
3027a0e8544cSFam Zheng     if (!blk) {
302875158ebbSMarkus Armbruster         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
302975158ebbSMarkus Armbruster                   "Device '%s' not found", device);
303099a9addfSStefan Hajnoczi         return;
303199a9addfSStefan Hajnoczi     }
303299a9addfSStefan Hajnoczi 
30335433c24fSMax Reitz     aio_context = blk_get_aio_context(blk);
3034761731b1SStefan Hajnoczi     aio_context_acquire(aio_context);
3035761731b1SStefan Hajnoczi 
3036c29c1dd3SFam Zheng     /* Although backup_run has this check too, we need to use bs->drv below, so
3037c29c1dd3SFam Zheng      * do an early check redundantly. */
30385433c24fSMax Reitz     if (!blk_is_available(blk)) {
3039c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
3040761731b1SStefan Hajnoczi         goto out;
304199a9addfSStefan Hajnoczi     }
30425433c24fSMax Reitz     bs = blk_bs(blk);
304399a9addfSStefan Hajnoczi 
304499a9addfSStefan Hajnoczi     if (!has_format) {
304599a9addfSStefan Hajnoczi         format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name;
304699a9addfSStefan Hajnoczi     }
304799a9addfSStefan Hajnoczi 
3048c29c1dd3SFam Zheng     /* Early check to avoid creating target */
30493718d8abSFam Zheng     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
3050761731b1SStefan Hajnoczi         goto out;
305199a9addfSStefan Hajnoczi     }
305299a9addfSStefan Hajnoczi 
305399a9addfSStefan Hajnoczi     flags = bs->open_flags | BDRV_O_RDWR;
305499a9addfSStefan Hajnoczi 
3055fc5d3f84SIan Main     /* See if we have a backing HD we can use to create our new image
3056fc5d3f84SIan Main      * on top of. */
3057fc5d3f84SIan Main     if (sync == MIRROR_SYNC_MODE_TOP) {
3058760e0063SKevin Wolf         source = backing_bs(bs);
3059fc5d3f84SIan Main         if (!source) {
3060fc5d3f84SIan Main             sync = MIRROR_SYNC_MODE_FULL;
3061fc5d3f84SIan Main         }
3062fc5d3f84SIan Main     }
3063fc5d3f84SIan Main     if (sync == MIRROR_SYNC_MODE_NONE) {
3064fc5d3f84SIan Main         source = bs;
3065fc5d3f84SIan Main     }
3066fc5d3f84SIan Main 
306799a9addfSStefan Hajnoczi     size = bdrv_getlength(bs);
306899a9addfSStefan Hajnoczi     if (size < 0) {
306999a9addfSStefan Hajnoczi         error_setg_errno(errp, -size, "bdrv_getlength failed");
3070761731b1SStefan Hajnoczi         goto out;
307199a9addfSStefan Hajnoczi     }
307299a9addfSStefan Hajnoczi 
307399a9addfSStefan Hajnoczi     if (mode != NEW_IMAGE_MODE_EXISTING) {
3074e6641719SMax Reitz         assert(format);
3075fc5d3f84SIan Main         if (source) {
3076fc5d3f84SIan Main             bdrv_img_create(target, format, source->filename,
3077fc5d3f84SIan Main                             source->drv->format_name, NULL,
3078fc5d3f84SIan Main                             size, flags, &local_err, false);
3079fc5d3f84SIan Main         } else {
3080fc5d3f84SIan Main             bdrv_img_create(target, format, NULL, NULL, NULL,
3081fc5d3f84SIan Main                             size, flags, &local_err, false);
3082fc5d3f84SIan Main         }
308399a9addfSStefan Hajnoczi     }
308499a9addfSStefan Hajnoczi 
308584d18f06SMarkus Armbruster     if (local_err) {
308699a9addfSStefan Hajnoczi         error_propagate(errp, local_err);
3087761731b1SStefan Hajnoczi         goto out;
308899a9addfSStefan Hajnoczi     }
308999a9addfSStefan Hajnoczi 
3090e6641719SMax Reitz     if (format) {
3091e6641719SMax Reitz         options = qdict_new();
3092e6641719SMax Reitz         qdict_put(options, "driver", qstring_from_str(format));
3093e6641719SMax Reitz     }
3094e6641719SMax Reitz 
3095f67503e5SMax Reitz     target_bs = NULL;
30966ebf9aa2SMax Reitz     ret = bdrv_open(&target_bs, target, NULL, options, flags, &local_err);
309799a9addfSStefan Hajnoczi     if (ret < 0) {
309834b5d2c6SMax Reitz         error_propagate(errp, local_err);
3099761731b1SStefan Hajnoczi         goto out;
310099a9addfSStefan Hajnoczi     }
310199a9addfSStefan Hajnoczi 
3102761731b1SStefan Hajnoczi     bdrv_set_aio_context(target_bs, aio_context);
3103761731b1SStefan Hajnoczi 
3104d58d8453SJohn Snow     if (has_bitmap) {
3105d58d8453SJohn Snow         bmap = bdrv_find_dirty_bitmap(bs, bitmap);
3106d58d8453SJohn Snow         if (!bmap) {
3107d58d8453SJohn Snow             error_setg(errp, "Bitmap '%s' could not be found", bitmap);
3108d58d8453SJohn Snow             goto out;
3109d58d8453SJohn Snow         }
3110d58d8453SJohn Snow     }
3111d58d8453SJohn Snow 
3112d58d8453SJohn Snow     backup_start(bs, target_bs, speed, sync, bmap,
3113d58d8453SJohn Snow                  on_source_error, on_target_error,
311478f51fdeSJohn Snow                  block_job_cb, bs, txn, &local_err);
311599a9addfSStefan Hajnoczi     if (local_err != NULL) {
31164f6fd349SFam Zheng         bdrv_unref(target_bs);
311799a9addfSStefan Hajnoczi         error_propagate(errp, local_err);
3118761731b1SStefan Hajnoczi         goto out;
311999a9addfSStefan Hajnoczi     }
3120761731b1SStefan Hajnoczi 
3121761731b1SStefan Hajnoczi out:
3122761731b1SStefan Hajnoczi     aio_context_release(aio_context);
312399a9addfSStefan Hajnoczi }
312499a9addfSStefan Hajnoczi 
312578f51fdeSJohn Snow void qmp_drive_backup(const char *device, const char *target,
312678f51fdeSJohn Snow                       bool has_format, const char *format,
312778f51fdeSJohn Snow                       enum MirrorSyncMode sync,
312878f51fdeSJohn Snow                       bool has_mode, enum NewImageMode mode,
312978f51fdeSJohn Snow                       bool has_speed, int64_t speed,
313078f51fdeSJohn Snow                       bool has_bitmap, const char *bitmap,
313178f51fdeSJohn Snow                       bool has_on_source_error, BlockdevOnError on_source_error,
313278f51fdeSJohn Snow                       bool has_on_target_error, BlockdevOnError on_target_error,
313378f51fdeSJohn Snow                       Error **errp)
313478f51fdeSJohn Snow {
313578f51fdeSJohn Snow     return do_drive_backup(device, target, has_format, format, sync,
313678f51fdeSJohn Snow                            has_mode, mode, has_speed, speed,
313778f51fdeSJohn Snow                            has_bitmap, bitmap,
313878f51fdeSJohn Snow                            has_on_source_error, on_source_error,
313978f51fdeSJohn Snow                            has_on_target_error, on_target_error,
314078f51fdeSJohn Snow                            NULL, errp);
314178f51fdeSJohn Snow }
314278f51fdeSJohn Snow 
3143c13163fbSBenoît Canet BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
3144c13163fbSBenoît Canet {
3145d5a8ee60SAlberto Garcia     return bdrv_named_nodes_list(errp);
3146c13163fbSBenoît Canet }
3147c13163fbSBenoît Canet 
314878f51fdeSJohn Snow void do_blockdev_backup(const char *device, const char *target,
3149c29c1dd3SFam Zheng                          enum MirrorSyncMode sync,
3150c29c1dd3SFam Zheng                          bool has_speed, int64_t speed,
3151c29c1dd3SFam Zheng                          bool has_on_source_error,
3152c29c1dd3SFam Zheng                          BlockdevOnError on_source_error,
3153c29c1dd3SFam Zheng                          bool has_on_target_error,
3154c29c1dd3SFam Zheng                          BlockdevOnError on_target_error,
315578f51fdeSJohn Snow                          BlockJobTxn *txn, Error **errp)
3156c29c1dd3SFam Zheng {
31575433c24fSMax Reitz     BlockBackend *blk, *target_blk;
3158c29c1dd3SFam Zheng     BlockDriverState *bs;
3159c29c1dd3SFam Zheng     BlockDriverState *target_bs;
3160c29c1dd3SFam Zheng     Error *local_err = NULL;
3161c29c1dd3SFam Zheng     AioContext *aio_context;
3162c29c1dd3SFam Zheng 
3163c29c1dd3SFam Zheng     if (!has_speed) {
3164c29c1dd3SFam Zheng         speed = 0;
3165c29c1dd3SFam Zheng     }
3166c29c1dd3SFam Zheng     if (!has_on_source_error) {
3167c29c1dd3SFam Zheng         on_source_error = BLOCKDEV_ON_ERROR_REPORT;
3168c29c1dd3SFam Zheng     }
3169c29c1dd3SFam Zheng     if (!has_on_target_error) {
3170c29c1dd3SFam Zheng         on_target_error = BLOCKDEV_ON_ERROR_REPORT;
3171c29c1dd3SFam Zheng     }
3172c29c1dd3SFam Zheng 
3173a0e8544cSFam Zheng     blk = blk_by_name(device);
3174a0e8544cSFam Zheng     if (!blk) {
31755b347c54SMarkus Armbruster         error_setg(errp, "Device '%s' not found", device);
3176c29c1dd3SFam Zheng         return;
3177c29c1dd3SFam Zheng     }
3178c29c1dd3SFam Zheng 
31795433c24fSMax Reitz     aio_context = blk_get_aio_context(blk);
3180c29c1dd3SFam Zheng     aio_context_acquire(aio_context);
3181c29c1dd3SFam Zheng 
31825433c24fSMax Reitz     if (!blk_is_available(blk)) {
31835433c24fSMax Reitz         error_setg(errp, "Device '%s' has no medium", device);
31845433c24fSMax Reitz         goto out;
31855433c24fSMax Reitz     }
31865433c24fSMax Reitz     bs = blk_bs(blk);
31875433c24fSMax Reitz 
31885433c24fSMax Reitz     target_blk = blk_by_name(target);
31895433c24fSMax Reitz     if (!target_blk) {
31905b347c54SMarkus Armbruster         error_setg(errp, "Device '%s' not found", target);
3191c29c1dd3SFam Zheng         goto out;
3192c29c1dd3SFam Zheng     }
31935433c24fSMax Reitz 
31945433c24fSMax Reitz     if (!blk_is_available(target_blk)) {
31955433c24fSMax Reitz         error_setg(errp, "Device '%s' has no medium", target);
31965433c24fSMax Reitz         goto out;
31975433c24fSMax Reitz     }
31985433c24fSMax Reitz     target_bs = blk_bs(target_blk);
3199c29c1dd3SFam Zheng 
3200c29c1dd3SFam Zheng     bdrv_ref(target_bs);
3201c29c1dd3SFam Zheng     bdrv_set_aio_context(target_bs, aio_context);
3202d58d8453SJohn Snow     backup_start(bs, target_bs, speed, sync, NULL, on_source_error,
320378f51fdeSJohn Snow                  on_target_error, block_job_cb, bs, txn, &local_err);
3204c29c1dd3SFam Zheng     if (local_err != NULL) {
3205c29c1dd3SFam Zheng         bdrv_unref(target_bs);
3206c29c1dd3SFam Zheng         error_propagate(errp, local_err);
3207c29c1dd3SFam Zheng     }
3208c29c1dd3SFam Zheng out:
3209c29c1dd3SFam Zheng     aio_context_release(aio_context);
3210c29c1dd3SFam Zheng }
3211c29c1dd3SFam Zheng 
321278f51fdeSJohn Snow void qmp_blockdev_backup(const char *device, const char *target,
321378f51fdeSJohn Snow                          enum MirrorSyncMode sync,
321478f51fdeSJohn Snow                          bool has_speed, int64_t speed,
321578f51fdeSJohn Snow                          bool has_on_source_error,
321678f51fdeSJohn Snow                          BlockdevOnError on_source_error,
321778f51fdeSJohn Snow                          bool has_on_target_error,
321878f51fdeSJohn Snow                          BlockdevOnError on_target_error,
321978f51fdeSJohn Snow                          Error **errp)
322078f51fdeSJohn Snow {
322178f51fdeSJohn Snow     do_blockdev_backup(device, target, sync, has_speed, speed,
322278f51fdeSJohn Snow                        has_on_source_error, on_source_error,
322378f51fdeSJohn Snow                        has_on_target_error, on_target_error,
322478f51fdeSJohn Snow                        NULL, errp);
322578f51fdeSJohn Snow }
322678f51fdeSJohn Snow 
3227d9b902dbSPaolo Bonzini void qmp_drive_mirror(const char *device, const char *target,
3228d9b902dbSPaolo Bonzini                       bool has_format, const char *format,
32294c828dc6SBenoît Canet                       bool has_node_name, const char *node_name,
323009158f00SBenoît Canet                       bool has_replaces, const char *replaces,
3231d9b902dbSPaolo Bonzini                       enum MirrorSyncMode sync,
3232d9b902dbSPaolo Bonzini                       bool has_mode, enum NewImageMode mode,
3233b952b558SPaolo Bonzini                       bool has_speed, int64_t speed,
3234eee13dfeSPaolo Bonzini                       bool has_granularity, uint32_t granularity,
323508e4ed6cSPaolo Bonzini                       bool has_buf_size, int64_t buf_size,
3236b952b558SPaolo Bonzini                       bool has_on_source_error, BlockdevOnError on_source_error,
3237b952b558SPaolo Bonzini                       bool has_on_target_error, BlockdevOnError on_target_error,
32380fc9f8eaSFam Zheng                       bool has_unmap, bool unmap,
3239b952b558SPaolo Bonzini                       Error **errp)
3240d9b902dbSPaolo Bonzini {
3241a0e8544cSFam Zheng     BlockBackend *blk;
3242d9b902dbSPaolo Bonzini     BlockDriverState *bs;
3243d9b902dbSPaolo Bonzini     BlockDriverState *source, *target_bs;
32445a7e7a0bSStefan Hajnoczi     AioContext *aio_context;
3245d9b902dbSPaolo Bonzini     Error *local_err = NULL;
3246e6641719SMax Reitz     QDict *options;
3247d9b902dbSPaolo Bonzini     int flags;
3248ac3c5d83SStefan Hajnoczi     int64_t size;
3249d9b902dbSPaolo Bonzini     int ret;
3250d9b902dbSPaolo Bonzini 
3251d9b902dbSPaolo Bonzini     if (!has_speed) {
3252d9b902dbSPaolo Bonzini         speed = 0;
3253d9b902dbSPaolo Bonzini     }
3254b952b558SPaolo Bonzini     if (!has_on_source_error) {
3255b952b558SPaolo Bonzini         on_source_error = BLOCKDEV_ON_ERROR_REPORT;
3256b952b558SPaolo Bonzini     }
3257b952b558SPaolo Bonzini     if (!has_on_target_error) {
3258b952b558SPaolo Bonzini         on_target_error = BLOCKDEV_ON_ERROR_REPORT;
3259b952b558SPaolo Bonzini     }
3260d9b902dbSPaolo Bonzini     if (!has_mode) {
3261d9b902dbSPaolo Bonzini         mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
3262d9b902dbSPaolo Bonzini     }
3263eee13dfeSPaolo Bonzini     if (!has_granularity) {
3264eee13dfeSPaolo Bonzini         granularity = 0;
3265eee13dfeSPaolo Bonzini     }
326608e4ed6cSPaolo Bonzini     if (!has_buf_size) {
326748ac0a4dSWen Congyang         buf_size = 0;
326808e4ed6cSPaolo Bonzini     }
32690fc9f8eaSFam Zheng     if (!has_unmap) {
32700fc9f8eaSFam Zheng         unmap = true;
32710fc9f8eaSFam Zheng     }
327208e4ed6cSPaolo Bonzini 
3273eee13dfeSPaolo Bonzini     if (granularity != 0 && (granularity < 512 || granularity > 1048576 * 64)) {
3274c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "granularity",
32753cbbe9fdSStefan Hajnoczi                    "a value in range [512B, 64MB]");
3276eee13dfeSPaolo Bonzini         return;
3277eee13dfeSPaolo Bonzini     }
3278eee13dfeSPaolo Bonzini     if (granularity & (granularity - 1)) {
3279c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "granularity",
3280c6bd8c70SMarkus Armbruster                    "power of 2");
3281eee13dfeSPaolo Bonzini         return;
3282eee13dfeSPaolo Bonzini     }
3283d9b902dbSPaolo Bonzini 
3284a0e8544cSFam Zheng     blk = blk_by_name(device);
3285a0e8544cSFam Zheng     if (!blk) {
328675158ebbSMarkus Armbruster         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
328775158ebbSMarkus Armbruster                   "Device '%s' not found", device);
3288d9b902dbSPaolo Bonzini         return;
3289d9b902dbSPaolo Bonzini     }
3290d9b902dbSPaolo Bonzini 
32915433c24fSMax Reitz     aio_context = blk_get_aio_context(blk);
32925a7e7a0bSStefan Hajnoczi     aio_context_acquire(aio_context);
32935a7e7a0bSStefan Hajnoczi 
32945433c24fSMax Reitz     if (!blk_is_available(blk)) {
3295c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
32965a7e7a0bSStefan Hajnoczi         goto out;
3297d9b902dbSPaolo Bonzini     }
32985433c24fSMax Reitz     bs = blk_bs(blk);
3299d9b902dbSPaolo Bonzini 
3300d9b902dbSPaolo Bonzini     if (!has_format) {
3301d9b902dbSPaolo Bonzini         format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name;
3302d9b902dbSPaolo Bonzini     }
3303d9b902dbSPaolo Bonzini 
33043718d8abSFam Zheng     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_MIRROR, errp)) {
33055a7e7a0bSStefan Hajnoczi         goto out;
3306d9b902dbSPaolo Bonzini     }
3307d9b902dbSPaolo Bonzini 
3308d9b902dbSPaolo Bonzini     flags = bs->open_flags | BDRV_O_RDWR;
3309760e0063SKevin Wolf     source = backing_bs(bs);
3310d9b902dbSPaolo Bonzini     if (!source && sync == MIRROR_SYNC_MODE_TOP) {
3311d9b902dbSPaolo Bonzini         sync = MIRROR_SYNC_MODE_FULL;
3312d9b902dbSPaolo Bonzini     }
3313117e0c82SMax Reitz     if (sync == MIRROR_SYNC_MODE_NONE) {
3314117e0c82SMax Reitz         source = bs;
3315117e0c82SMax Reitz     }
3316d9b902dbSPaolo Bonzini 
3317ac3c5d83SStefan Hajnoczi     size = bdrv_getlength(bs);
3318ac3c5d83SStefan Hajnoczi     if (size < 0) {
3319ac3c5d83SStefan Hajnoczi         error_setg_errno(errp, -size, "bdrv_getlength failed");
33205a7e7a0bSStefan Hajnoczi         goto out;
3321ac3c5d83SStefan Hajnoczi     }
3322ac3c5d83SStefan Hajnoczi 
332309158f00SBenoît Canet     if (has_replaces) {
332409158f00SBenoît Canet         BlockDriverState *to_replace_bs;
33255a7e7a0bSStefan Hajnoczi         AioContext *replace_aio_context;
33265a7e7a0bSStefan Hajnoczi         int64_t replace_size;
332709158f00SBenoît Canet 
332809158f00SBenoît Canet         if (!has_node_name) {
332909158f00SBenoît Canet             error_setg(errp, "a node-name must be provided when replacing a"
333009158f00SBenoît Canet                              " named node of the graph");
33315a7e7a0bSStefan Hajnoczi             goto out;
333209158f00SBenoît Canet         }
333309158f00SBenoît Canet 
3334e12f3784SWen Congyang         to_replace_bs = check_to_replace_node(bs, replaces, &local_err);
333509158f00SBenoît Canet 
333609158f00SBenoît Canet         if (!to_replace_bs) {
333709158f00SBenoît Canet             error_propagate(errp, local_err);
33385a7e7a0bSStefan Hajnoczi             goto out;
333909158f00SBenoît Canet         }
334009158f00SBenoît Canet 
33415a7e7a0bSStefan Hajnoczi         replace_aio_context = bdrv_get_aio_context(to_replace_bs);
33425a7e7a0bSStefan Hajnoczi         aio_context_acquire(replace_aio_context);
33435a7e7a0bSStefan Hajnoczi         replace_size = bdrv_getlength(to_replace_bs);
33445a7e7a0bSStefan Hajnoczi         aio_context_release(replace_aio_context);
33455a7e7a0bSStefan Hajnoczi 
33465a7e7a0bSStefan Hajnoczi         if (size != replace_size) {
334709158f00SBenoît Canet             error_setg(errp, "cannot replace image with a mirror image of "
334809158f00SBenoît Canet                              "different size");
33495a7e7a0bSStefan Hajnoczi             goto out;
335009158f00SBenoît Canet         }
335109158f00SBenoît Canet     }
335209158f00SBenoît Canet 
335314526864SMax Reitz     if ((sync == MIRROR_SYNC_MODE_FULL || !source)
335414526864SMax Reitz         && mode != NEW_IMAGE_MODE_EXISTING)
335514526864SMax Reitz     {
3356d9b902dbSPaolo Bonzini         /* create new image w/o backing file */
3357e6641719SMax Reitz         assert(format);
3358cf8f2426SLuiz Capitulino         bdrv_img_create(target, format,
3359f382d43aSMiroslav Rezanina                         NULL, NULL, NULL, size, flags, &local_err, false);
3360d9b902dbSPaolo Bonzini     } else {
3361d9b902dbSPaolo Bonzini         switch (mode) {
3362d9b902dbSPaolo Bonzini         case NEW_IMAGE_MODE_EXISTING:
3363d9b902dbSPaolo Bonzini             break;
3364d9b902dbSPaolo Bonzini         case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
3365d9b902dbSPaolo Bonzini             /* create new image with backing file */
3366cf8f2426SLuiz Capitulino             bdrv_img_create(target, format,
3367d9b902dbSPaolo Bonzini                             source->filename,
3368d9b902dbSPaolo Bonzini                             source->drv->format_name,
3369f382d43aSMiroslav Rezanina                             NULL, size, flags, &local_err, false);
3370d9b902dbSPaolo Bonzini             break;
3371d9b902dbSPaolo Bonzini         default:
3372d9b902dbSPaolo Bonzini             abort();
3373d9b902dbSPaolo Bonzini         }
3374d9b902dbSPaolo Bonzini     }
3375d9b902dbSPaolo Bonzini 
337684d18f06SMarkus Armbruster     if (local_err) {
3377cf8f2426SLuiz Capitulino         error_propagate(errp, local_err);
33785a7e7a0bSStefan Hajnoczi         goto out;
3379d9b902dbSPaolo Bonzini     }
3380d9b902dbSPaolo Bonzini 
33814c828dc6SBenoît Canet     options = qdict_new();
3382e6641719SMax Reitz     if (has_node_name) {
33834c828dc6SBenoît Canet         qdict_put(options, "node-name", qstring_from_str(node_name));
33844c828dc6SBenoît Canet     }
3385e6641719SMax Reitz     if (format) {
3386e6641719SMax Reitz         qdict_put(options, "driver", qstring_from_str(format));
3387e6641719SMax Reitz     }
33884c828dc6SBenoît Canet 
3389b812f671SPaolo Bonzini     /* Mirroring takes care of copy-on-write using the source's backing
3390b812f671SPaolo Bonzini      * file.
3391b812f671SPaolo Bonzini      */
3392f67503e5SMax Reitz     target_bs = NULL;
33934c828dc6SBenoît Canet     ret = bdrv_open(&target_bs, target, NULL, options,
33946ebf9aa2SMax Reitz                     flags | BDRV_O_NO_BACKING, &local_err);
3395d9b902dbSPaolo Bonzini     if (ret < 0) {
339634b5d2c6SMax Reitz         error_propagate(errp, local_err);
33975a7e7a0bSStefan Hajnoczi         goto out;
3398d9b902dbSPaolo Bonzini     }
3399d9b902dbSPaolo Bonzini 
34005a7e7a0bSStefan Hajnoczi     bdrv_set_aio_context(target_bs, aio_context);
34015a7e7a0bSStefan Hajnoczi 
340209158f00SBenoît Canet     /* pass the node name to replace to mirror start since it's loose coupling
340309158f00SBenoît Canet      * and will allow to check whether the node still exist at mirror completion
340409158f00SBenoît Canet      */
340509158f00SBenoît Canet     mirror_start(bs, target_bs,
340609158f00SBenoît Canet                  has_replaces ? replaces : NULL,
340709158f00SBenoît Canet                  speed, granularity, buf_size, sync,
3408eee13dfeSPaolo Bonzini                  on_source_error, on_target_error,
34090fc9f8eaSFam Zheng                  unmap,
3410b952b558SPaolo Bonzini                  block_job_cb, bs, &local_err);
3411d9b902dbSPaolo Bonzini     if (local_err != NULL) {
34124f6fd349SFam Zheng         bdrv_unref(target_bs);
3413d9b902dbSPaolo Bonzini         error_propagate(errp, local_err);
34145a7e7a0bSStefan Hajnoczi         goto out;
3415d9b902dbSPaolo Bonzini     }
34165a7e7a0bSStefan Hajnoczi 
34175a7e7a0bSStefan Hajnoczi out:
34185a7e7a0bSStefan Hajnoczi     aio_context_release(aio_context);
3419d9b902dbSPaolo Bonzini }
3420d9b902dbSPaolo Bonzini 
34213d948cdfSStefan Hajnoczi /* Get the block job for a given device name and acquire its AioContext */
342224d6bffeSMarkus Armbruster static BlockJob *find_block_job(const char *device, AioContext **aio_context,
342324d6bffeSMarkus Armbruster                                 Error **errp)
34242d47c6e9SStefan Hajnoczi {
3425a0e8544cSFam Zheng     BlockBackend *blk;
34262d47c6e9SStefan Hajnoczi     BlockDriverState *bs;
34272d47c6e9SStefan Hajnoczi 
34285433c24fSMax Reitz     *aio_context = NULL;
34295433c24fSMax Reitz 
3430a0e8544cSFam Zheng     blk = blk_by_name(device);
3431a0e8544cSFam Zheng     if (!blk) {
34323d948cdfSStefan Hajnoczi         goto notfound;
34332d47c6e9SStefan Hajnoczi     }
34343d948cdfSStefan Hajnoczi 
34355433c24fSMax Reitz     *aio_context = blk_get_aio_context(blk);
34363d948cdfSStefan Hajnoczi     aio_context_acquire(*aio_context);
34373d948cdfSStefan Hajnoczi 
34385433c24fSMax Reitz     if (!blk_is_available(blk)) {
34395433c24fSMax Reitz         goto notfound;
34405433c24fSMax Reitz     }
34415433c24fSMax Reitz     bs = blk_bs(blk);
34425433c24fSMax Reitz 
34433d948cdfSStefan Hajnoczi     if (!bs->job) {
34443d948cdfSStefan Hajnoczi         goto notfound;
34453d948cdfSStefan Hajnoczi     }
34463d948cdfSStefan Hajnoczi 
34472d47c6e9SStefan Hajnoczi     return bs->job;
34483d948cdfSStefan Hajnoczi 
34493d948cdfSStefan Hajnoczi notfound:
34502e3a0266SMarkus Armbruster     error_set(errp, ERROR_CLASS_DEVICE_NOT_ACTIVE,
34512e3a0266SMarkus Armbruster               "No active block job on device '%s'", device);
34525433c24fSMax Reitz     if (*aio_context) {
34535433c24fSMax Reitz         aio_context_release(*aio_context);
34543d948cdfSStefan Hajnoczi         *aio_context = NULL;
34555433c24fSMax Reitz     }
34563d948cdfSStefan Hajnoczi     return NULL;
34572d47c6e9SStefan Hajnoczi }
34582d47c6e9SStefan Hajnoczi 
3459882ec7ceSStefan Hajnoczi void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp)
34602d47c6e9SStefan Hajnoczi {
34613d948cdfSStefan Hajnoczi     AioContext *aio_context;
346224d6bffeSMarkus Armbruster     BlockJob *job = find_block_job(device, &aio_context, errp);
34632d47c6e9SStefan Hajnoczi 
34642d47c6e9SStefan Hajnoczi     if (!job) {
34652d47c6e9SStefan Hajnoczi         return;
34662d47c6e9SStefan Hajnoczi     }
34672d47c6e9SStefan Hajnoczi 
3468882ec7ceSStefan Hajnoczi     block_job_set_speed(job, speed, errp);
34693d948cdfSStefan Hajnoczi     aio_context_release(aio_context);
34702d47c6e9SStefan Hajnoczi }
3471370521a1SStefan Hajnoczi 
34726e37fb81SPaolo Bonzini void qmp_block_job_cancel(const char *device,
34736e37fb81SPaolo Bonzini                           bool has_force, bool force, Error **errp)
34746e37fb81SPaolo Bonzini {
34753d948cdfSStefan Hajnoczi     AioContext *aio_context;
347624d6bffeSMarkus Armbruster     BlockJob *job = find_block_job(device, &aio_context, errp);
34776e37fb81SPaolo Bonzini 
34786e37fb81SPaolo Bonzini     if (!job) {
34796e37fb81SPaolo Bonzini         return;
34806e37fb81SPaolo Bonzini     }
34813d948cdfSStefan Hajnoczi 
34823d948cdfSStefan Hajnoczi     if (!has_force) {
34833d948cdfSStefan Hajnoczi         force = false;
34843d948cdfSStefan Hajnoczi     }
34853d948cdfSStefan Hajnoczi 
3486751ebd76SFam Zheng     if (job->user_paused && !force) {
3487f231b88dSCole Robinson         error_setg(errp, "The block job for device '%s' is currently paused",
3488f231b88dSCole Robinson                    device);
34893d948cdfSStefan Hajnoczi         goto out;
34906e37fb81SPaolo Bonzini     }
34916e37fb81SPaolo Bonzini 
34926e37fb81SPaolo Bonzini     trace_qmp_block_job_cancel(job);
34936e37fb81SPaolo Bonzini     block_job_cancel(job);
34943d948cdfSStefan Hajnoczi out:
34953d948cdfSStefan Hajnoczi     aio_context_release(aio_context);
34966e37fb81SPaolo Bonzini }
34976e37fb81SPaolo Bonzini 
34986e37fb81SPaolo Bonzini void qmp_block_job_pause(const char *device, Error **errp)
3499370521a1SStefan Hajnoczi {
35003d948cdfSStefan Hajnoczi     AioContext *aio_context;
350124d6bffeSMarkus Armbruster     BlockJob *job = find_block_job(device, &aio_context, errp);
3502370521a1SStefan Hajnoczi 
3503751ebd76SFam Zheng     if (!job || job->user_paused) {
3504370521a1SStefan Hajnoczi         return;
3505370521a1SStefan Hajnoczi     }
35066e37fb81SPaolo Bonzini 
3507751ebd76SFam Zheng     job->user_paused = true;
35086e37fb81SPaolo Bonzini     trace_qmp_block_job_pause(job);
35096e37fb81SPaolo Bonzini     block_job_pause(job);
35103d948cdfSStefan Hajnoczi     aio_context_release(aio_context);
35116e37fb81SPaolo Bonzini }
35126e37fb81SPaolo Bonzini 
35136e37fb81SPaolo Bonzini void qmp_block_job_resume(const char *device, Error **errp)
35146e37fb81SPaolo Bonzini {
35153d948cdfSStefan Hajnoczi     AioContext *aio_context;
351624d6bffeSMarkus Armbruster     BlockJob *job = find_block_job(device, &aio_context, errp);
35176e37fb81SPaolo Bonzini 
3518751ebd76SFam Zheng     if (!job || !job->user_paused) {
35198acc72a4SPaolo Bonzini         return;
35208acc72a4SPaolo Bonzini     }
3521370521a1SStefan Hajnoczi 
3522751ebd76SFam Zheng     job->user_paused = false;
35236e37fb81SPaolo Bonzini     trace_qmp_block_job_resume(job);
35246e37fb81SPaolo Bonzini     block_job_resume(job);
35253d948cdfSStefan Hajnoczi     aio_context_release(aio_context);
3526370521a1SStefan Hajnoczi }
3527fb5458cdSStefan Hajnoczi 
3528aeae883bSPaolo Bonzini void qmp_block_job_complete(const char *device, Error **errp)
3529aeae883bSPaolo Bonzini {
35303d948cdfSStefan Hajnoczi     AioContext *aio_context;
353124d6bffeSMarkus Armbruster     BlockJob *job = find_block_job(device, &aio_context, errp);
3532aeae883bSPaolo Bonzini 
3533aeae883bSPaolo Bonzini     if (!job) {
3534aeae883bSPaolo Bonzini         return;
3535aeae883bSPaolo Bonzini     }
3536aeae883bSPaolo Bonzini 
3537aeae883bSPaolo Bonzini     trace_qmp_block_job_complete(job);
3538aeae883bSPaolo Bonzini     block_job_complete(job, errp);
35393d948cdfSStefan Hajnoczi     aio_context_release(aio_context);
3540aeae883bSPaolo Bonzini }
3541aeae883bSPaolo Bonzini 
3542fa40e656SJeff Cody void qmp_change_backing_file(const char *device,
3543fa40e656SJeff Cody                              const char *image_node_name,
3544fa40e656SJeff Cody                              const char *backing_file,
3545fa40e656SJeff Cody                              Error **errp)
3546fa40e656SJeff Cody {
3547a0e8544cSFam Zheng     BlockBackend *blk;
3548fa40e656SJeff Cody     BlockDriverState *bs = NULL;
3549729962f6SStefan Hajnoczi     AioContext *aio_context;
3550fa40e656SJeff Cody     BlockDriverState *image_bs = NULL;
3551fa40e656SJeff Cody     Error *local_err = NULL;
3552fa40e656SJeff Cody     bool ro;
3553fa40e656SJeff Cody     int open_flags;
3554fa40e656SJeff Cody     int ret;
3555fa40e656SJeff Cody 
3556a0e8544cSFam Zheng     blk = blk_by_name(device);
3557a0e8544cSFam Zheng     if (!blk) {
355875158ebbSMarkus Armbruster         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
355975158ebbSMarkus Armbruster                   "Device '%s' not found", device);
3560fa40e656SJeff Cody         return;
3561fa40e656SJeff Cody     }
3562fa40e656SJeff Cody 
35635433c24fSMax Reitz     aio_context = blk_get_aio_context(blk);
3564729962f6SStefan Hajnoczi     aio_context_acquire(aio_context);
3565729962f6SStefan Hajnoczi 
35665433c24fSMax Reitz     if (!blk_is_available(blk)) {
35675433c24fSMax Reitz         error_setg(errp, "Device '%s' has no medium", device);
35685433c24fSMax Reitz         goto out;
35695433c24fSMax Reitz     }
35705433c24fSMax Reitz     bs = blk_bs(blk);
35715433c24fSMax Reitz 
3572fa40e656SJeff Cody     image_bs = bdrv_lookup_bs(NULL, image_node_name, &local_err);
3573fa40e656SJeff Cody     if (local_err) {
3574fa40e656SJeff Cody         error_propagate(errp, local_err);
3575729962f6SStefan Hajnoczi         goto out;
3576fa40e656SJeff Cody     }
3577fa40e656SJeff Cody 
3578fa40e656SJeff Cody     if (!image_bs) {
3579fa40e656SJeff Cody         error_setg(errp, "image file not found");
3580729962f6SStefan Hajnoczi         goto out;
3581fa40e656SJeff Cody     }
3582fa40e656SJeff Cody 
3583fa40e656SJeff Cody     if (bdrv_find_base(image_bs) == image_bs) {
3584fa40e656SJeff Cody         error_setg(errp, "not allowing backing file change on an image "
3585fa40e656SJeff Cody                          "without a backing file");
3586729962f6SStefan Hajnoczi         goto out;
3587fa40e656SJeff Cody     }
3588fa40e656SJeff Cody 
3589fa40e656SJeff Cody     /* even though we are not necessarily operating on bs, we need it to
3590fa40e656SJeff Cody      * determine if block ops are currently prohibited on the chain */
3591fa40e656SJeff Cody     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_CHANGE, errp)) {
3592729962f6SStefan Hajnoczi         goto out;
3593fa40e656SJeff Cody     }
3594fa40e656SJeff Cody 
3595fa40e656SJeff Cody     /* final sanity check */
3596fa40e656SJeff Cody     if (!bdrv_chain_contains(bs, image_bs)) {
3597fa40e656SJeff Cody         error_setg(errp, "'%s' and image file are not in the same chain",
3598fa40e656SJeff Cody                    device);
3599729962f6SStefan Hajnoczi         goto out;
3600fa40e656SJeff Cody     }
3601fa40e656SJeff Cody 
3602fa40e656SJeff Cody     /* if not r/w, reopen to make r/w */
3603fa40e656SJeff Cody     open_flags = image_bs->open_flags;
3604fa40e656SJeff Cody     ro = bdrv_is_read_only(image_bs);
3605fa40e656SJeff Cody 
3606fa40e656SJeff Cody     if (ro) {
3607fa40e656SJeff Cody         bdrv_reopen(image_bs, open_flags | BDRV_O_RDWR, &local_err);
3608fa40e656SJeff Cody         if (local_err) {
3609fa40e656SJeff Cody             error_propagate(errp, local_err);
3610729962f6SStefan Hajnoczi             goto out;
3611fa40e656SJeff Cody         }
3612fa40e656SJeff Cody     }
3613fa40e656SJeff Cody 
3614fa40e656SJeff Cody     ret = bdrv_change_backing_file(image_bs, backing_file,
3615fa40e656SJeff Cody                                image_bs->drv ? image_bs->drv->format_name : "");
3616fa40e656SJeff Cody 
3617fa40e656SJeff Cody     if (ret < 0) {
3618fa40e656SJeff Cody         error_setg_errno(errp, -ret, "Could not change backing file to '%s'",
3619fa40e656SJeff Cody                          backing_file);
3620fa40e656SJeff Cody         /* don't exit here, so we can try to restore open flags if
3621fa40e656SJeff Cody          * appropriate */
3622fa40e656SJeff Cody     }
3623fa40e656SJeff Cody 
3624fa40e656SJeff Cody     if (ro) {
3625fa40e656SJeff Cody         bdrv_reopen(image_bs, open_flags, &local_err);
3626fa40e656SJeff Cody         if (local_err) {
3627fa40e656SJeff Cody             error_propagate(errp, local_err); /* will preserve prior errp */
3628fa40e656SJeff Cody         }
3629fa40e656SJeff Cody     }
3630729962f6SStefan Hajnoczi 
3631729962f6SStefan Hajnoczi out:
3632729962f6SStefan Hajnoczi     aio_context_release(aio_context);
3633fa40e656SJeff Cody }
3634fa40e656SJeff Cody 
3635d26c9a15SKevin Wolf void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
3636d26c9a15SKevin Wolf {
3637d26c9a15SKevin Wolf     QmpOutputVisitor *ov = qmp_output_visitor_new();
3638be4b67bcSMax Reitz     BlockDriverState *bs;
3639be4b67bcSMax Reitz     BlockBackend *blk = NULL;
3640d26c9a15SKevin Wolf     QObject *obj;
3641d26c9a15SKevin Wolf     QDict *qdict;
3642d26c9a15SKevin Wolf     Error *local_err = NULL;
3643d26c9a15SKevin Wolf 
364460e19e06SMarkus Armbruster     /* TODO Sort it out in raw-posix and drive_new(): Reject aio=native with
3645d26c9a15SKevin Wolf      * cache.direct=false instead of silently switching to aio=threads, except
364660e19e06SMarkus Armbruster      * when called from drive_new().
3647d26c9a15SKevin Wolf      *
3648d26c9a15SKevin Wolf      * For now, simply forbidding the combination for all drivers will do. */
3649d26c9a15SKevin Wolf     if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) {
3650c6e0bd9bSKevin Wolf         bool direct = options->has_cache &&
3651c6e0bd9bSKevin Wolf                       options->cache->has_direct &&
3652c6e0bd9bSKevin Wolf                       options->cache->direct;
3653c6e0bd9bSKevin Wolf         if (!direct) {
3654d26c9a15SKevin Wolf             error_setg(errp, "aio=native requires cache.direct=true");
3655d26c9a15SKevin Wolf             goto fail;
3656d26c9a15SKevin Wolf         }
3657d26c9a15SKevin Wolf     }
3658d26c9a15SKevin Wolf 
3659d26c9a15SKevin Wolf     visit_type_BlockdevOptions(qmp_output_get_visitor(ov),
3660d26c9a15SKevin Wolf                                &options, NULL, &local_err);
366184d18f06SMarkus Armbruster     if (local_err) {
3662d26c9a15SKevin Wolf         error_propagate(errp, local_err);
3663d26c9a15SKevin Wolf         goto fail;
3664d26c9a15SKevin Wolf     }
3665d26c9a15SKevin Wolf 
3666d26c9a15SKevin Wolf     obj = qmp_output_get_qobject(ov);
3667d26c9a15SKevin Wolf     qdict = qobject_to_qdict(obj);
3668d26c9a15SKevin Wolf 
3669d26c9a15SKevin Wolf     qdict_flatten(qdict);
3670d26c9a15SKevin Wolf 
3671be4b67bcSMax Reitz     if (options->has_id) {
367218e46a03SMarkus Armbruster         blk = blockdev_init(NULL, qdict, &local_err);
367384d18f06SMarkus Armbruster         if (local_err) {
3674b681072dSKevin Wolf             error_propagate(errp, local_err);
3675d26c9a15SKevin Wolf             goto fail;
3676d26c9a15SKevin Wolf         }
3677d26c9a15SKevin Wolf 
3678be4b67bcSMax Reitz         bs = blk_bs(blk);
3679be4b67bcSMax Reitz     } else {
3680be4b67bcSMax Reitz         if (!qdict_get_try_str(qdict, "node-name")) {
3681be4b67bcSMax Reitz             error_setg(errp, "'id' and/or 'node-name' need to be specified for "
3682be4b67bcSMax Reitz                        "the root node");
3683be4b67bcSMax Reitz             goto fail;
3684be4b67bcSMax Reitz         }
3685be4b67bcSMax Reitz 
3686bd745e23SMax Reitz         bs = bds_tree_init(qdict, errp);
3687bd745e23SMax Reitz         if (!bs) {
3688be4b67bcSMax Reitz             goto fail;
3689be4b67bcSMax Reitz         }
3690be4b67bcSMax Reitz     }
3691be4b67bcSMax Reitz 
3692be4b67bcSMax Reitz     if (bs && bdrv_key_required(bs)) {
3693be4b67bcSMax Reitz         if (blk) {
369418e46a03SMarkus Armbruster             blk_unref(blk);
3695be4b67bcSMax Reitz         } else {
3696be4b67bcSMax Reitz             bdrv_unref(bs);
3697be4b67bcSMax Reitz         }
36988ae8e904SKevin Wolf         error_setg(errp, "blockdev-add doesn't support encrypted devices");
36998ae8e904SKevin Wolf         goto fail;
37008ae8e904SKevin Wolf     }
37018ae8e904SKevin Wolf 
3702d26c9a15SKevin Wolf fail:
3703d26c9a15SKevin Wolf     qmp_output_visitor_cleanup(ov);
3704d26c9a15SKevin Wolf }
3705d26c9a15SKevin Wolf 
370681b936aeSAlberto Garcia void qmp_x_blockdev_del(bool has_id, const char *id,
370781b936aeSAlberto Garcia                         bool has_node_name, const char *node_name, Error **errp)
370881b936aeSAlberto Garcia {
370981b936aeSAlberto Garcia     AioContext *aio_context;
371081b936aeSAlberto Garcia     BlockBackend *blk;
371181b936aeSAlberto Garcia     BlockDriverState *bs;
371281b936aeSAlberto Garcia 
371381b936aeSAlberto Garcia     if (has_id && has_node_name) {
371481b936aeSAlberto Garcia         error_setg(errp, "Only one of id and node-name must be specified");
371581b936aeSAlberto Garcia         return;
371681b936aeSAlberto Garcia     } else if (!has_id && !has_node_name) {
371781b936aeSAlberto Garcia         error_setg(errp, "No block device specified");
371881b936aeSAlberto Garcia         return;
371981b936aeSAlberto Garcia     }
372081b936aeSAlberto Garcia 
372181b936aeSAlberto Garcia     if (has_id) {
372281b936aeSAlberto Garcia         blk = blk_by_name(id);
372381b936aeSAlberto Garcia         if (!blk) {
372481b936aeSAlberto Garcia             error_setg(errp, "Cannot find block backend %s", id);
372581b936aeSAlberto Garcia             return;
372681b936aeSAlberto Garcia         }
372781b936aeSAlberto Garcia         if (blk_get_refcnt(blk) > 1) {
372881b936aeSAlberto Garcia             error_setg(errp, "Block backend %s is in use", id);
372981b936aeSAlberto Garcia             return;
373081b936aeSAlberto Garcia         }
373181b936aeSAlberto Garcia         bs = blk_bs(blk);
373281b936aeSAlberto Garcia         aio_context = blk_get_aio_context(blk);
373381b936aeSAlberto Garcia     } else {
373481b936aeSAlberto Garcia         bs = bdrv_find_node(node_name);
373581b936aeSAlberto Garcia         if (!bs) {
373681b936aeSAlberto Garcia             error_setg(errp, "Cannot find node %s", node_name);
373781b936aeSAlberto Garcia             return;
373881b936aeSAlberto Garcia         }
373981b936aeSAlberto Garcia         blk = bs->blk;
374081b936aeSAlberto Garcia         if (blk) {
374181b936aeSAlberto Garcia             error_setg(errp, "Node %s is in use by %s",
374281b936aeSAlberto Garcia                        node_name, blk_name(blk));
374381b936aeSAlberto Garcia             return;
374481b936aeSAlberto Garcia         }
374581b936aeSAlberto Garcia         aio_context = bdrv_get_aio_context(bs);
374681b936aeSAlberto Garcia     }
374781b936aeSAlberto Garcia 
374881b936aeSAlberto Garcia     aio_context_acquire(aio_context);
374981b936aeSAlberto Garcia 
375081b936aeSAlberto Garcia     if (bs) {
375181b936aeSAlberto Garcia         if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, errp)) {
375281b936aeSAlberto Garcia             goto out;
375381b936aeSAlberto Garcia         }
375481b936aeSAlberto Garcia 
375581b936aeSAlberto Garcia         if (bs->refcnt > 1 || !QLIST_EMPTY(&bs->parents)) {
375681b936aeSAlberto Garcia             error_setg(errp, "Block device %s is in use",
375781b936aeSAlberto Garcia                        bdrv_get_device_or_node_name(bs));
375881b936aeSAlberto Garcia             goto out;
375981b936aeSAlberto Garcia         }
376081b936aeSAlberto Garcia     }
376181b936aeSAlberto Garcia 
376281b936aeSAlberto Garcia     if (blk) {
376381b936aeSAlberto Garcia         blk_unref(blk);
376481b936aeSAlberto Garcia     } else {
376581b936aeSAlberto Garcia         bdrv_unref(bs);
376681b936aeSAlberto Garcia     }
376781b936aeSAlberto Garcia 
376881b936aeSAlberto Garcia out:
376981b936aeSAlberto Garcia     aio_context_release(aio_context);
377081b936aeSAlberto Garcia }
377181b936aeSAlberto Garcia 
3772fb5458cdSStefan Hajnoczi BlockJobInfoList *qmp_query_block_jobs(Error **errp)
3773fb5458cdSStefan Hajnoczi {
3774fea68bb6SMarkus Armbruster     BlockJobInfoList *head = NULL, **p_next = &head;
3775fea68bb6SMarkus Armbruster     BlockDriverState *bs;
3776fea68bb6SMarkus Armbruster 
3777fea68bb6SMarkus Armbruster     for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
377869691e72SStefan Hajnoczi         AioContext *aio_context = bdrv_get_aio_context(bs);
377969691e72SStefan Hajnoczi 
378069691e72SStefan Hajnoczi         aio_context_acquire(aio_context);
378169691e72SStefan Hajnoczi 
3782fea68bb6SMarkus Armbruster         if (bs->job) {
3783fea68bb6SMarkus Armbruster             BlockJobInfoList *elem = g_new0(BlockJobInfoList, 1);
3784fea68bb6SMarkus Armbruster             elem->value = block_job_query(bs->job);
3785fea68bb6SMarkus Armbruster             *p_next = elem;
3786fea68bb6SMarkus Armbruster             p_next = &elem->next;
3787fea68bb6SMarkus Armbruster         }
378869691e72SStefan Hajnoczi 
378969691e72SStefan Hajnoczi         aio_context_release(aio_context);
3790fea68bb6SMarkus Armbruster     }
3791fea68bb6SMarkus Armbruster 
3792fea68bb6SMarkus Armbruster     return head;
3793fb5458cdSStefan Hajnoczi }
37944d454574SPaolo Bonzini 
37950006383eSKevin Wolf QemuOptsList qemu_common_drive_opts = {
37964d454574SPaolo Bonzini     .name = "drive",
37970006383eSKevin Wolf     .head = QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head),
37984d454574SPaolo Bonzini     .desc = {
37994d454574SPaolo Bonzini         {
38004d454574SPaolo Bonzini             .name = "snapshot",
38014d454574SPaolo Bonzini             .type = QEMU_OPT_BOOL,
38024d454574SPaolo Bonzini             .help = "enable/disable snapshot mode",
38034d454574SPaolo Bonzini         },{
3804a9384affSPaolo Bonzini             .name = "discard",
3805a9384affSPaolo Bonzini             .type = QEMU_OPT_STRING,
3806a9384affSPaolo Bonzini             .help = "discard operation (ignore/off, unmap/on)",
3807a9384affSPaolo Bonzini         },{
380854861b92SKevin Wolf             .name = BDRV_OPT_CACHE_WB,
380929c4e2b5SKevin Wolf             .type = QEMU_OPT_BOOL,
381029c4e2b5SKevin Wolf             .help = "enables writeback mode for any caches",
381129c4e2b5SKevin Wolf         },{
381254861b92SKevin Wolf             .name = BDRV_OPT_CACHE_DIRECT,
381329c4e2b5SKevin Wolf             .type = QEMU_OPT_BOOL,
381429c4e2b5SKevin Wolf             .help = "enables use of O_DIRECT (bypass the host page cache)",
381529c4e2b5SKevin Wolf         },{
381654861b92SKevin Wolf             .name = BDRV_OPT_CACHE_NO_FLUSH,
381729c4e2b5SKevin Wolf             .type = QEMU_OPT_BOOL,
381829c4e2b5SKevin Wolf             .help = "ignore any flush requests for the device",
38194d454574SPaolo Bonzini         },{
38204d454574SPaolo Bonzini             .name = "aio",
38214d454574SPaolo Bonzini             .type = QEMU_OPT_STRING,
38224d454574SPaolo Bonzini             .help = "host AIO implementation (threads, native)",
38234d454574SPaolo Bonzini         },{
38244d454574SPaolo Bonzini             .name = "format",
38254d454574SPaolo Bonzini             .type = QEMU_OPT_STRING,
38264d454574SPaolo Bonzini             .help = "disk format (raw, qcow2, ...)",
38274d454574SPaolo Bonzini         },{
38284d454574SPaolo Bonzini             .name = "rerror",
38294d454574SPaolo Bonzini             .type = QEMU_OPT_STRING,
38304d454574SPaolo Bonzini             .help = "read error action",
38314d454574SPaolo Bonzini         },{
38324d454574SPaolo Bonzini             .name = "werror",
38334d454574SPaolo Bonzini             .type = QEMU_OPT_STRING,
38344d454574SPaolo Bonzini             .help = "write error action",
38354d454574SPaolo Bonzini         },{
38360f227a94SKevin Wolf             .name = "read-only",
38374d454574SPaolo Bonzini             .type = QEMU_OPT_BOOL,
38384d454574SPaolo Bonzini             .help = "open drive file as read-only",
38394d454574SPaolo Bonzini         },{
384057975222SKevin Wolf             .name = "throttling.iops-total",
38414d454574SPaolo Bonzini             .type = QEMU_OPT_NUMBER,
38424d454574SPaolo Bonzini             .help = "limit total I/O operations per second",
38434d454574SPaolo Bonzini         },{
384457975222SKevin Wolf             .name = "throttling.iops-read",
38454d454574SPaolo Bonzini             .type = QEMU_OPT_NUMBER,
38464d454574SPaolo Bonzini             .help = "limit read operations per second",
38474d454574SPaolo Bonzini         },{
384857975222SKevin Wolf             .name = "throttling.iops-write",
38494d454574SPaolo Bonzini             .type = QEMU_OPT_NUMBER,
38504d454574SPaolo Bonzini             .help = "limit write operations per second",
38514d454574SPaolo Bonzini         },{
385257975222SKevin Wolf             .name = "throttling.bps-total",
38534d454574SPaolo Bonzini             .type = QEMU_OPT_NUMBER,
38544d454574SPaolo Bonzini             .help = "limit total bytes per second",
38554d454574SPaolo Bonzini         },{
385657975222SKevin Wolf             .name = "throttling.bps-read",
38574d454574SPaolo Bonzini             .type = QEMU_OPT_NUMBER,
38584d454574SPaolo Bonzini             .help = "limit read bytes per second",
38594d454574SPaolo Bonzini         },{
386057975222SKevin Wolf             .name = "throttling.bps-write",
38614d454574SPaolo Bonzini             .type = QEMU_OPT_NUMBER,
38624d454574SPaolo Bonzini             .help = "limit write bytes per second",
38634d454574SPaolo Bonzini         },{
38643e9fab69SBenoît Canet             .name = "throttling.iops-total-max",
38653e9fab69SBenoît Canet             .type = QEMU_OPT_NUMBER,
38663e9fab69SBenoît Canet             .help = "I/O operations burst",
38673e9fab69SBenoît Canet         },{
38683e9fab69SBenoît Canet             .name = "throttling.iops-read-max",
38693e9fab69SBenoît Canet             .type = QEMU_OPT_NUMBER,
38703e9fab69SBenoît Canet             .help = "I/O operations read burst",
38713e9fab69SBenoît Canet         },{
38723e9fab69SBenoît Canet             .name = "throttling.iops-write-max",
38733e9fab69SBenoît Canet             .type = QEMU_OPT_NUMBER,
38743e9fab69SBenoît Canet             .help = "I/O operations write burst",
38753e9fab69SBenoît Canet         },{
38763e9fab69SBenoît Canet             .name = "throttling.bps-total-max",
38773e9fab69SBenoît Canet             .type = QEMU_OPT_NUMBER,
38783e9fab69SBenoît Canet             .help = "total bytes burst",
38793e9fab69SBenoît Canet         },{
38803e9fab69SBenoît Canet             .name = "throttling.bps-read-max",
38813e9fab69SBenoît Canet             .type = QEMU_OPT_NUMBER,
38823e9fab69SBenoît Canet             .help = "total bytes read burst",
38833e9fab69SBenoît Canet         },{
38843e9fab69SBenoît Canet             .name = "throttling.bps-write-max",
38853e9fab69SBenoît Canet             .type = QEMU_OPT_NUMBER,
38863e9fab69SBenoît Canet             .help = "total bytes write burst",
38873e9fab69SBenoît Canet         },{
38882024c1dfSBenoît Canet             .name = "throttling.iops-size",
38892024c1dfSBenoît Canet             .type = QEMU_OPT_NUMBER,
38902024c1dfSBenoît Canet             .help = "when limiting by iops max size of an I/O in bytes",
38912024c1dfSBenoît Canet         },{
389276f4afb4SAlberto Garcia             .name = "throttling.group",
389376f4afb4SAlberto Garcia             .type = QEMU_OPT_STRING,
389476f4afb4SAlberto Garcia             .help = "name of the block throttling group",
389576f4afb4SAlberto Garcia         },{
38964d454574SPaolo Bonzini             .name = "copy-on-read",
38974d454574SPaolo Bonzini             .type = QEMU_OPT_BOOL,
38984d454574SPaolo Bonzini             .help = "copy read data from backing file into image file",
3899465bee1dSPeter Lieven         },{
3900465bee1dSPeter Lieven             .name = "detect-zeroes",
3901465bee1dSPeter Lieven             .type = QEMU_OPT_STRING,
3902465bee1dSPeter Lieven             .help = "try to optimize zero writes (off, on, unmap)",
39034d454574SPaolo Bonzini         },
39044d454574SPaolo Bonzini         { /* end of list */ }
39054d454574SPaolo Bonzini     },
39064d454574SPaolo Bonzini };
39070006383eSKevin Wolf 
3908bd745e23SMax Reitz static QemuOptsList qemu_root_bds_opts = {
3909bd745e23SMax Reitz     .name = "root-bds",
3910bd745e23SMax Reitz     .head = QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head),
3911bd745e23SMax Reitz     .desc = {
3912bd745e23SMax Reitz         {
3913bd745e23SMax Reitz             .name = "discard",
3914bd745e23SMax Reitz             .type = QEMU_OPT_STRING,
3915bd745e23SMax Reitz             .help = "discard operation (ignore/off, unmap/on)",
3916bd745e23SMax Reitz         },{
3917bd745e23SMax Reitz             .name = "cache.writeback",
3918bd745e23SMax Reitz             .type = QEMU_OPT_BOOL,
3919bd745e23SMax Reitz             .help = "enables writeback mode for any caches",
3920bd745e23SMax Reitz         },{
3921bd745e23SMax Reitz             .name = "cache.direct",
3922bd745e23SMax Reitz             .type = QEMU_OPT_BOOL,
3923bd745e23SMax Reitz             .help = "enables use of O_DIRECT (bypass the host page cache)",
3924bd745e23SMax Reitz         },{
3925bd745e23SMax Reitz             .name = "cache.no-flush",
3926bd745e23SMax Reitz             .type = QEMU_OPT_BOOL,
3927bd745e23SMax Reitz             .help = "ignore any flush requests for the device",
3928bd745e23SMax Reitz         },{
3929bd745e23SMax Reitz             .name = "aio",
3930bd745e23SMax Reitz             .type = QEMU_OPT_STRING,
3931bd745e23SMax Reitz             .help = "host AIO implementation (threads, native)",
3932bd745e23SMax Reitz         },{
3933bd745e23SMax Reitz             .name = "read-only",
3934bd745e23SMax Reitz             .type = QEMU_OPT_BOOL,
3935bd745e23SMax Reitz             .help = "open drive file as read-only",
3936bd745e23SMax Reitz         },{
3937bd745e23SMax Reitz             .name = "copy-on-read",
3938bd745e23SMax Reitz             .type = QEMU_OPT_BOOL,
3939bd745e23SMax Reitz             .help = "copy read data from backing file into image file",
3940bd745e23SMax Reitz         },{
3941bd745e23SMax Reitz             .name = "detect-zeroes",
3942bd745e23SMax Reitz             .type = QEMU_OPT_STRING,
3943bd745e23SMax Reitz             .help = "try to optimize zero writes (off, on, unmap)",
3944bd745e23SMax Reitz         },
3945bd745e23SMax Reitz         { /* end of list */ }
3946bd745e23SMax Reitz     },
3947bd745e23SMax Reitz };
3948bd745e23SMax Reitz 
39490006383eSKevin Wolf QemuOptsList qemu_drive_opts = {
39500006383eSKevin Wolf     .name = "drive",
39510006383eSKevin Wolf     .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head),
39520006383eSKevin Wolf     .desc = {
3953492fdc6fSKevin Wolf         /*
3954492fdc6fSKevin Wolf          * no elements => accept any params
3955492fdc6fSKevin Wolf          * validation will happen later
3956492fdc6fSKevin Wolf          */
39570006383eSKevin Wolf         { /* end of list */ }
39580006383eSKevin Wolf     },
39590006383eSKevin Wolf };
3960