From patchwork Wed Mar 11 10:28:13 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Denis V. Lunev" X-Patchwork-Id: 448926 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 9FEDE140157 for ; Wed, 11 Mar 2015 21:38:44 +1100 (AEDT) Received: from localhost ([::1]:53664 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YVe2E-0002Pc-KN for incoming@patchwork.ozlabs.org; Wed, 11 Mar 2015 06:38:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34568) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YVdrm-0008Sr-C7 for qemu-devel@nongnu.org; Wed, 11 Mar 2015 06:27:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YVdrf-0003xD-7h for qemu-devel@nongnu.org; Wed, 11 Mar 2015 06:27:54 -0400 Received: from mailhub.sw.ru ([195.214.232.25]:25641 helo=relay.sw.ru) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YVdre-0003tz-KE for qemu-devel@nongnu.org; Wed, 11 Mar 2015 06:27:46 -0400 Received: from hades.sw.ru ([10.30.8.132]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id t2BARgbf017637; Wed, 11 Mar 2015 13:27:43 +0300 (MSK) From: "Denis V. Lunev" To: Date: Wed, 11 Mar 2015 13:28:13 +0300 Message-Id: <1426069701-1405-20-git-send-email-den@openvz.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1426069701-1405-1-git-send-email-den@openvz.org> References: <1426069701-1405-1-git-send-email-den@openvz.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.0 [fuzzy] X-Received-From: 195.214.232.25 Cc: Kevin Wolf , "Denis V. Lunev" , qemu-devel@nongnu.org, Stefan Hajnoczi Subject: [Qemu-devel] [PATCH 19/27] block/parallels: implement incorrect close detection 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 The software driver must set inuse field in Parallels header to 0x746F6E59 when the image is opened in read-write mode. The presence of this magic in the header on open forces image consistency check. There is an unfortunate trick here. We can not check for inuse in parallels_check as this will happen too late. It is possible to do that for simple check, but during the fix this would always report an error as the image was opened in BDRV_O_RDWR mode. Thus we save the flag in BDRVParallelsState for this. On the other hand, nothing should be done to clear inuse in parallels_check. Generic close will do the job right. Signed-off-by: Denis V. Lunev Reviewed-by: Roman Kagan CC: Kevin Wolf CC: Stefan Hajnoczi Reviewed-by: Stefan Hajnoczi --- block/parallels.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/block/parallels.c b/block/parallels.c index 0e5d4c3..bafc74b 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -36,6 +36,7 @@ #define HEADER_MAGIC "WithoutFreeSpace" #define HEADER_MAGIC2 "WithouFreSpacExt" #define HEADER_VERSION 2 +#define HEADER_INUSE_MAGIC (0x746F6E59) #define DEFAULT_CLUSTER_SIZE 1048576 /* 1 MiB */ @@ -59,6 +60,8 @@ typedef struct BDRVParallelsState { ParallelsHeader *header; uint32_t header_size; + bool header_unclean; + uint32_t *bat_bitmap; unsigned int bat_size; @@ -246,6 +249,17 @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res, return size; } + if (s->header_unclean) { + fprintf(stderr, "%s image was not closed correctly\n", + fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR"); + res->corruptions++; + if (fix & BDRV_FIX_ERRORS) { + /* parallels_close will do the job right */ + res->corruptions_fixed++; + s->header_unclean = false; + } + } + res->bfi.total_clusters = s->bat_size; res->bfi.compressed_clusters = 0; /* compression is not supported */ @@ -404,6 +418,17 @@ static int parallels_probe(const uint8_t *buf, int buf_size, return 0; } +static int parallels_update_header(BlockDriverState *bs) +{ + BDRVParallelsState *s = bs->opaque; + unsigned size = MAX(bdrv_opt_mem_align(bs->file), sizeof(ParallelsHeader)); + + if (size > s->header_size) { + size = s->header_size; + } + return bdrv_pwrite_sync(bs->file, 0, s->header, size); +} + static int parallels_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { @@ -468,6 +493,25 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, } s->bat_bitmap = (uint32_t *)(s->header + 1); + if (le32_to_cpu(ph.inuse) == HEADER_INUSE_MAGIC) { + /* Image was not closed correctly. The check is mandatory */ + s->header_unclean = true; + if ((flags & BDRV_O_RDWR) && !(flags & BDRV_O_CHECK)) { + error_setg(errp, "parallels: Image was not closed correctly; " + "cannot be opened read/write"); + ret = -EACCES; + goto fail; + } + } + + if (flags & BDRV_O_RDWR) { + s->header->inuse = cpu_to_le32(HEADER_INUSE_MAGIC); + ret = parallels_update_header(bs); + if (ret < 0) { + goto fail; + } + } + qemu_co_mutex_init(&s->lock); return 0; @@ -483,6 +527,12 @@ fail: static void parallels_close(BlockDriverState *bs) { BDRVParallelsState *s = bs->opaque; + + if (bs->open_flags & BDRV_O_RDWR) { + s->header->inuse = 0; + parallels_update_header(bs); + } + qemu_vfree(s->header); }