Message ID | 1253287594-12905-4-git-send-email-wolfgang.mauerer@siemens.com |
---|---|
State | Superseded |
Headers | show |
Hi, > + dinfo = drive_get(type, bus, unit); > + if (!dinfo) { > + monitor_printf(mon, "Trying to remove non-existent device\n"); > + return; > + } No. Just don't do this silly if/bus/unit parsing. At very minimum use drive_get_by_id() here, then have something like 'drive_del $id'. IMHO much better would be to go qdev instead though. We should have generic device_add + device_del monitor commands which work for any device, pretty much like the -device command line switch. cheers, Gerd
Gerd Hoffmann wrote: > Hi, > >> + dinfo = drive_get(type, bus, unit); >> + if (!dinfo) { >> + monitor_printf(mon, "Trying to remove non-existent device\n"); >> + return; >> + } > > No. Just don't do this silly if/bus/unit parsing. At very minimum use > drive_get_by_id() here, then have something like 'drive_del $id'. > > IMHO much better would be to go qdev instead though. We should have > generic device_add + device_del monitor commands which work for any > device, pretty much like the -device command line switch. That makes sense, but I'd nevertheless prefer to stick with the more traditional approach right now, replacing the bus/unit parsing with an ID-based variant. However, is there any standard way to get from an instance of DriveInfo to the corresponding instance of SCSIDevice respectively SCSIDeviceInfo? It's a bit unclear to me if there is no such connection, of if I'm just overlooking something. Thanks, Wolfgang
On 09/30/09 17:45, Wolfgang Mauerer wrote: > Gerd Hoffmann wrote: >> Hi, >> >>> + dinfo = drive_get(type, bus, unit); >>> + if (!dinfo) { >>> + monitor_printf(mon, "Trying to remove non-existent device\n"); >>> + return; >>> + } >> >> No. Just don't do this silly if/bus/unit parsing. At very minimum use >> drive_get_by_id() here, then have something like 'drive_del $id'. >> >> IMHO much better would be to go qdev instead though. We should have >> generic device_add + device_del monitor commands which work for any >> device, pretty much like the -device command line switch. > > That makes sense, but I'd nevertheless prefer to stick with the > more traditional approach right now, replacing the > bus/unit parsing with an ID-based variant. Have a look at the "qdev: bus management updates." patch series posted a few days ago. It adds device_add+device_del. > However, is there any > standard way to get from an instance of DriveInfo to > the corresponding instance of SCSIDevice respectively > SCSIDeviceInfo? No. It is linked the other way around: The device has a reference to the DriveInfo. Which is one of the reasons why I think drive_del isn't that a great idea. cheers, Gerd
Gerd Hoffmann wrote: > On 09/30/09 17:45, Wolfgang Mauerer wrote: >> Gerd Hoffmann wrote: >>> Hi, >>> >>>> + dinfo = drive_get(type, bus, unit); >>>> + if (!dinfo) { >>>> + monitor_printf(mon, "Trying to remove non-existent device\n"); >>>> + return; >>>> + } >>> No. Just don't do this silly if/bus/unit parsing. At very minimum use >>> drive_get_by_id() here, then have something like 'drive_del $id'. >>> >>> IMHO much better would be to go qdev instead though. We should have >>> generic device_add + device_del monitor commands which work for any >>> device, pretty much like the -device command line switch. >> That makes sense, but I'd nevertheless prefer to stick with the >> more traditional approach right now, replacing the >> bus/unit parsing with an ID-based variant. > > Have a look at the "qdev: bus management updates." patch series posted a > few days ago. It adds device_add+device_del. Thanks for the pointer. The reason why I'd (still :-)) like to stick to the non-qdev variant is because I would want the patch to be applicable to older qemu releases for various reasons, and backporting all the required qdev changes does not seem to be a reasonable option (but please tell me if you think this would make sense) >> However, is there any >> standard way to get from an instance of DriveInfo to >> the corresponding instance of SCSIDevice respectively >> SCSIDeviceInfo? > > No. It is linked the other way around: The device has a reference to > the DriveInfo. Which is one of the reasons why I think drive_del isn't > that a great idea. Cheers, Wolfgang
On 10/01/09 09:54, Wolfgang Mauerer wrote: > Thanks for the pointer. The reason why I'd (still :-)) like > to stick to the non-qdev variant is because I would want > the patch to be applicable to older qemu releases for various > reasons, and backporting all the required qdev changes does > not seem to be a reasonable option (but please tell me if you > think this would make sense) Yes, backporting all qdev isn't going to fly. Note that support for looking up drives by name is available in 0.11+ only too, so you might have to stick with the lookup by pci address, depending on which versions you plan to backport it ... cheers, Gerd
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c index b8ea9ae..4455f17 100644 --- a/hw/pci-hotplug.c +++ b/hw/pci-hotplug.c @@ -50,6 +50,98 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon, return pci_nic_init(&nd_table[ret], "rtl8139", devaddr); } +void drive_hot_del(Monitor *mon, const QDict *qdict) +{ + int dom, pci_bus; + unsigned slot; + unsigned unit, bus; + int type; + int success = 0; + PCIDevice *dev; + DriveInfo *dinfo; + BlockDriverState *bs; + char buf[128]; + const char *strbuf; + QemuOpts *opts; + + static const char * const params[] = { "bus", "unit", "if", NULL }; + const char *pci_addr = qdict_get_str(qdict, "pci_addr"); + const char *optstring = qdict_get_try_str(qdict, "opts"); + + /* strip legacy tag */ + if (!strncmp(pci_addr, "pci_addr=", 9)) { + pci_addr += 9; + } + + if (check_params(buf, sizeof(buf), params, optstring) < 0) { + monitor_printf(mon, "qemu: unknown parameter '%s' in '%s'\n", + buf, optstring); + return; + } + opts = drive_add(NULL, "%s", optstring); // Just parses optstring + + if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) { + monitor_printf(mon, "Invalid pci address\n"); + return; + } + + dev = pci_find_device(pci_bus, slot, 0); + if (!dev) { + monitor_printf(mon, "No pci device with address %s\n", pci_addr); + return; + } + + bus = qemu_opt_get_number(opts, "bus", -1); + if (bus == -1) { + monitor_printf(mon, "Need to specify bus\n"); + return; + } + + unit = qemu_opt_get_number(opts, "unit", -1); + if (unit == -1) { + monitor_printf(mon, "Need to specify unit\n"); + return; + } + + if ((strbuf = qemu_opt_get(opts, "if")) != NULL) { + type = qemu_opt_get_if(strbuf); + + if (type == IF_COUNT) { + monitor_printf(mon, "Trying to remove device on invalid bus\n"); + return; + } + } else { + /* Assume SCSI for hot-remove per default */ + type = IF_SCSI; + } + + dinfo = drive_get(type, bus, unit); + if (!dinfo) { + monitor_printf(mon, "Trying to remove non-existent device\n"); + return; + } + + switch (type) { + case IF_SCSI: + success = 1; + lsi_scsi_detach(&dev->qdev, dinfo->bdrv, dinfo->unit); + + bs = dinfo->bdrv; + drive_uninit(bs); + bdrv_delete(bs); + break; + default: + monitor_printf(mon, "Hot-remove unsupported for interface type %d\n", + type); + } + + if (success) + monitor_printf(mon, "OK bus %d, unit %d\n", bus, unit); + + return; +} + + void drive_hot_add(Monitor *mon, const QDict *qdict) { int dom, pci_bus; diff --git a/qemu-monitor.hx b/qemu-monitor.hx index a889fed..aee5ff9 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -510,7 +510,19 @@ Add drive to PCI storage controller. ETEXI #if defined(TARGET_I386) - { "pci_add", "pci_addr:s,type:s,opts:s?", pci_device_hot_add, "auto|[[<domain>:]<bus>:]<slot> nic|storage|host [[vlan=n][,macaddr=addr][,model=type]] [file=file][,if=type][,bus=nr]... [host=02:00.0[,name=string][,dma=none]", "hot-add PCI device" }, + { "drive_del", "ss", drive_hot_del, "[[<domain>:]<bus>:]<slot>\n" + "bus=n,unit=m[,if=type]\n", + "Delete drive from PCI storage controller" }, +#endif +STEXI +@item drive_del +Delete drive from PCI storage controller. The device must be identified +by the bus and unit parameters. Currently, only the LSI SCSI driver +supports drive removal. +ETEXI + +#if defined(TARGET_I386) + { "pci_add", "sss?", pci_device_hot_add, "auto|[[<domain>:]<bus>:]<slot> nic|storage|host [[vlan=n][,macaddr=addr][,model=type]] [file=file][,if=type][,bus=nr]... [host=02:00.0[,name=string][,dma=none]", "hot-add PCI device" }, #endif STEXI @item pci_add diff --git a/sysemu.h b/sysemu.h index 4fabb2a..0c08b48 100644 --- a/sysemu.h +++ b/sysemu.h @@ -218,6 +218,7 @@ void destroy_bdrvs(dev_match_fn *match_fn, void *arg); /* pci-hotplug */ void pci_device_hot_add(Monitor *mon, const QDict *qdict); void drive_hot_add(Monitor *mon, const QDict *qdict); +void drive_hot_del(Monitor *mon, const QDict *qdict); void pci_device_hot_remove(Monitor *mon, const char *pci_addr); void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict); void pci_device_hot_remove_success(int pcibus, int slot);