Patchwork Make guest OS bootable when hardware failure happens in log disk

login
register
mail settings
Submitter Seiji Aguchi
Date March 28, 2013, 7:43 p.m.
Message ID <A5ED84D3BB3A384992CBB9C77DEDA4D41AF7CF2C@USINDEM103.corp.hds.com>
Download mbox | patch
Permalink /patch/232173/
State New
Headers show

Comments

Seiji Aguchi - March 28, 2013, 7:43 p.m.
[Problem]
Currently, guest OS's messages can be logged to a local disk of host OS by creating chadevs with options below.
  -chardev file,id=charserial0,path=<log file's path> -device isa-serial,chardev=chardevserial0,id=serial0

When a hardware failure happens in the disk, qemu-kvm can't create the chardevs.
In this case, guest OS doesn't boot up.

Actually, there are users who don't desire that guest OS goes down due to a hardware failure of a log disk only.
Therefore, qemu should offer some way to boot guest OS up even if the log disk is broken.

[Solution]
This patch skips error checks in case where opening a log file and creating chardev fail.

Signed-off-by: Seiji Aguchi <seiji.aguchi@hds.com>
---
 hw/qdev-properties-system.c |    2 +-
 hw/serial-isa.c             |   11 +++++++----
 hw/serial-pci.c             |   27 ++++++++++++++++-----------
 hw/serial.c                 |   33 +++++++++++++++++++--------------
 hw/serial.h                 |    2 +-
 vl.c                        |    4 +++-
 6 files changed, 47 insertions(+), 32 deletions(-)

-- 1.7.1
Paolo Bonzini - March 28, 2013, 11:45 p.m.
Il 28/03/2013 20:43, Seiji Aguchi ha scritto:
> [Problem]
> Currently, guest OS's messages can be logged to a local disk of host OS by creating chadevs with options below.
>   -chardev file,id=charserial0,path=<log file's path> -device isa-serial,chardev=chardevserial0,id=serial0
> 
> When a hardware failure happens in the disk, qemu-kvm can't create the chardevs.
> In this case, guest OS doesn't boot up.
> 
> Actually, there are users who don't desire that guest OS goes down due to a hardware failure of a log disk only.
> Therefore, qemu should offer some way to boot guest OS up even if the log disk is broken.
> 
> [Solution]
> This patch skips error checks in case where opening a log file and creating chardev fail.

This kind of policy does not belong in QEMU.  QEMU should always fail if
it sees a problem.

Your management tool should just open the file outside QEMU, and then
use either /dev/fd/NN or /dev/null as the destination.

Paolo

Patch

diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c
index d9934b5..99eff4f 100644
--- a/hw/qdev-properties-system.c
+++ b/hw/qdev-properties-system.c
@@ -121,7 +121,7 @@  static int parse_chr(DeviceState *dev, const char *str, void **ptr)
 {
     CharDriverState *chr = qemu_chr_find(str);
     if (chr == NULL) {
-        return -ENOENT;
+        return 0;
     }
     if (chr->avail_connections < 1) {
         return -EEXIST;
diff --git a/hw/serial-isa.c b/hw/serial-isa.c
index a630a7d..b6cfa0d 100644
--- a/hw/serial-isa.c
+++ b/hw/serial-isa.c
@@ -46,6 +46,7 @@  static int serial_isa_initfn(ISADevice *dev)
     static int index;
     ISASerialState *isa = DO_UPCAST(ISASerialState, dev, dev);
     SerialState *s = &isa->state;
+    int rc;
 
     if (isa->index == -1) {
         isa->index = index;
@@ -63,11 +64,13 @@  static int serial_isa_initfn(ISADevice *dev)
 
     s->baudbase = 115200;
     isa_init_irq(dev, &s->irq, isa->isairq);
-    serial_init_core(s);
-    qdev_set_legacy_instance_id(&dev->qdev, isa->iobase, 3);
+    rc = serial_init_core(s);
+    if (!rc) {
+        qdev_set_legacy_instance_id(&dev->qdev, isa->iobase, 3);
 
-    memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
-    isa_register_ioport(dev, &s->io, isa->iobase);
+        memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
+        isa_register_ioport(dev, &s->io, isa->iobase);
+    }
     return 0;
 }
 
diff --git a/hw/serial-pci.c b/hw/serial-pci.c
index 954657b..3e8b2d5 100644
--- a/hw/serial-pci.c
+++ b/hw/serial-pci.c
@@ -49,15 +49,18 @@  static int serial_pci_init(PCIDevice *dev)
 {
     PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev);
     SerialState *s = &pci->state;
+    int rc;
 
     s->baudbase = 115200;
-    serial_init_core(s);
+    rc = serial_init_core(s);
 
-    pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
-    s->irq = pci->dev.irq[0];
+    if (!rc) {
+        pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
+        s->irq = pci->dev.irq[0];
 
-    memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
-    pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
+        memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
+        pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
+    }
     return 0;
 }
 
@@ -80,7 +83,7 @@  static int multi_serial_pci_init(PCIDevice *dev)
     PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
     PCIMultiSerialState *pci = DO_UPCAST(PCIMultiSerialState, dev, dev);
     SerialState *s;
-    int i;
+    int i, rc;
 
     switch (pc->device_id) {
     case 0x0003:
@@ -102,11 +105,13 @@  static int multi_serial_pci_init(PCIDevice *dev)
     for (i = 0; i < pci->ports; i++) {
         s = pci->state + i;
         s->baudbase = 115200;
-        serial_init_core(s);
-        s->irq = pci->irqs[i];
-        pci->name[i] = g_strdup_printf("uart #%d", i+1);
-        memory_region_init_io(&s->io, &serial_io_ops, s, pci->name[i], 8);
-        memory_region_add_subregion(&pci->iobar, 8 * i, &s->io);
+        rc = serial_init_core(s);
+        if (!rc) {
+            s->irq = pci->irqs[i];
+            pci->name[i] = g_strdup_printf("uart #%d", i+1);
+            memory_region_init_io(&s->io, &serial_io_ops, s, pci->name[i], 8);
+            memory_region_add_subregion(&pci->iobar, 8 * i, &s->io);
+        }
     }
     return 0;
 }
diff --git a/hw/serial.c b/hw/serial.c
index 0ccc499..ab8929e 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -670,11 +670,11 @@  static void serial_reset(void *opaque)
     qemu_irq_lower(s->irq);
 }
 
