From patchwork Tue Jan 4 14:33:29 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juan Quintela X-Patchwork-Id: 77477 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id E7A9DB6EE9 for ; Wed, 5 Jan 2011 01:36:02 +1100 (EST) Received: from localhost ([127.0.0.1]:57807 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Pa7zS-0000C7-ER for incoming@patchwork.ozlabs.org; Tue, 04 Jan 2011 09:35:58 -0500 Received: from [140.186.70.92] (port=41248 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Pa7y7-000091-De for qemu-devel@nongnu.org; Tue, 04 Jan 2011 09:34:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Pa7y5-0004ZV-Bz for qemu-devel@nongnu.org; Tue, 04 Jan 2011 09:34:35 -0500 Received: from mx1.redhat.com ([209.132.183.28]:26772) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Pa7y5-0004ZL-4l for qemu-devel@nongnu.org; Tue, 04 Jan 2011 09:34:33 -0500 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id p04EYWh1024833 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 4 Jan 2011 09:34:32 -0500 Received: from neno.mitica (ovpn-113-93.phx2.redhat.com [10.3.113.93]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p04EYQ24004900; Tue, 4 Jan 2011 09:34:31 -0500 From: Juan Quintela To: qemu-devel@nongnu.org Date: Tue, 4 Jan 2011 15:33:29 +0100 Message-Id: <7fef2ab89110849603902ac62d8c164cd3ff01d2.1294150511.git.quintela@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. Subject: [Qemu-devel] [PATCH 4/5] Reopen files after migration X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org We need to invalidate the Read Cache on the destination, otherwise we have corruption. Easy way to reproduce it is: - create an qcow2 images - start qemu on destination of migration (qemu .... -incoming tcp:...) - start qemu on source of migration and do one install. - migrate at the end of install (when lot of disk IO has happened). Destination of migration has a local copy of the L1/L2 tables that existed at the beginning, before the install started. We have disk corruption at this point. The solution (for NFS) is to just re-open the file. Operations have to happen in this order: - source of migration: flush() - destination: close(file); - destination: open(file) it is not necesary that source of migration close the file. Signed-off-by: Juan Quintela --- blockdev.c | 42 +++++++++++++++++++++++++++++++++++++----- blockdev.h | 6 ++++++ migration.c | 6 ++++++ 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/blockdev.c b/blockdev.c index f9bb659..3f3df7a 100644 --- a/blockdev.c +++ b/blockdev.c @@ -116,6 +116,7 @@ void drive_uninit(DriveInfo *dinfo) bdrv_delete(dinfo->bdrv); QTAILQ_REMOVE(&drives, dinfo, next); qemu_free(dinfo->id); + qemu_free(dinfo->file); qemu_free(dinfo); } @@ -136,6 +137,36 @@ static int parse_block_error_action(const char *buf, int is_read) } } +static int drive_open(DriveInfo *dinfo) +{ + int res = bdrv_open(dinfo->bdrv, dinfo->file, dinfo->bdrv_flags, dinfo->drv); + + if (res < 0) { + fprintf(stderr, "qemu: could not open disk image %s: %s\n", + dinfo->file, strerror(errno)); + } + return res; +} + +int drives_reinit(void) +{ + DriveInfo *dinfo; + + QTAILQ_FOREACH(dinfo, &drives, next) { + if (dinfo->opened && !bdrv_is_read_only(dinfo->bdrv)) { + int res; + bdrv_close(dinfo->bdrv); + res = drive_open(dinfo); + if (res) { + fprintf(stderr, "qemu: re-open of %s failed wth error %d\n", + dinfo->file, res); + return res; + } + } + } + return 0; +} + DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error) { const char *buf; @@ -156,7 +187,6 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error) const char *devaddr; DriveInfo *dinfo; int snapshot = 0; - int ret; *fatal_error = 1; @@ -487,10 +517,12 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error) bdrv_flags |= ro ? 0 : BDRV_O_RDWR; - ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv); - if (ret < 0) { - fprintf(stderr, "qemu: could not open disk image %s: %s\n", - file, strerror(-ret)); + dinfo->file = qemu_strdup(file); + dinfo->bdrv_flags = bdrv_flags; + dinfo->drv = drv; + dinfo->opened = 1; + + if (drive_open(dinfo) < 0) { goto error; } diff --git a/blockdev.h b/blockdev.h index 4536b5c..e009fee 100644 --- a/blockdev.h +++ b/blockdev.h @@ -29,6 +29,10 @@ struct DriveInfo { QemuOpts *opts; char serial[BLOCK_SERIAL_STRLEN + 1]; QTAILQ_ENTRY(DriveInfo) next; + int opened; + int bdrv_flags; + char *file; + BlockDriver *drv; }; #define MAX_IDE_DEVS 2 @@ -42,6 +46,8 @@ DriveInfo *drive_get_by_blockdev(BlockDriverState *bs); QemuOpts *drive_add(const char *file, const char *fmt, ...) GCC_FMT_ATTR(2, 3); DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi, int *fatal_error); +extern int drives_reinit(void); + /* device-hotplug */ DriveInfo *add_init_drive(const char *opts); diff --git a/migration.c b/migration.c index a8b65e5..fdff804 100644 --- a/migration.c +++ b/migration.c @@ -17,6 +17,7 @@ #include "buffered_file.h" #include "sysemu.h" #include "block.h" +#include "blockdev.h" #include "qemu_socket.h" #include "block-migration.h" #include "qemu-objects.h" @@ -69,6 +70,11 @@ void process_incoming_migration(QEMUFile *f) incoming_expected = false; + if (drives_reinit() != 0) { + fprintf(stderr, "reopening of drives failed\n"); + exit(1); + } + if (autostart) vm_start(); }