* [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value @ 2013-09-11 18:26 Marcel Apfelbaum 2013-09-11 18:41 ` Marcel Apfelbaum 2013-09-12 7:49 ` Paolo Bonzini 0 siblings, 2 replies; 14+ messages in thread From: Marcel Apfelbaum @ 2013-09-11 18:26 UTC (permalink / raw) To: qemu-devel; +Cc: pbonzini, aliguori, afaerber, sw Qemu is expected to quit if the same boot index value is used by two devices. However, hot-plugging a device with a bootindex value already used should fail with a friendly message rather than quitting a running VM. Signed-off-by: Marcel Apfelbaum <marcel.a@redhat.com> --- qdev-monitor.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/qdev-monitor.c b/qdev-monitor.c index 410cdcb..654d086 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -24,6 +24,7 @@ #include "qmp-commands.h" #include "sysemu/arch_init.h" #include "qemu/config-file.h" +#include "sysemu/sysemu.h" /* * Aliases were a bad idea from the start. Let's keep them @@ -442,6 +443,31 @@ static BusState *qbus_find(const char *path) } } +#define OBJ_PROP_BOOTINDEX "bootindex" + +static bool bootindex_colision(Object *obj, QemuOpts *opts) +{ + int32_t bootindex; + + if (!object_property_find(obj, OBJ_PROP_BOOTINDEX, NULL)) { + return false; + } + + /* avoid parsing by setting the property and then getting it typed */ + object_property_parse(obj, qemu_opt_get(opts, OBJ_PROP_BOOTINDEX), + OBJ_PROP_BOOTINDEX, NULL); + bootindex = (int32_t)object_property_get_int(obj, OBJ_PROP_BOOTINDEX, + NULL); + + if (bootindex >= 0) { + if (get_boot_device(bootindex)) { + return true; + } + } + + return false; +} + DeviceState *qdev_device_add(QemuOpts *opts) { ObjectClass *obj; @@ -502,6 +528,13 @@ DeviceState *qdev_device_add(QemuOpts *opts) /* create device, set properties */ qdev = DEVICE(object_new(driver)); + if (qdev_hotplug && bootindex_colision(OBJECT(qdev), opts)) { + qerror_report(QERR_INVALID_PARAMETER_VALUE, + "bootindex", "an unused boot index value"); + qdev_free(qdev); + return NULL; + } + if (bus) { qdev_set_parent_bus(qdev, bus); } -- 1.8.3.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value 2013-09-11 18:26 [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value Marcel Apfelbaum @ 2013-09-11 18:41 ` Marcel Apfelbaum 2013-09-12 7:49 ` Paolo Bonzini 1 sibling, 0 replies; 14+ messages in thread From: Marcel Apfelbaum @ 2013-09-11 18:41 UTC (permalink / raw) To: qemu-devel; +Cc: pbonzini, aliguori, afaerber, sw On Wed, 2013-09-11 at 21:26 +0300, Marcel Apfelbaum wrote: > Qemu is expected to quit if the same boot index value is used by two devices. > However, hot-plugging a device with a bootindex value already used should > fail with a friendly message rather than quitting a running VM. > > Signed-off-by: Marcel Apfelbaum <marcel.a@redhat.com> > --- > qdev-monitor.c | 33 +++++++++++++++++++++++++++++++++ > 1 file changed, 33 insertions(+) > > diff --git a/qdev-monitor.c b/qdev-monitor.c > index 410cdcb..654d086 100644 > --- a/qdev-monitor.c > +++ b/qdev-monitor.c > @@ -24,6 +24,7 @@ > #include "qmp-commands.h" > #include "sysemu/arch_init.h" > #include "qemu/config-file.h" > +#include "sysemu/sysemu.h" > > /* > * Aliases were a bad idea from the start. Let's keep them > @@ -442,6 +443,31 @@ static BusState *qbus_find(const char *path) > } > } > > +#define OBJ_PROP_BOOTINDEX "bootindex" A drawback of this patch is that is based on the assumption that all devices supporting boot ordering will have a property with the same name: bootindex. A more robust approach would be to have some kind of interface for such devices with a single "getter" method: bootindex() Any thoughts? Thanks, Marcel > + > +static bool bootindex_colision(Object *obj, QemuOpts *opts) > +{ > + int32_t bootindex; > + > + if (!object_property_find(obj, OBJ_PROP_BOOTINDEX, NULL)) { > + return false; > + } > + > + /* avoid parsing by setting the property and then getting it typed */ > + object_property_parse(obj, qemu_opt_get(opts, OBJ_PROP_BOOTINDEX), > + OBJ_PROP_BOOTINDEX, NULL); > + bootindex = (int32_t)object_property_get_int(obj, OBJ_PROP_BOOTINDEX, > + NULL); > + > + if (bootindex >= 0) { > + if (get_boot_device(bootindex)) { > + return true; > + } > + } > + > + return false; > +} > + > DeviceState *qdev_device_add(QemuOpts *opts) > { > ObjectClass *obj; > @@ -502,6 +528,13 @@ DeviceState *qdev_device_add(QemuOpts *opts) > /* create device, set properties */ > qdev = DEVICE(object_new(driver)); > > + if (qdev_hotplug && bootindex_colision(OBJECT(qdev), opts)) { > + qerror_report(QERR_INVALID_PARAMETER_VALUE, > + "bootindex", "an unused boot index value"); > + qdev_free(qdev); > + return NULL; > + } > + > if (bus) { > qdev_set_parent_bus(qdev, bus); > } ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value 2013-09-11 18:26 [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value Marcel Apfelbaum 2013-09-11 18:41 ` Marcel Apfelbaum @ 2013-09-12 7:49 ` Paolo Bonzini 2013-09-12 8:38 ` Marcel Apfelbaum 2013-09-12 9:43 ` Markus Armbruster 1 sibling, 2 replies; 14+ messages in thread From: Paolo Bonzini @ 2013-09-12 7:49 UTC (permalink / raw) To: Marcel Apfelbaum; +Cc: sw, aliguori, qemu-devel, afaerber Il 11/09/2013 20:26, Marcel Apfelbaum ha scritto: > Qemu is expected to quit if the same boot index value is used by two devices. > However, hot-plugging a device with a bootindex value already used should > fail with a friendly message rather than quitting a running VM. I think the problem is right where QEMU exits, i.e. in add_boot_device_path. This function should return an error instead, via an Error ** argument. Callers, typically a device's init or realize function, will either print the error before returning an error code (e.g. -EBUSY for init) or propagate the error up (for realize). Returning/propagating failure will still cause QEMU to exit when the duplicate bootindexes are found on the command line. Paolo > Signed-off-by: Marcel Apfelbaum <marcel.a@redhat.com> > --- > qdev-monitor.c | 33 +++++++++++++++++++++++++++++++++ > 1 file changed, 33 insertions(+) > > diff --git a/qdev-monitor.c b/qdev-monitor.c > index 410cdcb..654d086 100644 > --- a/qdev-monitor.c > +++ b/qdev-monitor.c > @@ -24,6 +24,7 @@ > #include "qmp-commands.h" > #include "sysemu/arch_init.h" > #include "qemu/config-file.h" > +#include "sysemu/sysemu.h" > > /* > * Aliases were a bad idea from the start. Let's keep them > @@ -442,6 +443,31 @@ static BusState *qbus_find(const char *path) > } > } > > +#define OBJ_PROP_BOOTINDEX "bootindex" > + > +static bool bootindex_colision(Object *obj, QemuOpts *opts) > +{ > + int32_t bootindex; > + > + if (!object_property_find(obj, OBJ_PROP_BOOTINDEX, NULL)) { > + return false; > + } > + > + /* avoid parsing by setting the property and then getting it typed */ > + object_property_parse(obj, qemu_opt_get(opts, OBJ_PROP_BOOTINDEX), > + OBJ_PROP_BOOTINDEX, NULL); > + bootindex = (int32_t)object_property_get_int(obj, OBJ_PROP_BOOTINDEX, > + NULL); > + > + if (bootindex >= 0) { > + if (get_boot_device(bootindex)) { > + return true; > + } > + } > + > + return false; > +} > + > DeviceState *qdev_device_add(QemuOpts *opts) > { > ObjectClass *obj; > @@ -502,6 +528,13 @@ DeviceState *qdev_device_add(QemuOpts *opts) > /* create device, set properties */ > qdev = DEVICE(object_new(driver)); > > + if (qdev_hotplug && bootindex_colision(OBJECT(qdev), opts)) { > + qerror_report(QERR_INVALID_PARAMETER_VALUE, > + "bootindex", "an unused boot index value"); > + qdev_free(qdev); > + return NULL; > + } > + > if (bus) { > qdev_set_parent_bus(qdev, bus); > } > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value 2013-09-12 7:49 ` Paolo Bonzini @ 2013-09-12 8:38 ` Marcel Apfelbaum 2013-09-12 9:43 ` Markus Armbruster 1 sibling, 0 replies; 14+ messages in thread From: Marcel Apfelbaum @ 2013-09-12 8:38 UTC (permalink / raw) To: Paolo Bonzini; +Cc: sw, aliguori, qemu-devel, afaerber On Thu, 2013-09-12 at 09:49 +0200, Paolo Bonzini wrote: > Il 11/09/2013 20:26, Marcel Apfelbaum ha scritto: > > Qemu is expected to quit if the same boot index value is used by two devices. > > However, hot-plugging a device with a bootindex value already used should > > fail with a friendly message rather than quitting a running VM. > > I think the problem is right where QEMU exits, i.e. in > add_boot_device_path. This function should return an error instead, via > an Error ** argument. > > Callers, typically a device's init or realize function, will either > print the error before returning an error code (e.g. -EBUSY for init) or > propagate the error up (for realize). Thanks, I'll try this. Marcel > Returning/propagating failure will still cause QEMU to exit when the > duplicate bootindexes are found on the command line. > > Paolo > > > Signed-off-by: Marcel Apfelbaum <marcel.a@redhat.com> > > --- > > qdev-monitor.c | 33 +++++++++++++++++++++++++++++++++ > > 1 file changed, 33 insertions(+) > > > > diff --git a/qdev-monitor.c b/qdev-monitor.c > > index 410cdcb..654d086 100644 > > --- a/qdev-monitor.c > > +++ b/qdev-monitor.c > > @@ -24,6 +24,7 @@ > > #include "qmp-commands.h" > > #include "sysemu/arch_init.h" > > #include "qemu/config-file.h" > > +#include "sysemu/sysemu.h" > > > > /* > > * Aliases were a bad idea from the start. Let's keep them > > @@ -442,6 +443,31 @@ static BusState *qbus_find(const char *path) > > } > > } > > > > +#define OBJ_PROP_BOOTINDEX "bootindex" > > + > > +static bool bootindex_colision(Object *obj, QemuOpts *opts) > > +{ > > + int32_t bootindex; > > + > > + if (!object_property_find(obj, OBJ_PROP_BOOTINDEX, NULL)) { > > + return false; > > + } > > + > > + /* avoid parsing by setting the property and then getting it typed */ > > + object_property_parse(obj, qemu_opt_get(opts, OBJ_PROP_BOOTINDEX), > > + OBJ_PROP_BOOTINDEX, NULL); > > + bootindex = (int32_t)object_property_get_int(obj, OBJ_PROP_BOOTINDEX, > > + NULL); > > + > > + if (bootindex >= 0) { > > + if (get_boot_device(bootindex)) { > > + return true; > > + } > > + } > > + > > + return false; > > +} > > + > > DeviceState *qdev_device_add(QemuOpts *opts) > > { > > ObjectClass *obj; > > @@ -502,6 +528,13 @@ DeviceState *qdev_device_add(QemuOpts *opts) > > /* create device, set properties */ > > qdev = DEVICE(object_new(driver)); > > > > + if (qdev_hotplug && bootindex_colision(OBJECT(qdev), opts)) { > > + qerror_report(QERR_INVALID_PARAMETER_VALUE, > > + "bootindex", "an unused boot index value"); > > + qdev_free(qdev); > > + return NULL; > > + } > > + > > if (bus) { > > qdev_set_parent_bus(qdev, bus); > > } > > > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value 2013-09-12 7:49 ` Paolo Bonzini 2013-09-12 8:38 ` Marcel Apfelbaum @ 2013-09-12 9:43 ` Markus Armbruster 2013-09-12 10:33 ` Marcel Apfelbaum 1 sibling, 1 reply; 14+ messages in thread From: Markus Armbruster @ 2013-09-12 9:43 UTC (permalink / raw) To: Paolo Bonzini; +Cc: sw, aliguori, qemu-devel, afaerber, Marcel Apfelbaum Paolo Bonzini <pbonzini@redhat.com> writes: > Il 11/09/2013 20:26, Marcel Apfelbaum ha scritto: >> Qemu is expected to quit if the same boot index value is used by two devices. >> However, hot-plugging a device with a bootindex value already used should >> fail with a friendly message rather than quitting a running VM. > > I think the problem is right where QEMU exits, i.e. in > add_boot_device_path. This function should return an error instead, via > an Error ** argument. Agree. > Callers, typically a device's init or realize function, will either > print the error before returning an error code (e.g. -EBUSY for init) or > propagate the error up (for realize). > > Returning/propagating failure will still cause QEMU to exit when the > duplicate bootindexes are found on the command line. I have an unfinished patch in my tree that does exactly that. It's unfinished, because cleanup on error paths needs work. Current state appended with FIXMEs and all. Beware, the FIXMEs may not be correct and are almost certainly not complete. diff --git a/hw/block/fdc.c b/hw/block/fdc.c index c5a6c21..f8b2b27 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -2147,8 +2147,16 @@ static void isabus_fdc_realize(DeviceState *dev, Error **errp) return; } - add_boot_device_path(isa->bootindexA, dev, "/floppy@0"); - add_boot_device_path(isa->bootindexB, dev, "/floppy@1"); + add_boot_device_path_err(isa->bootindexA, dev, "/floppy@0", &err); + if (err) { + error_propagate(errp, err); + return; + } + add_boot_device_path_err(isa->bootindexB, dev, "/floppy@1", &err); + if (err) { + error_propagate(errp, err); + return; + } } static void sysbus_fdc_initfn(Object *obj) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index e2f55cc..de7ca31 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -678,6 +678,10 @@ static int virtio_blk_device_init(VirtIODevice *vdev) return -1; } + if (add_boot_device_path(s->conf->bootindex, qdev, "/disk@0,0") < 0) { + return -1; + } + virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK, sizeof(struct virtio_blk_config)); @@ -691,6 +695,7 @@ static int virtio_blk_device_init(VirtIODevice *vdev) #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE if (!virtio_blk_data_plane_create(vdev, blk, &s->dataplane)) { virtio_cleanup(vdev); + /* FIXME rm_boot_device_path() */ return -1; } s->migration_state_notifier.notify = virtio_blk_migration_state_changed; @@ -705,7 +710,6 @@ static int virtio_blk_device_init(VirtIODevice *vdev) bdrv_iostatus_enable(s->bs); - add_boot_device_path(s->conf->bootindex, qdev, "/disk@0,0"); return 0; } diff --git a/hw/core/loader.c b/hw/core/loader.c index 7b3d3ee..c9568f5 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -687,12 +687,16 @@ int rom_add_file(const char *file, const char *fw_dir, snprintf(devpath, sizeof(devpath), "/rom@" TARGET_FMT_plx, addr); } - add_boot_device_path(bootindex, NULL, devpath); + if (add_boot_device_path(bootindex, NULL, devpath) < 0) { + goto err_closed; + /* FIXME undo rom_insert()? */ + } return 0; err: if (fd != -1) close(fd); +err_closed: g_free(rom->data); g_free(rom->path); g_free(rom->name); diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c index 011764f..d532b21 100644 --- a/hw/i386/kvm/pci-assign.c +++ b/hw/i386/kvm/pci-assign.c @@ -1813,9 +1813,7 @@ static int assigned_initfn(struct PCIDevice *pci_dev) assigned_dev_load_option_rom(dev); - add_boot_device_path(dev->bootindex, &pci_dev->qdev, NULL); - - return 0; + return add_boot_device_path(dev->bootindex, &pci_dev->qdev, NULL); assigned_out: deassign_device(dev); diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 18c4b7e..557be55 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -166,10 +166,16 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) return -1; } + if (add_boot_device_path(dev->conf.bootindex, &dev->qdev, + dev->unit ? "/disk@1" : "/disk@0") < 0) { + return -1; + } + if (ide_init_drive(s, dev->conf.bs, kind, dev->version, dev->serial, dev->model, dev->wwn, dev->conf.cyls, dev->conf.heads, dev->conf.secs, dev->chs_trans) < 0) { + /* FIXME rm_boot_device_path() */ return -1; } @@ -180,9 +186,6 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) dev->serial = g_strdup(s->drive_serial_str); } - add_boot_device_path(dev->conf.bootindex, &dev->qdev, - dev->unit ? "/disk@1" : "/disk@0"); - return 0; } diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index a1c08fb..9c064ce 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -3185,7 +3185,10 @@ static int vfio_initfn(PCIDevice *pdev) } } - add_boot_device_path(vdev->bootindex, &pdev->qdev, NULL); + if (add_boot_device_path(vdev->bootindex, &pdev->qdev, NULL) < 0) { + // FIXME cleanup + goto out_teardown; + } vfio_register_err_notifier(vdev); return 0; diff --git a/hw/net/e1000.c b/hw/net/e1000.c index d3f274c..ede2a35 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -1490,7 +1490,10 @@ static int pci_e1000_init(PCIDevice *pci_dev) qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr); - add_boot_device_path(d->conf.bootindex, dev, "/ethernet-phy@0"); + if (add_boot_device_path(d->conf.bootindex, dev, "/ethernet-phy@0") < 0) { + // FIXME cleanup + return -1; + } d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d); d->mit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000_mit_timer, d); diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index ffa60d5..3cb986e 100644 --- a/hw/net/eepro100.c +++ b/hw/net/eepro100.c @@ -1905,9 +1905,8 @@ static int e100_nic_init(PCIDevice *pci_dev) s->vmstate->name = qemu_get_queue(s->nic)->model; vmstate_register(&pci_dev->qdev, -1, s->vmstate, s); - add_boot_device_path(s->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0"); - - return 0; + return add_boot_device_path(s->conf.bootindex, &pci_dev->qdev, + "/ethernet-phy@0"); } static E100PCIDeviceInfo e100_devices[] = { diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c index c961258..5541f2f 100644 --- a/hw/net/ne2000.c +++ b/hw/net/ne2000.c @@ -740,9 +740,8 @@ static int pci_ne2000_init(PCIDevice *pci_dev) object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); - add_boot_device_path(s->c.bootindex, &pci_dev->qdev, "/ethernet-phy@0"); - - return 0; + return add_boot_device_path(s->c.bootindex, &pci_dev->qdev, + "/ethernet-phy@0"); } static void pci_ne2000_exit(PCIDevice *pci_dev) diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c index 7cb47b3..66cac7c 100644 --- a/hw/net/pcnet.c +++ b/hw/net/pcnet.c @@ -1737,7 +1737,9 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info) s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); - add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0"); + if (add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0") < 0) { + return -1; + } /* Initialize the PROM */ diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index c31199f..9e5b648 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -3538,9 +3538,7 @@ static int pci_rtl8139_init(PCIDevice *dev) s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, rtl8139_timer, s); rtl8139_set_next_tctr_time(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); - add_boot_device_path(s->conf.bootindex, d, "/ethernet-phy@0"); - - return 0; + return add_boot_device_path(s->conf.bootindex, d, "/ethernet-phy@0"); } static Property rtl8139_properties[] = { diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index dd41008..020a8c1 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -1564,8 +1564,7 @@ static int virtio_net_device_init(VirtIODevice *vdev) register_savevm(qdev, "virtio-net", -1, VIRTIO_NET_VM_VERSION, virtio_net_save, virtio_net_load, n); - add_boot_device_path(n->nic_conf.bootindex, qdev, "/ethernet-phy@0"); - return 0; + return add_boot_device_path(n->nic_conf.bootindex, qdev, "/ethernet-phy@0"); } static int virtio_net_device_exit(DeviceState *qdev) diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 49c2466..1da4c7b 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -2106,9 +2106,7 @@ static int vmxnet3_pci_init(PCIDevice *pci_dev) register_savevm(dev, "vmxnet3-msix", -1, 1, vmxnet3_msix_save, vmxnet3_msix_load, s); - add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0"); - - return 0; + return add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0"); } diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 74e6a14..3450782 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2120,8 +2120,7 @@ static int scsi_initfn(SCSIDevice *dev) bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize); bdrv_iostatus_enable(s->qdev.conf.bs); - add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL); - return 0; + return add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL); } static int scsi_hd_initfn(SCSIDevice *dev) diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 8f195be..2e830e3 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -433,7 +433,9 @@ static int scsi_generic_initfn(SCSIDevice *s) s->type = scsiid.scsi_type; DPRINTF("device type %d\n", s->type); if (s->type == TYPE_DISK || s->type == TYPE_ROM) { - add_boot_device_path(s->conf.bootindex, &s->qdev, NULL); + if (add_boot_device_path(s->conf.bootindex, &s->qdev, NULL) < 0) { + return -1; + } } switch (s->type) { diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 660d774..07d75af 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -1373,8 +1373,7 @@ static int usb_net_initfn(USBDevice *dev) s->conf.macaddr.a[5]); usb_desc_set_string(dev, STRING_ETHADDR, s->usbstring_mac); - add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet@0"); - return 0; + return add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet@0"); } static USBDevice *usb_net_init(USBBus *bus, const char *cmdline) diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index 128955d..5724bb5 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -904,7 +904,9 @@ static int usb_host_initfn(USBDevice *udev) qemu_add_exit_notifier(&s->exit); QTAILQ_INSERT_TAIL(&hostdevs, s, next); - add_boot_device_path(s->bootindex, &udev->qdev, NULL); + if (add_boot_device_path(s->bootindex, &udev->qdev, NULL) < 0) { + return -1; + } usb_host_auto_check(NULL); return 0; } diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c index 65cd3b4..c7a7bd0 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -1488,8 +1488,7 @@ static int usb_host_initfn(USBDevice *dev) if (s->match.bus_num != 0 && s->match.port != NULL) { usb_host_claim_port(s); } - add_boot_device_path(s->bootindex, &dev->qdev, NULL); - return 0; + return add_boot_device_path(s->bootindex, &dev->qdev, NULL); } static const VMStateDescription vmstate_usb_host = { diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 287a505..b4d01f6 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1314,7 +1314,9 @@ static int usbredir_initfn(USBDevice *udev) usbredir_chardev_read, usbredir_chardev_event, dev); qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev); - add_boot_device_path(dev->bootindex, &udev->qdev, NULL); + if (add_boot_device_path(dev->bootindex, &udev->qdev, NULL) < 0) { + return -1; + } return 0; } diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index b1aa059..b033d97 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -178,8 +178,10 @@ void usb_info(Monitor *mon, const QDict *qdict); void rtc_change_mon_event(struct tm *tm); -void add_boot_device_path(int32_t bootindex, DeviceState *dev, - const char *suffix); +void add_boot_device_path_err(int32_t bootindex, DeviceState *dev, + const char *suffix, Error **errp); +int add_boot_device_path(int32_t bootindex, DeviceState *dev, + const char *suffix) QEMU_WARN_UNUSED_RESULT; char *get_boot_devices_list(size_t *size); DeviceState *get_boot_device(uint32_t position); diff --git a/vl.c b/vl.c index 4e709d5..18f9297 100644 --- a/vl.c +++ b/vl.c @@ -1158,8 +1158,8 @@ static void restore_boot_order(void *opaque) g_free(normal_boot_order); } -void add_boot_device_path(int32_t bootindex, DeviceState *dev, - const char *suffix) +void add_boot_device_path_err(int32_t bootindex, DeviceState *dev, + const char *suffix, Error **errp) { FWBootEntry *node, *i; @@ -1176,8 +1176,9 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev, QTAILQ_FOREACH(i, &fw_boot_order, link) { if (i->bootindex == bootindex) { - fprintf(stderr, "Two devices with same boot index %d\n", bootindex); - exit(1); + error_setg(errp, "Two devices with same boot index %d", + bootindex); + return; } else if (i->bootindex < bootindex) { continue; } @@ -1187,6 +1188,20 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev, QTAILQ_INSERT_TAIL(&fw_boot_order, node, link); } +int add_boot_device_path(int32_t bootindex, DeviceState *dev, + const char *suffix) +{ + Error *local_err = NULL; + + add_boot_device_path_err(bootindex, dev, suffix, &local_err); + if (local_err) { + qerror_report_err(local_err); + error_free(local_err); + return -1; + } + return 0; +} + DeviceState *get_boot_device(uint32_t position) { uint32_t counter = 0; -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value 2013-09-12 9:43 ` Markus Armbruster @ 2013-09-12 10:33 ` Marcel Apfelbaum 2013-09-12 11:04 ` Markus Armbruster 0 siblings, 1 reply; 14+ messages in thread From: Marcel Apfelbaum @ 2013-09-12 10:33 UTC (permalink / raw) To: Markus Armbruster; +Cc: Paolo Bonzini, aliguori, qemu-devel, afaerber, sw On Thu, 2013-09-12 at 11:43 +0200, Markus Armbruster wrote: > Paolo Bonzini <pbonzini@redhat.com> writes: > > > Il 11/09/2013 20:26, Marcel Apfelbaum ha scritto: > >> Qemu is expected to quit if the same boot index value is used by two devices. > >> However, hot-plugging a device with a bootindex value already used should > >> fail with a friendly message rather than quitting a running VM. > > > > I think the problem is right where QEMU exits, i.e. in > > add_boot_device_path. This function should return an error instead, via > > an Error ** argument. > > Agree. > > > Callers, typically a device's init or realize function, will either > > print the error before returning an error code (e.g. -EBUSY for init) or > > propagate the error up (for realize). > > > > Returning/propagating failure will still cause QEMU to exit when the > > duplicate bootindexes are found on the command line. > > I have an unfinished patch in my tree that does exactly that. It's > unfinished, because cleanup on error paths needs work. Current state > appended with FIXMEs and all. Beware, the FIXMEs may not be correct and > are almost certainly not complete. Thanks Markus, Should I use it as my starting point and finish it or you intend to? Marcel > > > diff --git a/hw/block/fdc.c b/hw/block/fdc.c > index c5a6c21..f8b2b27 100644 > --- a/hw/block/fdc.c > +++ b/hw/block/fdc.c > @@ -2147,8 +2147,16 @@ static void isabus_fdc_realize(DeviceState *dev, Error **errp) > return; > } > > - add_boot_device_path(isa->bootindexA, dev, "/floppy@0"); > - add_boot_device_path(isa->bootindexB, dev, "/floppy@1"); > + add_boot_device_path_err(isa->bootindexA, dev, "/floppy@0", &err); > + if (err) { > + error_propagate(errp, err); > + return; > + } > + add_boot_device_path_err(isa->bootindexB, dev, "/floppy@1", &err); > + if (err) { > + error_propagate(errp, err); > + return; > + } > } > > static void sysbus_fdc_initfn(Object *obj) > diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c > index e2f55cc..de7ca31 100644 > --- a/hw/block/virtio-blk.c > +++ b/hw/block/virtio-blk.c > @@ -678,6 +678,10 @@ static int virtio_blk_device_init(VirtIODevice *vdev) > return -1; > } > > + if (add_boot_device_path(s->conf->bootindex, qdev, "/disk@0,0") < 0) { > + return -1; > + } > + > virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK, > sizeof(struct virtio_blk_config)); > > @@ -691,6 +695,7 @@ static int virtio_blk_device_init(VirtIODevice *vdev) > #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE > if (!virtio_blk_data_plane_create(vdev, blk, &s->dataplane)) { > virtio_cleanup(vdev); > + /* FIXME rm_boot_device_path() */ > return -1; > } > s->migration_state_notifier.notify = virtio_blk_migration_state_changed; > @@ -705,7 +710,6 @@ static int virtio_blk_device_init(VirtIODevice *vdev) > > bdrv_iostatus_enable(s->bs); > > - add_boot_device_path(s->conf->bootindex, qdev, "/disk@0,0"); > return 0; > } > > diff --git a/hw/core/loader.c b/hw/core/loader.c > index 7b3d3ee..c9568f5 100644 > --- a/hw/core/loader.c > +++ b/hw/core/loader.c > @@ -687,12 +687,16 @@ int rom_add_file(const char *file, const char *fw_dir, > snprintf(devpath, sizeof(devpath), "/rom@" TARGET_FMT_plx, addr); > } > > - add_boot_device_path(bootindex, NULL, devpath); > + if (add_boot_device_path(bootindex, NULL, devpath) < 0) { > + goto err_closed; > + /* FIXME undo rom_insert()? */ > + } > return 0; > > err: > if (fd != -1) > close(fd); > +err_closed: > g_free(rom->data); > g_free(rom->path); > g_free(rom->name); > diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c > index 011764f..d532b21 100644 > --- a/hw/i386/kvm/pci-assign.c > +++ b/hw/i386/kvm/pci-assign.c > @@ -1813,9 +1813,7 @@ static int assigned_initfn(struct PCIDevice *pci_dev) > > assigned_dev_load_option_rom(dev); > > - add_boot_device_path(dev->bootindex, &pci_dev->qdev, NULL); > - > - return 0; > + return add_boot_device_path(dev->bootindex, &pci_dev->qdev, NULL); > > assigned_out: > deassign_device(dev); > diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c > index 18c4b7e..557be55 100644 > --- a/hw/ide/qdev.c > +++ b/hw/ide/qdev.c > @@ -166,10 +166,16 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) > return -1; > } > > + if (add_boot_device_path(dev->conf.bootindex, &dev->qdev, > + dev->unit ? "/disk@1" : "/disk@0") < 0) { > + return -1; > + } > + > if (ide_init_drive(s, dev->conf.bs, kind, > dev->version, dev->serial, dev->model, dev->wwn, > dev->conf.cyls, dev->conf.heads, dev->conf.secs, > dev->chs_trans) < 0) { > + /* FIXME rm_boot_device_path() */ > return -1; > } > > @@ -180,9 +186,6 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) > dev->serial = g_strdup(s->drive_serial_str); > } > > - add_boot_device_path(dev->conf.bootindex, &dev->qdev, > - dev->unit ? "/disk@1" : "/disk@0"); > - > return 0; > } > > diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c > index a1c08fb..9c064ce 100644 > --- a/hw/misc/vfio.c > +++ b/hw/misc/vfio.c > @@ -3185,7 +3185,10 @@ static int vfio_initfn(PCIDevice *pdev) > } > } > > - add_boot_device_path(vdev->bootindex, &pdev->qdev, NULL); > + if (add_boot_device_path(vdev->bootindex, &pdev->qdev, NULL) < 0) { > + // FIXME cleanup > + goto out_teardown; > + } > vfio_register_err_notifier(vdev); > > return 0; > diff --git a/hw/net/e1000.c b/hw/net/e1000.c > index d3f274c..ede2a35 100644 > --- a/hw/net/e1000.c > +++ b/hw/net/e1000.c > @@ -1490,7 +1490,10 @@ static int pci_e1000_init(PCIDevice *pci_dev) > > qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr); > > - add_boot_device_path(d->conf.bootindex, dev, "/ethernet-phy@0"); > + if (add_boot_device_path(d->conf.bootindex, dev, "/ethernet-phy@0") < 0) { > + // FIXME cleanup > + return -1; > + } > > d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d); > d->mit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000_mit_timer, d); > diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c > index ffa60d5..3cb986e 100644 > --- a/hw/net/eepro100.c > +++ b/hw/net/eepro100.c > @@ -1905,9 +1905,8 @@ static int e100_nic_init(PCIDevice *pci_dev) > s->vmstate->name = qemu_get_queue(s->nic)->model; > vmstate_register(&pci_dev->qdev, -1, s->vmstate, s); > > - add_boot_device_path(s->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0"); > - > - return 0; > + return add_boot_device_path(s->conf.bootindex, &pci_dev->qdev, > + "/ethernet-phy@0"); > } > > static E100PCIDeviceInfo e100_devices[] = { > diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c > index c961258..5541f2f 100644 > --- a/hw/net/ne2000.c > +++ b/hw/net/ne2000.c > @@ -740,9 +740,8 @@ static int pci_ne2000_init(PCIDevice *pci_dev) > object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s); > qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); > > - add_boot_device_path(s->c.bootindex, &pci_dev->qdev, "/ethernet-phy@0"); > - > - return 0; > + return add_boot_device_path(s->c.bootindex, &pci_dev->qdev, > + "/ethernet-phy@0"); > } > > static void pci_ne2000_exit(PCIDevice *pci_dev) > diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c > index 7cb47b3..66cac7c 100644 > --- a/hw/net/pcnet.c > +++ b/hw/net/pcnet.c > @@ -1737,7 +1737,9 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info) > s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s); > qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); > > - add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0"); > + if (add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0") < 0) { > + return -1; > + } > > /* Initialize the PROM */ > > diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c > index c31199f..9e5b648 100644 > --- a/hw/net/rtl8139.c > +++ b/hw/net/rtl8139.c > @@ -3538,9 +3538,7 @@ static int pci_rtl8139_init(PCIDevice *dev) > s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, rtl8139_timer, s); > rtl8139_set_next_tctr_time(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); > > - add_boot_device_path(s->conf.bootindex, d, "/ethernet-phy@0"); > - > - return 0; > + return add_boot_device_path(s->conf.bootindex, d, "/ethernet-phy@0"); > } > > static Property rtl8139_properties[] = { > diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c > index dd41008..020a8c1 100644 > --- a/hw/net/virtio-net.c > +++ b/hw/net/virtio-net.c > @@ -1564,8 +1564,7 @@ static int virtio_net_device_init(VirtIODevice *vdev) > register_savevm(qdev, "virtio-net", -1, VIRTIO_NET_VM_VERSION, > virtio_net_save, virtio_net_load, n); > > - add_boot_device_path(n->nic_conf.bootindex, qdev, "/ethernet-phy@0"); > - return 0; > + return add_boot_device_path(n->nic_conf.bootindex, qdev, "/ethernet-phy@0"); > } > > static int virtio_net_device_exit(DeviceState *qdev) > diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c > index 49c2466..1da4c7b 100644 > --- a/hw/net/vmxnet3.c > +++ b/hw/net/vmxnet3.c > @@ -2106,9 +2106,7 @@ static int vmxnet3_pci_init(PCIDevice *pci_dev) > register_savevm(dev, "vmxnet3-msix", -1, 1, > vmxnet3_msix_save, vmxnet3_msix_load, s); > > - add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0"); > - > - return 0; > + return add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0"); > } > > > diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c > index 74e6a14..3450782 100644 > --- a/hw/scsi/scsi-disk.c > +++ b/hw/scsi/scsi-disk.c > @@ -2120,8 +2120,7 @@ static int scsi_initfn(SCSIDevice *dev) > bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize); > > bdrv_iostatus_enable(s->qdev.conf.bs); > - add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL); > - return 0; > + return add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL); > } > > static int scsi_hd_initfn(SCSIDevice *dev) > diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c > index 8f195be..2e830e3 100644 > --- a/hw/scsi/scsi-generic.c > +++ b/hw/scsi/scsi-generic.c > @@ -433,7 +433,9 @@ static int scsi_generic_initfn(SCSIDevice *s) > s->type = scsiid.scsi_type; > DPRINTF("device type %d\n", s->type); > if (s->type == TYPE_DISK || s->type == TYPE_ROM) { > - add_boot_device_path(s->conf.bootindex, &s->qdev, NULL); > + if (add_boot_device_path(s->conf.bootindex, &s->qdev, NULL) < 0) { > + return -1; > + } > } > > switch (s->type) { > diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c > index 660d774..07d75af 100644 > --- a/hw/usb/dev-network.c > +++ b/hw/usb/dev-network.c > @@ -1373,8 +1373,7 @@ static int usb_net_initfn(USBDevice *dev) > s->conf.macaddr.a[5]); > usb_desc_set_string(dev, STRING_ETHADDR, s->usbstring_mac); > > - add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet@0"); > - return 0; > + return add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet@0"); > } > > static USBDevice *usb_net_init(USBBus *bus, const char *cmdline) > diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c > index 128955d..5724bb5 100644 > --- a/hw/usb/host-libusb.c > +++ b/hw/usb/host-libusb.c > @@ -904,7 +904,9 @@ static int usb_host_initfn(USBDevice *udev) > qemu_add_exit_notifier(&s->exit); > > QTAILQ_INSERT_TAIL(&hostdevs, s, next); > - add_boot_device_path(s->bootindex, &udev->qdev, NULL); > + if (add_boot_device_path(s->bootindex, &udev->qdev, NULL) < 0) { > + return -1; > + } > usb_host_auto_check(NULL); > return 0; > } > diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c > index 65cd3b4..c7a7bd0 100644 > --- a/hw/usb/host-linux.c > +++ b/hw/usb/host-linux.c > @@ -1488,8 +1488,7 @@ static int usb_host_initfn(USBDevice *dev) > if (s->match.bus_num != 0 && s->match.port != NULL) { > usb_host_claim_port(s); > } > - add_boot_device_path(s->bootindex, &dev->qdev, NULL); > - return 0; > + return add_boot_device_path(s->bootindex, &dev->qdev, NULL); > } > > static const VMStateDescription vmstate_usb_host = { > diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c > index 287a505..b4d01f6 100644 > --- a/hw/usb/redirect.c > +++ b/hw/usb/redirect.c > @@ -1314,7 +1314,9 @@ static int usbredir_initfn(USBDevice *udev) > usbredir_chardev_read, usbredir_chardev_event, dev); > > qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev); > - add_boot_device_path(dev->bootindex, &udev->qdev, NULL); > + if (add_boot_device_path(dev->bootindex, &udev->qdev, NULL) < 0) { > + return -1; > + } > return 0; > } > > diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h > index b1aa059..b033d97 100644 > --- a/include/sysemu/sysemu.h > +++ b/include/sysemu/sysemu.h > @@ -178,8 +178,10 @@ void usb_info(Monitor *mon, const QDict *qdict); > > void rtc_change_mon_event(struct tm *tm); > > -void add_boot_device_path(int32_t bootindex, DeviceState *dev, > - const char *suffix); > +void add_boot_device_path_err(int32_t bootindex, DeviceState *dev, > + const char *suffix, Error **errp); > +int add_boot_device_path(int32_t bootindex, DeviceState *dev, > + const char *suffix) QEMU_WARN_UNUSED_RESULT; > char *get_boot_devices_list(size_t *size); > > DeviceState *get_boot_device(uint32_t position); > diff --git a/vl.c b/vl.c > index 4e709d5..18f9297 100644 > --- a/vl.c > +++ b/vl.c > @@ -1158,8 +1158,8 @@ static void restore_boot_order(void *opaque) > g_free(normal_boot_order); > } > > -void add_boot_device_path(int32_t bootindex, DeviceState *dev, > - const char *suffix) > +void add_boot_device_path_err(int32_t bootindex, DeviceState *dev, > + const char *suffix, Error **errp) > { > FWBootEntry *node, *i; > > @@ -1176,8 +1176,9 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev, > > QTAILQ_FOREACH(i, &fw_boot_order, link) { > if (i->bootindex == bootindex) { > - fprintf(stderr, "Two devices with same boot index %d\n", bootindex); > - exit(1); > + error_setg(errp, "Two devices with same boot index %d", > + bootindex); > + return; > } else if (i->bootindex < bootindex) { > continue; > } > @@ -1187,6 +1188,20 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev, > QTAILQ_INSERT_TAIL(&fw_boot_order, node, link); > } > > +int add_boot_device_path(int32_t bootindex, DeviceState *dev, > + const char *suffix) > +{ > + Error *local_err = NULL; > + > + add_boot_device_path_err(bootindex, dev, suffix, &local_err); > + if (local_err) { > + qerror_report_err(local_err); > + error_free(local_err); > + return -1; > + } > + return 0; > +} > + > DeviceState *get_boot_device(uint32_t position) > { > uint32_t counter = 0; ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value 2013-09-12 10:33 ` Marcel Apfelbaum @ 2013-09-12 11:04 ` Markus Armbruster 2013-09-12 11:23 ` Marcel Apfelbaum 2013-09-16 9:54 ` Marcel Apfelbaum 0 siblings, 2 replies; 14+ messages in thread From: Markus Armbruster @ 2013-09-12 11:04 UTC (permalink / raw) To: Marcel Apfelbaum; +Cc: Paolo Bonzini, aliguori, qemu-devel, afaerber, sw Marcel Apfelbaum <marcel.a@redhat.com> writes: > On Thu, 2013-09-12 at 11:43 +0200, Markus Armbruster wrote: >> Paolo Bonzini <pbonzini@redhat.com> writes: >> >> > Il 11/09/2013 20:26, Marcel Apfelbaum ha scritto: >> >> Qemu is expected to quit if the same boot index value is used by >> >> two devices. >> >> However, hot-plugging a device with a bootindex value already used should >> >> fail with a friendly message rather than quitting a running VM. >> > >> > I think the problem is right where QEMU exits, i.e. in >> > add_boot_device_path. This function should return an error instead, via >> > an Error ** argument. >> >> Agree. >> >> > Callers, typically a device's init or realize function, will either >> > print the error before returning an error code (e.g. -EBUSY for init) or >> > propagate the error up (for realize). >> > >> > Returning/propagating failure will still cause QEMU to exit when the >> > duplicate bootindexes are found on the command line. >> >> I have an unfinished patch in my tree that does exactly that. It's >> unfinished, because cleanup on error paths needs work. Current state >> appended with FIXMEs and all. Beware, the FIXMEs may not be correct and >> are almost certainly not complete. > Thanks Markus, > Should I use it as my starting point and finish it or you intend to? If you have cycles to spare, you're quite welcome to take this patch and run with it! You may have noticed that my patch moves the code to add the boot device path in a few cases. I did this in the hope of simplifying error paths. Do not hesitate to undo such moves where they turn out not to simplify anything. Here's an issue that exists before my patch: DeviceClass method unrealize() should clean up everything done by realize(). In particular, unrealize() needs to remove any entry added to fw_boot_order by realize() via add_boot_device_path(). Code to do that doesn't exist, yet. Hot unplug is technically broken for all devices with bootindex. Impact unknown. Should probably be fixed in a separate patch. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value 2013-09-12 11:04 ` Markus Armbruster @ 2013-09-12 11:23 ` Marcel Apfelbaum 2013-09-16 9:54 ` Marcel Apfelbaum 1 sibling, 0 replies; 14+ messages in thread From: Marcel Apfelbaum @ 2013-09-12 11:23 UTC (permalink / raw) To: Markus Armbruster; +Cc: Paolo Bonzini, aliguori, qemu-devel, afaerber, sw On Thu, 2013-09-12 at 13:04 +0200, Markus Armbruster wrote: > Marcel Apfelbaum <marcel.a@redhat.com> writes: > > > On Thu, 2013-09-12 at 11:43 +0200, Markus Armbruster wrote: > >> Paolo Bonzini <pbonzini@redhat.com> writes: > >> > >> > Il 11/09/2013 20:26, Marcel Apfelbaum ha scritto: > >> >> Qemu is expected to quit if the same boot index value is used by > >> >> two devices. > >> >> However, hot-plugging a device with a bootindex value already used should > >> >> fail with a friendly message rather than quitting a running VM. > >> > > >> > I think the problem is right where QEMU exits, i.e. in > >> > add_boot_device_path. This function should return an error instead, via > >> > an Error ** argument. > >> > >> Agree. > >> > >> > Callers, typically a device's init or realize function, will either > >> > print the error before returning an error code (e.g. -EBUSY for init) or > >> > propagate the error up (for realize). > >> > > >> > Returning/propagating failure will still cause QEMU to exit when the > >> > duplicate bootindexes are found on the command line. > >> > >> I have an unfinished patch in my tree that does exactly that. It's > >> unfinished, because cleanup on error paths needs work. Current state > >> appended with FIXMEs and all. Beware, the FIXMEs may not be correct and > >> are almost certainly not complete. > > Thanks Markus, > > Should I use it as my starting point and finish it or you intend to? > > If you have cycles to spare, you're quite welcome to take this patch and > run with it! I'll try to finish it, thanks! > > You may have noticed that my patch moves the code to add the boot device > path in a few cases. I did this in the hope of simplifying error paths. > Do not hesitate to undo such moves where they turn out not to simplify > anything. > > Here's an issue that exists before my patch: DeviceClass method > unrealize() should clean up everything done by realize(). In > particular, unrealize() needs to remove any entry added to fw_boot_order > by realize() via add_boot_device_path(). Code to do that doesn't exist, > yet. Hot unplug is technically broken for all devices with bootindex. > Impact unknown. Should probably be fixed in a separate patch. The outcome is that after hot-unplugging a device with bootindex=x, the device still remains in the fw_boot_order and no device can be hot-plugged with the same bootindex 'x'. Furthermore, because of the current issue Qemu quits on an operation that should succeed! I plan to send a patch to fix this too. Thanks, Marcel ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value 2013-09-12 11:04 ` Markus Armbruster 2013-09-12 11:23 ` Marcel Apfelbaum @ 2013-09-16 9:54 ` Marcel Apfelbaum 2013-09-16 10:11 ` Paolo Bonzini 2013-09-16 11:03 ` Gleb Natapov 1 sibling, 2 replies; 14+ messages in thread From: Marcel Apfelbaum @ 2013-09-16 9:54 UTC (permalink / raw) To: Markus Armbruster Cc: aliguori, gleb, mst, sw, qemu-devel, Paolo Bonzini, afaerber On Thu, 2013-09-12 at 13:04 +0200, Markus Armbruster wrote: > Marcel Apfelbaum <marcel.a@redhat.com> writes: > > > On Thu, 2013-09-12 at 11:43 +0200, Markus Armbruster wrote: > >> Paolo Bonzini <pbonzini@redhat.com> writes: > >> > >> > Il 11/09/2013 20:26, Marcel Apfelbaum ha scritto: > >> >> Qemu is expected to quit if the same boot index value is used by > >> >> two devices. > >> >> However, hot-plugging a device with a bootindex value already used should > >> >> fail with a friendly message rather than quitting a running VM. > >> > > >> > I think the problem is right where QEMU exits, i.e. in > >> > add_boot_device_path. This function should return an error instead, via > >> > an Error ** argument. > >> > >> Agree. I understood that the boot order is passed in fw cfg and updated only once at "machine done". There is no update of this list after this point. Modifying the boot order from monitor does not work at all. So in order to solve this issue we can: 1. Don't allow use of bootindex at hot-plug 2. Change the architecture so boot order changing during hot-plug will be possible. > >> > >> > Callers, typically a device's init or realize function, will either > >> > print the error before returning an error code (e.g. -EBUSY for init) or > >> > propagate the error up (for realize). > >> > > >> > Returning/propagating failure will still cause QEMU to exit when the > >> > duplicate bootindexes are found on the command line. > >> > >> I have an unfinished patch in my tree that does exactly that. It's > >> unfinished, because cleanup on error paths needs work. Current state > >> appended with FIXMEs and all. Beware, the FIXMEs may not be correct and > >> are almost certainly not complete. > > Thanks Markus, > > Should I use it as my starting point and finish it or you intend to? > > If you have cycles to spare, you're quite welcome to take this patch and > run with it! I really wanted to take this, but I think we need first to sort out the issues mentioned above and only then follow this path Thanks, Marcel > > You may have noticed that my patch moves the code to add the boot device > path in a few cases. I did this in the hope of simplifying error paths. > Do not hesitate to undo such moves where they turn out not to simplify > anything. > > Here's an issue that exists before my patch: DeviceClass method > unrealize() should clean up everything done by realize(). In > particular, unrealize() needs to remove any entry added to fw_boot_order > by realize() via add_boot_device_path(). Code to do that doesn't exist, > yet. Hot unplug is technically broken for all devices with bootindex. > Impact unknown. Should probably be fixed in a separate patch. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value 2013-09-16 9:54 ` Marcel Apfelbaum @ 2013-09-16 10:11 ` Paolo Bonzini 2013-09-16 15:14 ` Michael S. Tsirkin 2013-09-16 11:03 ` Gleb Natapov 1 sibling, 1 reply; 14+ messages in thread From: Paolo Bonzini @ 2013-09-16 10:11 UTC (permalink / raw) To: Marcel Apfelbaum Cc: aliguori, gleb, mst, sw, qemu-devel, Markus Armbruster, afaerber Il 16/09/2013 11:54, Marcel Apfelbaum ha scritto: > On Thu, 2013-09-12 at 13:04 +0200, Markus Armbruster wrote: >> Marcel Apfelbaum <marcel.a@redhat.com> writes: >> >>> On Thu, 2013-09-12 at 11:43 +0200, Markus Armbruster wrote: >>>> Paolo Bonzini <pbonzini@redhat.com> writes: >>>> >>>>> Il 11/09/2013 20:26, Marcel Apfelbaum ha scritto: >>>>>> Qemu is expected to quit if the same boot index value is used by >>>>>> two devices. >>>>>> However, hot-plugging a device with a bootindex value already used should >>>>>> fail with a friendly message rather than quitting a running VM. >>>>> >>>>> I think the problem is right where QEMU exits, i.e. in >>>>> add_boot_device_path. This function should return an error instead, via >>>>> an Error ** argument. >>>> >>>> Agree. > > I understood that the boot order is passed in fw cfg and updated only once at > "machine done". There is no update of this list after this point. > Modifying the boot order from monitor does not work at all. > > So in order to solve this issue we can: > 1. Don't allow use of bootindex at hot-plug > 2. Change the architecture so boot order changing during hot-plug will be possible. This is done relatively easily in add_boot_device_path (check the qdev_hotplug variable and return an error if it is 1). You can do it on top of Markus's patch. Paolo ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value 2013-09-16 10:11 ` Paolo Bonzini @ 2013-09-16 15:14 ` Michael S. Tsirkin 2013-09-16 15:34 ` Paolo Bonzini 0 siblings, 1 reply; 14+ messages in thread From: Michael S. Tsirkin @ 2013-09-16 15:14 UTC (permalink / raw) To: Paolo Bonzini Cc: aliguori, gleb, Marcel Apfelbaum, sw, qemu-devel, Markus Armbruster, afaerber On Mon, Sep 16, 2013 at 12:11:35PM +0200, Paolo Bonzini wrote: > Il 16/09/2013 11:54, Marcel Apfelbaum ha scritto: > > On Thu, 2013-09-12 at 13:04 +0200, Markus Armbruster wrote: > >> Marcel Apfelbaum <marcel.a@redhat.com> writes: > >> > >>> On Thu, 2013-09-12 at 11:43 +0200, Markus Armbruster wrote: > >>>> Paolo Bonzini <pbonzini@redhat.com> writes: > >>>> > >>>>> Il 11/09/2013 20:26, Marcel Apfelbaum ha scritto: > >>>>>> Qemu is expected to quit if the same boot index value is used by > >>>>>> two devices. > >>>>>> However, hot-plugging a device with a bootindex value already used should > >>>>>> fail with a friendly message rather than quitting a running VM. > >>>>> > >>>>> I think the problem is right where QEMU exits, i.e. in > >>>>> add_boot_device_path. This function should return an error instead, via > >>>>> an Error ** argument. > >>>> > >>>> Agree. > > > > I understood that the boot order is passed in fw cfg and updated only once at > > "machine done". There is no update of this list after this point. > > Modifying the boot order from monitor does not work at all. > > > > So in order to solve this issue we can: > > 1. Don't allow use of bootindex at hot-plug > > 2. Change the architecture so boot order changing during hot-plug will be possible. > > This is done relatively easily in add_boot_device_path (check the > qdev_hotplug variable and return an error if it is 1). This refers to 1) here? That's nice but it's not really all that helpful. > You can do it on top of Markus's patch. > > Paolo ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value 2013-09-16 15:14 ` Michael S. Tsirkin @ 2013-09-16 15:34 ` Paolo Bonzini 2013-09-16 15:59 ` Michael S. Tsirkin 0 siblings, 1 reply; 14+ messages in thread From: Paolo Bonzini @ 2013-09-16 15:34 UTC (permalink / raw) To: Michael S. Tsirkin Cc: aliguori, gleb, Marcel Apfelbaum, sw, qemu-devel, Markus Armbruster, afaerber Il 16/09/2013 17:14, Michael S. Tsirkin ha scritto: > On Mon, Sep 16, 2013 at 12:11:35PM +0200, Paolo Bonzini wrote: >> Il 16/09/2013 11:54, Marcel Apfelbaum ha scritto: >>> On Thu, 2013-09-12 at 13:04 +0200, Markus Armbruster wrote: >>>> Marcel Apfelbaum <marcel.a@redhat.com> writes: >>>> >>>>> On Thu, 2013-09-12 at 11:43 +0200, Markus Armbruster wrote: >>>>>> Paolo Bonzini <pbonzini@redhat.com> writes: >>>>>> >>>>>>> Il 11/09/2013 20:26, Marcel Apfelbaum ha scritto: >>>>>>>> Qemu is expected to quit if the same boot index value is used by >>>>>>>> two devices. >>>>>>>> However, hot-plugging a device with a bootindex value already used should >>>>>>>> fail with a friendly message rather than quitting a running VM. >>>>>>> >>>>>>> I think the problem is right where QEMU exits, i.e. in >>>>>>> add_boot_device_path. This function should return an error instead, via >>>>>>> an Error ** argument. >>>>>> >>>>>> Agree. >>> >>> I understood that the boot order is passed in fw cfg and updated only once at >>> "machine done". There is no update of this list after this point. >>> Modifying the boot order from monitor does not work at all. >>> >>> So in order to solve this issue we can: >>> 1. Don't allow use of bootindex at hot-plug >>> 2. Change the architecture so boot order changing during hot-plug will be possible. >> >> This is done relatively easily in add_boot_device_path (check the >> qdev_hotplug variable and return an error if it is 1). > > This refers to 1) here? That's nice but it's not really all that helpful. True, but the error propagation changes are the base for both cases, and (1) is just 4 lines of code. So this seems like a plan to me: do the error propagation changes and (1), then we can revert those four lines when (2) is ready. Paolo ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value 2013-09-16 15:34 ` Paolo Bonzini @ 2013-09-16 15:59 ` Michael S. Tsirkin 0 siblings, 0 replies; 14+ messages in thread From: Michael S. Tsirkin @ 2013-09-16 15:59 UTC (permalink / raw) To: Paolo Bonzini Cc: aliguori, gleb, Marcel Apfelbaum, sw, qemu-devel, Markus Armbruster, afaerber On Mon, Sep 16, 2013 at 05:34:04PM +0200, Paolo Bonzini wrote: > Il 16/09/2013 17:14, Michael S. Tsirkin ha scritto: > > On Mon, Sep 16, 2013 at 12:11:35PM +0200, Paolo Bonzini wrote: > >> Il 16/09/2013 11:54, Marcel Apfelbaum ha scritto: > >>> On Thu, 2013-09-12 at 13:04 +0200, Markus Armbruster wrote: > >>>> Marcel Apfelbaum <marcel.a@redhat.com> writes: > >>>> > >>>>> On Thu, 2013-09-12 at 11:43 +0200, Markus Armbruster wrote: > >>>>>> Paolo Bonzini <pbonzini@redhat.com> writes: > >>>>>> > >>>>>>> Il 11/09/2013 20:26, Marcel Apfelbaum ha scritto: > >>>>>>>> Qemu is expected to quit if the same boot index value is used by > >>>>>>>> two devices. > >>>>>>>> However, hot-plugging a device with a bootindex value already used should > >>>>>>>> fail with a friendly message rather than quitting a running VM. > >>>>>>> > >>>>>>> I think the problem is right where QEMU exits, i.e. in > >>>>>>> add_boot_device_path. This function should return an error instead, via > >>>>>>> an Error ** argument. > >>>>>> > >>>>>> Agree. > >>> > >>> I understood that the boot order is passed in fw cfg and updated only once at > >>> "machine done". There is no update of this list after this point. > >>> Modifying the boot order from monitor does not work at all. > >>> > >>> So in order to solve this issue we can: > >>> 1. Don't allow use of bootindex at hot-plug > >>> 2. Change the architecture so boot order changing during hot-plug will be possible. > >> > >> This is done relatively easily in add_boot_device_path (check the > >> qdev_hotplug variable and return an error if it is 1). > > > > This refers to 1) here? That's nice but it's not really all that helpful. > > True, but the error propagation changes are the base for both cases, and > (1) is just 4 lines of code. So this seems like a plan to me: do the > error propagation changes and (1), then we can revert those four lines > when (2) is ready. > > Paolo I'm fine with applying error propagation, but maybe not (1). Basically if you accept incorrect code the result often is that controbutor disappears and it's never completed, others are discouraged from addressing the problem because incorrect code created maintainance issues, and a half-solved problem is a less interesting target than an unsolved one. So if a contributor basically says he does not want to address the complete problem, we should weight carefully whether we want to be stuck with half a solution for a long time. In this case, I don't think it's justified. -- MST ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value 2013-09-16 9:54 ` Marcel Apfelbaum 2013-09-16 10:11 ` Paolo Bonzini @ 2013-09-16 11:03 ` Gleb Natapov 1 sibling, 0 replies; 14+ messages in thread From: Gleb Natapov @ 2013-09-16 11:03 UTC (permalink / raw) To: Marcel Apfelbaum Cc: aliguori, mst, sw, qemu-devel, Markus Armbruster, Paolo Bonzini, afaerber On Mon, Sep 16, 2013 at 12:54:39PM +0300, Marcel Apfelbaum wrote: > On Thu, 2013-09-12 at 13:04 +0200, Markus Armbruster wrote: > > Marcel Apfelbaum <marcel.a@redhat.com> writes: > > > > > On Thu, 2013-09-12 at 11:43 +0200, Markus Armbruster wrote: > > >> Paolo Bonzini <pbonzini@redhat.com> writes: > > >> > > >> > Il 11/09/2013 20:26, Marcel Apfelbaum ha scritto: > > >> >> Qemu is expected to quit if the same boot index value is used by > > >> >> two devices. > > >> >> However, hot-plugging a device with a bootindex value already used should > > >> >> fail with a friendly message rather than quitting a running VM. > > >> > > > >> > I think the problem is right where QEMU exits, i.e. in > > >> > add_boot_device_path. This function should return an error instead, via > > >> > an Error ** argument. > > >> > > >> Agree. > > I understood that the boot order is passed in fw cfg and updated only once at > "machine done". There is no update of this list after this point. The reason it is done at his point is because when add_boot_device_path() is called dev is not fully instantiated so qdev_get_fw_dev_path() cannot be called on it yet. For hotplug we need to re-create boot device list when device is fully ready. > Modifying the boot order from monitor does not work at all. > > So in order to solve this issue we can: > 1. Don't allow use of bootindex at hot-plug I'd rather have a proper fix then workaround. BTW this will change qmp interface so a command that worked before (for some definition of "worked") will start to fail. Markus proposed to ignore bootindex clash, also simple solution and has no downside described above, but has others that we discussed. > 2. Change the architecture so boot order changing during hot-plug will be possible. > This is an easy part of the problem though. The hard part how not to exit when bootindex clash happens ans this is easy since nobody knows how well device creation errors are handled by qdev. -- Gleb. ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2013-09-16 15:57 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-09-11 18:26 [Qemu-devel] [PATCH] qdev-monitor: Avoid exiting when hot-plugging two devices with the same bootindex value Marcel Apfelbaum 2013-09-11 18:41 ` Marcel Apfelbaum 2013-09-12 7:49 ` Paolo Bonzini 2013-09-12 8:38 ` Marcel Apfelbaum 2013-09-12 9:43 ` Markus Armbruster 2013-09-12 10:33 ` Marcel Apfelbaum 2013-09-12 11:04 ` Markus Armbruster 2013-09-12 11:23 ` Marcel Apfelbaum 2013-09-16 9:54 ` Marcel Apfelbaum 2013-09-16 10:11 ` Paolo Bonzini 2013-09-16 15:14 ` Michael S. Tsirkin 2013-09-16 15:34 ` Paolo Bonzini 2013-09-16 15:59 ` Michael S. Tsirkin 2013-09-16 11:03 ` Gleb Natapov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).