From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 05/29] qcow2: Repair unaligned preallocated zero clusters
Date: Tue, 23 Jan 2018 15:01:37 +0100 [thread overview]
Message-ID: <20180123140201.31163-6-kwolf@redhat.com> (raw)
In-Reply-To: <20180123140201.31163-1-kwolf@redhat.com>
From: Max Reitz <mreitz@redhat.com>
We can easily repair unaligned preallocated zero clusters by discarding
them, so why not do it?
Signed-off-by: Max Reitz <mreitz@redhat.com>
Message-id: 20171110203759.14018-2-mreitz@redhat.com
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block/qcow2-refcount.c | 70 ++++++++++++++++++++++++++++++++++++++--------
tests/qemu-iotests/060 | 3 +-
tests/qemu-iotests/060.out | 9 ++++++
3 files changed, 69 insertions(+), 13 deletions(-)
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 3de1ab51ba..92701ab7af 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1508,7 +1508,7 @@ enum {
static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
void **refcount_table,
int64_t *refcount_table_size, int64_t l2_offset,
- int flags)
+ int flags, BdrvCheckMode fix)
{
BDRVQcow2State *s = bs->opaque;
uint64_t *l2_table, l2_entry;
@@ -1579,6 +1579,57 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
next_contiguous_offset = offset + s->cluster_size;
}
+ /* Correct offsets are cluster aligned */
+ if (offset_into_cluster(s, offset)) {
+ if (qcow2_get_cluster_type(l2_entry) ==
+ QCOW2_CLUSTER_ZERO_ALLOC)
+ {
+ fprintf(stderr, "%s offset=%" PRIx64 ": Preallocated zero "
+ "cluster is not properly aligned; L2 entry "
+ "corrupted.\n",
+ fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR",
+ offset);
+ if (fix & BDRV_FIX_ERRORS) {
+ uint64_t l2e_offset =
+ l2_offset + (uint64_t)i * sizeof(uint64_t);
+
+ l2_entry = QCOW_OFLAG_ZERO;
+ l2_table[i] = cpu_to_be64(l2_entry);
+ ret = qcow2_pre_write_overlap_check(bs,
+ QCOW2_OL_ACTIVE_L2 | QCOW2_OL_INACTIVE_L2,
+ l2e_offset, sizeof(uint64_t));
+ if (ret < 0) {
+ fprintf(stderr, "ERROR: Overlap check failed\n");
+ res->check_errors++;
+ /* Something is seriously wrong, so abort checking
+ * this L2 table */
+ goto fail;
+ }
+
+ ret = bdrv_pwrite_sync(bs->file, l2e_offset,
+ &l2_table[i], sizeof(uint64_t));
+ if (ret < 0) {
+ fprintf(stderr, "ERROR: Failed to overwrite L2 "
+ "table entry: %s\n", strerror(-ret));
+ res->check_errors++;
+ /* Do not abort, continue checking the rest of this
+ * L2 table's entries */
+ } else {
+ res->corruptions_fixed++;
+ /* Skip marking the cluster as used
+ * (it is unused now) */
+ continue;
+ }
+ } else {
+ res->corruptions++;
+ }
+ } else {
+ fprintf(stderr, "ERROR offset=%" PRIx64 ": Data cluster is "
+ "not properly aligned; L2 entry corrupted.\n", offset);
+ res->corruptions++;
+ }
+ }
+
/* Mark cluster as used */
ret = qcow2_inc_refcounts_imrt(bs, res,
refcount_table, refcount_table_size,
@@ -1586,13 +1637,6 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
if (ret < 0) {
goto fail;
}
-
- /* Correct offsets are cluster aligned */
- if (offset_into_cluster(s, offset)) {
- fprintf(stderr, "ERROR offset=%" PRIx64 ": Cluster is not "
- "properly aligned; L2 entry corrupted.\n", offset);
- res->corruptions++;
- }
break;
}
@@ -1626,7 +1670,7 @@ static int check_refcounts_l1(BlockDriverState *bs,
void **refcount_table,
int64_t *refcount_table_size,
int64_t l1_table_offset, int l1_size,
- int flags)
+ int flags, BdrvCheckMode fix)
{
BDRVQcow2State *s = bs->opaque;
uint64_t *l1_table = NULL, l2_offset, l1_size2;
@@ -1681,7 +1725,8 @@ static int check_refcounts_l1(BlockDriverState *bs,
/* Process and check L2 entries */
ret = check_refcounts_l2(bs, res, refcount_table,
- refcount_table_size, l2_offset, flags);
+ refcount_table_size, l2_offset, flags,
+ fix);
if (ret < 0) {
goto fail;
}
@@ -1957,7 +2002,8 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
/* current L1 table */
ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters,
- s->l1_table_offset, s->l1_size, CHECK_FRAG_INFO);
+ s->l1_table_offset, s->l1_size, CHECK_FRAG_INFO,
+ fix);
if (ret < 0) {
return ret;
}
@@ -1966,7 +2012,7 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
for (i = 0; i < s->nb_snapshots; i++) {
sn = s->snapshots + i;
ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters,
- sn->l1_table_offset, sn->l1_size, 0);
+ sn->l1_table_offset, sn->l1_size, 0, fix);
if (ret < 0) {
return ret;
}
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
index 14797dd3b0..6c7407f499 100755
--- a/tests/qemu-iotests/060
+++ b/tests/qemu-iotests/060
@@ -335,7 +335,8 @@ poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x00\x2a\x01"
# Let's write to it!
$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io
-# Can't repair this yet (TODO: We can just deallocate the cluster)
+echo '--- Repairing ---'
+_check_test_img -r all
echo
echo '=== Discarding with an unaligned refblock ==='
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
index c4cb7c665e..25d5c3938b 100644
--- a/tests/qemu-iotests/060.out
+++ b/tests/qemu-iotests/060.out
@@ -317,6 +317,15 @@ discard 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qcow2: Marking image as corrupt: Preallocated zero cluster offset 0x2a00 unaligned (guest offset: 0); further corruption events will be suppressed
write failed: Input/output error
+--- Repairing ---
+Repairing offset=2a00: Preallocated zero cluster is not properly aligned; L2 entry corrupted.
+The following inconsistencies were found and repaired:
+
+ 0 leaked clusters
+ 1 corruptions
+
+Double checking the fixed image now...
+No errors were found on the image.
=== Discarding with an unaligned refblock ===
--
2.13.6
next prev parent reply other threads:[~2018-01-23 14:02 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-23 14:01 [Qemu-devel] [PULL 00/29] Block layer patches Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 01/29] osdep: Retry SETLK upon EINTR Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 02/29] hw/block: Fix pin-based interrupt behaviour of NVMe Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 03/29] tests/.gitignore: Add test-bdrv-drain Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 04/29] tests/qemu-iotests: adding savevm/loadvm with postcopy flag test Kevin Wolf
2018-01-23 14:01 ` Kevin Wolf [this message]
2018-01-23 14:01 ` [Qemu-devel] [PULL 06/29] iotests: Make BD-{remove, insert}-medium use @id Kevin Wolf
2018-02-12 11:16 ` Christian Borntraeger
2018-02-12 11:33 ` Christian Borntraeger
2018-02-12 12:34 ` Max Reitz
2018-01-23 14:01 ` [Qemu-devel] [PULL 07/29] tests/ahci: Switch tray and medium commands to @id Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 08/29] blockdev: Drop BD-{remove, insert}-medium's @device Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 09/29] blockdev: Mark BD-{remove, insert}-medium stable Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 10/29] qemu-iotests: Fix locking issue in 102 Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 11/29] block/vmdk: Fix , instead of ; at end of line Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 12/29] qcow2: No persistent dirty bitmaps for compat=0.10 Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 13/29] block/qcow: Add blkdebug events Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 14/29] block/vmdk: " Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 15/29] iotests: Fix _img_info for backslashes Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 16/29] iotests: Drop format-specific in _filter_img_info Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 17/29] iotests: Forbid 020 for non-file protocols Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 18/29] iotests: Skip 103 for refcount_bits=1 Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 19/29] iotests: Fix 020 for vmdk Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 20/29] iotests: Fix 051 for compat=0.10 Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 21/29] iotests: Fix 059's reference output Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 22/29] iotests: Fix 067 for compat=0.10 Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 23/29] iotests: Make 089 compatible with compat=0.10 Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 24/29] iotests: Make 184 image-less Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 25/29] iotests: Make 191 work with qcow2 options Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 26/29] iotests: Filter compat-dependent info in 198 Kevin Wolf
2018-01-23 14:01 ` [Qemu-devel] [PULL 27/29] iotests: Make 059 pass on machines with little RAM Kevin Wolf
2018-01-23 14:02 ` [Qemu-devel] [PULL 28/29] iotests: Split 177 into two parts for compat=0.10 Kevin Wolf
2018-01-23 14:02 ` [Qemu-devel] [PULL 29/29] iotests: Disable some tests " Kevin Wolf
2018-01-25 9:53 ` [Qemu-devel] [PULL 00/29] Block layer patches Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180123140201.31163-6-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.