From patchwork Thu Jul 17 11:03:51 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Dovgalyuk X-Patchwork-Id: 371171 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id EF98C140179 for ; Thu, 17 Jul 2014 23:59:39 +1000 (EST) Received: from localhost ([::1]:44492 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X7mDh-0001gm-Uv for incoming@patchwork.ozlabs.org; Thu, 17 Jul 2014 09:59:37 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55284) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X7jkg-0000kM-9s for qemu-devel@nongnu.org; Thu, 17 Jul 2014 07:21:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X7jkY-0002S5-Vf for qemu-devel@nongnu.org; Thu, 17 Jul 2014 07:21:30 -0400 Received: from mail.ispras.ru ([83.149.199.45]:47456) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X7jTY-00053N-V7 for qemu-devel@nongnu.org; Thu, 17 Jul 2014 07:03:49 -0400 Received: from [10.10.150.172] (unknown [80.250.189.177]) by mail.ispras.ru (Postfix) with ESMTPSA id 24496540151; Thu, 17 Jul 2014 15:03:48 +0400 (MSK) To: qemu-devel@nongnu.org From: Pavel Dovgalyuk Date: Thu, 17 Jul 2014 15:03:51 +0400 Message-ID: <20140717110351.8352.96585.stgit@PASHA-ISP> In-Reply-To: <20140717110153.8352.80175.stgit@PASHA-ISP> References: <20140717110153.8352.80175.stgit@PASHA-ISP> User-Agent: StGit/0.16 MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 83.149.199.45 X-Mailman-Approved-At: Thu, 17 Jul 2014 09:36:33 -0400 Cc: peter.maydell@linaro.org, peter.crosthwaite@xilinx.com, mark.burton@greensocs.com, real@ispras.ru, batuzovk@ispras.ru, pavel.dovgaluk@ispras.ru, pbonzini@redhat.com, fred.konrad@greensocs.com Subject: [Qemu-devel] [RFC PATCH v2 20/49] block: add suffix parameter to bdrv_open functions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch adds parameter with suffix for overlay filenames. This parameter will be used by replay to automatically create overlay files based on drive images supplied to VM. Signed-off-by: Pavel Dovgalyuk --- block.c | 44 ++++++++++++++++++++++++++++++-------------- block/blkdebug.c | 2 +- block/blkverify.c | 4 ++-- block/cow.c | 2 +- block/qcow.c | 2 +- block/qcow2.c | 6 +++--- block/qed.c | 2 +- block/sheepdog.c | 4 ++-- block/vmdk.c | 8 ++++---- block/vvfat.c | 2 +- blockdev.c | 11 ++++++----- include/block/block.h | 6 +++--- qemu-img.c | 6 +++--- qemu-io.c | 4 ++-- qemu-nbd.c | 2 +- 15 files changed, 61 insertions(+), 44 deletions(-) diff --git a/block.c b/block.c index 8800a6b..3ff1052 100644 --- a/block.c +++ b/block.c @@ -35,6 +35,7 @@ #include "qmp-commands.h" #include "qemu/timer.h" #include "qapi-event.h" +#include "replay/replay.h" #ifdef CONFIG_BSD #include @@ -1209,7 +1210,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) assert(bs->backing_hd == NULL); ret = bdrv_open(&backing_hd, *backing_filename ? backing_filename : NULL, NULL, options, - bdrv_backing_flags(bs->open_flags), back_drv, &local_err); + bdrv_backing_flags(bs->open_flags), back_drv, &local_err, NULL); if (ret < 0) { bdrv_unref(backing_hd); backing_hd = NULL; @@ -1244,7 +1245,7 @@ free_exit: */ int bdrv_open_image(BlockDriverState **pbs, const char *filename, QDict *options, const char *bdref_key, int flags, - bool allow_none, Error **errp) + bool allow_none, Error **errp, const char *fname_suffix) { QDict *image_options; int ret; @@ -1271,14 +1272,14 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename, goto done; } - ret = bdrv_open(pbs, filename, reference, image_options, flags, NULL, errp); + ret = bdrv_open(pbs, filename, reference, image_options, flags, NULL, errp, NULL); done: qdict_del(options, bdref_key); return ret; } -int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp) +int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp, const char *fname_suffix) { /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */ char *tmp_filename = g_malloc0(PATH_MAX + 1); @@ -1303,17 +1304,29 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp) total_size &= BDRV_SECTOR_MASK; /* Create the temporary image */ - ret = get_tmp_filename(tmp_filename, PATH_MAX + 1); - if (ret < 0) { - error_setg_errno(errp, -ret, "Could not get temporary filename"); - goto out; + /* We will not delete created file in record/replay mode */ + if (replay_mode != REPLAY_NONE && fname_suffix) { + ret = snprintf(tmp_filename, PATH_MAX + 1, "%s.%s", bs->filename, fname_suffix); + if (ret < 0) { + goto out; + } + } else { + ret = get_tmp_filename(tmp_filename, PATH_MAX + 1); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not get temporary filename"); + goto out; + } } bdrv_qcow2 = bdrv_find_format("qcow2"); opts = qemu_opts_create(bdrv_qcow2->create_opts, NULL, 0, &error_abort); qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_size); - ret = bdrv_create(bdrv_qcow2, tmp_filename, opts, &local_err); + if (replay_mode == REPLAY_PLAY) { + ret = 0; + } else { + ret = bdrv_create(bdrv_qcow2, tmp_filename, opts, &local_err); + } qemu_opts_del(opts); if (ret < 0) { error_setg_errno(errp, -ret, "Could not create temporary overlay " @@ -1333,7 +1346,7 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp) bs_snapshot = bdrv_new("", &error_abort); ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options, - flags, bdrv_qcow2, &local_err); + flags, bdrv_qcow2, &local_err, NULL); if (ret < 0) { error_propagate(errp, local_err); goto out; @@ -1363,7 +1376,7 @@ out: */ int bdrv_open(BlockDriverState **pbs, const char *filename, const char *reference, QDict *options, int flags, - BlockDriver *drv, Error **errp) + BlockDriver *drv, Error **errp, const char *fname_suffix) { int ret; BlockDriverState *file = NULL, *bs; @@ -1444,13 +1457,16 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, } if (flags & BDRV_O_SNAPSHOT) { snapshot_flags = bdrv_temp_snapshot_flags(flags); + if (replay_mode != REPLAY_NONE) { + snapshot_flags &= ~BDRV_O_TEMPORARY; + } flags = bdrv_backing_flags(flags); } assert(file == NULL); ret = bdrv_open_image(&file, filename, options, "file", bdrv_inherited_flags(flags), - true, &local_err); + true, &local_err, NULL); if (ret < 0) { goto fail; } @@ -1493,7 +1509,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, /* For snapshot=on, create a temporary qcow2 overlay. bs points to the * temporary snapshot afterwards. */ if (snapshot_flags) { - ret = bdrv_append_temp_snapshot(bs, snapshot_flags, &local_err); + ret = bdrv_append_temp_snapshot(bs, snapshot_flags, &local_err, fname_suffix); if (local_err) { goto close_and_fail; } @@ -5573,7 +5589,7 @@ void bdrv_img_create(const char *filename, const char *fmt, bs = NULL; ret = bdrv_open(&bs, backing_file, NULL, NULL, back_flags, - backing_drv, &local_err); + backing_drv, &local_err, NULL); if (ret < 0) { error_setg_errno(errp, -ret, "Could not open '%s': %s", backing_file, diff --git a/block/blkdebug.c b/block/blkdebug.c index f51407d..151538a 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -412,7 +412,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, /* Open the backing file */ assert(bs->file == NULL); ret = bdrv_open_image(&bs->file, qemu_opt_get(opts, "x-image"), options, "image", - flags | BDRV_O_PROTOCOL, false, &local_err); + flags | BDRV_O_PROTOCOL, false, &local_err, NULL); if (ret < 0) { error_propagate(errp, local_err); goto out; diff --git a/block/blkverify.c b/block/blkverify.c index 621b785..94d7db7 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -138,7 +138,7 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, /* Open the raw file */ assert(bs->file == NULL); ret = bdrv_open_image(&bs->file, qemu_opt_get(opts, "x-raw"), options, - "raw", flags | BDRV_O_PROTOCOL, false, &local_err); + "raw", flags | BDRV_O_PROTOCOL, false, &local_err, NULL); if (ret < 0) { error_propagate(errp, local_err); goto fail; @@ -147,7 +147,7 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, /* Open the test file */ assert(s->test_file == NULL); ret = bdrv_open_image(&s->test_file, qemu_opt_get(opts, "x-image"), options, - "test", flags, false, &local_err); + "test", flags, false, &local_err, NULL); if (ret < 0) { error_propagate(errp, local_err); s->test_file = NULL; diff --git a/block/cow.c b/block/cow.c index 6ee4833..d99c4d7 100644 --- a/block/cow.c +++ b/block/cow.c @@ -345,7 +345,7 @@ static int cow_create(const char *filename, QemuOpts *opts, Error **errp) } ret = bdrv_open(&cow_bs, filename, NULL, NULL, - BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err); + BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err, NULL); if (ret < 0) { error_propagate(errp, local_err); goto exit; diff --git a/block/qcow.c b/block/qcow.c index a874056..6e21cea 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -720,7 +720,7 @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp) qcow_bs = NULL; ret = bdrv_open(&qcow_bs, filename, NULL, NULL, - BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err); + BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err, NULL); if (ret < 0) { error_propagate(errp, local_err); goto cleanup; diff --git a/block/qcow2.c b/block/qcow2.c index 67e55c9..d9da238 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1635,7 +1635,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, bs = NULL; ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, - NULL, &local_err); + NULL, &local_err, NULL); if (ret < 0) { error_propagate(errp, local_err); return ret; @@ -1697,7 +1697,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, BlockDriver* drv = bdrv_find_format("qcow2"); assert(drv != NULL); ret = bdrv_open(&bs, filename, NULL, NULL, - BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv, &local_err); + BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv, &local_err, NULL); if (ret < 0) { error_propagate(errp, local_err); goto out; @@ -1749,7 +1749,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, /* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning */ ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_BACKING, - drv, &local_err); + drv, &local_err, NULL); if (local_err) { error_propagate(errp, local_err); goto out; diff --git a/block/qed.c b/block/qed.c index b69374b..3417187 100644 --- a/block/qed.c +++ b/block/qed.c @@ -595,7 +595,7 @@ static int qed_create(const char *filename, uint32_t cluster_size, bs = NULL; ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_PROTOCOL, NULL, - &local_err); + &local_err, NULL); if (ret < 0) { error_propagate(errp, local_err); return ret; diff --git a/block/sheepdog.c b/block/sheepdog.c index 8d9350c..bb3dfef 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1576,7 +1576,7 @@ static int sd_prealloc(const char *filename, Error **errp) int ret; ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, - NULL, errp); + NULL, errp, NULL); if (ret < 0) { goto out_with_err_set; } @@ -1739,7 +1739,7 @@ static int sd_create(const char *filename, QemuOpts *opts, bs = NULL; ret = bdrv_open(&bs, backing_file, NULL, NULL, BDRV_O_PROTOCOL, NULL, - errp); + errp, NULL); if (ret < 0) { goto out; } diff --git a/block/vmdk.c b/block/vmdk.c index 27a78da..5bafe31 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -809,7 +809,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, desc_file_path, fname); extent_file = NULL; ret = bdrv_open(&extent_file, extent_path, NULL, NULL, - bs->open_flags | BDRV_O_PROTOCOL, NULL, errp); + bs->open_flags | BDRV_O_PROTOCOL, NULL, errp, NULL); if (ret) { return ret; } @@ -1547,7 +1547,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize, assert(bs == NULL); ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, - NULL, &local_err); + NULL, &local_err, NULL); if (ret < 0) { error_propagate(errp, local_err); goto exit; @@ -1805,7 +1805,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) if (backing_file) { BlockDriverState *bs = NULL; ret = bdrv_open(&bs, backing_file, NULL, NULL, BDRV_O_NO_BACKING, NULL, - errp); + errp, NULL); if (ret != 0) { goto exit; } @@ -1881,7 +1881,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) } assert(new_bs == NULL); ret = bdrv_open(&new_bs, filename, NULL, NULL, - BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err); + BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err, NULL); if (ret < 0) { error_propagate(errp, local_err); goto exit; diff --git a/block/vvfat.c b/block/vvfat.c index 70176b1..f86f890 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -2939,7 +2939,7 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp) s->qcow = NULL; ret = bdrv_open(&s->qcow, s->qcow_filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, - bdrv_qcow, errp); + bdrv_qcow, errp, NULL); if (ret < 0) { goto err; } diff --git a/blockdev.c b/blockdev.c index 48bd9a3..e5d4b4d 100644 --- a/blockdev.c +++ b/blockdev.c @@ -44,6 +44,7 @@ #include "qmp-commands.h" #include "trace.h" #include "sysemu/arch_init.h" +#include "replay/replay.h" static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives); @@ -520,7 +521,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, bdrv_flags |= ro ? 0 : BDRV_O_RDWR; QINCREF(bs_opts); - ret = bdrv_open(&dinfo->bdrv, file, NULL, bs_opts, bdrv_flags, drv, &error); + ret = bdrv_open(&dinfo->bdrv, file, NULL, bs_opts, bdrv_flags, drv, &error, replay_image_suffix); if (ret < 0) { error_setg(errp, "could not open disk image %s: %s", @@ -1367,7 +1368,7 @@ static void external_snapshot_prepare(BlkTransactionState *common, * extended QMP command? */ assert(state->new_bs == NULL); ret = bdrv_open(&state->new_bs, new_image_file, NULL, options, - flags | BDRV_O_NO_BACKING, drv, &local_err); + flags | BDRV_O_NO_BACKING, drv, &local_err, NULL); /* We will manually add the backing_hd field to the bs later */ if (ret != 0) { error_propagate(errp, local_err); @@ -1616,7 +1617,7 @@ static void qmp_bdrv_open_encrypted(BlockDriverState *bs, const char *filename, Error *local_err = NULL; int ret; - ret = bdrv_open(&bs, filename, NULL, NULL, bdrv_flags, drv, &local_err); + ret = bdrv_open(&bs, filename, NULL, NULL, bdrv_flags, drv, &local_err, NULL); if (ret < 0) { error_propagate(errp, local_err); return; @@ -2108,7 +2109,7 @@ void qmp_drive_backup(const char *device, const char *target, } target_bs = NULL; - ret = bdrv_open(&target_bs, target, NULL, NULL, flags, drv, &local_err); + ret = bdrv_open(&target_bs, target, NULL, NULL, flags, drv, &local_err, NULL); if (ret < 0) { error_propagate(errp, local_err); return; @@ -2282,7 +2283,7 @@ void qmp_drive_mirror(const char *device, const char *target, */ target_bs = NULL; ret = bdrv_open(&target_bs, target, NULL, options, - flags | BDRV_O_NO_BACKING, drv, &local_err); + flags | BDRV_O_NO_BACKING, drv, &local_err, NULL); if (ret < 0) { error_propagate(errp, local_err); return; diff --git a/include/block/block.h b/include/block/block.h index 32d3676..dd05458 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -211,13 +211,13 @@ int bdrv_parse_cache_flags(const char *mode, int *flags); int bdrv_parse_discard_flags(const char *mode, int *flags); int bdrv_open_image(BlockDriverState **pbs, const char *filename, QDict *options, const char *bdref_key, int flags, - bool allow_none, Error **errp); + bool allow_none, Error **errp, const char *fname_suffix); void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd); int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp); -int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp); +int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp, const char *fname_suffix); int bdrv_open(BlockDriverState **pbs, const char *filename, const char *reference, QDict *options, int flags, - BlockDriver *drv, Error **errp); + BlockDriver *drv, Error **errp, const char *fname_suffix); BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue, BlockDriverState *bs, int flags); int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp); diff --git a/qemu-img.c b/qemu-img.c index c98896b..d38c398 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -321,7 +321,7 @@ static BlockDriverState *bdrv_new_open(const char *id, drv = NULL; } - ret = bdrv_open(&bs, filename, NULL, NULL, flags, drv, &local_err); + ret = bdrv_open(&bs, filename, NULL, NULL, flags, drv, &local_err, NULL); if (ret < 0) { error_report("Could not open '%s': %s", filename, error_get_pretty(local_err)); @@ -2384,7 +2384,7 @@ static int img_rebase(int argc, char **argv) bs_old_backing = bdrv_new("old_backing", &error_abort); bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name)); ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, BDRV_O_FLAGS, - old_backing_drv, &local_err); + old_backing_drv, &local_err, NULL); if (ret) { error_report("Could not open old backing file '%s': %s", backing_name, error_get_pretty(local_err)); @@ -2394,7 +2394,7 @@ static int img_rebase(int argc, char **argv) if (out_baseimg[0]) { bs_new_backing = bdrv_new("new_backing", &error_abort); ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, - BDRV_O_FLAGS, new_backing_drv, &local_err); + BDRV_O_FLAGS, new_backing_drv, &local_err, NULL); if (ret) { error_report("Could not open new backing file '%s': %s", out_baseimg, error_get_pretty(local_err)); diff --git a/qemu-io.c b/qemu-io.c index b55a550..849067d 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -60,7 +60,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts) if (growable) { if (bdrv_open(&qemuio_bs, name, NULL, opts, flags | BDRV_O_PROTOCOL, - NULL, &local_err)) + NULL, &local_err, NULL)) { fprintf(stderr, "%s: can't open%s%s: %s\n", progname, name ? " device " : "", name ?: "", @@ -71,7 +71,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts) } else { qemuio_bs = bdrv_new("hda", &error_abort); - if (bdrv_open(&qemuio_bs, name, NULL, opts, flags, NULL, &local_err) + if (bdrv_open(&qemuio_bs, name, NULL, opts, flags, NULL, &local_err, NULL) < 0) { fprintf(stderr, "%s: can't open%s%s: %s\n", progname, diff --git a/qemu-nbd.c b/qemu-nbd.c index 626e584..e780d1c 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -663,7 +663,7 @@ int main(int argc, char **argv) bs = bdrv_new("hda", &error_abort); srcpath = argv[optind]; - ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err); + ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err, NULL); if (ret < 0) { errno = -ret; err(EXIT_FAILURE, "Failed to bdrv_open '%s': %s", argv[optind],