From c49782a51ece39446c434273d37fcb05567d874d Mon Sep 17 00:00:00 2001 From: Xiao Wang <jasowang@redhat.com> Date: Thu, 2 Jun 2011 05:20:24 -0300 Subject: [PATCH] floppy: save and restore DIR register RH-Author: Xiao Wang <jasowang@redhat.com> Message-id: <20110602052024.11619.9832.stgit@dhcp-8-149.nay.redhat.com> Patchwork-id: 26206 O-Subject: [RHEL5.7 V2 PATCH] floppy: save and restore DIR register Bugzilla: 699370 RH-Acked-by: Juan Quintela <quintela@redhat.com> RH-Acked-by: Markus Armbruster <armbru@redhat.com> RH-Acked-by: Michael S. Tsirkin <mst@redhat.com> Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=699370 Upstream: a backport of 7d905f716bea633f2836e1d661387983aacdc6d6 Test status: Tested in my local desktop We need to keep DIR register unchanged across migration, but currently it depends on the media_changed flags from block layer. Since we do not save/restore it and the bdrv_open() called in dest node may set the media_changed flag when trying to open floppy image, guest driver may think floppy have changed after migration. To fix this, we need to pass the media_changed during migration. Notes: - Since RHEL5 does not have subsections, I just use the register_optional_savevm() interface as a substitute for upstream subsections. This would make sure the to keep compatibility in normal cases. - As there's no vmstate support in RHEL5, all media_changed flags was migrated together. - Since drives_reopen() in RHEL5 also call bdrv_close()/bdrv_open() which may touch media_changed flag after migration. I simply cache it there to make sure its value was not changed after drives_reopen(). Changes from V1: Comments from Markus: - convert tabs to spaces - Safe cast by using drive->bs->media_changed != 0 Signed-off-by: Jason Wang <jasowang@redhat.com> --- 0 files changed, 0 insertions(+), 0 deletions(-) Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> --- qemu/hw/fdc.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu/vl.c | 3 +++ 2 files changed, 58 insertions(+), 0 deletions(-) diff --git a/qemu/hw/fdc.c b/qemu/hw/fdc.c index dd87a13..223076b 100644 --- a/qemu/hw/fdc.c +++ b/qemu/hw/fdc.c @@ -31,6 +31,7 @@ #include "block.h" #include "qemu-timer.h" #include "isa.h" +#include "block_int.h" /********************************************************/ /* debug Floppy devices */ @@ -508,6 +509,55 @@ struct fdctrl_t { fdrive_t drives[MAX_FD]; }; +static void fdctrl_media_changed_save(QEMUFile *f, void *opaque, int version_id) +{ + fdctrl_t *fdctrl = opaque; + int i; + + for (i = 0; i < MAX_FD; i++) { + fdrive_t *drive = &fdctrl->drives[i]; + if (drive->bs != NULL) { + qemu_put_ubyte(f, (uint8_t)(drive->bs->media_changed != 0)); + } else { + /* no drive, put a hint to let dest know about this. */ + qemu_put_ubyte(f, 2u); + } + } +} + +static int fdctrl_media_changed_load(QEMUFile *f, void *opaque, int version_id) +{ + fdctrl_t *fdctrl = opaque; + int i; + + for (i = 0; i < MAX_FD; i++) { + fdrive_t *drive = &fdctrl->drives[i]; + uint8_t changed = qemu_get_ubyte(f); + if (changed == 2 || drive->bs == NULL) { + /* no drive in either src or dst */ + continue; + } else { + drive->bs->media_changed = changed; + } + } + + return 0; +} + +static int fdctrl_media_changed_needed(void *opaque) +{ + fdctrl_t *fdctrl = opaque; + int i; + + for (i = 0; i < MAX_FD; i++) { + fdrive_t *drive = &fdctrl->drives[i]; + if (drive->bs != NULL && drive->bs->media_changed != 1) { + return 1; + } + } + return 0; +} + static uint32_t fdctrl_read (void *opaque, uint32_t reg) { fdctrl_t *fdctrl = opaque; @@ -1883,6 +1933,11 @@ static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann, } fdctrl_external_reset(fdctrl); register_savevm("fdc", io_base, 2, fdc_save, fdc_load, fdctrl); + register_optional_savevm("fdc/media_changed", 0, 1, + fdctrl_media_changed_save, + fdctrl_media_changed_load, + fdctrl_media_changed_needed, + fdctrl); qemu_register_reset(fdctrl_external_reset, fdctrl); for (i = 0; i < MAX_FD; i++) { fd_revalidate(&fdctrl->drives[i]); diff --git a/qemu/vl.c b/qemu/vl.c index 781f11c..1685d48 100644 --- a/qemu/vl.c +++ b/qemu/vl.c @@ -47,6 +47,7 @@ #include "kvm.h" #include "balloon.h" #include "qemu-kvm.h" +#include "block_int.h" #include <unistd.h> #include <fcntl.h> @@ -2798,9 +2799,11 @@ int drives_reopen(void) for (i=0; i < nb_drives; i++) if (drives_table[i].used && drives_table[i].opened) { int res; + int media_changed = drives_table[i].bdrv->media_changed; bdrv_close(drives_table[i].bdrv); res = drive_open(drives_table[i]); + drives_table[i].bdrv->media_changed = media_changed; if (res) { fprintf(stderr, "qemu: re-open of %s failed wth error %d\n", drives_table[i].file, res); -- 1.7.3.2