From: Max Reitz <mreitz@redhat.com>
To: Kevin Wolf <kwolf@redhat.com>
Cc: qemu-devel@nongnu.org, "Stefan Hajnoczi" <stefanha@redhat.com>,
"Benoît Canet" <benoit.canet@nodalink.com>
Subject: Re: [Qemu-devel] [PATCH v6 06/11] qcow2: Fix refcount blocks beyond image end
Date: Tue, 21 Oct 2014 09:14:02 +0200 [thread overview]
Message-ID: <544607BA.2010206@redhat.com> (raw)
In-Reply-To: <20141020164420.GT3585@noname.redhat.com>
On 2014-10-20 at 18:44, Kevin Wolf wrote:
> Am 20.10.2014 um 16:35 hat Max Reitz geschrieben:
>> If the qcow2 check function detects a refcount block located beyond the
>> image end, grow the image appropriately. This cannot break anything and
>> is the logical fix for such a case.
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> Reviewed-by: Eric Blake <eblake@redhat.com>
>> ---
>> block/qcow2-refcount.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++----
>> 1 file changed, 58 insertions(+), 4 deletions(-)
>>
>> diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
>> index 55a539f..0225769 100644
>> --- a/block/qcow2-refcount.c
>> +++ b/block/qcow2-refcount.c
>> @@ -1544,7 +1544,8 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
>> int64_t *nb_clusters)
>> {
>> BDRVQcowState *s = bs->opaque;
>> - int64_t i;
>> + int64_t i, size;
>> + int ret;
>>
>> for(i = 0; i < s->refcount_table_size; i++) {
>> uint64_t offset, cluster;
>> @@ -1560,9 +1561,62 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
>> }
>>
>> if (cluster >= *nb_clusters) {
>> - fprintf(stderr, "ERROR refcount block %" PRId64
>> - " is outside image\n", i);
>> - res->corruptions++;
>> + fprintf(stderr, "%s refcount block %" PRId64 " is outside image\n",
>> + fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", i);
>> +
>> + if (fix & BDRV_FIX_ERRORS) {
>> + int64_t old_nb_clusters = *nb_clusters;
>> +
>> + if (offset + s->cluster_size < offset ||
>> + offset + s->cluster_size > INT64_MAX)
> I _think_ this code is correct because offset is unsigned, but it would
> be easier and not rely on overflow semantics like this:
>
> if (offset > INT64_MAX - s->cluster_size)
Okay.
>> + {
>> + ret = -EINVAL;
>> + goto resize_fail;
>> + }
>> +
>> + ret = bdrv_truncate(bs->file, offset + s->cluster_size);
>> + if (ret < 0) {
>> + goto resize_fail;
>> + }
>> + size = bdrv_getlength(bs->file);
>> + if (size < 0) {
>> + ret = size;
>> + goto resize_fail;
>> + }
>> +
>> + *nb_clusters = size_to_clusters(s, size);
>> + assert(*nb_clusters >= old_nb_clusters);
>> +
>> + *refcount_table = g_try_realloc(*refcount_table,
>> + *nb_clusters * sizeof(uint16_t));
>> + if (!*refcount_table) {
>> + res->check_errors++;
>> + return -ENOMEM;
>> + }
>> +
>> + memset(*refcount_table + old_nb_clusters, 0,
>> + (*nb_clusters - old_nb_clusters) * sizeof(uint16_t));
> Considering the comments you got in previous comments,
> sizeof(**refcount_table) might make it more obvious what's going on, and
> would also be more robust against later changes of the type.
I highly doubt I'll change the type so that sizeof(**refcount_table)
works. If variable refcounts are implemented, I'll probably make
*refcount_table just a void * and then access its elements through a
function; sadly, qemu's make doesn't error out against sizeof(void)
(which would be -Wpointer-arith or just -pedantic), so just using
sizeof(**refcount_table) so that everything throws an error once it's a
void ** won't work.
I guess I'll change it in a v7 because sizeof(**refcount_table) is
easier to grep for than sizeof(uint16_t).
>> + if (cluster >= *nb_clusters) {
>> + ret = -EINVAL;
>> + goto resize_fail;
>> + }
>> +
>> + res->corruptions_fixed++;
>> + inc_refcounts(bs, res, *refcount_table, *nb_clusters,
>> + offset, s->cluster_size);
>> + /* No need to check whether the refcount is now greater than 1:
>> + * This area was just allocated and zeroed, so it can only be
>> + * exactly 1 after inc_refcounts() */
>> + continue;
>> +
>> +resize_fail:
>> + res->corruptions++;
>> + fprintf(stderr, "ERROR could not resize image: %s\n",
>> + strerror(-ret));
>> + } else {
>> + res->corruptions++;
>> + }
>> continue;
>> }
> Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Thanks!
Max
next prev parent reply other threads:[~2014-10-21 7:14 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-20 14:35 [Qemu-devel] [PATCH v6 00/11] qcow2: Fix image repairing Max Reitz
2014-10-20 14:35 ` [Qemu-devel] [PATCH v6 01/11] qcow2: Calculate refcount block entry count Max Reitz
2014-10-20 14:35 ` [Qemu-devel] [PATCH v6 02/11] qcow2: Fix leaks in dirty images Max Reitz
2014-10-20 14:35 ` [Qemu-devel] [PATCH v6 03/11] qcow2: Split qcow2_check_refcounts() Max Reitz
2014-10-20 14:35 ` [Qemu-devel] [PATCH v6 04/11] qcow2: Pull check_refblocks() up Max Reitz
2014-10-20 15:07 ` Kevin Wolf
2014-10-20 14:35 ` [Qemu-devel] [PATCH v6 05/11] qcow2: Reuse refcount table in calculate_refcounts() Max Reitz
2014-10-20 15:09 ` Kevin Wolf
2014-10-20 14:35 ` [Qemu-devel] [PATCH v6 06/11] qcow2: Fix refcount blocks beyond image end Max Reitz
2014-10-20 16:44 ` Kevin Wolf
2014-10-21 7:14 ` Max Reitz [this message]
2014-10-20 14:35 ` [Qemu-devel] [PATCH v6 07/11] qcow2: Do not perform potentially damaging repairs Max Reitz
2014-10-21 7:52 ` Kevin Wolf
2014-10-21 10:10 ` Max Reitz
2014-10-20 14:35 ` [Qemu-devel] [PATCH v6 08/11] qcow2: Rebuild refcount structure during check Max Reitz
2014-10-21 9:31 ` Kevin Wolf
2014-10-21 9:52 ` Max Reitz
2014-10-21 10:12 ` Kevin Wolf
2014-10-20 14:35 ` [Qemu-devel] [PATCH v6 09/11] qcow2: Clean up after refcount rebuild Max Reitz
2014-10-21 9:59 ` Kevin Wolf
2014-10-21 10:16 ` Max Reitz
2014-10-21 14:55 ` Max Reitz
2014-10-21 15:11 ` Kevin Wolf
2014-10-21 15:17 ` Max Reitz
2014-10-20 14:35 ` [Qemu-devel] [PATCH v6 10/11] iotests: Fix test outputs Max Reitz
2014-10-21 13:42 ` Kevin Wolf
2014-10-20 14:35 ` [Qemu-devel] [PATCH v6 11/11] iotests: Add test for potentially damaging repairs Max Reitz
2014-10-21 14:12 ` Kevin Wolf
2014-10-21 14:20 ` Max Reitz
2014-10-21 15:16 ` Kevin Wolf
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=544607BA.2010206@redhat.com \
--to=mreitz@redhat.com \
--cc=benoit.canet@nodalink.com \
--cc=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/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.