Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 340e01248478ba8b78a6d4d1809b1eff > files > 376

kvm-83-270.el5_11.src.rpm

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