From 28409ef05260973788a1ca3c4a41350db6a49f90 Mon Sep 17 00:00:00 2001 Message-Id: <28409ef05260973788a1ca3c4a41350db6a49f90.1429902956.git.jen@redhat.com> In-Reply-To: <67968bc615637394c3ef7dfefa360dab90f33d5d.1429902956.git.jen@redhat.com> References: <67968bc615637394c3ef7dfefa360dab90f33d5d.1429902956.git.jen@redhat.com> From: Max Reitz Date: Wed, 18 Mar 2015 19:21:57 -0500 Subject: [CHANGE 14/42] qcow2: Add qcow2_signal_corruption() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To: rhvirt-patches@redhat.com, jen@redhat.com RH-Author: Max Reitz Message-id: <1426706542-30384-15-git-send-email-mreitz@redhat.com> Patchwork-id: 64478 O-Subject: [RHEL-6.7 qemu-kvm PATCH v2 14/39] qcow2: Add qcow2_signal_corruption() Bugzilla: 1129892 RH-Acked-by: Jeffrey Cody RH-Acked-by: Kevin Wolf RH-Acked-by: Stefan Hajnoczi BZ: 1129892 Add a helper function for easily marking an image corrupt (on fatal corruptions) while outputting an informative message to stderr and via QAPI. Signed-off-by: Max Reitz Reviewed-by: Eric Blake Reviewed-by: BenoƮt Canet Message-id: 1409926039-29044-3-git-send-email-mreitz@redhat.com Signed-off-by: Stefan Hajnoczi (cherry picked from commit 85186ebdac7e183242deaa55d5049988de832be1) Signed-off-by: Jeff E. Nelson Conflicts: block/qcow2.c block/qcow2.h Different handling of QMP events downstream and different reaction to fatal corruptions: The image cannot be marked corrupt, it can only be made unusable for this QEMU instance, and because there is no corruption flag, the new function requires an additional flag for determining whether a fatal corruption has been signaled before. Not having nice event emission function downstreams means preparing the JSON format string manually; because both 'offset' and 'size' are optional, this would in theory result in four different combinations. In practice, 'offset' and 'size' are both either given or not, though, which reduces the number of combinations to a much nicer two. Signed-off-by: Max Reitz --- block/qcow2.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ block/qcow2.h | 5 +++++ 2 files changed, 67 insertions(+) Signed-off-by: Jeff E. Nelson --- block/qcow2.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ block/qcow2.h | 5 +++++ 2 files changed, 67 insertions(+) diff --git a/block/qcow2.c b/block/qcow2.c index aaf2729..b2c175f 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -31,6 +31,8 @@ #include "qerror.h" #include "qapi/util.h" #include "qapi-visit.h" +#include "qemu-objects.h" +#include "monitor.h" /* Differences with QCOW: @@ -1488,6 +1490,66 @@ static int qcow2_load_vmstate(BlockDriverState *bs, uint8_t *buf, return ret; } +/* + * If offset or size are negative, respectively, they will not be included in + * the BLOCK_IMAGE_CORRUPTED event emitted. + * fatal will be ignored for read-only BDS; corruptions found there will always + * be considered non-fatal. + */ +void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset, + int64_t size, const char *message_format, ...) +{ + BDRVQcowState *s = bs->opaque; + char *message; + QObject *data; + va_list ap; + + fatal = fatal && !bs->read_only; + + if (fatal ? s->signaled_fatal_corruption : s->signaled_corruption) { + return; + } + + va_start(ap, message_format); + message = g_strdup_vprintf(message_format, ap); + va_end(ap); + + if (fatal) { + fprintf(stderr, "qcow2: Image is corrupt (further access will be " + "prevented): %s; please use qemu-img check -r. Further " + "corruption events will be suppressed\n", message); + } else { + fprintf(stderr, "qcow2: Image is corrupt: %s; please use qemu-img " + "check -r. Further non-fatal corruption events will be " + "suppressed\n", message); + } + + assert((offset >= 0) == (size >= 0)); + + if (offset >= 0) { + data = qobject_from_jsonf("{ 'device': %s, 'msg': %s, 'offset': %" + PRId64 ", 'size': %" PRId64 ", 'fatal': %s }", + bdrv_get_device_name(bs), message, + offset, size, fatal ? "true" : "false"); + } else { + data = qobject_from_jsonf("{ 'device': %s, 'msg': %s, 'fatal': %s }", + bdrv_get_device_name(bs), message, + fatal ? "true" : "false"); + } + + monitor_protocol_event(QEVENT_BLOCK_IMAGE_CORRUPTED, data); + qobject_decref(data); + + g_free(message); + + if (fatal) { + bs->drv = NULL; /* make BDS unusable */ + s->signaled_fatal_corruption = true; + } + + s->signaled_corruption = true; +} + static QEMUOptionParameter qcow2_create_options[] = { { .name = BLOCK_OPT_SIZE, diff --git a/block/qcow2.h b/block/qcow2.h index 10b9c0a..767f373 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -165,6 +165,7 @@ typedef struct BDRVQcowState { QCowSnapshot *snapshots; int overlap_check; /* bitmask of Qcow2MetadataOverlap values */ + bool signaled_corruption, signaled_fatal_corruption; QLIST_HEAD(, Qcow2UnknownHeaderExtension) unknown_header_ext; } BDRVQcowState; @@ -297,6 +298,10 @@ int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov, int64_t sector_num, int nb_sectors); int qcow2_update_header(BlockDriverState *bs); +void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset, + int64_t size, const char *message_format, ...) + GCC_FMT_ATTR(5, 6); + /* qcow2-refcount.c functions */ int qcow2_refcount_init(BlockDriverState *bs); void qcow2_refcount_close(BlockDriverState *bs); -- 2.1.0