From nobody Sat Feb 7 04:57:05 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543859656068364.6238067964605; Mon, 3 Dec 2018 09:54:16 -0800 (PST) Received: from localhost ([::1]:51226 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTsQ9-0007dW-QY for importer@patchew.org; Mon, 03 Dec 2018 12:54:13 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44887) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTsOQ-0006Ef-In for qemu-devel@nongnu.org; Mon, 03 Dec 2018 12:52:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTsOO-0007L7-LW for qemu-devel@nongnu.org; Mon, 03 Dec 2018 12:52:26 -0500 Received: from mx1.redhat.com ([209.132.183.28]:42366) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gTsOJ-0007HB-05; Mon, 03 Dec 2018 12:52:19 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5A846308FC52; Mon, 3 Dec 2018 17:52:17 +0000 (UTC) Received: from localhost (unknown [10.36.118.45]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C89DA5D6B3; Mon, 3 Dec 2018 17:52:16 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Mon, 3 Dec 2018 18:52:06 +0100 Message-Id: <20181203175211.8230-2-mreitz@redhat.com> In-Reply-To: <20181203175211.8230-1-mreitz@redhat.com> References: <20181203175211.8230-1-mreitz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Mon, 03 Dec 2018 17:52:17 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-next 1/6] qemu-img: Move quiet into ImgConvertState X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Markus Armbruster , qemu-devel@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Move img_convert()'s quiet flag into the ImgConvertState so it is accessible by nested functions. -q dictates that it suppresses anything but errors, so if those functions want to emit warnings, they need to query this flag first. (There currently are no such warnings, but there will be as of the next patch.) Signed-off-by: Max Reitz Reviewed-by: Eric Blake --- qemu-img.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index ad04f59565..1582ef63f3 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1569,6 +1569,7 @@ typedef struct ImgConvertState { int64_t target_backing_sectors; /* negative if unknown */ bool wr_in_order; bool copy_range; + bool quiet; int min_sparse; int alignment; size_t cluster_sectors; @@ -2008,7 +2009,7 @@ static int img_convert(int argc, char **argv) QDict *open_opts =3D NULL; char *options =3D NULL; Error *local_err =3D NULL; - bool writethrough, src_writethrough, quiet =3D false, image_opts =3D f= alse, + bool writethrough, src_writethrough, image_opts =3D false, skip_create =3D false, progress =3D false, tgt_image_opts =3D fal= se; int64_t ret =3D -EINVAL; bool force_share =3D false; @@ -2116,7 +2117,7 @@ static int img_convert(int argc, char **argv) src_cache =3D optarg; break; case 'q': - quiet =3D true; + s.quiet =3D true; break; case 'n': skip_create =3D true; @@ -2205,7 +2206,7 @@ static int img_convert(int argc, char **argv) } =20 /* Initialize before goto out */ - if (quiet) { + if (s.quiet) { progress =3D false; } qemu_progress_init(progress, 1.0); @@ -2216,7 +2217,7 @@ static int img_convert(int argc, char **argv) =20 for (bs_i =3D 0; bs_i < s.src_num; bs_i++) { s.src[bs_i] =3D img_open(image_opts, argv[optind + bs_i], - fmt, src_flags, src_writethrough, quiet, + fmt, src_flags, src_writethrough, s.quiet, force_share); if (!s.src[bs_i]) { ret =3D -1; @@ -2379,7 +2380,7 @@ static int img_convert(int argc, char **argv) =20 if (skip_create) { s.target =3D img_open(tgt_image_opts, out_filename, out_fmt, - flags, writethrough, quiet, false); + flags, writethrough, s.quiet, false); } else { /* TODO ultimately we should allow --target-image-opts * to be used even when -n is not given. @@ -2387,7 +2388,7 @@ static int img_convert(int argc, char **argv) * to allow filenames in option syntax */ s.target =3D img_open_file(out_filename, open_opts, out_fmt, - flags, writethrough, quiet, false); + flags, writethrough, s.quiet, false); open_opts =3D NULL; /* blk_new_open will have freed it */ } if (!s.target) { --=20 2.19.2 From nobody Sat Feb 7 04:57:05 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543860101205637.0900245235067; Mon, 3 Dec 2018 10:01:41 -0800 (PST) Received: from localhost ([::1]:51287 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTsXL-0008AF-Dy for importer@patchew.org; Mon, 03 Dec 2018 13:01:39 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45042) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTsOd-0006NG-0m for qemu-devel@nongnu.org; Mon, 03 Dec 2018 12:52:40 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTsOa-0007TI-PV for qemu-devel@nongnu.org; Mon, 03 Dec 2018 12:52:38 -0500 Received: from mx1.redhat.com ([209.132.183.28]:39424) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gTsOW-0007Ic-Ao; Mon, 03 Dec 2018 12:52:32 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 792F83082190; Mon, 3 Dec 2018 17:52:20 +0000 (UTC) Received: from localhost (unknown [10.36.118.45]) by smtp.corp.redhat.com (Postfix) with ESMTPS id BBF5A6A517; Mon, 3 Dec 2018 17:52:19 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Mon, 3 Dec 2018 18:52:07 +0100 Message-Id: <20181203175211.8230-3-mreitz@redhat.com> In-Reply-To: <20181203175211.8230-1-mreitz@redhat.com> References: <20181203175211.8230-1-mreitz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.47]); Mon, 03 Dec 2018 17:52:20 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-next 2/6] qemu-img: Add salvaging mode to convert X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Markus Armbruster , qemu-devel@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" This adds a salvaging mode (--salvage) to qemu-img convert which ignores read errors and treats the respective areas as containing only zeroes. This can be used for instance to at least partially recover the data from terminally corrupted qcow2 images. Signed-off-by: Max Reitz --- qemu-img.c | 84 +++++++++++++++++++++++++++++++++++++----------- qemu-img-cmds.hx | 4 +-- qemu-img.texi | 5 +++ 3 files changed, 72 insertions(+), 21 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index 1582ef63f3..395c1973fe 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -66,6 +66,7 @@ enum { OPTION_SIZE =3D 264, OPTION_PREALLOCATION =3D 265, OPTION_SHRINK =3D 266, + OPTION_SALVAGE =3D 267, }; =20 typedef enum OutputFormat { @@ -1569,6 +1570,7 @@ typedef struct ImgConvertState { int64_t target_backing_sectors; /* negative if unknown */ bool wr_in_order; bool copy_range; + bool salvage; bool quiet; int min_sparse; int alignment; @@ -1616,23 +1618,43 @@ static int convert_iteration_sectors(ImgConvertStat= e *s, int64_t sector_num) } =20 if (s->sector_next_status <=3D sector_num) { - int64_t count =3D n * BDRV_SECTOR_SIZE; + uint64_t offset =3D (sector_num - src_cur_offset) * BDRV_SECTOR_SI= ZE; + int64_t count; =20 - if (s->target_has_backing) { + do { + count =3D n * BDRV_SECTOR_SIZE; + + if (s->target_has_backing) { + ret =3D bdrv_block_status(blk_bs(s->src[src_cur]), offset, + count, &count, NULL, NULL); + } else { + ret =3D bdrv_block_status_above(blk_bs(s->src[src_cur]), N= ULL, + offset, count, &count, NULL, + NULL); + } + + if (ret < 0) { + if (s->salvage) { + if (n =3D=3D 1) { + if (!s->quiet) { + warn_report("Failed to inquire block status of= %s " + "at offset %#" PRIx64 ": %s", + blk_bs(s->src[src_cur])->filename, + offset, strerror(-ret)); + } + /* Just try to read the data, then */ + ret =3D BDRV_BLOCK_DATA; + count =3D BDRV_SECTOR_SIZE; + } else { + /* Retry on a shorter range */ + n =3D DIV_ROUND_UP(n, 4); + } + } else { + return ret; + } + } + } while (ret < 0); =20 - ret =3D bdrv_block_status(blk_bs(s->src[src_cur]), - (sector_num - src_cur_offset) * - BDRV_SECTOR_SIZE, - count, &count, NULL, NULL); - } else { - ret =3D bdrv_block_status_above(blk_bs(s->src[src_cur]), NULL, - (sector_num - src_cur_offset) * - BDRV_SECTOR_SIZE, - count, &count, NULL, NULL); - } - if (ret < 0) { - return ret; - } n =3D DIV_ROUND_UP(count, BDRV_SECTOR_SIZE); =20 if (ret & BDRV_BLOCK_ZERO) { @@ -1669,6 +1691,7 @@ static int convert_iteration_sectors(ImgConvertState = *s, int64_t sector_num) static int coroutine_fn convert_co_read(ImgConvertState *s, int64_t sector= _num, int nb_sectors, uint8_t *buf) { + uint64_t single_read_until =3D 0; int n, ret; QEMUIOVector qiov; struct iovec iov; @@ -1678,6 +1701,7 @@ static int coroutine_fn convert_co_read(ImgConvertSta= te *s, int64_t sector_num, BlockBackend *blk; int src_cur; int64_t bs_sectors, src_cur_offset; + uint64_t offset; =20 /* In the case of compression with multiple source files, we can g= et a * nb_sectors that spreads into the next part. So we must be able = to @@ -1686,16 +1710,34 @@ static int coroutine_fn convert_co_read(ImgConvertS= tate *s, int64_t sector_num, blk =3D s->src[src_cur]; bs_sectors =3D s->src_sectors[src_cur]; =20 + offset =3D (sector_num - src_cur_offset) << BDRV_SECTOR_BITS; + n =3D MIN(nb_sectors, bs_sectors - (sector_num - src_cur_offset)); + if (single_read_until > offset) { + n =3D 1; + } + iov.iov_base =3D buf; iov.iov_len =3D n << BDRV_SECTOR_BITS; qemu_iovec_init_external(&qiov, &iov, 1); =20 - ret =3D blk_co_preadv( - blk, (sector_num - src_cur_offset) << BDRV_SECTOR_BITS, - n << BDRV_SECTOR_BITS, &qiov, 0); + ret =3D blk_co_preadv(blk, offset, n << BDRV_SECTOR_BITS, &qiov, 0= ); if (ret < 0) { - return ret; + if (s->salvage) { + if (n > 1) { + single_read_until =3D offset + (n << BDRV_SECTOR_BITS); + continue; + } else { + if (!s->quiet) { + warn_report("Failed to read offset %#" PRIx64 " fr= om " + "%s: %s", offset, blk_bs(blk)->filenam= e, + strerror(-ret)); + } + memset(buf, 0, BDRV_SECTOR_SIZE); + } + } else { + return ret; + } } =20 sector_num +=3D n; @@ -2031,6 +2073,7 @@ static int img_convert(int argc, char **argv) {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {"force-share", no_argument, 0, 'U'}, {"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS= }, + {"salvage", no_argument, 0, OPTION_SALVAGE}, {0, 0, 0, 0} }; c =3D getopt_long(argc, argv, ":hf:O:B:Cco:l:S:pt:T:qnm:WU", @@ -2148,6 +2191,9 @@ static int img_convert(int argc, char **argv) case OPTION_IMAGE_OPTS: image_opts =3D true; break; + case OPTION_SALVAGE: + s.salvage =3D true; + break; case OPTION_TARGET_IMAGE_OPTS: tgt_image_opts =3D true; break; diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx index 1526f327a5..d6f444586c 100644 --- a/qemu-img-cmds.hx +++ b/qemu-img-cmds.hx @@ -44,9 +44,9 @@ STEXI ETEXI =20 DEF("convert", img_convert, - "convert [--object objectdef] [--image-opts] [--target-image-opts] [-U= ] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fm= t] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m = num_coroutines] [-W] filename [filename2 [...]] output_filename") + "convert [--object objectdef] [--image-opts] [--target-image-opts] [-U= ] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fm= t] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m = num_coroutines] [-W] [--salvage] filename [filename2 [...]] output_filename= ") STEXI -@item convert [--object @var{objectdef}] [--image-opts] [--target-image-op= ts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_c= ache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-l= @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W= ] @var{filename} [@var{filename2} [...]] @var{output_filename} +@item convert [--object @var{objectdef}] [--image-opts] [--target-image-op= ts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_c= ache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-l= @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W= ] [--salvage] @var{filename} [@var{filename2} [...]] @var{output_filename} ETEXI =20 DEF("create", img_create, diff --git a/qemu-img.texi b/qemu-img.texi index 3b6710a580..827ee9fe32 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -175,6 +175,11 @@ improve performance if the data is remote, such as wit= h NFS or iSCSI backends, but will not automatically sparsify zero sectors, and may result in a fully allocated target image depending on the host support for getting allocation information. +@item --salvage +Try to ignore I/O errors when reading. Unless in quiet mode (@code{-q}), = errors +will still be printed. Areas that cannot be read from the source will be +treated as containing only zeroes. This option has no effect in copy offl= oading +mode (@code{-C}). @end table =20 Parameters to dd subcommand: --=20 2.19.2 From nobody Sat Feb 7 04:57:05 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543859806389397.14415666004265; Mon, 3 Dec 2018 09:56:46 -0800 (PST) Received: from localhost ([::1]:51250 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTsSX-0001Vv-70 for importer@patchew.org; Mon, 03 Dec 2018 12:56:41 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45045) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTsOd-0006NJ-0i for qemu-devel@nongnu.org; Mon, 03 Dec 2018 12:52:40 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTsOZ-0007SX-Ri for qemu-devel@nongnu.org; Mon, 03 Dec 2018 12:52:38 -0500 Received: from mx1.redhat.com ([209.132.183.28]:55022) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gTsOS-0007Kg-FK; Mon, 03 Dec 2018 12:52:29 -0500 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 601FB308212B; Mon, 3 Dec 2018 17:52:23 +0000 (UTC) Received: from localhost (unknown [10.36.118.45]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8277B600C1; Mon, 3 Dec 2018 17:52:22 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Mon, 3 Dec 2018 18:52:08 +0100 Message-Id: <20181203175211.8230-4-mreitz@redhat.com> In-Reply-To: <20181203175211.8230-1-mreitz@redhat.com> References: <20181203175211.8230-1-mreitz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Mon, 03 Dec 2018 17:52:23 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-next 3/6] blkdebug: Add @iotype error option X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Markus Armbruster , qemu-devel@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" This new error option allows users of blkdebug to inject errors only on certain kinds of I/O operations. Users usually want to make a very specific operation fail, not just any; but right now they simply hope that the event that triggers the error injection is followed up with that very operation. That may not be true, however, because the block layer is changing (including blkdebug, which may increase the number of types of I/O operations on which to inject errors). The new option's default has been chosen to keep backwards compatibility. Note that similar to the internal representation, we could choose to expose this option as a list of I/O types. But there is no practical use for this, because as described above, users usually know exactly which kind of operation they want to make fail, so there is no need to specify multiple I/O types at once. In addition, exposing this option as a list would require non-trivial changes to qemu_opts_absorb_qdict(). Signed-off-by: Max Reitz Reviewed-by: Eric Blake --- If you want @iotype be a list, I have patches. --- qapi/block-core.json | 26 +++++++++++++++++++++++ block/blkdebug.c | 50 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index d4fe710836..469d889753 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3024,6 +3024,26 @@ 'l1_shrink_write_table', 'l1_shrink_free_l2_clusters', 'cor_write'] } =20 +## +# @BlkdebugIOType: +# +# Kinds of I/O that blkdebug can inject errors in. +# +# @read: .bdrv_co_preadv() +# +# @write: .bdrv_co_pwritev() +# +# @write-zeroes: .bdrv_co_pwrite_zeroes() +# +# @discard: .bdrv_co_pdiscard() +# +# @flush: .bdrv_co_flush_to_disk() +# +# Since: 4.0 +## +{ 'enum': 'BlkdebugIOType', + 'data': [ 'read', 'write', 'write-zeroes', 'discard', 'flush' ] } + ## # @BlkdebugInjectErrorOptions: # @@ -3034,6 +3054,11 @@ # @state: the state identifier blkdebug needs to be in to # actually trigger the event; defaults to "any" # +# @iotype: the type of I/O operations on which this error should +# be injected; defaults to "all read, write, +# write-zeroes, discard, and flush operations" +# (since: 4.0) +# # @errno: error identifier (errno) to be returned; defaults to # EIO # @@ -3051,6 +3076,7 @@ { 'struct': 'BlkdebugInjectErrorOptions', 'data': { 'event': 'BlkdebugEvent', '*state': 'int', + '*iotype': 'BlkdebugIOType', '*errno': 'int', '*sector': 'int', '*once': 'bool', diff --git a/block/blkdebug.c b/block/blkdebug.c index 0759452925..d15b6c5fef 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -75,6 +75,7 @@ typedef struct BlkdebugRule { int state; union { struct { + uint64_t iotype_mask; int error; int immediately; int once; @@ -91,6 +92,9 @@ typedef struct BlkdebugRule { QSIMPLEQ_ENTRY(BlkdebugRule) active_next; } BlkdebugRule; =20 +QEMU_BUILD_BUG_MSG(BLKDEBUGIO_TYPE__MAX > 64, + "BlkdebugIOType mask does not fit into an uint64_t"); + static QemuOptsList inject_error_opts =3D { .name =3D "inject-error", .head =3D QTAILQ_HEAD_INITIALIZER(inject_error_opts.head), @@ -103,6 +107,10 @@ static QemuOptsList inject_error_opts =3D { .name =3D "state", .type =3D QEMU_OPT_NUMBER, }, + { + .name =3D "iotype", + .type =3D QEMU_OPT_STRING, + }, { .name =3D "errno", .type =3D QEMU_OPT_NUMBER, @@ -162,6 +170,8 @@ static int add_rule(void *opaque, QemuOpts *opts, Error= **errp) int event; struct BlkdebugRule *rule; int64_t sector; + BlkdebugIOType iotype; + Error *local_error =3D NULL; =20 /* Find the right event for the rule */ event_name =3D qemu_opt_get(opts, "event"); @@ -192,6 +202,26 @@ static int add_rule(void *opaque, QemuOpts *opts, Erro= r **errp) sector =3D qemu_opt_get_number(opts, "sector", -1); rule->options.inject.offset =3D sector =3D=3D -1 ? -1 : sector * BDRV_SECTOR_SIZE; + + iotype =3D qapi_enum_parse(&BlkdebugIOType_lookup, + qemu_opt_get(opts, "iotype"), + BLKDEBUGIO_TYPE__MAX, &local_error); + if (local_error) { + error_propagate(errp, local_error); + return -1; + } + if (iotype !=3D BLKDEBUGIO_TYPE__MAX) { + rule->options.inject.iotype_mask =3D (1ull << iotype); + } else { + /* Apply the default */ + rule->options.inject.iotype_mask =3D + (1ull << BLKDEBUGIO_TYPE_READ) + | (1ull << BLKDEBUGIO_TYPE_WRITE) + | (1ull << BLKDEBUGIO_TYPE_WRITE_ZEROES) + | (1ull << BLKDEBUGIO_TYPE_DISCARD) + | (1ull << BLKDEBUGIO_TYPE_FLUSH); + } + break; =20 case ACTION_SET_STATE: @@ -470,7 +500,8 @@ out: return ret; } =20 -static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t byte= s) +static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t byte= s, + BlkdebugIOType iotype) { BDRVBlkdebugState *s =3D bs->opaque; BlkdebugRule *rule =3D NULL; @@ -480,9 +511,10 @@ static int rule_check(BlockDriverState *bs, uint64_t o= ffset, uint64_t bytes) QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) { uint64_t inject_offset =3D rule->options.inject.offset; =20 - if (inject_offset =3D=3D -1 || - (bytes && inject_offset >=3D offset && - inject_offset < offset + bytes)) + if ((inject_offset =3D=3D -1 || + (bytes && inject_offset >=3D offset && + inject_offset < offset + bytes)) && + (rule->options.inject.iotype_mask & (1ull << iotype))) { break; } @@ -521,7 +553,7 @@ blkdebug_co_preadv(BlockDriverState *bs, uint64_t offse= t, uint64_t bytes, assert(bytes <=3D bs->bl.max_transfer); } =20 - err =3D rule_check(bs, offset, bytes); + err =3D rule_check(bs, offset, bytes, BLKDEBUGIO_TYPE_READ); if (err) { return err; } @@ -542,7 +574,7 @@ blkdebug_co_pwritev(BlockDriverState *bs, uint64_t offs= et, uint64_t bytes, assert(bytes <=3D bs->bl.max_transfer); } =20 - err =3D rule_check(bs, offset, bytes); + err =3D rule_check(bs, offset, bytes, BLKDEBUGIO_TYPE_WRITE); if (err) { return err; } @@ -552,7 +584,7 @@ blkdebug_co_pwritev(BlockDriverState *bs, uint64_t offs= et, uint64_t bytes, =20 static int blkdebug_co_flush(BlockDriverState *bs) { - int err =3D rule_check(bs, 0, 0); + int err =3D rule_check(bs, 0, 0, BLKDEBUGIO_TYPE_FLUSH); =20 if (err) { return err; @@ -586,7 +618,7 @@ static int coroutine_fn blkdebug_co_pwrite_zeroes(Block= DriverState *bs, assert(bytes <=3D bs->bl.max_pwrite_zeroes); } =20 - err =3D rule_check(bs, offset, bytes); + err =3D rule_check(bs, offset, bytes, BLKDEBUGIO_TYPE_WRITE_ZEROES); if (err) { return err; } @@ -620,7 +652,7 @@ static int coroutine_fn blkdebug_co_pdiscard(BlockDrive= rState *bs, assert(bytes <=3D bs->bl.max_pdiscard); } =20 - err =3D rule_check(bs, offset, bytes); + err =3D rule_check(bs, offset, bytes, BLKDEBUGIO_TYPE_DISCARD); if (err) { return err; } --=20 2.19.2 From nobody Sat Feb 7 04:57:05 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543859953088528.1647705896977; Mon, 3 Dec 2018 09:59:13 -0800 (PST) Received: from localhost ([::1]:51261 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTsUx-0005y0-Cf for importer@patchew.org; Mon, 03 Dec 2018 12:59:11 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45049) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTsOd-0006NM-1G for qemu-devel@nongnu.org; Mon, 03 Dec 2018 12:52:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTsOa-0007T5-Fl for qemu-devel@nongnu.org; Mon, 03 Dec 2018 12:52:38 -0500 Received: from mx1.redhat.com ([209.132.183.28]:42470) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gTsOW-0007MK-E3; Mon, 03 Dec 2018 12:52:32 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6032C3001FCD; Mon, 3 Dec 2018 17:52:26 +0000 (UTC) Received: from localhost (unknown [10.36.118.45]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C450D1019637; Mon, 3 Dec 2018 17:52:25 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Mon, 3 Dec 2018 18:52:09 +0100 Message-Id: <20181203175211.8230-5-mreitz@redhat.com> In-Reply-To: <20181203175211.8230-1-mreitz@redhat.com> References: <20181203175211.8230-1-mreitz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.45]); Mon, 03 Dec 2018 17:52:26 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-next 4/6] blkdebug: Add "none" event X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Markus Armbruster , qemu-devel@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Together with @iotypes and @sector, this can be used to trap e.g. the first read or write access to a certain sector without having to know what happens internally in the block layer, i.e. which "real" events happen right before such an access. Signed-off-by: Max Reitz Reviewed-by: Eric Blake --- qapi/block-core.json | 4 +++- block/blkdebug.c | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 469d889753..045206196b 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3004,6 +3004,8 @@ # # @cor_write: a write due to copy-on-read (since 2.11) # +# @none: triggers once at creation of the blkdebug node (since 4.0) +# # Since: 2.9 ## { 'enum': 'BlkdebugEvent', 'prefix': 'BLKDBG', @@ -3022,7 +3024,7 @@ 'pwritev_rmw_tail', 'pwritev_rmw_after_tail', 'pwritev', 'pwritev_zero', 'pwritev_done', 'empty_image_prepare', 'l1_shrink_write_table', 'l1_shrink_free_l2_clusters', - 'cor_write'] } + 'cor_write', 'none' ] } =20 ## # @BlkdebugIOType: diff --git a/block/blkdebug.c b/block/blkdebug.c index d15b6c5fef..51f07648ba 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -491,6 +491,8 @@ static int blkdebug_open(BlockDriverState *bs, QDict *o= ptions, int flags, goto out; } =20 + bdrv_debug_event(bs, BLKDBG_NONE); + ret =3D 0; out: if (ret < 0) { --=20 2.19.2 From nobody Sat Feb 7 04:57:05 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543859670320625.7923040084249; Mon, 3 Dec 2018 09:54:30 -0800 (PST) Received: from localhost ([::1]:51232 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTsQL-0007pq-3H for importer@patchew.org; Mon, 03 Dec 2018 12:54:25 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45043) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTsOd-0006NH-0g for qemu-devel@nongnu.org; Mon, 03 Dec 2018 12:52:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTsOZ-0007SR-RD for qemu-devel@nongnu.org; Mon, 03 Dec 2018 12:52:38 -0500 Received: from mx1.redhat.com ([209.132.183.28]:43886) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gTsOW-0007N7-C7; Mon, 03 Dec 2018 12:52:32 -0500 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CB09B356F1; Mon, 3 Dec 2018 17:52:28 +0000 (UTC) Received: from localhost (unknown [10.36.118.45]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 3AF921974C; Mon, 3 Dec 2018 17:52:28 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Mon, 3 Dec 2018 18:52:10 +0100 Message-Id: <20181203175211.8230-6-mreitz@redhat.com> In-Reply-To: <20181203175211.8230-1-mreitz@redhat.com> References: <20181203175211.8230-1-mreitz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Mon, 03 Dec 2018 17:52:28 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-next 5/6] blkdebug: Inject errors on .bdrv_co_block_status() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Markus Armbruster , qemu-devel@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Signed-off-by: Max Reitz Reviewed-by: Eric Blake --- qapi/block-core.json | 5 ++++- block/blkdebug.c | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 045206196b..bfe48f71f4 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3041,10 +3041,13 @@ # # @flush: .bdrv_co_flush_to_disk() # +# @block-status: .bdrv_co_block_status() +# # Since: 4.0 ## { 'enum': 'BlkdebugIOType', - 'data': [ 'read', 'write', 'write-zeroes', 'discard', 'flush' ] } + 'data': [ 'read', 'write', 'write-zeroes', 'discard', 'flush', + 'block-status' ] } =20 ## # @BlkdebugInjectErrorOptions: diff --git a/block/blkdebug.c b/block/blkdebug.c index 51f07648ba..b86dfe58b5 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -670,7 +670,15 @@ static int coroutine_fn blkdebug_co_block_status(Block= DriverState *bs, int64_t *map, BlockDriverState **file) { + int err; + assert(QEMU_IS_ALIGNED(offset | bytes, bs->bl.request_alignment)); + + err =3D rule_check(bs, offset, bytes, BLKDEBUGIO_TYPE_BLOCK_STATUS); + if (err) { + return err; + } + return bdrv_co_block_status_from_file(bs, want_zero, offset, bytes, pnum, map, file); } --=20 2.19.2 From nobody Sat Feb 7 04:57:05 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543860196070524.0654279712443; Mon, 3 Dec 2018 10:03:16 -0800 (PST) Received: from localhost ([::1]:51292 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTsYn-0000a0-UU for importer@patchew.org; Mon, 03 Dec 2018 13:03:09 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45092) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTsOg-0006RW-IN for qemu-devel@nongnu.org; Mon, 03 Dec 2018 12:52:43 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTsOf-0007WI-16 for qemu-devel@nongnu.org; Mon, 03 Dec 2018 12:52:42 -0500 Received: from mx1.redhat.com ([209.132.183.28]:39466) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gTsOZ-0007Ru-Rk; Mon, 03 Dec 2018 12:52:36 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D5EA030820C3; Mon, 3 Dec 2018 17:52:34 +0000 (UTC) Received: from localhost (unknown [10.36.118.45]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 27119103BAB6; Mon, 3 Dec 2018 17:52:30 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Mon, 3 Dec 2018 18:52:11 +0100 Message-Id: <20181203175211.8230-7-mreitz@redhat.com> In-Reply-To: <20181203175211.8230-1-mreitz@redhat.com> References: <20181203175211.8230-1-mreitz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.47]); Mon, 03 Dec 2018 17:52:34 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-next 6/6] iotests: Test qemu-img convert --salvage X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Markus Armbruster , qemu-devel@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" This test converts a simple image to another, but blkdebug injects block_status and read faults at some offsets. The resulting image should be the same as the input image, except that sectors that could not be read have to be 0. Signed-off-by: Max Reitz --- tests/qemu-iotests/236 | 164 +++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/236.out | 43 ++++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 208 insertions(+) create mode 100755 tests/qemu-iotests/236 create mode 100644 tests/qemu-iotests/236.out diff --git a/tests/qemu-iotests/236 b/tests/qemu-iotests/236 new file mode 100755 index 0000000000..02b032ebb5 --- /dev/null +++ b/tests/qemu-iotests/236 @@ -0,0 +1,164 @@ +#!/bin/bash +# +# Test qemu-img convert --salvage +# +# Copyright (C) 2018 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# creator +owner=3Dmreitz@redhat.com + +seq=3D$(basename $0) +echo "QA output created by $seq" + +here=3D$PWD +status=3D1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter +. ./common.qemu + +_supported_fmt generic +_supported_proto file +_supported_os Linux + + +TEST_IMG=3D"$TEST_IMG.orig" _make_test_img 64M + +$QEMU_IO -c 'write -P 42 0 64M' "$TEST_IMG.orig" | _filter_qemu_io + + +sector_size=3D512 + +# Offsets on which to fail block-status. Keep in ascending order so +# the indexing done by _filter_offsets will appear in ascending order +# in the output as well. +status_fail_offsets=3D"$((16 * 1024 * 1024 + 8192)) + $((33 * 1024 * 1024 + 512))" + +# Offsets on which to fail reads. Keep in ascending order for the +# same reason. +# Element 1 is shared with $status_fail_offsets on purpose. +# Elements 2 and later test what happens when a continuous range of +# sectors is inaccessible. +read_fail_offsets=3D"$((32 * 1024 * 1024 - 65536)) + $((33 * 1024 * 1024 + 512)) + $(seq $((34 * 1024 * 1024)) $sector_size \ + $((34 * 1024 * 1024 + 4096 - $sector_size)))" + + +# blkdebug must be above the format layer so it can intercept all +# block-status events +source_img=3D"json:{'driver': 'blkdebug', + 'image': { + 'driver': '$IMGFMT', + 'file': { + 'driver': 'file', + 'filename': '$TEST_IMG.orig' + } + }, + 'inject-error': [" + +for ofs in $status_fail_offsets +do + source_img+=3D"{ 'event': 'none', + 'iotype': 'block-status', + 'errno': 5, + 'sector': $((ofs / sector_size)) }," +done + +for ofs in $read_fail_offsets +do + source_img+=3D"{ 'event': 'none', + 'iotype': 'read', + 'errno': 5, + 'sector': $((ofs / sector_size)) }," +done + +# Remove the trailing comma and terminate @inject-error and json:{} +source_img=3D"${source_img%,} ] }" + + +echo + + +_filter_offsets() { + filters=3D + + index=3D0 + for ofs in $2 + do + filters+=3D" -e s/$(printf "$1" $ofs)/status_fail_offset_$index/" + index=3D$((index + 1)) + done + + index=3D0 + for ofs in $3 + do + filters+=3D" -e s/$(printf "$1" $ofs)/read_fail_offset_$index/" + index=3D$((index + 1)) + done + + sed $filters +} + +# While determining the number of allocated sectors in the input +# image, we should see one block status warning per element of +# $status_fail_offsets. +# +# Then, the image is read. Since the block status is queried in +# basically the same way, the same warnings as in the previous step +# should reappear. Interleaved with those we should see a read +# warning per element of $read_fail_offsets. +# Note that $read_fail_offsets and $status_fail_offsets share an +# element (read_fail_offset_1 =3D=3D status_fail_offset_1), so +# "status_fail_offset_1" in the output is the same as +# "read_fail_offset_1". +$QEMU_IMG convert --salvage "$source_img" "$TEST_IMG" 2>&1 \ + | sed -e 's/json:{.*}/SOURCE_IMG/' \ + | _filter_offsets '%#x' "$status_fail_offsets" "$read_fail_offsets" + +echo + +# The offsets where the block status could not be determined should +# have been treated as containing data and thus should be correct in +# the output image. +# The offsets where reading failed altogether should be 0. Make them +# 0 in the input image, too, so we can compare both images. +for ofs in $read_fail_offsets +do + $QEMU_IO -c "write -z $ofs $sector_size" "$TEST_IMG.orig" \ + | _filter_qemu_io \ + | _filter_offsets '%i' '' "$read_fail_offsets" +done + +echo + +# These should be equal now. +$QEMU_IMG compare "$TEST_IMG.orig" "$TEST_IMG" + + +# success, all done +echo "*** done" +rm -f $seq.full +status=3D0 diff --git a/tests/qemu-iotests/236.out b/tests/qemu-iotests/236.out new file mode 100644 index 0000000000..df240685ab --- /dev/null +++ b/tests/qemu-iotests/236.out @@ -0,0 +1,43 @@ +QA output created by 236 +Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=3DIMGFMT size=3D67108864 +wrote 67108864/67108864 bytes at offset 0 +64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +qemu-img: warning: Failed to inquire block status of SOURCE_IMG at offset = status_fail_offset_0: Input/output error +qemu-img: warning: Failed to inquire block status of SOURCE_IMG at offset = status_fail_offset_1: Input/output error +qemu-img: warning: Failed to inquire block status of SOURCE_IMG at offset = status_fail_offset_0: Input/output error +qemu-img: warning: Failed to read offset read_fail_offset_0 from SOURCE_IM= G: Input/output error +qemu-img: warning: Failed to inquire block status of SOURCE_IMG at offset = status_fail_offset_1: Input/output error +qemu-img: warning: Failed to read offset status_fail_offset_1 from SOURCE_= IMG: Input/output error +qemu-img: warning: Failed to read offset read_fail_offset_2 from SOURCE_IM= G: Input/output error +qemu-img: warning: Failed to read offset read_fail_offset_3 from SOURCE_IM= G: Input/output error +qemu-img: warning: Failed to read offset read_fail_offset_4 from SOURCE_IM= G: Input/output error +qemu-img: warning: Failed to read offset read_fail_offset_5 from SOURCE_IM= G: Input/output error +qemu-img: warning: Failed to read offset read_fail_offset_6 from SOURCE_IM= G: Input/output error +qemu-img: warning: Failed to read offset read_fail_offset_7 from SOURCE_IM= G: Input/output error +qemu-img: warning: Failed to read offset read_fail_offset_8 from SOURCE_IM= G: Input/output error +qemu-img: warning: Failed to read offset read_fail_offset_9 from SOURCE_IM= G: Input/output error + +wrote 512/512 bytes at offset read_fail_offset_0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset read_fail_offset_1 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset read_fail_offset_2 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset read_fail_offset_3 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset read_fail_offset_4 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset read_fail_offset_5 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset read_fail_offset_6 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset read_fail_offset_7 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset read_fail_offset_8 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset read_fail_offset_9 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +Images are identical. +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 61a6d98ebd..f6b245917a 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -233,3 +233,4 @@ 233 auto quick 234 auto quick migration 235 auto quick +236 auto quick --=20 2.19.2