-void serial_init_core(SerialState *s)
+int serial_init_core(SerialState *s)
 {
     if (!s->chr) {
         fprintf(stderr, "Can't create serial device, empty char device\n");
-	exit(1);
+        return 1;
     }
 
     s->modem_status_poll = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) serial_update_msl, s);
@@ -684,6 +684,7 @@  void serial_init_core(SerialState *s)
 
     qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
                           serial_event, s);
+    return 0;
 }
 
 void serial_exit_core(SerialState *s)
@@ -713,19 +714,20 @@  SerialState *serial_init(int base, qemu_irq irq, int baudbase,
                          CharDriverState *chr, MemoryRegion *system_io)
 {
     SerialState *s;
+    int rc;
 
     s = g_malloc0(sizeof(SerialState));
 
     s->irq = irq;
     s->baudbase = baudbase;
     s->chr = chr;
-    serial_init_core(s);
-
-    vmstate_register(NULL, base, &vmstate_serial, s);
-
-    memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
-    memory_region_add_subregion(system_io, base, &s->io);
+    rc = serial_init_core(s);
+    if (!rc) {
+        vmstate_register(NULL, base, &vmstate_serial, s);
 
+        memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
+        memory_region_add_subregion(system_io, base, &s->io);
+    }
     return s;
 }
 
@@ -769,6 +771,7 @@  SerialState *serial_mm_init(MemoryRegion *address_space,
                             CharDriverState *chr, enum device_endian end)
 {
     SerialState *s;
+    int rc;
 
     s = g_malloc0(sizeof(SerialState));
 
@@ -777,13 +780,15 @@  SerialState *serial_mm_init(MemoryRegion *address_space,
     s->baudbase = baudbase;
     s->chr = chr;
 
-    serial_init_core(s);
-    vmstate_register(NULL, base, &vmstate_serial, s);
+    rc = serial_init_core(s);
+    if (!rc) {
+        vmstate_register(NULL, base, &vmstate_serial, s);
 
-    memory_region_init_io(&s->io, &serial_mm_ops[end], s,
-                          "serial", 8 << it_shift);
-    memory_region_add_subregion(address_space, base, &s->io);
+        memory_region_init_io(&s->io, &serial_mm_ops[end], s,
+                              "serial", 8 << it_shift);
+        memory_region_add_subregion(address_space, base, &s->io);
 
-    serial_update_msl(s);
+        serial_update_msl(s);
+    }
     return s;
 }
diff --git a/hw/serial.h b/hw/serial.h
index e884499..0ba2332 100644
--- a/hw/serial.h
+++ b/hw/serial.h
@@ -83,7 +83,7 @@  struct SerialState {
 extern const VMStateDescription vmstate_serial;
 extern const MemoryRegionOps serial_io_ops;
 
-void serial_init_core(SerialState *s);
+int serial_init_core(SerialState *s);
 void serial_exit_core(SerialState *s);
 void serial_set_frequency(SerialState *s, uint32_t frequency);
 
diff --git a/vl.c b/vl.c
index 7643f16..62e983e 100644
--- a/vl.c
+++ b/vl.c
@@ -2348,7 +2348,9 @@  static int chardev_init_func(QemuOpts *opts, void *opaque)
     if (error_is_set(&local_err)) {
         fprintf(stderr, "%s\n", error_get_pretty(local_err));
         error_free(local_err);
-        return -1;
+        if (strcmp("file", qemu_opt_get(opts, "backend"))) {
+            return -1;
+        }
     }
     return 0;
 }