Re: [libvirt] [RFC v1 4/6] migration: Migration support for ephemeral hostdevs
On 05/13/2015 10:30 PM, Laine Stump wrote: On 05/13/2015 05:57 AM, Daniel P. Berrange wrote: On Wed, May 13, 2015 at 11:36:30AM +0800, Chen Fan wrote: add migration support for ephemeral host devices, introduce two 'detach' and 'restore' functions to unplug/plug host devices during migration. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_migration.c | 171 -- src/qemu/qemu_migration.h | 9 +++ src/qemu/qemu_process.c | 11 +++ 3 files changed, 187 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 56112f9..d5a698f 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c +void +qemuMigrationRestoreEphemeralDevices(virQEMUDriverPtr driver, + virConnectPtr conn, + virDomainObjPtr vm, + bool live) +{ +qemuDomainObjPrivatePtr priv = vm-privateData; +virDomainDeviceDefPtr dev; +int ret = -1; +size_t i; + +VIR_DEBUG(Rum domain restore ephemeral devices); + +for (i = 0; i priv-nEphemeralDevices; i++) { +dev = priv-ephemeralDevices[i]; + +switch ((virDomainDeviceType) dev-type) { +case VIR_DOMAIN_DEVICE_NET: +if (live) { +ret = qemuDomainAttachNetDevice(conn, driver, vm, +dev-data.net); +} else { +ret = virDomainNetInsert(vm-def, dev-data.net); +} + +if (!ret) +dev-data.net = NULL; +break; +case VIR_DOMAIN_DEVICE_HOSTDEV: +if (live) { +ret = qemuDomainAttachHostDevice(conn, driver, vm, + dev-data.hostdev); + } else { +ret =virDomainHostdevInsert(vm-def, dev-data.hostdev); +} This re-attach step is where we actually have far far far worse problems than with detach. This is blindly assuming that the guest on the target host can use the same hostdev that it was using on the source host. (kind of pointless to comment on, since pkrempa has changed my opinion by forcing me to think about the failure to reattach condition, but could be useful info for others) For a hostdev, yes, but not for interface type='network' (which would point to a libvirt network pool of VFs). This is essentially useless in the real world. Agreed (for plain hostdev) Even if the same vendor/model device is available on the target host, it is very unlikely to be available at the same bus/slot/function that it was on the source. It is quite likely neccessary to allocate a complete different NIC, or if using SRIOV allocate a different function. It is also not uncommon to have different vendor/models, so a completely different NIC may be required. In the case of a network device, a different brand/model of NIC at a different PCI address using a different guest driver shouldn't be a problem for the guest, as long as the MAC address is the same (for a Linux guest anyway; not sure what a Windows guest would do with a NIC that had the same MAC but used a different driver). This points out the folly of trying to do migration with attached hostdevs (managed at *any* level), for anything other than SRIOV VFs (which can have their MAC address set before attach, unlike non-SRIOV NICs). . So should we focus on implementing the feature that support migration with SRIOV VFs at first? I think that is simple to achieve my original target that implement NIC passthrough device migration. because sometimes we assign a native NIC to guest to keep the performance of network I/O, due to the MAC limitation of the non-SRIOV NICs, as laine said the cost of SRIOV NIC is cheaper than what we try. Thanks, Chen -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [RFC v1 3/6] qemu: add check ephemeral devices only for PCI host devices
On 05/13/2015 04:17 PM, Peter Krempa wrote: On Wed, May 13, 2015 at 11:36:29 +0800, Chen Fan wrote: currently, we only support PCI host devices with ephemeral flag. and USB already supports migration. so maybe in the near future we can support SCSI. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_command.c | 10 ++ src/qemu/qemu_migration.c | 11 +++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index fc81214..5acd8b4 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -10182,6 +10182,16 @@ qemuBuildCommandLine(virConnectPtr conn, /* PCI */ if (hostdev-mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS +hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB +(hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI + hostdev-ephemeral)) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(non-USB and non-PCI device assignment with ephemeral + flag are not supported by this version of qemu)); This functionality is not based on qemu support but on libvirt implementation so the error message is incorrect. indeed. thanks for pointing out this. Chen +goto error; +} + +if (hostdev-mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS hostdev-source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) { int backend = hostdev-source.subsys.u.pci.backend; diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 83be435..56112f9 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1981,21 +1981,24 @@ qemuMigrationIsAllowed(virQEMUDriverPtr driver, virDomainObjPtr vm, def = vm-def; } -/* Migration with USB host devices is allowed, all other devices are - * forbidden. +/* + * Migration with USB and ephemeral PCI host devices host devices are allowed, + * all other devices are forbidden. */ forbid = false; for (i = 0; i def-nhostdevs; i++) { virDomainHostdevDefPtr hostdev = def-hostdevs[i]; if (hostdev-mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || -hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { +(hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB +!hostdev-ephemeral)) { forbid = true; break; } } if (forbid) { virReportError(VIR_ERR_OPERATION_INVALID, %s, - _(domain has assigned non-USB host devices)); + _(domain has assigned non-USB and + non-ephemeral host devices)); return false; } This patch has to be moved after you actually implement the ephemeral device unplug code, since an intermediate state would allow to bypass the check while the devices actually would not be unplugged. Peter -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [RFC v1 4/6] migration: Migration support for ephemeral hostdevs
On 05/13/2015 04:36 PM, Peter Krempa wrote: On Wed, May 13, 2015 at 11:36:30 +0800, Chen Fan wrote: add migration support for ephemeral host devices, introduce two 'detach' and 'restore' functions to unplug/plug host devices during migration. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_migration.c | 171 -- src/qemu/qemu_migration.h | 9 +++ src/qemu/qemu_process.c | 11 +++ 3 files changed, 187 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 56112f9..d5a698f 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -3384,6 +3384,158 @@ qemuMigrationPrepareDef(virQEMUDriverPtr driver, return def; } +int +qemuMigrationDetachEphemeralDevices(virQEMUDriverPtr driver, +virDomainObjPtr vm, +bool live) +{ +qemuDomainObjPrivatePtr priv = vm-privateData; +virDomainHostdevDefPtr hostdev; +virDomainNetDefPtr net; +virDomainDeviceDef dev; +virDomainDeviceDefPtr dev_copy = NULL; +virCapsPtr caps = NULL; +int actualType; +int ret = -1; +size_t i; + +VIR_DEBUG(Rum domain detach ephemeral devices); + +if (!(caps = virQEMUDriverGetCapabilities(driver, false))) +return ret; + +for (i = 0; i vm-def-nnets;) { +net = vm-def-nets[i]; + +actualType = virDomainNetGetActualType(net); +if (actualType != VIR_DOMAIN_NET_TYPE_HOSTDEV) { +i++; +continue; +} + +hostdev = virDomainNetGetActualHostdev(net); +if (hostdev-mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || +hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI || +!hostdev-ephemeral) { +i++; +continue; +} + +dev.type = VIR_DOMAIN_DEVICE_NET; +dev.data.net = net; + +dev_copy = virDomainDeviceDefCopy(dev, vm-def, + caps, driver-xmlopt); +if (!dev_copy) +goto cleanup; + +if (live) { +/* nnets reduced */ +if (qemuDomainDetachNetDevice(driver, vm, dev_copy) 0) +goto cleanup; So this is where the fun begins. qemuDomainDetachNetDevice is not designed to be called this way since the detach API where it's used normally returns 0 in the following two cases: 1) The detach was successfull, the guest removed the device 2) The detach request was successful, but guest did not remove the device yet In the latter case you need to wait for a event to successfully know when the device was removed. Since this might very well happen the code will need to be changed to take that option into account. Please note that that step will make all the things really complicated. did you said the event is DEVICE_DELETED ? I saw the code the funcition qemuDomainWaitForDeviceRemoval has been used for waiting device removed from guest. Thanks, Chen Peter -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RFC v1 1/6] conf: add ephemeral element for hostdev supporting migration
the ephemeral flag helps support migration with PCI-passthrough. An ephemeral hostdev is automatically unplugged before migration and replugged (if one is available on the destination) after migration. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- docs/schemas/domaincommon.rng | 10 ++ docs/schemas/network.rng | 5 + src/conf/domain_conf.c | 14 +- src/conf/domain_conf.h | 1 + src/conf/network_conf.c| 13 + src/conf/network_conf.h| 1 + src/network/bridge_driver.c| 1 + src/qemu/qemu_command.c| 1 + tests/networkxml2xmlin/hostdev-pf.xml | 2 +- tests/networkxml2xmlin/hostdev.xml | 2 +- tests/networkxml2xmlout/hostdev-pf.xml | 2 +- tests/networkxml2xmlout/hostdev.xml| 2 +- .../qemuxml2argv-controller-order.xml | 2 +- .../qemuxml2argv-hostdev-pci-address-device.xml| 2 +- .../qemuxml2argv-hostdev-pci-address.xml | 2 +- .../qemuxml2argv-hostdev-scsi-autogen-address.xml | 22 +++--- .../qemuxml2argv-hostdev-scsi-lsi-iscsi-auth.xml | 4 ++-- .../qemuxml2argv-hostdev-scsi-lsi-iscsi.xml| 4 ++-- .../qemuxml2argv-hostdev-scsi-lsi.xml | 2 +- .../qemuxml2argv-hostdev-scsi-rawio.xml| 2 +- .../qemuxml2argv-hostdev-scsi-readonly.xml | 2 +- .../qemuxml2argv-hostdev-scsi-sgio.xml | 2 +- .../qemuxml2argv-hostdev-scsi-shareable.xml| 2 +- ...qemuxml2argv-hostdev-scsi-virtio-iscsi-auth.xml | 4 ++-- .../qemuxml2argv-hostdev-scsi-virtio-iscsi.xml | 4 ++-- .../qemuxml2argv-hostdev-scsi-virtio-scsi.xml | 2 +- ...emuxml2argv-hostdev-usb-address-device-boot.xml | 2 +- .../qemuxml2argv-hostdev-usb-address-device.xml| 2 +- .../qemuxml2argv-hostdev-usb-address.xml | 2 +- .../qemuxml2argv-hostdev-vfio-multidomain.xml | 2 +- .../qemuxml2argvdata/qemuxml2argv-hostdev-vfio.xml | 2 +- .../qemuxml2argv-net-hostdev-multidomain.xml | 2 +- .../qemuxml2argv-net-hostdev-vfio-multidomain.xml | 2 +- .../qemuxml2argv-net-hostdev-vfio.xml | 2 +- .../qemuxml2argvdata/qemuxml2argv-net-hostdev.xml | 2 +- tests/qemuxml2argvdata/qemuxml2argv-pci-rom.xml| 4 ++-- ...qemuxml2xmlout-hostdev-scsi-autogen-address.xml | 22 +++--- 37 files changed, 99 insertions(+), 55 deletions(-) diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index b1d883f..6f4551c 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2261,6 +2261,11 @@ ref name=virYesNo/ /attribute /optional + optional +attribute name=ephemeral + ref name=virYesNo/ +/attribute + /optional interleave element name=source optional @@ -3717,6 +3722,11 @@ ref name=virYesNo/ /attribute /optional +optional + attribute name=ephemeral +ref name=virYesNo/ + /attribute +/optional choice ref name=hostdevsubsyspci/ ref name=hostdevsubsysusb/ diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng index 4edb6eb..d63b066 100644 --- a/docs/schemas/network.rng +++ b/docs/schemas/network.rng @@ -115,6 +115,11 @@ ref name=virYesNo/ /attribute /optional +optional + attribute name=ephemeral +ref name=virYesNo/ + /attribute +/optional interleave choice group diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 3d05844..a1a0602 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4823,6 +4823,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, { xmlNodePtr sourcenode; char *managed = NULL; +char *ephemeral = NULL; char *sgio = NULL; char *rawio = NULL; char *backendStr = NULL; @@ -4841,6 +4842,11 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, def-managed = true; } +if ((ephemeral = virXMLPropString(node, ephemeral)) != NULL) { +if (STREQ(ephemeral, yes)) +def-ephemeral = true; +} + sgio = virXMLPropString(node, sgio); rawio = virXMLPropString(node, rawio); @@ -18064,8 +18070,10 @@ virDomainActualNetDefFormat(virBufferPtr buf, virBufferAsprintf(buf, actual type='%s', typeStr); if (type == VIR_DOMAIN_NET_TYPE_HOSTDEV) { virDomainHostdevDefPtr hostdef = virDomainNetGetActualHostdev(def); -if (hostdef hostdef-managed) +if (hostdef hostdef-managed) virBufferAddLit(buf, managed='yes
[libvirt] [RFC v1 4/6] migration: Migration support for ephemeral hostdevs
add migration support for ephemeral host devices, introduce two 'detach' and 'restore' functions to unplug/plug host devices during migration. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_migration.c | 171 -- src/qemu/qemu_migration.h | 9 +++ src/qemu/qemu_process.c | 11 +++ 3 files changed, 187 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 56112f9..d5a698f 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -3384,6 +3384,158 @@ qemuMigrationPrepareDef(virQEMUDriverPtr driver, return def; } +int +qemuMigrationDetachEphemeralDevices(virQEMUDriverPtr driver, +virDomainObjPtr vm, +bool live) +{ +qemuDomainObjPrivatePtr priv = vm-privateData; +virDomainHostdevDefPtr hostdev; +virDomainNetDefPtr net; +virDomainDeviceDef dev; +virDomainDeviceDefPtr dev_copy = NULL; +virCapsPtr caps = NULL; +int actualType; +int ret = -1; +size_t i; + +VIR_DEBUG(Rum domain detach ephemeral devices); + +if (!(caps = virQEMUDriverGetCapabilities(driver, false))) +return ret; + +for (i = 0; i vm-def-nnets;) { +net = vm-def-nets[i]; + +actualType = virDomainNetGetActualType(net); +if (actualType != VIR_DOMAIN_NET_TYPE_HOSTDEV) { +i++; +continue; +} + +hostdev = virDomainNetGetActualHostdev(net); +if (hostdev-mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || +hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI || +!hostdev-ephemeral) { +i++; +continue; +} + +dev.type = VIR_DOMAIN_DEVICE_NET; +dev.data.net = net; + +dev_copy = virDomainDeviceDefCopy(dev, vm-def, + caps, driver-xmlopt); +if (!dev_copy) +goto cleanup; + +if (live) { +/* nnets reduced */ +if (qemuDomainDetachNetDevice(driver, vm, dev_copy) 0) +goto cleanup; +} else { +virDomainNetDefFree(virDomainNetRemove(vm-def, i)); +} +if (VIR_APPEND_ELEMENT(priv-ephemeralDevices, + priv-nEphemeralDevices, + dev_copy) 0) { +goto cleanup; +} +dev_copy = NULL; +} + +for (i = 0; i vm-def-nhostdevs;) { +hostdev = vm-def-hostdevs[i]; + +if (hostdev-mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || +hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI || +!hostdev-ephemeral) { +i++; +continue; +} + +dev.type = VIR_DOMAIN_DEVICE_HOSTDEV; +dev.data.hostdev = hostdev; + +VIR_FREE(dev_copy); +dev_copy = virDomainDeviceDefCopy(dev, vm-def, + caps, driver-xmlopt); +if (!dev_copy) +goto cleanup; + +if (live) { +/* nhostdevs reduced */ +if (qemuDomainDetachHostDevice(driver, vm, dev_copy) 0) +goto cleanup; +} else { +virDomainHostdevDefFree(virDomainHostdevRemove(vm-def, i)); +} +if (VIR_APPEND_ELEMENT(priv-ephemeralDevices, + priv-nEphemeralDevices, + dev_copy) 0) { +goto cleanup; +} +dev_copy = NULL; +} + +ret = 0; + cleanup: +virDomainDeviceDefFree(dev_copy); +virObjectUnref(caps); + +return ret; +} + +void +qemuMigrationRestoreEphemeralDevices(virQEMUDriverPtr driver, + virConnectPtr conn, + virDomainObjPtr vm, + bool live) +{ +qemuDomainObjPrivatePtr priv = vm-privateData; +virDomainDeviceDefPtr dev; +int ret = -1; +size_t i; + +VIR_DEBUG(Rum domain restore ephemeral devices); + +for (i = 0; i priv-nEphemeralDevices; i++) { +dev = priv-ephemeralDevices[i]; + +switch ((virDomainDeviceType) dev-type) { +case VIR_DOMAIN_DEVICE_NET: +if (live) { +ret = qemuDomainAttachNetDevice(conn, driver, vm, +dev-data.net); +} else { +ret = virDomainNetInsert(vm-def, dev-data.net); +} + +if (!ret) +dev-data.net = NULL; +break; +case VIR_DOMAIN_DEVICE_HOSTDEV: +if (live) { +ret = qemuDomainAttachHostDevice(conn, driver, vm, + dev-data.hostdev); + } else { +ret =virDomainHostdevInsert(vm-def, dev-data.hostdev); +} +if (!ret
[libvirt] [RFC v1 0/6] Live Migration with ephemeral host NIC devices
my main goal is to add support migration with host NIC passthrough devices and keep the network connectivity. this series patch base on Shradha's patches on https://www.redhat.com/archives/libvir-list/2012-November/msg01324.html which is add migration support for host passthrough devices. 1) unplug the ephemeral devices before migration 2) do native migration 3) when migration finished, hotplug the ephemeral devices TODO: keep network connectivity on guest level by bonding device. Chen Fan (6): conf: add ephemeral element for hostdev supporting migration qemu: Save ephemeral devices into qemuDomainObjPrivate qemu: add check ephemeral devices only for PCI host devices migration: Migration support for ephemeral hostdevs managedsave: move the domain xml handling forward to stop CPU managedsave: add managedsave support for ephemeral host devices docs/schemas/domaincommon.rng | 10 ++ docs/schemas/network.rng | 5 + src/conf/domain_conf.c | 14 +- src/conf/domain_conf.h | 1 + src/conf/network_conf.c| 13 ++ src/conf/network_conf.h| 1 + src/network/bridge_driver.c| 1 + src/qemu/qemu_command.c| 11 ++ src/qemu/qemu_domain.c | 5 + src/qemu/qemu_domain.h | 3 + src/qemu/qemu_driver.c | 48 +++--- src/qemu/qemu_migration.c | 182 - src/qemu/qemu_migration.h | 9 + src/qemu/qemu_process.c| 12 ++ tests/networkxml2xmlin/hostdev-pf.xml | 2 +- tests/networkxml2xmlin/hostdev.xml | 2 +- tests/networkxml2xmlout/hostdev-pf.xml | 2 +- tests/networkxml2xmlout/hostdev.xml| 2 +- .../qemuxml2argv-controller-order.xml | 2 +- .../qemuxml2argv-hostdev-pci-address-device.xml| 2 +- .../qemuxml2argv-hostdev-pci-address.xml | 2 +- .../qemuxml2argv-hostdev-scsi-autogen-address.xml | 22 +-- .../qemuxml2argv-hostdev-scsi-lsi-iscsi-auth.xml | 4 +- .../qemuxml2argv-hostdev-scsi-lsi-iscsi.xml| 4 +- .../qemuxml2argv-hostdev-scsi-lsi.xml | 2 +- .../qemuxml2argv-hostdev-scsi-rawio.xml| 2 +- .../qemuxml2argv-hostdev-scsi-readonly.xml | 2 +- .../qemuxml2argv-hostdev-scsi-sgio.xml | 2 +- .../qemuxml2argv-hostdev-scsi-shareable.xml| 2 +- ...qemuxml2argv-hostdev-scsi-virtio-iscsi-auth.xml | 4 +- .../qemuxml2argv-hostdev-scsi-virtio-iscsi.xml | 4 +- .../qemuxml2argv-hostdev-scsi-virtio-scsi.xml | 2 +- ...emuxml2argv-hostdev-usb-address-device-boot.xml | 2 +- .../qemuxml2argv-hostdev-usb-address-device.xml| 2 +- .../qemuxml2argv-hostdev-usb-address.xml | 2 +- .../qemuxml2argv-hostdev-vfio-multidomain.xml | 2 +- .../qemuxml2argvdata/qemuxml2argv-hostdev-vfio.xml | 2 +- .../qemuxml2argv-net-hostdev-multidomain.xml | 2 +- .../qemuxml2argv-net-hostdev-vfio-multidomain.xml | 2 +- .../qemuxml2argv-net-hostdev-vfio.xml | 2 +- .../qemuxml2argvdata/qemuxml2argv-net-hostdev.xml | 2 +- tests/qemuxml2argvdata/qemuxml2argv-pci-rom.xml| 4 +- ...qemuxml2xmlout-hostdev-scsi-autogen-address.xml | 22 +-- 43 files changed, 340 insertions(+), 83 deletions(-) -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RFC v1 5/6] managedsave: move the domain xml handling forward to stop CPU
we should save the XML information to image head before we hotunplug the ephemeral devices. so here we handle XML ahead. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_driver.c | 40 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b3263ac..86d93d2 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3179,26 +3179,6 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom, priv-job.current-type = VIR_DOMAIN_JOB_UNBOUNDED; -/* Pause */ -if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { -was_running = true; -if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE, -QEMU_ASYNC_JOB_SAVE) 0) -goto endjob; - -if (!virDomainObjIsActive(vm)) { -virReportError(VIR_ERR_INTERNAL_ERROR, %s, - _(guest unexpectedly quit)); -goto endjob; -} -} - - /* libvirt.c already guaranteed these two flags are exclusive. */ -if (flags VIR_DOMAIN_SAVE_RUNNING) -was_running = true; -else if (flags VIR_DOMAIN_SAVE_PAUSED) -was_running = false; - /* Get XML for the domain. Restore needs only the inactive xml, * including secure. We should get the same result whether xmlin * is NULL or whether it was the live xml of the domain moments @@ -3225,6 +3205,26 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom, goto endjob; } +/* Pause */ +if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { +was_running = true; +if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE, +QEMU_ASYNC_JOB_SAVE) 0) +goto endjob; + +if (!virDomainObjIsActive(vm)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(guest unexpectedly quit)); +goto endjob; +} +} + + /* libvirt.c already guaranteed these two flags are exclusive. */ +if (flags VIR_DOMAIN_SAVE_RUNNING) +was_running = true; +else if (flags VIR_DOMAIN_SAVE_PAUSED) +was_running = false; + ret = qemuDomainSaveMemory(driver, vm, path, xml, compressed, was_running, flags, QEMU_ASYNC_JOB_SAVE); if (ret 0) -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RFC v1 3/6] qemu: add check ephemeral devices only for PCI host devices
currently, we only support PCI host devices with ephemeral flag. and USB already supports migration. so maybe in the near future we can support SCSI. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_command.c | 10 ++ src/qemu/qemu_migration.c | 11 +++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index fc81214..5acd8b4 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -10182,6 +10182,16 @@ qemuBuildCommandLine(virConnectPtr conn, /* PCI */ if (hostdev-mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS +hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB +(hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI + hostdev-ephemeral)) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(non-USB and non-PCI device assignment with ephemeral + flag are not supported by this version of qemu)); +goto error; +} + +if (hostdev-mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS hostdev-source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) { int backend = hostdev-source.subsys.u.pci.backend; diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 83be435..56112f9 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1981,21 +1981,24 @@ qemuMigrationIsAllowed(virQEMUDriverPtr driver, virDomainObjPtr vm, def = vm-def; } -/* Migration with USB host devices is allowed, all other devices are - * forbidden. +/* + * Migration with USB and ephemeral PCI host devices host devices are allowed, + * all other devices are forbidden. */ forbid = false; for (i = 0; i def-nhostdevs; i++) { virDomainHostdevDefPtr hostdev = def-hostdevs[i]; if (hostdev-mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || -hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { +(hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB +!hostdev-ephemeral)) { forbid = true; break; } } if (forbid) { virReportError(VIR_ERR_OPERATION_INVALID, %s, - _(domain has assigned non-USB host devices)); + _(domain has assigned non-USB and + non-ephemeral host devices)); return false; } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RFC v1 6/6] managedsave: add managedsave support for ephemeral host devices
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_driver.c | 8 src/qemu/qemu_process.c | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 86d93d2..112acb1 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3208,6 +3208,10 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom, /* Pause */ if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { was_running = true; +/* Detach ephemeral host devices first */ +if (qemuMigrationDetachEphemeralDevices(driver, vm, true) 0) +goto endjob; + if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE, QEMU_ASYNC_JOB_SAVE) 0) goto endjob; @@ -3249,6 +3253,8 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom, VIR_DOMAIN_EVENT_SUSPENDED, VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR); } +qemuMigrationRestoreEphemeralDevices(driver, dom-conn, vm, true); + virSetError(save_err); virFreeError(save_err); } @@ -6404,6 +6410,8 @@ qemuDomainSaveImageStartVM(virConnectPtr conn, if (event) qemuDomainEventQueue(driver, event); +/* Restore ephemeral devices */ +qemuMigrationRestoreEphemeralDevices(driver, NULL, vm, true); /* If it was running before, resume it now unless caller requested pause. */ if (header-was_running !start_paused) { diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 904c447..6519477 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4501,7 +4501,8 @@ int qemuProcessStart(virConnectPtr conn, * during migration. hence we should remove the reserved * PCI address for ephemeral device. */ -if (vmop == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START) +if (vmop == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START || +vmop == VIR_NETDEV_VPORT_PROFILE_OP_RESTORE) if (qemuMigrationDetachEphemeralDevices(driver, vm, false) 0) goto cleanup; -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RFC v1 2/6] qemu: Save ephemeral devices into qemuDomainObjPrivate
after migration we should restore the ephemeral devices. so we save them to qemuDomainObjPrivate. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_domain.c | 5 + src/qemu/qemu_domain.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index d8a2087..5ce933d 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -425,6 +425,7 @@ static void qemuDomainObjPrivateFree(void *data) { qemuDomainObjPrivatePtr priv = data; +size_t i; virObjectUnref(priv-qemuCaps); @@ -441,6 +442,10 @@ qemuDomainObjPrivateFree(void *data) virCondDestroy(priv-unplugFinished); virChrdevFree(priv-devs); +for (i = 0; i priv-nEphemeralDevices; i++) +virDomainDeviceDefFree(priv-ephemeralDevices[i]); +VIR_FREE(priv-ephemeralDevices); + /* This should never be non-NULL if we get here, but just in case... */ if (priv-mon) { VIR_ERROR(_(Unexpected QEMU monitor still active during domain deletion)); diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index fe3e2b1..e75c828 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -180,6 +180,9 @@ struct _qemuDomainObjPrivate { size_t ncleanupCallbacks; size_t ncleanupCallbacks_max; +virDomainDeviceDefPtr *ephemeralDevices; +size_t nEphemeralDevices; + virCgroupPtr cgroup; virCond unplugFinished; /* signals that unpluggingDevice was unplugged */ -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [RFC 0/7] Live Migration with Pass-through Devices proposal
On 04/20/2015 06:29 AM, Laine Stump wrote: On 04/17/2015 04:53 AM, Chen Fan wrote: backgrond: Live migration is one of the most important features of virtualization technology. With regard to recent virtualization techniques, performance of network I/O is critical. Current network I/O virtualization (e.g. Para-virtualized I/O, VMDq) has a significant performance gap with native network I/O. Pass-through network devices have near native performance, however, they have thus far prevented live migration. No existing methods solve the problem of live migration with pass-through devices perfectly. There was an idea to solve the problem in website: https://www.kernel.org/doc/ols/2008/ols2008v2-pages-261-267.pdf Please refer to above document for detailed information. This functionality has been on my mind/bug list for a long time, but I haven't been able to pursue it much. See this BZ, along with the original patches submitted by Shradha Shah from SolarFlare: https://bugzilla.redhat.com/show_bug.cgi?id=896716 (I was a bit optimistic in my initial review of the patches - there are actually a lot of issues that weren't handled by those patches.) So I think this problem maybe could be solved by using the combination of existing technology. and the following steps are we considering to implement: - before boot VM, we anticipate to specify two NICs for creating bonding device (one plugged and one virtual NIC) in XML. here we can specify the NIC's mac addresses in XML, which could facilitate qemu-guest-agent to find the network interfaces in guest. An interesting idea, but I think that is a 2nd level enhancement, not necessary initially (and maybe not ever, due to the high possibility of it being extremely difficult to get right in 100% of the cases). - when qemu-guest-agent startup in guest it would send a notification to libvirt, then libvirt will call the previous registered initialize callbacks. so through the callback functions, we can create the bonding device according to the XML configuration. and here we use netcf tool which can facilitate to create bonding device easily. This isn't quite making sense - the bond will be on the guest, which may not have netcf installed. Anyway, I think it should be up to the guest's own system network config to have the bond already setup. If you try to impose it from outside that infrastructure, you run too much risk of running afoul of something on the guest (e.g. NetworkManager) - during migration, unplug the passthroughed NIC. then do native migration. Correct. This is the most important part. But not just unplugging it, you also need to wait until the unplug operation completes (it is asynchronous). (After this point, the emulated NIC that is part of the bond would get all of the traffic). - on destination side, check whether need to hotplug new NIC according to specified XML. usually, we use migrate --xml command option to specify the destination host NIC mac address to hotplug a new NIC, because source side passthrough NIC mac address is different, then hotplug the deivce according to the destination XML configuration. Why does the MAC address need to be different? Are you suggesting doing this with passed-through non-SRIOV NICs? An SRIOV virtual function gets its MAC address from the libvirt config, so it's very simple to use the same MAC address across the migration. Any network card that would be able to do this on any sort of useful scale will be SRIOV-capable (or should be replaced with one that is - some of them are not that expensive). Hi Laine, I think SRIOV virtual NIC to support migration is good idea, but I also think some passthrough NIC without SRIOV-capable. for these NIC devices we only able to use hostdev to specify the passthrough function, so for these NIC I think we should support too. Thanks, Chen TODO: 1. when hot add a new NIC in destination side after migration finished, the NIC device need to re-enslave on bonding device in guest. otherwise, it is offline. maybe we should consider bonding driver to support add interfaces dynamically. I never looked at the details of how SolarFlare's code handled the guest side (they have/had their own patchset they maintained for some older version of libvirt which integrated with some sort of enhanced bonding driver on the guests). I assumed the bond driver could handle this already, but have to say I never investigated. This is an example on how this might work, so I want to hear some voices about this scenario. Thanks, Chen Chen Fan (7): qemu-agent: add agent init callback when detecting guest setup qemu: add guest init event callback to do the initialize work for guest hostdev: add a 'bond' type element in hostdev element Putting this into hostdev is the wrong approach, for two reasons: 1) it doesn't account for the device to be used being in a different address on the source
Re: [libvirt] [RFC 0/7] Live Migration with Pass-through Devices proposal
Hi Laine, Thanks for your review for my patches. and do you know that solarflare's patches have made some update version since https://www.redhat.com/archives/libvir-list/2012-November/msg01324.html ? if not, I hope to go on to complete this work. ;) Thanks, Chen On 04/20/2015 06:29 AM, Laine Stump wrote: On 04/17/2015 04:53 AM, Chen Fan wrote: backgrond: Live migration is one of the most important features of virtualization technology. With regard to recent virtualization techniques, performance of network I/O is critical. Current network I/O virtualization (e.g. Para-virtualized I/O, VMDq) has a significant performance gap with native network I/O. Pass-through network devices have near native performance, however, they have thus far prevented live migration. No existing methods solve the problem of live migration with pass-through devices perfectly. There was an idea to solve the problem in website: https://www.kernel.org/doc/ols/2008/ols2008v2-pages-261-267.pdf Please refer to above document for detailed information. This functionality has been on my mind/bug list for a long time, but I haven't been able to pursue it much. See this BZ, along with the original patches submitted by Shradha Shah from SolarFlare: https://bugzilla.redhat.com/show_bug.cgi?id=896716 (I was a bit optimistic in my initial review of the patches - there are actually a lot of issues that weren't handled by those patches.) So I think this problem maybe could be solved by using the combination of existing technology. and the following steps are we considering to implement: - before boot VM, we anticipate to specify two NICs for creating bonding device (one plugged and one virtual NIC) in XML. here we can specify the NIC's mac addresses in XML, which could facilitate qemu-guest-agent to find the network interfaces in guest. An interesting idea, but I think that is a 2nd level enhancement, not necessary initially (and maybe not ever, due to the high possibility of it being extremely difficult to get right in 100% of the cases). - when qemu-guest-agent startup in guest it would send a notification to libvirt, then libvirt will call the previous registered initialize callbacks. so through the callback functions, we can create the bonding device according to the XML configuration. and here we use netcf tool which can facilitate to create bonding device easily. This isn't quite making sense - the bond will be on the guest, which may not have netcf installed. Anyway, I think it should be up to the guest's own system network config to have the bond already setup. If you try to impose it from outside that infrastructure, you run too much risk of running afoul of something on the guest (e.g. NetworkManager) - during migration, unplug the passthroughed NIC. then do native migration. Correct. This is the most important part. But not just unplugging it, you also need to wait until the unplug operation completes (it is asynchronous). (After this point, the emulated NIC that is part of the bond would get all of the traffic). - on destination side, check whether need to hotplug new NIC according to specified XML. usually, we use migrate --xml command option to specify the destination host NIC mac address to hotplug a new NIC, because source side passthrough NIC mac address is different, then hotplug the deivce according to the destination XML configuration. Why does the MAC address need to be different? Are you suggesting doing this with passed-through non-SRIOV NICs? An SRIOV virtual function gets its MAC address from the libvirt config, so it's very simple to use the same MAC address across the migration. Any network card that would be able to do this on any sort of useful scale will be SRIOV-capable (or should be replaced with one that is - some of them are not that expensive). TODO: 1. when hot add a new NIC in destination side after migration finished, the NIC device need to re-enslave on bonding device in guest. otherwise, it is offline. maybe we should consider bonding driver to support add interfaces dynamically. I never looked at the details of how SolarFlare's code handled the guest side (they have/had their own patchset they maintained for some older version of libvirt which integrated with some sort of enhanced bonding driver on the guests). I assumed the bond driver could handle this already, but have to say I never investigated. This is an example on how this might work, so I want to hear some voices about this scenario. Thanks, Chen Chen Fan (7): qemu-agent: add agent init callback when detecting guest setup qemu: add guest init event callback to do the initialize work for guest hostdev: add a 'bond' type element in hostdev element Putting this into hostdev is the wrong approach, for two reasons: 1) it doesn't account for the device to be used being in a different address on the source and destination hosts
[libvirt] [RFC 6/7] migrate: hot remove hostdev at perform phase for bond device
For bond device, we can support the migrate, we can simple to hot remove the device from source side, and after migration end, we hot add the new device at destination side. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_driver.c| 57 +++ src/qemu/qemu_migration.c | 7 ++ 2 files changed, 64 insertions(+) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7368145..0ba9e4a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -12353,6 +12353,58 @@ qemuDomainMigrateBegin3(virDomainPtr domain, cookieout, cookieoutlen, flags); } +static int +qemuDomainRemovePciPassThruDevices(virConnectPtr conn, + virDomainObjPtr vm) +{ +virQEMUDriverPtr driver = conn-privateData; +virDomainDeviceDef dev; +virDomainDeviceDefPtr dev_copy = NULL; +virCapsPtr caps = NULL; +int ret = -1; +size_t i; + +if (!(caps = virQEMUDriverGetCapabilities(driver, false))) +goto cleanup; + +if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_OUT)) +goto cleanup; + +/* unplug passthrough bond device */ +for (i = 0; i vm-def-nhostdevs; i++) { +virDomainHostdevDefPtr hostdev = vm-def-hostdevs[i]; + +if (hostdev-mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS +hostdev-source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI +hostdev-source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO +hostdev-source.subsys.u.pci.device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND) { + +dev.type = VIR_DOMAIN_DEVICE_HOSTDEV; +dev.data.hostdev = hostdev; + +dev_copy = virDomainDeviceDefCopy(dev, vm-def, caps, driver-xmlopt); +if (!dev_copy) +goto cleanup; + +if (qemuDomainDetachHostDevice(driver, vm, dev_copy) 0) { +virDomainDeviceDefFree(dev_copy); +goto cleanup; +} + +virDomainDeviceDefFree(dev_copy); +if (qemuDomainUpdateDeviceList(driver, vm, QEMU_ASYNC_JOB_NONE) 0) +goto cleanup; +} +} + +ret = 0; + + cleanup: +virObjectUnref(caps); + +return ret; +} + static char * qemuDomainMigrateBegin3Params(virDomainPtr domain, virTypedParameterPtr params, @@ -12688,6 +12740,11 @@ qemuDomainMigratePerform3Params(virDomainPtr dom, return -1; } +if (qemuDomainRemovePciPassThruDevices(dom-conn, vm) 0) { +qemuDomObjEndAPI(vm); +return -1; +} + return qemuMigrationPerform(driver, dom-conn, vm, dom_xml, dconnuri, uri, graphicsuri, listenAddress, cookiein, cookieinlen, cookieout, cookieoutlen, diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 611f53a..9ea83df 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2000,6 +2000,13 @@ qemuMigrationIsAllowed(virQEMUDriverPtr driver, virDomainObjPtr vm, forbid = false; for (i = 0; i def-nhostdevs; i++) { virDomainHostdevDefPtr hostdev = def-hostdevs[i]; + +if (hostdev-mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS +hostdev-source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI +hostdev-source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO +hostdev-source.subsys.u.pci.device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND) +continue; + if (hostdev-mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { forbid = true; -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RFC 2/3] qemu-agent: add guest-network-delete-interface command
Add a corresponding command to guest-network-set-interface. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- qga/commands-posix.c | 51 +++ qga/commands-win32.c | 6 ++ qga/qapi-schema.json | 11 +++ 3 files changed, 68 insertions(+) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 5ee7949..058085f 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -1971,6 +1971,51 @@ int64_t qmp_guest_network_set_interface(GuestNetworkInterface2 *interface, return 0; } + +int64_t qmp_guest_network_delete_interface(const char *name, Error **errp) +{ +struct netcf_if *iface; +int ret = -1; +unsigned int flags = 0; + +/* open netcf */ +if (netcf == NULL) { +if (ncf_init(netcf, NULL) != 0) { +error_setg(errp, netcf init failed); +return ret; +} +} + +iface = ncf_lookup_by_name(netcf, name); +if (!iface) { + error_setg(errp, couldn't find interface named '%s', name); + return ret; +} + +if (ncf_if_status(iface, flags) 0) { +error_setg(errp, netcf interface get status failed); +goto cleanup; +} + +if (flags NETCF_IFACE_ACTIVE) { +ret = ncf_if_down(iface); +if (ret 0) { +error_setg(errp, netcf interface stop failed); +goto cleanup; +} +} + +ret = ncf_if_undefine(iface); +if (ret 0) { +error_setg(errp, netcf interface delete failed); +goto cleanup; +} + +ret = 0; +cleanup: +ncf_if_free(iface); +return ret; +} #else int64_t qmp_guest_network_set_interface(GuestNetworkInterface2 *interface, Error **errp) @@ -1978,6 +2023,12 @@ int64_t qmp_guest_network_set_interface(GuestNetworkInterface2 *interface, error_set(errp, QERR_UNSUPPORTED); return -1; } + +int64_t qmp_guest_network_delete_interface(const char *name, Error **errp) +{ +error_set(errp, QERR_UNSUPPORTED); +return -1; +} #endif #define SYSCONF_EXACT(name, errp) sysconf_exact((name), #name, (errp)) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 4c14514..52f6e47 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -453,6 +453,12 @@ int64_t qmp_guest_network_set_interface(GuestNetworkInterface2 *interface, return -1; } +int64_t qmp_guest_network_delete_interface(const char *name, Error **errp) +{ +error_set(errp, QERR_UNSUPPORTED); +return -1; +} + /* add unsupported commands to the blacklist */ GList *ga_command_blacklist_init(GList *blacklist) { diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index 77f499b..b886f97 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -642,6 +642,17 @@ 'returns': 'int' } ## +# @guest-network-delete-interface: +# +# @name: interface name. +# +# Since: 2.3 +## +{ 'command': 'guest-network-delete-interface', + 'data' : {'name': 'str' }, + 'returns': 'int' } + +## # @GuestLogicalProcessor: # # @logical-id: Arbitrary guest-specific unique identifier of the VCPU. -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RFC 0/7] Live Migration with Pass-through Devices proposal
backgrond: Live migration is one of the most important features of virtualization technology. With regard to recent virtualization techniques, performance of network I/O is critical. Current network I/O virtualization (e.g. Para-virtualized I/O, VMDq) has a significant performance gap with native network I/O. Pass-through network devices have near native performance, however, they have thus far prevented live migration. No existing methods solve the problem of live migration with pass-through devices perfectly. There was an idea to solve the problem in website: https://www.kernel.org/doc/ols/2008/ols2008v2-pages-261-267.pdf Please refer to above document for detailed information. So I think this problem maybe could be solved by using the combination of existing technology. and the following steps are we considering to implement: - before boot VM, we anticipate to specify two NICs for creating bonding device (one plugged and one virtual NIC) in XML. here we can specify the NIC's mac addresses in XML, which could facilitate qemu-guest-agent to find the network interfaces in guest. - when qemu-guest-agent startup in guest it would send a notification to libvirt, then libvirt will call the previous registered initialize callbacks. so through the callback functions, we can create the bonding device according to the XML configuration. and here we use netcf tool which can facilitate to create bonding device easily. - during migration, unplug the passthroughed NIC. then do native migration. - on destination side, check whether need to hotplug new NIC according to specified XML. usually, we use migrate --xml command option to specify the destination host NIC mac address to hotplug a new NIC, because source side passthrough NIC mac address is different, then hotplug the deivce according to the destination XML configuration. TODO: 1. when hot add a new NIC in destination side after migration finished, the NIC device need to re-enslave on bonding device in guest. otherwise, it is offline. maybe we should consider bonding driver to support add interfaces dynamically. This is an example on how this might work, so I want to hear some voices about this scenario. Thanks, Chen Chen Fan (7): qemu-agent: add agent init callback when detecting guest setup qemu: add guest init event callback to do the initialize work for guest hostdev: add a 'bond' type element in hostdev element qemu-agent: add qemuAgentCreateBond interface hostdev: add parse ip and route for bond configure migrate: hot remove hostdev at perform phase for bond device migrate: add hostdev migrate status to support hostdev migration docs/schemas/basictypes.rng | 6 ++ docs/schemas/domaincommon.rng | 37 src/conf/domain_conf.c| 195 ++--- src/conf/domain_conf.h| 40 +++-- src/conf/networkcommon_conf.c | 17 src/conf/networkcommon_conf.h | 17 src/libvirt_private.syms | 1 + src/qemu/qemu_agent.c | 196 +- src/qemu/qemu_agent.h | 12 +++ src/qemu/qemu_command.c | 3 + src/qemu/qemu_domain.c| 70 +++ src/qemu/qemu_domain.h| 14 +++ src/qemu/qemu_driver.c| 38 src/qemu/qemu_hotplug.c | 8 +- src/qemu/qemu_migration.c | 91 src/qemu/qemu_migration.h | 4 + src/qemu/qemu_process.c | 32 +++ src/util/virhostdev.c | 3 + 18 files changed, 745 insertions(+), 39 deletions(-) -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RFC 1/3] qemu-agent: add guest-network-set-interface command
Nowadays, qemu has supported physical NIC hotplug for high network throughput. but it's in conflict with live migration feature, to keep network connectivity, we could to create bond device interface which provides a mechanism for enslaving multiple network interfaces into a single bond interface. the active-backup mode can be used for an automatic switch. so this patch is adding a guest-network-set-interface command for creating bond device. so the management can easy to create a bond device dynamically when guest running. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- configure| 16 qga/commands-posix.c | 261 +++ qga/commands-win32.c | 7 ++ qga/qapi-schema.json | 54 +++ 4 files changed, 338 insertions(+) diff --git a/configure b/configure index f185dd0..ebfcc6a 100755 --- a/configure +++ b/configure @@ -3618,6 +3618,18 @@ if test $darwin != yes -a $mingw32 != yes -a $solaris != yes -a \ fi ## +# Do we need netcf +netcf=no +cat $TMPC EOF +#include netcf.h +int main(void) { return 0; } +EOF +if compile_prog -lnetcf ; then +netcf=yes +libs_qga=$libs_qga -lnetcf +fi + +## # spice probe if test $spice != no ; then cat $TMPC EOF @@ -4697,6 +4709,10 @@ if test $spice = yes ; then echo CONFIG_SPICE=y $config_host_mak fi +if test $netcf = yes ; then + echo CONFIG_NETCF=y $config_host_mak +fi + if test $smartcard_nss = yes ; then echo CONFIG_SMARTCARD_NSS=y $config_host_mak echo NSS_LIBS=$nss_libs $config_host_mak diff --git a/qga/commands-posix.c b/qga/commands-posix.c index f6f3e3c..5ee7949 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -46,6 +46,10 @@ extern char **environ; #include sys/socket.h #include net/if.h +#ifdef CONFIG_NETCF +#include netcf.h +#endif + #ifdef FIFREEZE #define CONFIG_FSFREEZE #endif @@ -1719,6 +1723,263 @@ error: return NULL; } +#ifdef CONFIG_NETCF +static const char *interface_type_string[] = { +bond, +}; + +static const char *ip_address_type_string[] = { +ipv4, +ipv6, +}; + +static char *parse_options(const char *str, const char *needle) +{ +char *start, *end, *buffer = NULL; +char *ret = NULL; + +buffer = g_strdup(str); +start = buffer; +if ((start = strstr(start, needle))) { +start += strlen(needle); +end = strchr(start, ' '); +if (end) { +*end = '\0'; +} +if (strlen(start) == 0) { +goto cleanup; +} +ret = g_strdup(start); +} + +cleanup: +g_free(buffer); +return ret; +} + +/** + * @buffer: xml string data to be formatted + * @indent: indent number relative to first line + * + */ +static void adjust_indent(char **buffer, int indent) +{ +char spaces[1024]; +int i; + +if (!*buffer) { +return; +} + +if (indent 0 || indent = 1024) { +return; +} +memset(spaces, 0, sizeof(spaces)); +for (i = 0; i indent; i++) { +spaces[i] = ' '; +} + +sprintf(*buffer + strlen(*buffer), %s, spaces); +} + +static char *create_bond_interface(GuestNetworkInterface2 *interface) +{ +char *target_xml; + +target_xml = g_malloc0(1024); +if (!target_xml) { +return NULL; +} + +sprintf(target_xml, interface type='%s' name='%s'\n, +interface_type_string[interface-type], interface-name); +adjust_indent(target_xml, 2); +sprintf(target_xml + strlen(target_xml), start mode='%s'/\n, +interface-has_onboot ? interface-onboot : none); +if (interface-has_ip_address) { +GuestIpAddress *address_item = interface-ip_address; + +adjust_indent(target_xml, 2); +sprintf(target_xml + strlen(target_xml), protocol family='%s'\n, +ip_address_type_string[address_item-ip_address_type]); +adjust_indent(target_xml, 4); +sprintf(target_xml + strlen(target_xml), ip address='%s' prefix='% PRId64 '/\n, +address_item-ip_address, address_item-prefix); +if (address_item-has_gateway) { +adjust_indent(target_xml, 4); +sprintf(target_xml + strlen(target_xml), route gateway='%s'/\n, +address_item-gateway); +} +adjust_indent(target_xml, 2); +sprintf(target_xml + strlen(target_xml), %s\n, /protocol); +} + +adjust_indent(target_xml, 2); +if (interface-has_options) { +char *value; + +value = parse_options(interface-options, mode=); +if (value) { +sprintf(target_xml + strlen(target_xml), bond mode='%s'\n, +value); +g_free(value); +} else { +sprintf(target_xml + strlen(target_xml), %s\n, bond); +} + +value = parse_options(interface-options, miimon=); +if (value) { +adjust_indent(target_xml
[libvirt] [RFC 1/7] qemu-agent: add agent init callback when detecting guest setup
sometimes, we want to do some initialize work in guest when guest startup, but currently, qemu-agent doesn't support that. so here we add an init callback, when guest startup, notify libvirt it has been up, then libvirt can do some work for guest. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_agent.c | 26 +++--- src/qemu/qemu_agent.h | 2 ++ src/qemu/qemu_process.c | 6 ++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 548d580..cee0f8b 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -92,6 +92,7 @@ struct _qemuAgent { int watch; bool connectPending; +bool connected; virDomainObjPtr vm; @@ -306,6 +307,7 @@ qemuAgentIOProcessLine(qemuAgentPtr mon, virJSONValuePtr obj = NULL; int ret = -1; unsigned long long id; +const char *status; VIR_DEBUG(Line [%s], line); @@ -318,7 +320,11 @@ qemuAgentIOProcessLine(qemuAgentPtr mon, goto cleanup; } -if (virJSONValueObjectHasKey(obj, QMP) == 1) { +if (virJSONValueObjectHasKey(obj, QMP) == 1 || +virJSONValueObjectHasKey(obj, status) == 1) { +status = virJSONValueObjectGetString(obj, status); +if (STREQ(status, connected)) +mon-connected = true; ret = 0; } else if (virJSONValueObjectHasKey(obj, event) == 1) { ret = qemuAgentIOProcessEvent(mon, obj); @@ -700,8 +706,22 @@ qemuAgentIO(int watch, int fd, int events, void *opaque) VIR_DEBUG(Triggering error callback); (errorNotify)(mon, vm); } else { -virObjectUnlock(mon); -virObjectUnref(mon); +if (mon-connected) { +void (*init)(qemuAgentPtr, virDomainObjPtr) += mon-cb-init; +virDomainObjPtr vm = mon-vm; + +mon-connected = false; + +virObjectUnlock(mon); +virObjectUnref(mon); + +VIR_DEBUG(Triggering init callback); +(init)(mon, vm); +} else { +virObjectUnlock(mon); +virObjectUnref(mon); +} } } diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 1cd5749..42414a7 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -34,6 +34,8 @@ typedef qemuAgent *qemuAgentPtr; typedef struct _qemuAgentCallbacks qemuAgentCallbacks; typedef qemuAgentCallbacks *qemuAgentCallbacksPtr; struct _qemuAgentCallbacks { +void (*init)(qemuAgentPtr mon, + virDomainObjPtr vm); void (*destroy)(qemuAgentPtr mon, virDomainObjPtr vm); void (*eofNotify)(qemuAgentPtr mon, diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 276837e..e6fc53a 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -194,8 +194,14 @@ static void qemuProcessHandleAgentDestroy(qemuAgentPtr agent, virObjectUnref(vm); } +static void qemuProcessHandleAgentInit(qemuAgentPtr agent ATTRIBUTE_UNUSED, + virDomainObjPtr vm) +{ +VIR_DEBUG(Received init from agent on %p '%s', vm, vm-def-name); +} static qemuAgentCallbacks agentCallbacks = { +.init = qemuProcessHandleAgentInit, .destroy = qemuProcessHandleAgentDestroy, .eofNotify = qemuProcessHandleAgentEOF, .errorNotify = qemuProcessHandleAgentError, -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RFC 0/3] add support migration with passthrough device
the patches is for libvirt to support migration with passthrough device using existing feacture. Chen Fan (3): qemu-agent: add guest-network-set-interface command qemu-agent: add guest-network-delete-interface command qemu-agent: add notify for qemu-ga boot configure| 16 +++ qga/commands-posix.c | 312 +++ qga/commands-win32.c | 13 +++ qga/main.c | 13 +++ qga/qapi-schema.json | 65 +++ 5 files changed, 419 insertions(+) -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RFC 5/7] hostdev: add parse ip and route for bond configure
bond device always need to configure the ip address and route way address. so here we add the interface. xml like: hostdev mode='subsystem' type='pci' managed='no' driver name='vfio' type='bond'/ bond ip address='192.168.122.5' family='ipv4' prefix='24'/ route family='ipv4' address='0.0.0.0' gateway='192.168.122.1'/ interface address='52:54:00:e8:c0:f3'/ interface address='44:33:4c:06:f5:8e'/ /bond Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- docs/schemas/domaincommon.rng | 21 +++ src/conf/domain_conf.c| 87 --- src/conf/domain_conf.h| 24 src/conf/networkcommon_conf.c | 17 - src/conf/networkcommon_conf.h | 17 + src/qemu/qemu_agent.c | 58 +++-- 6 files changed, 183 insertions(+), 41 deletions(-) diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 0cf82cb..4056cbd 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3779,6 +3779,27 @@ optional element name=bond zeroOrMore +element name=ip + attribute name=address +ref name=ipAddr/ + /attribute + optional +attribute name=family + ref name=addr-family/ +/attribute + /optional + optional +attribute name=prefix + ref name=ipPrefix/ +/attribute + /optional + empty/ +/element + /zeroOrMore + zeroOrMore +ref name=route/ + /zeroOrMore + zeroOrMore element name=interface ref name=pciinterface/ /element diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 14bcae1..7d1cd3e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -797,6 +797,8 @@ static virClassPtr virDomainXMLOptionClass; static void virDomainObjDispose(void *obj); static void virDomainObjListDispose(void *obj); static void virDomainXMLOptionClassDispose(void *obj); +static virDomainNetIpDefPtr virDomainNetIpParseXML(xmlNodePtr node); + static int virDomainObjOnceInit(void) { @@ -1914,8 +1916,17 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def) } } else if (def-source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) { virDomainHostdevSubsysPCIPtr pcisrc = def-source.subsys.u.pci; -if (pcisrc-device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND) -VIR_FREE(pcisrc-macs); +if (pcisrc-device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND) { +for (i = 0; i pcisrc-net.nmacs; i++) +VIR_FREE(pcisrc-net.macs[i]); +VIR_FREE(pcisrc-net.macs); +for (i = 0; i pcisrc-net.nips; i++) +VIR_FREE(pcisrc-net.ips[i]); +VIR_FREE(pcisrc-net.ips); +for (i = 0; i pcisrc-net.nroutes; i++) +VIR_FREE(pcisrc-net.routes[i]); +VIR_FREE(pcisrc-net.routes); +} } break; } @@ -5102,26 +5113,68 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, if (device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND) { xmlNodePtr *macs = NULL; int n = 0; -int i; +size_t i; char *macStr = NULL; +xmlNodePtr *ipnodes = NULL; +int nipnodes; +xmlNodePtr *routenodes = NULL; +int nroutenodes; if (!(virXPathNode(./bond, ctxt))) { virReportError(VIR_ERR_XML_ERROR, %s, - _(missing nond node specified by bond type)); + _(missing bond node specified by bond type)); goto error; } +if ((nipnodes = virXPathNodeSet(./bond/ip, ctxt, ipnodes)) 0) +goto error; + +if (nipnodes) { +for (i = 0; i nipnodes; i++) { +virDomainNetIpDefPtr ip = virDomainNetIpParseXML(ipnodes[i]); + +if (!ip) +goto error; + +if (VIR_APPEND_ELEMENT(pcisrc-net.ips, + pcisrc-net.nips, ip) 0) { +VIR_FREE(ip); +goto error; +} +} +} + +if ((nroutenodes = virXPathNodeSet(./bond/route, ctxt, routenodes)) 0) +goto error; + +if (nroutenodes) { +for (i = 0; i nroutenodes; i++) { +virNetworkRouteDefPtr route = NULL; + +if (!(route = virNetworkRouteDefParseXML(_(Domain hostdev device
[libvirt] [RFC 7/7] migrate: add hostdev migrate status to support hostdev migration
we add a migrate status for hostdev to specify the device don't need to initialze when VM startup, after migration end, we add the migrate status hostdev, so can support hostdev migration. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/domain_conf.c| 3 ++ src/conf/domain_conf.h| 7 src/qemu/qemu_command.c | 3 ++ src/qemu/qemu_driver.c| 53 +-- src/qemu/qemu_hotplug.c | 8 +++-- src/qemu/qemu_migration.c | 92 --- src/qemu/qemu_migration.h | 4 +++ src/util/virhostdev.c | 3 ++ 8 files changed, 114 insertions(+), 59 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 7d1cd3e..b56c6fa 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3035,6 +3035,9 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def, device.type = VIR_DOMAIN_DEVICE_HOSTDEV; for (i = 0; i def-nhostdevs; i++) { device.data.hostdev = def-hostdevs[i]; +if (device.data.hostdev-state == VIR_DOMAIN_HOSTDEV_STATE_READY_FOR_MIGRATE) +continue; + if (cb(def, device, def-hostdevs[i]-info, opaque) 0) return -1; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 723f07b..4b7b4c9 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -543,6 +543,12 @@ struct _virDomainHostdevCaps { } u; }; +typedef enum { +VIR_DOMAIN_HOSTDEV_STATE_DEFAULT, +VIR_DOMAIN_HOSTDEV_STATE_READY_FOR_MIGRATE, + +VIR_DOMAIN_HOSTDEV_STATE_LAST +} virDomainHostdevState; /* basic device for direct passthrough */ struct _virDomainHostdevDef { @@ -559,6 +565,7 @@ struct _virDomainHostdevDef { } source; virDomainHostdevOrigStates origstates; virDomainDeviceInfoPtr info; /* Guest address */ +int state; }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index e7e0937..dc5245a 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -10365,6 +10365,9 @@ qemuBuildCommandLine(virConnectPtr conn, virDomainHostdevDefPtr hostdev = def-hostdevs[i]; char *devstr; +if (hostdev-state == VIR_DOMAIN_HOSTDEV_STATE_READY_FOR_MIGRATE) +continue; + if (hostdev-info-bootIndex) { if (hostdev-mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || (hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0ba9e4a..4724171 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -12353,57 +12353,6 @@ qemuDomainMigrateBegin3(virDomainPtr domain, cookieout, cookieoutlen, flags); } -static int -qemuDomainRemovePciPassThruDevices(virConnectPtr conn, - virDomainObjPtr vm) -{ -virQEMUDriverPtr driver = conn-privateData; -virDomainDeviceDef dev; -virDomainDeviceDefPtr dev_copy = NULL; -virCapsPtr caps = NULL; -int ret = -1; -size_t i; - -if (!(caps = virQEMUDriverGetCapabilities(driver, false))) -goto cleanup; - -if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_OUT)) -goto cleanup; - -/* unplug passthrough bond device */ -for (i = 0; i vm-def-nhostdevs; i++) { -virDomainHostdevDefPtr hostdev = vm-def-hostdevs[i]; - -if (hostdev-mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS -hostdev-source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI -hostdev-source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO -hostdev-source.subsys.u.pci.device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND) { - -dev.type = VIR_DOMAIN_DEVICE_HOSTDEV; -dev.data.hostdev = hostdev; - -dev_copy = virDomainDeviceDefCopy(dev, vm-def, caps, driver-xmlopt); -if (!dev_copy) -goto cleanup; - -if (qemuDomainDetachHostDevice(driver, vm, dev_copy) 0) { -virDomainDeviceDefFree(dev_copy); -goto cleanup; -} - -virDomainDeviceDefFree(dev_copy); -if (qemuDomainUpdateDeviceList(driver, vm, QEMU_ASYNC_JOB_NONE) 0) -goto cleanup; -} -} - -ret = 0; - - cleanup: -virObjectUnref(caps); - -return ret; -} static char * qemuDomainMigrateBegin3Params(virDomainPtr domain, @@ -12740,7 +12689,7 @@ qemuDomainMigratePerform3Params(virDomainPtr dom, return -1; } -if (qemuDomainRemovePciPassThruDevices(dom-conn, vm) 0) { +if (qemuDomainMigratePciPassThruDevices(driver, vm, false) 0) { qemuDomObjEndAPI(vm); return -1; } diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index f07c54d..13a7338 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1239,8 +1239,9 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver
[libvirt] [RFC 2/7] qemu: add guest init event callback to do the initialize work for guest
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_domain.h | 7 +++ src/qemu/qemu_driver.c | 32 src/qemu/qemu_process.c | 22 ++ 3 files changed, 61 insertions(+) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 3225abb..19f4b27 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -136,6 +136,8 @@ struct qemuDomainJobObj { typedef void (*qemuDomainCleanupCallback)(virQEMUDriverPtr driver, virDomainObjPtr vm); +typedef void (*qemuDomainInitCallback)(virDomainObjPtr vm); + typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate; typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr; struct _qemuDomainObjPrivate { @@ -185,6 +187,10 @@ struct _qemuDomainObjPrivate { size_t ncleanupCallbacks; size_t ncleanupCallbacks_max; +qemuDomainInitCallback *initCallbacks; +size_t nInitCallbacks; +size_t nInitCallbacks_max; + virCgroupPtr cgroup; virCond unplugFinished; /* signals that unpluggingDevice was unplugged */ @@ -205,6 +211,7 @@ typedef enum { QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED, QEMU_PROCESS_EVENT_SERIAL_CHANGED, QEMU_PROCESS_EVENT_BLOCK_JOB, +QEMU_PROCESS_EVENT_GUESTINIT, QEMU_PROCESS_EVENT_LAST } qemuProcessEventType; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f37b95d..7368145 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4073,6 +4073,35 @@ processGuestPanicEvent(virQEMUDriverPtr driver, static void +processGuestInitEvent(virQEMUDriverPtr driver, + virDomainObjPtr vm) +{ +qemuDomainObjPrivatePtr priv; +int i; + +VIR_DEBUG(init guest from domain %p %s, + vm, vm-def-name); + +if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) 0) +return; + +if (!virDomainObjIsActive(vm)) { +VIR_DEBUG(Domain is not running); +goto endjob; +} + +priv = vm-privateData; + +for (i = 0; i priv-nInitCallbacks; i++) { +if (priv-initCallbacks[i]) +priv-initCallbacks[i](vm); +} + + endjob: +qemuDomainObjEndJob(driver, vm); +} + +static void processDeviceDeletedEvent(virQEMUDriverPtr driver, virDomainObjPtr vm, char *devAlias) @@ -4627,6 +4656,9 @@ static void qemuProcessEventHandler(void *data, void *opaque) processEvent-action, processEvent-status); break; +case QEMU_PROCESS_EVENT_GUESTINIT: +processGuestInitEvent(driver, vm); +break; case QEMU_PROCESS_EVENT_LAST: break; } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index e6fc53a..fcc0566 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -197,7 +197,29 @@ static void qemuProcessHandleAgentDestroy(qemuAgentPtr agent, static void qemuProcessHandleAgentInit(qemuAgentPtr agent ATTRIBUTE_UNUSED, virDomainObjPtr vm) { +struct qemuProcessEvent *processEvent = NULL; +virQEMUDriverPtr driver = qemu_driver; + +virObjectLock(vm); + VIR_DEBUG(Received init from agent on %p '%s', vm, vm-def-name); + +if (VIR_ALLOC(processEvent) 0) +goto cleanup; + +processEvent-eventType = QEMU_PROCESS_EVENT_GUESTINIT; +processEvent-vm = vm; + +virObjectRef(vm); +if (virThreadPoolSendJob(driver-workerPool, 0, processEvent) 0) { +if (!virObjectUnref(vm)) +vm = NULL; +VIR_FREE(processEvent); +} + + cleanup: +if (vm) +virObjectUnlock(vm); } static qemuAgentCallbacks agentCallbacks = { -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RFC 3/7] hostdev: add a 'bond' type element in hostdev element
this 'bond' element is to create bond device when guest startup, the xml like: hostdev mode='subsystem' type='pci' managed='yes' driver name='vfio' type='bond'/ bond interface address='XXX'/ interface address='XXX1'/ /bond /hostdev Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- docs/schemas/basictypes.rng | 6 ++ docs/schemas/domaincommon.rng | 16 ++ src/conf/domain_conf.c| 131 ++ src/conf/domain_conf.h| 13 + src/libvirt_private.syms | 1 + 5 files changed, 157 insertions(+), 10 deletions(-) diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index f086ad2..aef24fe 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/schemas/basictypes.rng @@ -66,6 +66,12 @@ /choice /define + define name=pciinterface +attribute name=address + ref name=uniMacAddr/ +/attribute + /define + define name=pciaddress optional attribute name=domain diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 03fd541..0cf82cb 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3766,9 +3766,25 @@ valuexen/value /choice /attribute + optional +attribute name=type + choice +valuebond/value + /choice +/attribute + /optional empty/ /element /optional + optional +element name=bond + zeroOrMore +element name=interface + ref name=pciinterface/ +/element + /zeroOrMore +/element + /optional element name=source optional ref name=startupPolicy/ diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 4d7e3c9..14bcae1 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -610,6 +610,11 @@ VIR_ENUM_IMPL(virDomainHostdevSubsysPCIBackend, vfio, xen) +VIR_ENUM_IMPL(virDomainHostdevSubsysPCIDevice, + VIR_DOMAIN_HOSTDEV_PCI_DEVICE_TYPE_LAST, + default, + bond) + VIR_ENUM_IMPL(virDomainHostdevSubsysSCSIProtocol, VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_LAST, adapter, @@ -1907,6 +1912,10 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def) } else { VIR_FREE(scsisrc-u.host.adapter); } +} else if (def-source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) { +virDomainHostdevSubsysPCIPtr pcisrc = def-source.subsys.u.pci; +if (pcisrc-device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND) +VIR_FREE(pcisrc-macs); } break; } @@ -4978,7 +4987,9 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, char *sgio = NULL; char *rawio = NULL; char *backendStr = NULL; +char *deviceStr = NULL; int backend; +int device; int ret = -1; virDomainHostdevSubsysPCIPtr pcisrc = def-source.subsys.u.pci; virDomainHostdevSubsysSCSIPtr scsisrc = def-source.subsys.u.scsi; @@ -5077,6 +5088,68 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, } pcisrc-backend = backend; +device = VIR_DOMAIN_HOSTDEV_PCI_DEVICE_DEFAULT; +if ((deviceStr = virXPathString(string(./driver/@type), ctxt)) +(((device = virDomainHostdevSubsysPCIDeviceTypeFromString(deviceStr)) 0) || + device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_DEFAULT)) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _(Unknown PCI device driver type='%s'/ + has been specified), deviceStr); +goto error; +} +pcisrc-device = device; + +if (device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND) { +xmlNodePtr *macs = NULL; +int n = 0; +int i; +char *macStr = NULL; + +if (!(virXPathNode(./bond, ctxt))) { +virReportError(VIR_ERR_XML_ERROR, %s, + _(missing nond node specified by bond type)); +goto error; +} + +if ((n = virXPathNodeSet(./bond/interface, ctxt, macs)) 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(Cannot extract interface nodes)); +goto error; +} + +VIR_FREE(pcisrc-macs); +if (VIR_ALLOC_N(pcisrc-macs, n) 0) +goto error; + +pcisrc-nmac = n; +for (i = 0; i n; i++) { +xmlNodePtr cur_node = macs[i]; + +macStr = virXMLPropString(cur_node, address); +if (!macStr) { +virReportError(VIR_ERR_XML_ERROR, %s, + _(Missing required address attribute
[libvirt] [RFC 4/7] qemu-agent: add qemuAgentCreateBond interface
via initialize callback to create bond device. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_agent.c | 118 src/qemu/qemu_agent.h | 10 src/qemu/qemu_domain.c | 70 src/qemu/qemu_domain.h | 7 +++ src/qemu/qemu_process.c | 4 ++ 5 files changed, 209 insertions(+) diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index cee0f8b..b8eba01 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -2169,3 +2169,121 @@ qemuAgentGetInterfaces(qemuAgentPtr mon, goto cleanup; } + +static virDomainInterfacePtr +findInterfaceByMac(virDomainInterfacePtr *info, + size_t len, + const char *macstr) +{ +size_t i; +bool found = false; + +for (i = 0; i len; i++) { +if (info[i]-hwaddr +STREQ(info[i]-hwaddr, macstr)) { +found = true; +break; +} +} + +if (found) { +return info[i]; +} + +return NULL; +} + +/* + * qemuAgentSetInterface: + */ +int +qemuAgentCreateBond(qemuAgentPtr mon, +virDomainHostdevSubsysPCIPtr pcisrc) +{ +int ret = -1; +virJSONValuePtr cmd = NULL; +virJSONValuePtr reply = NULL; +size_t i; +char macstr[VIR_MAC_STRING_BUFLEN]; +virDomainInterfacePtr *interfaceInfo = NULL; +virDomainInterfacePtr interface; +virJSONValuePtr new_interface = NULL; +virJSONValuePtr subInterfaces = NULL; +virJSONValuePtr subInterface = NULL; +int len; + +if (!(pcisrc-nmac || pcisrc-macs)) +return ret; + +len = qemuAgentGetInterfaces(mon, interfaceInfo); +if (len 0) +return ret; + +if (!(new_interface = virJSONValueNewObject())) +goto cleanup; + +if (virJSONValueObjectAppendString(new_interface, type, bond) 0) +goto cleanup; + +if (virJSONValueObjectAppendString(new_interface, name, bond0) 0) +goto cleanup; + +if (virJSONValueObjectAppendString(new_interface, onboot, onboot) 0) +goto cleanup; + +if (!(subInterfaces = virJSONValueNewArray())) +goto cleanup; + +for (i = 0; i pcisrc-nmac; i++) { +virMacAddrFormat(pcisrc-macs[i], macstr); +interface = findInterfaceByMac(interfaceInfo, len, macstr); +if (!interface) { +goto cleanup; +} + +if (!(subInterface = virJSONValueNewObject())) +goto cleanup; + +if (virJSONValueObjectAppendString(subInterface, name, interface-name) 0) +goto cleanup; + +if (virJSONValueArrayAppend(subInterfaces, subInterface) 0) +goto cleanup; + +subInterface = NULL; +} + +if (i virJSONValueObjectAppend(new_interface, subInterfaces, subInterfaces) 0) +goto cleanup; + +cmd = qemuAgentMakeCommand(guest-network-set-interface, + a:interface, new_interface, + NULL); + +if (!cmd) +goto cleanup; + +subInterfaces = NULL; +new_interface = NULL; + +if (qemuAgentCommand(mon, cmd, reply, true, + VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) 0) +goto cleanup; + +if (virJSONValueObjectGetNumberInt(reply, return, ret) 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(malformed return value)); +} + + cleanup: +virJSONValueFree(subInterfaces); +virJSONValueFree(subInterface); +virJSONValueFree(new_interface); +virJSONValueFree(cmd); +virJSONValueFree(reply); +if (interfaceInfo) +for (i = 0; i len; i++) +virDomainInterfaceFree(interfaceInfo[i]); +VIR_FREE(interfaceInfo); +return ret; +} diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 42414a7..744cb0a 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -97,6 +97,13 @@ struct _qemuAgentCPUInfo { bool offlinable;/* true if the CPU can be offlined */ }; +typedef struct _qemuAgentInterfaceInfo qemuAgentInterfaceInfo; +typedef qemuAgentInterfaceInfo *qemuAgentInterfaceInfoPtr; +struct _qemuAgentInterfaceInfo { +char *name; +char *hardware_address; +}; + int qemuAgentGetVCPUs(qemuAgentPtr mon, qemuAgentCPUInfoPtr *info); int qemuAgentSetVCPUs(qemuAgentPtr mon, qemuAgentCPUInfoPtr cpus, size_t ncpus); int qemuAgentUpdateCPUInfo(unsigned int nvcpus, @@ -114,4 +121,7 @@ int qemuAgentSetTime(qemuAgentPtr mon, int qemuAgentGetInterfaces(qemuAgentPtr mon, virDomainInterfacePtr **ifaces); +int qemuAgentCreateBond(qemuAgentPtr mon, +virDomainHostdevSubsysPCIPtr pcisrc); + #endif /* __QEMU_AGENT_H__ */ diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 603360f..584fefb 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2722,6 +2722,46 @@ qemuDomainCleanupRun(virQEMUDriverPtr driver, priv
[libvirt] [RFC 3/3] qemu-agent: add notify for qemu-ga boot
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- qga/main.c | 13 + 1 file changed, 13 insertions(+) diff --git a/qga/main.c b/qga/main.c index 9939a2b..f011ce0 100644 --- a/qga/main.c +++ b/qga/main.c @@ -1170,6 +1170,19 @@ int main(int argc, char **argv) g_critical(failed to initialize guest agent channel); goto out_bad; } + +/* send a notification to path */ +if (ga_state-channel) { +QDict *qdict = qdict_new(); +int ret; + +qdict_put_obj(qdict, status, QOBJECT(qstring_from_str(connected))); +ret = send_response(s, QOBJECT(qdict)); +if (ret 0) { +g_warning(error sending connected status); +} +} + #ifndef _WIN32 g_main_loop_run(ga_state-main_loop); #else -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 2/2] docs: route element must specify network address
because network address is required by route, so here we should add one avoid user misunderstand. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- docs/formatdomain.html.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 3b3d2d9..d7fe942 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -4472,7 +4472,7 @@ qemu-kvm -net nic,model=? /dev/null lt;target dev='vnet0'/gt; blt;ip address='192.168.122.5' prefix='24'/gt;/b blt;route family='ipv4' address='192.168.122.0' prefix='24' gateway='192.168.122.1'/gt;/b - blt;route family='ipv4' gateway='192.168.122.1'/gt;/b + blt;route family='ipv4' address='192.168.122.8' gateway='192.168.122.1'/gt;/b lt;/interfacegt; ... lt;hostdev mode='capabilities' type='net'gt; @@ -4481,7 +4481,7 @@ qemu-kvm -net nic,model=? /dev/null lt;/sourcegt; blt;ip address='192.168.122.6' prefix='24'/gt;/b blt;route family='ipv4' address='192.168.122.0' prefix='24' gateway='192.168.122.1'/gt;/b - blt;route family='ipv4' gateway='192.168.122.1'/gt;/b + blt;route family='ipv4' address='192.168.122.8' gateway='192.168.122.1'/gt;/b lt;/hostdevgt; lt;/devicesgt; -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 1/2] docs: no 'via' attribute in route element
via - gateway Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- docs/formatdomain.html.in | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 82aa14f..3b3d2d9 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -4471,8 +4471,8 @@ qemu-kvm -net nic,model=? /dev/null lt;source network='default'/gt; lt;target dev='vnet0'/gt; blt;ip address='192.168.122.5' prefix='24'/gt;/b - blt;route family='ipv4' address='192.168.122.0' prefix='24' via='192.168.122.1'/gt;/b - blt;route family='ipv4' via='192.168.122.1'/gt;/b + blt;route family='ipv4' address='192.168.122.0' prefix='24' gateway='192.168.122.1'/gt;/b + blt;route family='ipv4' gateway='192.168.122.1'/gt;/b lt;/interfacegt; ... lt;hostdev mode='capabilities' type='net'gt; @@ -4480,8 +4480,8 @@ qemu-kvm -net nic,model=? /dev/null lt;interfacegt;eth0lt;/interfacegt; lt;/sourcegt; blt;ip address='192.168.122.6' prefix='24'/gt;/b - blt;route family='ipv4' address='192.168.122.0' prefix='24' via='192.168.122.1'/gt;/b - blt;route family='ipv4' via='192.168.122.1'/gt;/b + blt;route family='ipv4' address='192.168.122.0' prefix='24' gateway='192.168.122.1'/gt;/b + blt;route family='ipv4' gateway='192.168.122.1'/gt;/b lt;/hostdevgt; lt;/devicesgt; -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 0/2] fix domain documentation error
Chen Fan (2): docs: no 'via' attribute in route element docs: route element must specify network address docs/formatdomain.html.in | 8 1 file changed, 4 insertions(+), 4 deletions(-) -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] qemu: fix memory leak in qemuAgentGetFSInfo
in virDomainFSInfoFree(), don't free the virDomainFSInfo data. ==10670== 80 bytes in 2 blocks are definitely lost in loss record 576 of 793 ==10670==at 0x4A06BC3: calloc (vg_replace_malloc.c:618) ==10670==by 0x509DEBD: virAlloc (viralloc.c:144) ==10670==by 0x19FBD558: qemuAgentGetFSInfo (qemu_agent.c:1837) ==10670==by 0x1A03CF91: qemuDomainGetFSInfo (qemu_driver.c:19238) Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/libvirt-domain.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 04545fd..7f8a7ce 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11337,4 +11337,6 @@ virDomainFSInfoFree(virDomainFSInfoPtr info) for (i = 0; i info-ndevAlias; i++) VIR_FREE(info-devAlias[i]); VIR_FREE(info-devAlias); + +VIR_FREE(info); } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] qemu: fix memory leak in qemuAgentGetFSInfo
On 03/10/2015 05:32 PM, Ján Tomko wrote: On Tue, Mar 10, 2015 at 01:56:11PM +0800, Chen Fan wrote: in virDomainFSInfoFree(), don't free the virDomainFSInfo data. ==10670== 80 bytes in 2 blocks are definitely lost in loss record 576 of 793 ==10670==at 0x4A06BC3: calloc (vg_replace_malloc.c:618) ==10670==by 0x509DEBD: virAlloc (viralloc.c:144) ==10670==by 0x19FBD558: qemuAgentGetFSInfo (qemu_agent.c:1837) ==10670==by 0x1A03CF91: qemuDomainGetFSInfo (qemu_driver.c:19238) Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/libvirt-domain.c | 2 ++ 1 file changed, 2 insertions(+) This does fix the memory leak and makes the function behave like it's documented in virDomainGetFSInfo and virDomainFSInfoFree: http://libvirt.org/html/libvirt-libvirt-domain.html#virDomainGetFSInfo http://libvirt.org/html/libvirt-libvirt-domain.html#virDomainFSInfoFree But it changes the public API - if there are applications that already work around this function by freeing the info, this change would introduce a double free. I would NACK this if the documentation for both APIs didn't say that's how this function should behave. I'd like to hear a second opinion. I don't think this documentation make any confusable. for using the function virDomainGetFSInfo(), user also need to call virDomainFSInfoFree() on each array element, and call free() info. example: virDomainFSInfoPtr *info; ndata = virDomainGetFSInfo(dom, info, 0); for (i = 0; i ndata; i++) virDomainFSInfoFree(info[i]); VIR_FREE(info); Thanks, Chen Jan diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 04545fd..7f8a7ce 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11337,4 +11337,6 @@ virDomainFSInfoFree(virDomainFSInfoPtr info) for (i = 0; i info-ndevAlias; i++) VIR_FREE(info-devAlias[i]); VIR_FREE(info-devAlias); + +VIR_FREE(info); } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] docs: network: fix some trivial typos in docs/formatnetwork.html
this patch fix some weird typos: 1. hostdev = hostdev 2. type= type 3. virtualport = virtualport 4. redundant comma 5. missing right-half bracket Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- docs/formatnetwork.html.in | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in index dc438ae..7bcf316 100644 --- a/docs/formatnetwork.html.in +++ b/docs/formatnetwork.html.in @@ -288,7 +288,7 @@ (Single Root I/O Virtualization) virtual function (VF) devices can be assigned in this manner; to assign a standard single-port PCI or PCIe ethernet card to a guest, -use the traditional codelt; hostdevgt;/code device +use the traditional codelt;hostdevgt;/code device definition. span class=since Since 0.10.0/span p @@ -312,9 +312,9 @@ pNote that this intelligent passthrough of network devices is very similar to the functionality of a -standard codelt; hostdevgt;/code device, the +standard codelt;hostdevgt;/code device, the difference being that this method allows specifying a MAC -address, vlan tag, and codelt;virtualport gt;/code +address, vlan tag, and codelt;virtualportgt;/code for the passed-through device. If these capabilities are not required, if you have a standard single-port PCI, PCIe, or USB network card that doesn't support SR-IOV (and @@ -383,9 +383,9 @@ span class=sincesince 0.10.0/span When using forward mode 'hostdev', the interface pool is specified with a list of codelt;addressgt;/code elements, each of which has - codelt; typegt;/code (must always be code'pci'/code, + codelt;typegt;/code (must always be code'pci'/code), codelt;domaingt;/code, codelt;busgt;/code, - codelt;slotgt;/code, and codelt;functiongt;/code + codelt;slotgt;/codeand codelt;functiongt;/code attributes. /p pre -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] docs: fix a typo in formatdomain.html
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- docs/formatdomain.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 9364eb5..6a15074 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3413,7 +3413,7 @@ setting for the attribute is codeno/code for security reasons and support depends on the guest network device model as well as the type of connection on the host - currently it is - only supported for the virtio ddevice model and for macvtap + only supported for the virtio device model and for macvtap connections on the host. /p p -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] virnuma: add notset NULL check in virNumaSetupMemoryPolicy
introduce by commit c63ef0452b, when nodeset is NULL, validation will pass in virNumaSetupMemoryPolicy, but virBitmapNextSetBit must ensure bitmap is not Null. there will cause a segmentation fault. this patch fixed it. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/util/virnuma.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 06520f7..b8d76f4 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -97,6 +97,9 @@ virNumaSetupMemoryPolicy(virDomainNumatuneMemMode mode, size_t i; int maxnode = 0; +if (!nodeset) +return 0; + if (!virNumaNodesetIsAvailable(nodeset)) return -1; -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v4 1/3] bitmap: add virBitmapLastSetBit for finding the last bit position of bitmap
On Mon, 2014-11-03 at 14:18 +0100, Martin Kletzander wrote: On Thu, Oct 30, 2014 at 01:44:17PM +0800, Chen Fan wrote: Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/libvirt_private.syms | 1 + src/util/virbitmap.c | 45 + src/util/virbitmap.h | 3 +++ tests/virbitmaptest.c| 13 - 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d63a8f0..1e2bc0a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1011,6 +1011,7 @@ virBitmapFree; virBitmapGetBit; virBitmapIsAllClear; virBitmapIsAllSet; +virBitmapLastSetBit; virBitmapNew; virBitmapNewCopy; virBitmapNewData; diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c index b6bd074..3e7269e 100644 --- a/src/util/virbitmap.c +++ b/src/util/virbitmap.c @@ -651,6 +651,51 @@ virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos) } /** + * virBitmapLastSetBit: + * @bitmap: the bitmap + * + * Search for the last set bit in bitmap @bitmap. + * + * Returns the position of the found bit, or -1 if no bit found. s/found/is set/ + */ +ssize_t +virBitmapLastSetBit(virBitmapPtr bitmap) +{ +ssize_t i; +int unusedBits; +ssize_t sz; +unsigned long bits; + +unusedBits = bitmap-map_len * VIR_BITMAP_BITS_PER_UNIT - bitmap-max_bit; + +sz = bitmap-map_len - 1; +if (unusedBits 0) { +bits = bitmap-map[sz] (VIR_BITMAP_BIT(VIR_BITMAP_BITS_PER_UNIT - unusedBits) - 1); +if (bits != 0) +goto found; + +sz--; +} + +for (; sz = 0; sz--) { +bits = bitmap-map[sz]; +if (bits != 0) +goto found; +} + +if (bits == 0) +return -1; + +found: Missing space before label. make syntax-check would tell you that instead of me ;) Thanks for your remind. I will do that. Chen -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v4 2/3] numatune: add check for numatune nodeset range
On Mon, 2014-11-03 at 14:18 +0100, Martin Kletzander wrote: On Thu, Oct 30, 2014 at 01:44:18PM +0800, Chen Fan wrote: There was no check for 'nodeset' attribute in numatune-related elements. This patch adds validation that any nodeset specified does not exceed maximum host node. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/numatune_conf.c | 28 src/conf/numatune_conf.h | 1 + src/libvirt_private.syms | 1 + src/qemu/qemu_command.c| 4 +++ src/util/virnuma.c | 38 ++ src/util/virnuma.h | 1 + ...rgv-numatune-static-nodeset-exceed-hostnode.xml | 36 tests/qemuxml2argvmock.c | 9 + tests/qemuxml2argvtest.c | 1 + 9 files changed, 119 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-static-nodeset-exceed-hostnode.xml diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index 21d9a64..6986739 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -612,3 +612,31 @@ virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune) return false; } + +int +virDomainNumatuneSpecifiedMaxNode(virDomainNumatunePtr numatune) +{ +int ret = -1; +virBitmapPtr nodemask = NULL; +size_t i; +int bit; + +if (!numatune) +return ret; + +nodemask = virDomainNumatuneGetNodeset(numatune, NULL, -1); +if (nodemask) +ret = virBitmapLastSetBit(nodemask); + +for (i = 0; i numatune-nmem_nodes; i++) { +nodemask = numatune-mem_nodes[i].nodeset; +if (!nodemask) +continue; + +bit = virBitmapLastSetBit(nodemask); +if (bit ret) +ret = bit; +} + +return ret; +} diff --git a/src/conf/numatune_conf.h b/src/conf/numatune_conf.h index 5254629..15dc0d6 100644 --- a/src/conf/numatune_conf.h +++ b/src/conf/numatune_conf.h @@ -102,4 +102,5 @@ bool virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune); bool virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune); +int virDomainNumatuneSpecifiedMaxNode(virDomainNumatunePtr numatune); #endif /* __NUMATUNE_CONF_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 1e2bc0a..4a30ad7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1729,6 +1729,7 @@ virNumaGetPageInfo; virNumaGetPages; virNumaIsAvailable; virNumaNodeIsAvailable; +virNumaNodesetIsAvailable; virNumaSetPagePoolSize; virNumaSetupMemoryPolicy; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2e5af4f..d2c5f0c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -53,6 +53,7 @@ #include virstoragefile.h #include virtpm.h #include virscsi.h +#include virnuma.h #if defined(__linux__) # include linux/capability.h #endif @@ -6663,6 +6664,9 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, goto cleanup; } +if (!virNumaNodesetIsAvailable(def-numatune)) +goto cleanup; + for (i = 0; i def-mem.nhugepages; i++) { ssize_t next_bit, pos = 0; diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 690615f..4188ef5 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -165,6 +165,33 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, return ret; } +bool +virNumaNodesetIsAvailable(virDomainNumatunePtr numatune) +{ +int maxnode; +int bit; + +if (!numatune) +return true; + +bit = virDomainNumatuneSpecifiedMaxNode(numatune); +if (bit == -1) (bit 0) would go with the rest of the code, the functions can be then modified to report various kinds of errors more easily. +return true; + +if ((maxnode = virNumaGetMaxNode()) 0) +return false; + +maxnode = maxnode NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; +if (bit maxnode) +goto error; + +return true; + + error: +virReportError(VIR_ERR_INTERNAL_ERROR, + _(NUMA node %d is out of range), bit); +return false; +} bool virNumaIsAvailable(void) @@ -330,6 +357,17 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, return 0; } +bool +virNumaNodesetIsAvailable(virDomainNumatunePtr numatune) +{ +if (virDomainNumatuneSpecifiedMaxNode(numatune) != -1) { similarly = 0 here. +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(libvirt is compiled without NUMA tuning support)); +return false; +} + +return true; +} bool virNumaIsAvailable(void) diff --git a/src/util/virnuma.h b/src/util/virnuma.h index 04b6b8c..5bb37b8 100644
Re: [libvirt] [PATCH v4 3/3] virnuma: use virNumaNodesetIsAvailable checking nodeset in virNumaSetupMemoryPolicy
On Mon, 2014-11-03 at 14:18 +0100, Martin Kletzander wrote: On Thu, Oct 30, 2014 at 01:44:19PM +0800, Chen Fan wrote: Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/util/virnuma.c | 23 --- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 4188ef5..613a43c 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -95,31 +95,19 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, int ret = -1; int bit = 0; size_t i; -int maxnode = 0; virBitmapPtr tmp_nodemask = NULL; +if (!virNumaNodesetIsAvailable(numatune)) +return -1; + tmp_nodemask = virDomainNumatuneGetNodeset(numatune, nodemask, -1); if (!tmp_nodemask) return 0; -if (numa_available() 0) { -virReportError(VIR_ERR_INTERNAL_ERROR, - %s, _(Host kernel is not aware of NUMA.)); -return -1; -} - -maxnode = numa_max_node(); -maxnode = maxnode NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; - /* Convert nodemask to NUMA bitmask. */ nodemask_zero(mask); bit = -1; while ((bit = virBitmapNextSetBit(tmp_nodemask, bit)) = 0) { -if (bit maxnode) { -virReportError(VIR_ERR_INTERNAL_ERROR, - _(NUMA node %d is out of range), bit); -return -1; -} nodemask_set(mask, bit); } I think this is safe, numad returning nodeset that's not on the host would be weird error and it is easy to find in the logs. I think virNumaNodesetIsAvailable() has checked the case, but retain it here is ok. @@ -347,10 +335,7 @@ int virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, virBitmapPtr nodemask ATTRIBUTE_UNUSED) { -if (virDomainNumatuneGetNodeset(numatune, NULL, -1)) { -virReportError(VIR_ERR_INTERNAL_ERROR, %s, - _(libvirt is compiled without NUMA tuning support)); - +if (!virNumaNodesetIsAvailable(numatune)) { return -1; } This makes the square brackets obsolete. Thanks, Chen -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v4 0/3] add nodeset check in numatune
On Mon, 2014-11-03 at 14:18 +0100, Martin Kletzander wrote: On Thu, Oct 30, 2014 at 01:44:16PM +0800, Chen Fan wrote: when setting elements memnode and nodeset in attribute numatune more than the host nodes in XML file, VM boot should fail. so add check for that. You should run make syntax-check and make check on those patches, it would find at least two things ;) Anyway, ACK series with the changes I mentioned. If you're OK with them, I'll push the series. I will send a new series after change them. and Thanks for your review. Chen Martin -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v5 2/3] numatune: add check for numatune nodeset range
There was no check for 'nodeset' attribute in numatune-related elements. This patch adds validation that any nodeset specified does not exceed maximum host node. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/numatune_conf.c | 28 src/conf/numatune_conf.h | 1 + src/libvirt_private.syms | 1 + src/qemu/qemu_command.c| 4 +++ src/util/virnuma.c | 38 ++ src/util/virnuma.h | 1 + ...rgv-numatune-static-nodeset-exceed-hostnode.xml | 35 tests/qemuxml2argvmock.c | 9 + tests/qemuxml2argvtest.c | 2 ++ 9 files changed, 119 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-static-nodeset-exceed-hostnode.xml diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index 21d9a64..6986739 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -612,3 +612,31 @@ virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune) return false; } + +int +virDomainNumatuneSpecifiedMaxNode(virDomainNumatunePtr numatune) +{ +int ret = -1; +virBitmapPtr nodemask = NULL; +size_t i; +int bit; + +if (!numatune) +return ret; + +nodemask = virDomainNumatuneGetNodeset(numatune, NULL, -1); +if (nodemask) +ret = virBitmapLastSetBit(nodemask); + +for (i = 0; i numatune-nmem_nodes; i++) { +nodemask = numatune-mem_nodes[i].nodeset; +if (!nodemask) +continue; + +bit = virBitmapLastSetBit(nodemask); +if (bit ret) +ret = bit; +} + +return ret; +} diff --git a/src/conf/numatune_conf.h b/src/conf/numatune_conf.h index 5254629..15dc0d6 100644 --- a/src/conf/numatune_conf.h +++ b/src/conf/numatune_conf.h @@ -102,4 +102,5 @@ bool virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune); bool virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune); +int virDomainNumatuneSpecifiedMaxNode(virDomainNumatunePtr numatune); #endif /* __NUMATUNE_CONF_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 1e2bc0a..4a30ad7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1729,6 +1729,7 @@ virNumaGetPageInfo; virNumaGetPages; virNumaIsAvailable; virNumaNodeIsAvailable; +virNumaNodesetIsAvailable; virNumaSetPagePoolSize; virNumaSetupMemoryPolicy; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2e5af4f..d2c5f0c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -53,6 +53,7 @@ #include virstoragefile.h #include virtpm.h #include virscsi.h +#include virnuma.h #if defined(__linux__) # include linux/capability.h #endif @@ -6663,6 +6664,9 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, goto cleanup; } +if (!virNumaNodesetIsAvailable(def-numatune)) +goto cleanup; + for (i = 0; i def-mem.nhugepages; i++) { ssize_t next_bit, pos = 0; diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 690615f..2540bd2 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -165,6 +165,33 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, return ret; } +bool +virNumaNodesetIsAvailable(virDomainNumatunePtr numatune) +{ +int maxnode; +int bit; + +if (!numatune) +return true; + +bit = virDomainNumatuneSpecifiedMaxNode(numatune); +if (bit 0) +return true; + +if ((maxnode = virNumaGetMaxNode()) 0) +return false; + +maxnode = maxnode NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; +if (bit maxnode) +goto error; + +return true; + + error: +virReportError(VIR_ERR_INTERNAL_ERROR, + _(NUMA node %d is out of range), bit); +return false; +} bool virNumaIsAvailable(void) @@ -330,6 +357,17 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, return 0; } +bool +virNumaNodesetIsAvailable(virDomainNumatunePtr numatune) +{ +if (virDomainNumatuneSpecifiedMaxNode(numatune) = 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(libvirt is compiled without NUMA tuning support)); +return false; +} + +return true; +} bool virNumaIsAvailable(void) diff --git a/src/util/virnuma.h b/src/util/virnuma.h index 04b6b8c..5bb37b8 100644 --- a/src/util/virnuma.h +++ b/src/util/virnuma.h @@ -34,6 +34,7 @@ char *virNumaGetAutoPlacementAdvice(unsigned short vcups, int virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, virBitmapPtr nodemask); +bool virNumaNodesetIsAvailable(virDomainNumatunePtr numatune); bool virNumaIsAvailable(void); int virNumaGetMaxNode(void); bool virNumaNodeIsAvailable(int node); diff --git a/tests/qemuxml2argvdata
[libvirt] [PATCH v5 0/3] add nodeset check in numatune
when setting elements memnode and nodeset in attribute numatune more than the host nodes in XML file, VM boot should fail. so add check for that. Chen Fan (3): bitmap: add virBitmapLastSetBit for finding the last bit position of bitmap numatune: add check for numatune nodeset range virnuma: use virNumaNodesetIsAvailable checking nodeset in virNumaSetupMemoryPolicy src/conf/numatune_conf.c | 28 src/conf/numatune_conf.h | 1 + src/libvirt_private.syms | 2 + src/qemu/qemu_command.c| 4 ++ src/util/virbitmap.c | 45 ++ src/util/virbitmap.h | 3 ++ src/util/virnuma.c | 53 +- src/util/virnuma.h | 1 + ...rgv-numatune-static-nodeset-exceed-hostnode.xml | 35 ++ tests/qemuxml2argvmock.c | 9 tests/qemuxml2argvtest.c | 2 + tests/virbitmaptest.c | 13 +- 12 files changed, 184 insertions(+), 12 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-static-nodeset-exceed-hostnode.xml -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v5 1/3] bitmap: add virBitmapLastSetBit for finding the last bit position of bitmap
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/libvirt_private.syms | 1 + src/util/virbitmap.c | 45 + src/util/virbitmap.h | 3 +++ tests/virbitmaptest.c| 13 - 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d63a8f0..1e2bc0a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1011,6 +1011,7 @@ virBitmapFree; virBitmapGetBit; virBitmapIsAllClear; virBitmapIsAllSet; +virBitmapLastSetBit; virBitmapNew; virBitmapNewCopy; virBitmapNewData; diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c index b6bd074..04a2388 100644 --- a/src/util/virbitmap.c +++ b/src/util/virbitmap.c @@ -651,6 +651,51 @@ virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos) } /** + * virBitmapLastSetBit: + * @bitmap: the bitmap + * + * Search for the last set bit in bitmap @bitmap. + * + * Returns the position of the found bit, or -1 if no bit is set. + */ +ssize_t +virBitmapLastSetBit(virBitmapPtr bitmap) +{ +ssize_t i; +int unusedBits; +ssize_t sz; +unsigned long bits; + +unusedBits = bitmap-map_len * VIR_BITMAP_BITS_PER_UNIT - bitmap-max_bit; + +sz = bitmap-map_len - 1; +if (unusedBits 0) { +bits = bitmap-map[sz] (VIR_BITMAP_BIT(VIR_BITMAP_BITS_PER_UNIT - unusedBits) - 1); +if (bits != 0) +goto found; + +sz--; +} + +for (; sz = 0; sz--) { +bits = bitmap-map[sz]; +if (bits != 0) +goto found; +} + +if (bits == 0) +return -1; + + found: +for (i = VIR_BITMAP_BITS_PER_UNIT - 1; i = 0; i--) { +if (bits 1UL i) +return i + sz * VIR_BITMAP_BITS_PER_UNIT; +} + +return -1; +} + +/** * virBitmapNextClearBit: * @bitmap: the bitmap * @pos: the position after which to search for a clear bit diff --git a/src/util/virbitmap.h b/src/util/virbitmap.h index 4493cc9..565264c 100644 --- a/src/util/virbitmap.h +++ b/src/util/virbitmap.h @@ -105,6 +105,9 @@ bool virBitmapIsAllClear(virBitmapPtr bitmap) ssize_t virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos) ATTRIBUTE_NONNULL(1); +ssize_t virBitmapLastSetBit(virBitmapPtr bitmap) +ATTRIBUTE_NONNULL(1); + ssize_t virBitmapNextClearBit(virBitmapPtr bitmap, ssize_t pos) ATTRIBUTE_NONNULL(1); diff --git a/tests/virbitmaptest.c b/tests/virbitmaptest.c index ea832ad..ac5f298 100644 --- a/tests/virbitmaptest.c +++ b/tests/virbitmaptest.c @@ -171,7 +171,7 @@ test3(const void *data ATTRIBUTE_UNUSED) return ret; } -/* test for virBitmapNextSetBit, virBitmapNextClearBit */ +/* test for virBitmapNextSetBit, virBitmapLastSetBit, virBitmapNextClearBit */ static int test4(const void *data ATTRIBUTE_UNUSED) { @@ -200,6 +200,9 @@ test4(const void *data ATTRIBUTE_UNUSED) if (virBitmapNextSetBit(bitmap, -1) != -1) goto error; +if (virBitmapLastSetBit(bitmap) != -1) +goto error; + for (i = 0; i size; i++) { if (virBitmapNextClearBit(bitmap, i - 1) != i) goto error; @@ -232,6 +235,11 @@ test4(const void *data ATTRIBUTE_UNUSED) if (virBitmapNextSetBit(bitmap, i) != -1) goto error; +j = sizeof(bitsPos)/sizeof(int) - 1; + +if (virBitmapLastSetBit(bitmap) != bitsPos[j]) +goto error; + j = 0; i = -1; @@ -255,6 +263,9 @@ test4(const void *data ATTRIBUTE_UNUSED) if (virBitmapNextSetBit(bitmap, i) != -1) goto error; +if (virBitmapLastSetBit(bitmap) != size - 1) +goto error; + if (virBitmapNextClearBit(bitmap, -1) != -1) goto error; -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v5 3/3] virnuma: use virNumaNodesetIsAvailable checking nodeset in virNumaSetupMemoryPolicy
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/util/virnuma.c | 15 --- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 2540bd2..89435de 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -98,16 +98,13 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, int maxnode = 0; virBitmapPtr tmp_nodemask = NULL; +if (!virNumaNodesetIsAvailable(numatune)) +return -1; + tmp_nodemask = virDomainNumatuneGetNodeset(numatune, nodemask, -1); if (!tmp_nodemask) return 0; -if (numa_available() 0) { -virReportError(VIR_ERR_INTERNAL_ERROR, - %s, _(Host kernel is not aware of NUMA.)); -return -1; -} - maxnode = numa_max_node(); maxnode = maxnode NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; @@ -347,12 +344,8 @@ int virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, virBitmapPtr nodemask ATTRIBUTE_UNUSED) { -if (virDomainNumatuneGetNodeset(numatune, NULL, -1)) { -virReportError(VIR_ERR_INTERNAL_ERROR, %s, - _(libvirt is compiled without NUMA tuning support)); - +if (!virNumaNodesetIsAvailable(numatune)) return -1; -} return 0; } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 1/3] numatune: add check for numatune nodeset range
On Thu, 2014-10-30 at 07:55 +0100, Martin Kletzander wrote: On Thu, Oct 30, 2014 at 02:23:00AM +, Chen, Fan wrote: On Wed, 2014-10-29 at 14:20 +0100, Martin Kletzander wrote: On Wed, Oct 29, 2014 at 08:33:32PM +0800, Chen Fan wrote: diff --git a/src/util/virnuma.c b/src/util/virnuma.c @@ -373,6 +400,12 @@ virNumaGetNodeCPUs(int node ATTRIBUTE_UNUSED, _(NUMA isn't available on this host)); return -1; } + +bool +virNumaNodesetIsAvailable(virDomainNumatunePtr numatune) +{ +return true; +} #endif In what case would you like this to return true? when libvirt does not support numa, we can not check it. maybe we should return false if setting nodeset. That was my idea, I just wanted to make sure we're on the same page. The thing is that if you want something that's not available, it makes more sense to say NO then just allow it because libvirt doesn't know. Make the user fix it :) Yes, I had made a v4 and sent it, please help to review. Thanks, Chen Martin -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 2/3] lxc controller: add check for numatune
On Wed, 2014-10-29 at 08:00 +0100, Martin Kletzander wrote: On Tue, Oct 28, 2014 at 04:22:22PM +0800, Chen Fan wrote: Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/lxc/lxc_controller.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 1861dd6..1ee89ab 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -689,7 +689,8 @@ static int virLXCControllerSetupResourceLimits(virLXCControllerPtr ctrl) int ret = -1; if (virLXCControllerGetNumadAdvice(ctrl, nodemask) 0 || -virNumaSetupMemoryPolicy(ctrl-def-numatune, nodemask) 0) +(virNumaNodesetIsAvailable (ctrl-def-numatune) + virNumaSetupMemoryPolicy(ctrl-def-numatune, nodemask) 0)) goto cleanup; This would mean it will succeed if the numa node is not available on the host. Don't you want to error out? By the way, it would make sense to make the check in virNumaSetupMemoryPolicy() itself. Oh, you are right. As for output because virNumaNodesetIsAvailable is self error output. so I think it not necessary. I think the check !virNumaNodesetIsAvailable (ctrl-def-numatune) || virNumaSetupMemoryPolicy(ctrl-def-numatune, nodemask) 0 would be OK. Thanks, Chen Martin -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 1/3] numatune: add check for numatune nodeset range
On Wed, 2014-10-29 at 07:58 +0100, Martin Kletzander wrote: On Tue, Oct 28, 2014 at 04:22:21PM +0800, Chen Fan wrote: For memnode in numatune element, the range of attribute 'nodeset' was not validated. on my host maxnodes was 1, but when setting nodeset to '0-2' or more, guest also started succuss. there probably was qemu's bug too. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/numatune_conf.c | 21 - src/conf/numatune_conf.h | 19 src/libvirt_private.syms | 1 + src/qemu/qemu_command.c| 3 ++ src/qemu/qemu_command.h| 1 + src/util/virnuma.c | 55 ++ src/util/virnuma.h | 2 + ...rgv-numatune-static-nodeset-exceed-hostnode.xml | 35 ++ tests/qemuxml2argvmock.c | 9 tests/qemuxml2argvtest.c | 1 + 10 files changed, 126 insertions(+), 21 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-static-nodeset-exceed-hostnode.xml diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index 21d9a64..d440b86 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -42,27 +42,6 @@ VIR_ENUM_IMPL(virDomainNumatunePlacement, static, auto); -typedef struct _virDomainNumatuneNode virDomainNumatuneNode; -typedef virDomainNumatuneNode *virDomainNumatuneNodePtr; - -struct _virDomainNumatune { -struct { -bool specified; -virBitmapPtr nodeset; -virDomainNumatuneMemMode mode; -virDomainNumatunePlacement placement; -} memory; /* pinning for all the memory */ - -struct _virDomainNumatuneNode { -virBitmapPtr nodeset; -virDomainNumatuneMemMode mode; -} *mem_nodes; /* fine tuning per guest node */ -size_t nmem_nodes; - -/* Future NUMA tuning related stuff should go here. */ -}; - - static inline bool virDomainNumatuneNodeSpecified(virDomainNumatunePtr numatune, int cellid) diff --git a/src/conf/numatune_conf.h b/src/conf/numatune_conf.h index 5254629..650b6e7 100644 --- a/src/conf/numatune_conf.h +++ b/src/conf/numatune_conf.h @@ -45,6 +45,25 @@ typedef enum { VIR_ENUM_DECL(virDomainNumatunePlacement) VIR_ENUM_DECL(virDomainNumatuneMemMode) +typedef struct _virDomainNumatuneNode virDomainNumatuneNode; +typedef virDomainNumatuneNode *virDomainNumatuneNodePtr; + +struct _virDomainNumatune { +struct { +bool specified; +virBitmapPtr nodeset; +virDomainNumatuneMemMode mode; +virDomainNumatunePlacement placement; +} memory; /* pinning for all the memory */ + +struct _virDomainNumatuneNode { +virBitmapPtr nodeset; +virDomainNumatuneMemMode mode; +} *mem_nodes; /* fine tuning per guest node */ +size_t nmem_nodes; + +/* Future NUMA tuning related stuff should go here. */ +}; void virDomainNumatuneFree(virDomainNumatunePtr numatune); NACK to these two hunks. The point of the structure being hidden in the .c file was to abstract it. You can provide accessors to those members you need if they are not available already. Got it! diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d63a8f0..16a5864 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1728,6 +1728,7 @@ virNumaGetPageInfo; virNumaGetPages; virNumaIsAvailable; virNumaNodeIsAvailable; +virNumaNodesetIsAvailable; virNumaSetPagePoolSize; virNumaSetupMemoryPolicy; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2e5af4f..9757d3e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6663,6 +6663,9 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, goto cleanup; } +if (!virNumaNodesetIsAvailable(def-numatune)) +goto cleanup; + for (i = 0; i def-mem.nhugepages; i++) { ssize_t next_bit, pos = 0; diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index aa40c9e..f263665 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -27,6 +27,7 @@ # include domain_addr.h # include domain_conf.h # include vircommand.h +# include virnuma.h # include capabilities.h # include qemu_conf.h # include qemu_domain.h diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 690615f..411719d 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -312,6 +312,55 @@ virNumaGetNodeCPUs(int node, return ret; } + +bool +virNumaNodesetIsAvailable(virDomainNumatunePtr numatune) +{ +int maxnode; +int bit = -1; +size_t i; +virBitmapPtr nodemask = NULL
[libvirt] [PATCH v3 2/3] lxc controller: add check for numatune
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/lxc/lxc_controller.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 1861dd6..a23dff7 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -689,6 +689,7 @@ static int virLXCControllerSetupResourceLimits(virLXCControllerPtr ctrl) int ret = -1; if (virLXCControllerGetNumadAdvice(ctrl, nodemask) 0 || +!virNumaNodesetIsAvailable (ctrl-def-numatune) || virNumaSetupMemoryPolicy(ctrl-def-numatune, nodemask) 0) goto cleanup; -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 1/3] numatune: add check for numatune nodeset range
For memnode in numatune element, the range of attribute 'nodeset' was not validated. on my host maxnodes was 1, but when setting nodeset to '0-2' or more, guest also started succuss. there probably was qemu's bug too. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/numatune_conf.c | 28 + src/conf/numatune_conf.h | 1 + src/libvirt_private.syms | 2 + src/qemu/qemu_command.c| 3 ++ src/qemu/qemu_command.h| 1 + src/util/virbitmap.c | 49 ++ src/util/virbitmap.h | 3 ++ src/util/virnuma.c | 33 +++ src/util/virnuma.h | 2 + ...rgv-numatune-static-nodeset-exceed-hostnode.xml | 35 tests/qemuxml2argvmock.c | 9 tests/qemuxml2argvtest.c | 1 + tests/virbitmaptest.c | 26 +++- 13 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-static-nodeset-exceed-hostnode.xml diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index 21d9a64..54f309a 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -612,3 +612,31 @@ virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune) return false; } + +int +virDomainNumatuneSpecifiedMaxNode(virDomainNumatunePtr numatune) +{ +int ret = -1; +virBitmapPtr nodemask = NULL; +size_t i; + +if (!numatune) +return ret; + +nodemask = virDomainNumatuneGetNodeset(numatune, NULL, -1); +if (nodemask) { +ret = virBitmapLastSetBit(nodemask, -1); +} +for (i = 0; i numatune-nmem_nodes; i++) { +int bit = -1; +nodemask = virDomainNumatuneGetNodeset(numatune, NULL, i); +if (!nodemask) +continue; + +bit = virBitmapLastSetBit(nodemask, -1); +if (bit ret) +ret = bit; +} + +return ret; +} diff --git a/src/conf/numatune_conf.h b/src/conf/numatune_conf.h index 5254629..15dc0d6 100644 --- a/src/conf/numatune_conf.h +++ b/src/conf/numatune_conf.h @@ -102,4 +102,5 @@ bool virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune); bool virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune); +int virDomainNumatuneSpecifiedMaxNode(virDomainNumatunePtr numatune); #endif /* __NUMATUNE_CONF_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d63a8f0..4a30ad7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1011,6 +1011,7 @@ virBitmapFree; virBitmapGetBit; virBitmapIsAllClear; virBitmapIsAllSet; +virBitmapLastSetBit; virBitmapNew; virBitmapNewCopy; virBitmapNewData; @@ -1728,6 +1729,7 @@ virNumaGetPageInfo; virNumaGetPages; virNumaIsAvailable; virNumaNodeIsAvailable; +virNumaNodesetIsAvailable; virNumaSetPagePoolSize; virNumaSetupMemoryPolicy; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2e5af4f..9757d3e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6663,6 +6663,9 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, goto cleanup; } +if (!virNumaNodesetIsAvailable(def-numatune)) +goto cleanup; + for (i = 0; i def-mem.nhugepages; i++) { ssize_t next_bit, pos = 0; diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index aa40c9e..f263665 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -27,6 +27,7 @@ # include domain_addr.h # include domain_conf.h # include vircommand.h +# include virnuma.h # include capabilities.h # include qemu_conf.h # include qemu_domain.h diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c index b6bd074..aed525a 100644 --- a/src/util/virbitmap.c +++ b/src/util/virbitmap.c @@ -651,6 +651,55 @@ virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos) } /** + * virBitmapLastSetBit: + * @bitmap: the bitmap + * @pos: the position after which to search for a set bit + * + * Search for the last set bit before position @pos in bitmap @bitmap. + * @pos can be -1 to search for the last set bit. Position starts + * at max_bit. + * + * Returns the position of the found bit, or -1 if no bit found. + */ +ssize_t +virBitmapLastSetBit(virBitmapPtr bitmap, ssize_t pos) +{ +size_t nl; +size_t nb; +unsigned long bits; +size_t i; + +if (pos 0) +pos = bitmap-max_bit; + +pos--; + +if (pos = bitmap-max_bit) +return -1; + +nl = pos / VIR_BITMAP_BITS_PER_UNIT; +nb = pos % VIR_BITMAP_BITS_PER_UNIT; + +bits = bitmap-map[nl] ((1UL (nb + 1)) - 1); + +while (bits == 0 --nl bitmap-map_len) { +bits = bitmap-map[nl]; +} + +if (bits == 0) +return -1; + +i
[libvirt] [PATCH v3 3/3] virnuma: remove redundant check for numanode
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/util/virnuma.c | 15 --- 1 file changed, 15 deletions(-) diff --git a/src/util/virnuma.c b/src/util/virnuma.c index fbe8fd1..5a08049 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -95,31 +95,16 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, int ret = -1; int bit = 0; size_t i; -int maxnode = 0; virBitmapPtr tmp_nodemask = NULL; tmp_nodemask = virDomainNumatuneGetNodeset(numatune, nodemask, -1); if (!tmp_nodemask) return 0; -if (numa_available() 0) { -virReportError(VIR_ERR_INTERNAL_ERROR, - %s, _(Host kernel is not aware of NUMA.)); -return -1; -} - -maxnode = numa_max_node(); -maxnode = maxnode NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; - /* Convert nodemask to NUMA bitmask. */ nodemask_zero(mask); bit = -1; while ((bit = virBitmapNextSetBit(tmp_nodemask, bit)) = 0) { -if (bit maxnode) { -virReportError(VIR_ERR_INTERNAL_ERROR, - _(NUMA node %d is out of range), bit); -return -1; -} nodemask_set(mask, bit); } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 3/3] virnuma: remove redundant check for numanode
On Wed, 2014-10-29 at 14:23 +0100, Martin Kletzander wrote: On Wed, Oct 29, 2014 at 08:33:34PM +0800, Chen Fan wrote: Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/util/virnuma.c | 15 --- 1 file changed, 15 deletions(-) I think this harmless check may prevent future problems (if SetupMemoryPolicy is called from some new codepath. Either keep it here or call virNumaNodesetIsAvailable() in the start of the function. call virNumaNodesetIsAvailable() in the start of the function will be fine. Thanks, Chen diff --git a/src/util/virnuma.c b/src/util/virnuma.c index fbe8fd1..5a08049 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -95,31 +95,16 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, int ret = -1; int bit = 0; size_t i; -int maxnode = 0; virBitmapPtr tmp_nodemask = NULL; tmp_nodemask = virDomainNumatuneGetNodeset(numatune, nodemask, -1); if (!tmp_nodemask) return 0; -if (numa_available() 0) { -virReportError(VIR_ERR_INTERNAL_ERROR, - %s, _(Host kernel is not aware of NUMA.)); -return -1; -} - -maxnode = numa_max_node(); -maxnode = maxnode NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; - /* Convert nodemask to NUMA bitmask. */ nodemask_zero(mask); bit = -1; while ((bit = virBitmapNextSetBit(tmp_nodemask, bit)) = 0) { -if (bit maxnode) { -virReportError(VIR_ERR_INTERNAL_ERROR, - _(NUMA node %d is out of range), bit); -return -1; -} nodemask_set(mask, bit); } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 1/3] numatune: add check for numatune nodeset range
On Wed, 2014-10-29 at 14:20 +0100, Martin Kletzander wrote: On Wed, Oct 29, 2014 at 08:33:32PM +0800, Chen Fan wrote: For memnode in numatune element, the range of attribute 'nodeset' was not validated. on my host maxnodes was 1, but when setting nodeset to '0-2' or more, guest also started succuss. there probably was qemu's bug too. How about rewording this as: There was no check for 'nodeset' attribute in numatune-related elements. This patch adds validation that any nodeset specified does not exceed maximum host node. Look good to me. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/numatune_conf.c | 28 + src/conf/numatune_conf.h | 1 + src/libvirt_private.syms | 2 + src/qemu/qemu_command.c| 3 ++ src/qemu/qemu_command.h| 1 + src/util/virbitmap.c | 49 ++ src/util/virbitmap.h | 3 ++ src/util/virnuma.c | 33 +++ src/util/virnuma.h | 2 + ...rgv-numatune-static-nodeset-exceed-hostnode.xml | 35 tests/qemuxml2argvmock.c | 9 tests/qemuxml2argvtest.c | 1 + tests/virbitmaptest.c | 26 +++- 13 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-static-nodeset-exceed-hostnode.xml diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index 21d9a64..54f309a 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -612,3 +612,31 @@ virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune) return false; } + +int +virDomainNumatuneSpecifiedMaxNode(virDomainNumatunePtr numatune) +{ +int ret = -1; +virBitmapPtr nodemask = NULL; +size_t i; + +if (!numatune) +return ret; + +nodemask = virDomainNumatuneGetNodeset(numatune, NULL, -1); +if (nodemask) { +ret = virBitmapLastSetBit(nodemask, -1); +} +for (i = 0; i numatune-nmem_nodes; i++) { Well, you're using the advantage of accessible structure members here (numatune-nmem_nodes), but using accessors around. These particular ones are useless here when you don't need any of the logic they provide. right, I should use numatune-mem_nodes[i].nodeset directly. +int bit = -1; +nodemask = virDomainNumatuneGetNodeset(numatune, NULL, i); +if (!nodemask) +continue; + +bit = virBitmapLastSetBit(nodemask, -1); +if (bit ret) +ret = bit; +} + +return ret; +} diff --git a/src/conf/numatune_conf.h b/src/conf/numatune_conf.h index 5254629..15dc0d6 100644 --- a/src/conf/numatune_conf.h +++ b/src/conf/numatune_conf.h @@ -102,4 +102,5 @@ bool virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune); bool virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune); +int virDomainNumatuneSpecifiedMaxNode(virDomainNumatunePtr numatune); #endif /* __NUMATUNE_CONF_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d63a8f0..4a30ad7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1011,6 +1011,7 @@ virBitmapFree; virBitmapGetBit; virBitmapIsAllClear; virBitmapIsAllSet; +virBitmapLastSetBit; virBitmapNew; virBitmapNewCopy; virBitmapNewData; @@ -1728,6 +1729,7 @@ virNumaGetPageInfo; virNumaGetPages; virNumaIsAvailable; virNumaNodeIsAvailable; +virNumaNodesetIsAvailable; virNumaSetPagePoolSize; virNumaSetupMemoryPolicy; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2e5af4f..9757d3e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6663,6 +6663,9 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, goto cleanup; } +if (!virNumaNodesetIsAvailable(def-numatune)) +goto cleanup; + for (i = 0; i def-mem.nhugepages; i++) { ssize_t next_bit, pos = 0; diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index aa40c9e..f263665 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -27,6 +27,7 @@ # include domain_addr.h # include domain_conf.h # include vircommand.h +# include virnuma.h # include capabilities.h # include qemu_conf.h # include qemu_domain.h diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c index b6bd074..aed525a 100644 --- a/src/util/virbitmap.c +++ b/src/util/virbitmap.c @@ -651,6 +651,55 @@ virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos) } /** + * virBitmapLastSetBit: + * @bitmap: the bitmap + * @pos: the position after which to search for a set bit + * + * Search
[libvirt] [PATCH v4 0/3] add nodeset check in numatune
when setting elements memnode and nodeset in attribute numatune more than the host nodes in XML file, VM boot should fail. so add check for that. Chen Fan (3): bitmap: add virBitmapLastSetBit for finding the last bit position of bitmap numatune: add check for numatune nodeset range virnuma: use virNumaNodesetIsAvailable checking nodeset in virNumaSetupMemoryPolicy src/conf/numatune_conf.c | 28 ++ src/conf/numatune_conf.h | 1 + src/libvirt_private.syms | 2 + src/qemu/qemu_command.c| 4 ++ src/util/virbitmap.c | 45 src/util/virbitmap.h | 3 ++ src/util/virnuma.c | 61 +++--- src/util/virnuma.h | 1 + ...rgv-numatune-static-nodeset-exceed-hostnode.xml | 36 + tests/qemuxml2argvmock.c | 9 tests/qemuxml2argvtest.c | 1 + tests/virbitmaptest.c | 13 - 12 files changed, 184 insertions(+), 20 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-static-nodeset-exceed-hostnode.xml -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 1/3] bitmap: add virBitmapLastSetBit for finding the last bit position of bitmap
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/libvirt_private.syms | 1 + src/util/virbitmap.c | 45 + src/util/virbitmap.h | 3 +++ tests/virbitmaptest.c| 13 - 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d63a8f0..1e2bc0a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1011,6 +1011,7 @@ virBitmapFree; virBitmapGetBit; virBitmapIsAllClear; virBitmapIsAllSet; +virBitmapLastSetBit; virBitmapNew; virBitmapNewCopy; virBitmapNewData; diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c index b6bd074..3e7269e 100644 --- a/src/util/virbitmap.c +++ b/src/util/virbitmap.c @@ -651,6 +651,51 @@ virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos) } /** + * virBitmapLastSetBit: + * @bitmap: the bitmap + * + * Search for the last set bit in bitmap @bitmap. + * + * Returns the position of the found bit, or -1 if no bit found. + */ +ssize_t +virBitmapLastSetBit(virBitmapPtr bitmap) +{ +ssize_t i; +int unusedBits; +ssize_t sz; +unsigned long bits; + +unusedBits = bitmap-map_len * VIR_BITMAP_BITS_PER_UNIT - bitmap-max_bit; + +sz = bitmap-map_len - 1; +if (unusedBits 0) { +bits = bitmap-map[sz] (VIR_BITMAP_BIT(VIR_BITMAP_BITS_PER_UNIT - unusedBits) - 1); +if (bits != 0) +goto found; + +sz--; +} + +for (; sz = 0; sz--) { +bits = bitmap-map[sz]; +if (bits != 0) +goto found; +} + +if (bits == 0) +return -1; + +found: +for (i = VIR_BITMAP_BITS_PER_UNIT - 1; i = 0; i--) { +if (bits 1UL i) +return i + sz * VIR_BITMAP_BITS_PER_UNIT; +} + +return -1; +} + +/** * virBitmapNextClearBit: * @bitmap: the bitmap * @pos: the position after which to search for a clear bit diff --git a/src/util/virbitmap.h b/src/util/virbitmap.h index 4493cc9..565264c 100644 --- a/src/util/virbitmap.h +++ b/src/util/virbitmap.h @@ -105,6 +105,9 @@ bool virBitmapIsAllClear(virBitmapPtr bitmap) ssize_t virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos) ATTRIBUTE_NONNULL(1); +ssize_t virBitmapLastSetBit(virBitmapPtr bitmap) +ATTRIBUTE_NONNULL(1); + ssize_t virBitmapNextClearBit(virBitmapPtr bitmap, ssize_t pos) ATTRIBUTE_NONNULL(1); diff --git a/tests/virbitmaptest.c b/tests/virbitmaptest.c index ea832ad..ac5f298 100644 --- a/tests/virbitmaptest.c +++ b/tests/virbitmaptest.c @@ -171,7 +171,7 @@ test3(const void *data ATTRIBUTE_UNUSED) return ret; } -/* test for virBitmapNextSetBit, virBitmapNextClearBit */ +/* test for virBitmapNextSetBit, virBitmapLastSetBit, virBitmapNextClearBit */ static int test4(const void *data ATTRIBUTE_UNUSED) { @@ -200,6 +200,9 @@ test4(const void *data ATTRIBUTE_UNUSED) if (virBitmapNextSetBit(bitmap, -1) != -1) goto error; +if (virBitmapLastSetBit(bitmap) != -1) +goto error; + for (i = 0; i size; i++) { if (virBitmapNextClearBit(bitmap, i - 1) != i) goto error; @@ -232,6 +235,11 @@ test4(const void *data ATTRIBUTE_UNUSED) if (virBitmapNextSetBit(bitmap, i) != -1) goto error; +j = sizeof(bitsPos)/sizeof(int) - 1; + +if (virBitmapLastSetBit(bitmap) != bitsPos[j]) +goto error; + j = 0; i = -1; @@ -255,6 +263,9 @@ test4(const void *data ATTRIBUTE_UNUSED) if (virBitmapNextSetBit(bitmap, i) != -1) goto error; +if (virBitmapLastSetBit(bitmap) != size - 1) +goto error; + if (virBitmapNextClearBit(bitmap, -1) != -1) goto error; -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 3/3] virnuma: use virNumaNodesetIsAvailable checking nodeset in virNumaSetupMemoryPolicy
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/util/virnuma.c | 23 --- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 4188ef5..613a43c 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -95,31 +95,19 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, int ret = -1; int bit = 0; size_t i; -int maxnode = 0; virBitmapPtr tmp_nodemask = NULL; +if (!virNumaNodesetIsAvailable(numatune)) +return -1; + tmp_nodemask = virDomainNumatuneGetNodeset(numatune, nodemask, -1); if (!tmp_nodemask) return 0; -if (numa_available() 0) { -virReportError(VIR_ERR_INTERNAL_ERROR, - %s, _(Host kernel is not aware of NUMA.)); -return -1; -} - -maxnode = numa_max_node(); -maxnode = maxnode NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; - /* Convert nodemask to NUMA bitmask. */ nodemask_zero(mask); bit = -1; while ((bit = virBitmapNextSetBit(tmp_nodemask, bit)) = 0) { -if (bit maxnode) { -virReportError(VIR_ERR_INTERNAL_ERROR, - _(NUMA node %d is out of range), bit); -return -1; -} nodemask_set(mask, bit); } @@ -347,10 +335,7 @@ int virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, virBitmapPtr nodemask ATTRIBUTE_UNUSED) { -if (virDomainNumatuneGetNodeset(numatune, NULL, -1)) { -virReportError(VIR_ERR_INTERNAL_ERROR, %s, - _(libvirt is compiled without NUMA tuning support)); - +if (!virNumaNodesetIsAvailable(numatune)) { return -1; } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 2/3] numatune: add check for numatune nodeset range
There was no check for 'nodeset' attribute in numatune-related elements. This patch adds validation that any nodeset specified does not exceed maximum host node. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/numatune_conf.c | 28 src/conf/numatune_conf.h | 1 + src/libvirt_private.syms | 1 + src/qemu/qemu_command.c| 4 +++ src/util/virnuma.c | 38 ++ src/util/virnuma.h | 1 + ...rgv-numatune-static-nodeset-exceed-hostnode.xml | 36 tests/qemuxml2argvmock.c | 9 + tests/qemuxml2argvtest.c | 1 + 9 files changed, 119 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-static-nodeset-exceed-hostnode.xml diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index 21d9a64..6986739 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -612,3 +612,31 @@ virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune) return false; } + +int +virDomainNumatuneSpecifiedMaxNode(virDomainNumatunePtr numatune) +{ +int ret = -1; +virBitmapPtr nodemask = NULL; +size_t i; +int bit; + +if (!numatune) +return ret; + +nodemask = virDomainNumatuneGetNodeset(numatune, NULL, -1); +if (nodemask) +ret = virBitmapLastSetBit(nodemask); + +for (i = 0; i numatune-nmem_nodes; i++) { +nodemask = numatune-mem_nodes[i].nodeset; +if (!nodemask) +continue; + +bit = virBitmapLastSetBit(nodemask); +if (bit ret) +ret = bit; +} + +return ret; +} diff --git a/src/conf/numatune_conf.h b/src/conf/numatune_conf.h index 5254629..15dc0d6 100644 --- a/src/conf/numatune_conf.h +++ b/src/conf/numatune_conf.h @@ -102,4 +102,5 @@ bool virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune); bool virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune); +int virDomainNumatuneSpecifiedMaxNode(virDomainNumatunePtr numatune); #endif /* __NUMATUNE_CONF_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 1e2bc0a..4a30ad7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1729,6 +1729,7 @@ virNumaGetPageInfo; virNumaGetPages; virNumaIsAvailable; virNumaNodeIsAvailable; +virNumaNodesetIsAvailable; virNumaSetPagePoolSize; virNumaSetupMemoryPolicy; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2e5af4f..d2c5f0c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -53,6 +53,7 @@ #include virstoragefile.h #include virtpm.h #include virscsi.h +#include virnuma.h #if defined(__linux__) # include linux/capability.h #endif @@ -6663,6 +6664,9 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, goto cleanup; } +if (!virNumaNodesetIsAvailable(def-numatune)) +goto cleanup; + for (i = 0; i def-mem.nhugepages; i++) { ssize_t next_bit, pos = 0; diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 690615f..4188ef5 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -165,6 +165,33 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, return ret; } +bool +virNumaNodesetIsAvailable(virDomainNumatunePtr numatune) +{ +int maxnode; +int bit; + +if (!numatune) +return true; + +bit = virDomainNumatuneSpecifiedMaxNode(numatune); +if (bit == -1) +return true; + +if ((maxnode = virNumaGetMaxNode()) 0) +return false; + +maxnode = maxnode NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; +if (bit maxnode) +goto error; + +return true; + + error: +virReportError(VIR_ERR_INTERNAL_ERROR, + _(NUMA node %d is out of range), bit); +return false; +} bool virNumaIsAvailable(void) @@ -330,6 +357,17 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, return 0; } +bool +virNumaNodesetIsAvailable(virDomainNumatunePtr numatune) +{ +if (virDomainNumatuneSpecifiedMaxNode(numatune) != -1) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(libvirt is compiled without NUMA tuning support)); +return false; +} + +return true; +} bool virNumaIsAvailable(void) diff --git a/src/util/virnuma.h b/src/util/virnuma.h index 04b6b8c..5bb37b8 100644 --- a/src/util/virnuma.h +++ b/src/util/virnuma.h @@ -34,6 +34,7 @@ char *virNumaGetAutoPlacementAdvice(unsigned short vcups, int virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, virBitmapPtr nodemask); +bool virNumaNodesetIsAvailable(virDomainNumatunePtr numatune); bool virNumaIsAvailable(void); int virNumaGetMaxNode(void); bool virNumaNodeIsAvailable(int node); diff --git a/tests
[libvirt] [PATCH v2 1/3] numatune: add check for numatune nodeset range
For memnode in numatune element, the range of attribute 'nodeset' was not validated. on my host maxnodes was 1, but when setting nodeset to '0-2' or more, guest also started succuss. there probably was qemu's bug too. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/numatune_conf.c | 21 - src/conf/numatune_conf.h | 19 src/libvirt_private.syms | 1 + src/qemu/qemu_command.c| 3 ++ src/qemu/qemu_command.h| 1 + src/util/virnuma.c | 55 ++ src/util/virnuma.h | 2 + ...rgv-numatune-static-nodeset-exceed-hostnode.xml | 35 ++ tests/qemuxml2argvmock.c | 9 tests/qemuxml2argvtest.c | 1 + 10 files changed, 126 insertions(+), 21 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-static-nodeset-exceed-hostnode.xml diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index 21d9a64..d440b86 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -42,27 +42,6 @@ VIR_ENUM_IMPL(virDomainNumatunePlacement, static, auto); -typedef struct _virDomainNumatuneNode virDomainNumatuneNode; -typedef virDomainNumatuneNode *virDomainNumatuneNodePtr; - -struct _virDomainNumatune { -struct { -bool specified; -virBitmapPtr nodeset; -virDomainNumatuneMemMode mode; -virDomainNumatunePlacement placement; -} memory; /* pinning for all the memory */ - -struct _virDomainNumatuneNode { -virBitmapPtr nodeset; -virDomainNumatuneMemMode mode; -} *mem_nodes; /* fine tuning per guest node */ -size_t nmem_nodes; - -/* Future NUMA tuning related stuff should go here. */ -}; - - static inline bool virDomainNumatuneNodeSpecified(virDomainNumatunePtr numatune, int cellid) diff --git a/src/conf/numatune_conf.h b/src/conf/numatune_conf.h index 5254629..650b6e7 100644 --- a/src/conf/numatune_conf.h +++ b/src/conf/numatune_conf.h @@ -45,6 +45,25 @@ typedef enum { VIR_ENUM_DECL(virDomainNumatunePlacement) VIR_ENUM_DECL(virDomainNumatuneMemMode) +typedef struct _virDomainNumatuneNode virDomainNumatuneNode; +typedef virDomainNumatuneNode *virDomainNumatuneNodePtr; + +struct _virDomainNumatune { +struct { +bool specified; +virBitmapPtr nodeset; +virDomainNumatuneMemMode mode; +virDomainNumatunePlacement placement; +} memory; /* pinning for all the memory */ + +struct _virDomainNumatuneNode { +virBitmapPtr nodeset; +virDomainNumatuneMemMode mode; +} *mem_nodes; /* fine tuning per guest node */ +size_t nmem_nodes; + +/* Future NUMA tuning related stuff should go here. */ +}; void virDomainNumatuneFree(virDomainNumatunePtr numatune); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d63a8f0..16a5864 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1728,6 +1728,7 @@ virNumaGetPageInfo; virNumaGetPages; virNumaIsAvailable; virNumaNodeIsAvailable; +virNumaNodesetIsAvailable; virNumaSetPagePoolSize; virNumaSetupMemoryPolicy; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2e5af4f..9757d3e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6663,6 +6663,9 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, goto cleanup; } +if (!virNumaNodesetIsAvailable(def-numatune)) +goto cleanup; + for (i = 0; i def-mem.nhugepages; i++) { ssize_t next_bit, pos = 0; diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index aa40c9e..f263665 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -27,6 +27,7 @@ # include domain_addr.h # include domain_conf.h # include vircommand.h +# include virnuma.h # include capabilities.h # include qemu_conf.h # include qemu_domain.h diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 690615f..411719d 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -312,6 +312,55 @@ virNumaGetNodeCPUs(int node, return ret; } + +bool +virNumaNodesetIsAvailable(virDomainNumatunePtr numatune) +{ +int maxnode; +int bit = -1; +size_t i; +virBitmapPtr nodemask = NULL; + +if (!numatune) +return true; + +if ((maxnode = virNumaGetMaxNode()) 0) +return false; + +maxnode = maxnode NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; + +/* verify memory and memnode element in numatune */ +nodemask = virDomainNumatuneGetNodeset(numatune, NULL, -1); +if (nodemask) { +while ((bit = virBitmapNextSetBit(nodemask, bit)) = 0) { +if (bit maxnode) { +goto error
[libvirt] [PATCH v2 0/3] add nodeset check in numatune
when setting elements memnode and nodeset in attribute numatune more than the host nodes in XML file, VM boot should fail. so add check for that. Chen Fan (3): numatune: add check for numatune nodeset range lxc controller: add check for numatune virnuma: remove redundant check for numanode src/conf/numatune_conf.c | 21 --- src/conf/numatune_conf.h | 19 ++ src/libvirt_private.syms | 1 + src/lxc/lxc_controller.c | 3 +- src/qemu/qemu_command.c| 3 + src/qemu/qemu_command.h| 1 + src/util/virnuma.c | 70 +- src/util/virnuma.h | 2 + ...rgv-numatune-static-nodeset-exceed-hostnode.xml | 35 +++ tests/qemuxml2argvmock.c | 9 +++ tests/qemuxml2argvtest.c | 1 + 11 files changed, 128 insertions(+), 37 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-static-nodeset-exceed-hostnode.xml -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 3/3] virnuma: remove redundant check for numanode
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/util/virnuma.c | 15 --- 1 file changed, 15 deletions(-) diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 411719d..8431b3c 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -95,31 +95,16 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, int ret = -1; int bit = 0; size_t i; -int maxnode = 0; virBitmapPtr tmp_nodemask = NULL; tmp_nodemask = virDomainNumatuneGetNodeset(numatune, nodemask, -1); if (!tmp_nodemask) return 0; -if (numa_available() 0) { -virReportError(VIR_ERR_INTERNAL_ERROR, - %s, _(Host kernel is not aware of NUMA.)); -return -1; -} - -maxnode = numa_max_node(); -maxnode = maxnode NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; - /* Convert nodemask to NUMA bitmask. */ nodemask_zero(mask); bit = -1; while ((bit = virBitmapNextSetBit(tmp_nodemask, bit)) = 0) { -if (bit maxnode) { -virReportError(VIR_ERR_INTERNAL_ERROR, - _(NUMA node %d is out of range), bit); -return -1; -} nodemask_set(mask, bit); } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 2/3] lxc controller: add check for numatune
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/lxc/lxc_controller.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 1861dd6..1ee89ab 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -689,7 +689,8 @@ static int virLXCControllerSetupResourceLimits(virLXCControllerPtr ctrl) int ret = -1; if (virLXCControllerGetNumadAdvice(ctrl, nodemask) 0 || -virNumaSetupMemoryPolicy(ctrl-def-numatune, nodemask) 0) +(virNumaNodesetIsAvailable (ctrl-def-numatune) + virNumaSetupMemoryPolicy(ctrl-def-numatune, nodemask) 0)) goto cleanup; if (virLXCControllerSetupCpuAffinity(ctrl) 0) -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] conf: fix a wrong comment in virSocketAddrNumericFamily()
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/util/virsocketaddr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index a19e3af..8c9f05f 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -859,8 +859,7 @@ virSocketAddrGetIpPrefix(const virSocketAddr *address, * virSocketAddrNumericFamily: * @address: address to check * - * Check if passed address is an IP address in numeric format. and - * return the address family, otherwise return 0. + * Check if passed address is an IP address in numeric format. * * Returns: AF_INET or AF_INET6 if @address is an numeric IP address, * -1 otherwise. -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] conf: fix a wrong comment in virSocketAddrNumericFamily()
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/util/virsocketaddr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index a19e3af..8c9f05f 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -859,8 +859,7 @@ virSocketAddrGetIpPrefix(const virSocketAddr *address, * virSocketAddrNumericFamily: * @address: address to check * - * Check if passed address is an IP address in numeric format. and - * return the address family, otherwise return 0. + * Check if passed address is an IP address in numeric format. * * Returns: AF_INET or AF_INET6 if @address is an numeric IP address, * -1 otherwise. -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 2/3] conf: add check if migration_host is a localhost address
On Wed, 2014-10-15 at 04:46 -0400, John Ferlan wrote: This patch has triggered a Coverity RESOURCE_LEAK (3 actually) Right, I will make a patch to fix it. Thank you for catching that. On 10/08/2014 09:54 PM, Chen, Fan wrote: On Wed, 2014-10-08 at 12:33 +0200, Ján Tomko wrote: On 10/07/2014 06:07 AM, Chen Fan wrote: Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 6d36689..a19e3af 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -889,15 +889,24 @@ virSocketAddrNumericFamily(const char *address) * false otherwise */ bool -virSocketAddrIsNumericLocalhost(const virSocketAddr *addr) +virSocketAddrIsNumericLocalhost(const char *addr) { +struct addrinfo *res; struct in_addr tmp = { .s_addr = htonl(INADDR_LOOPBACK) }; -switch (addr-data.stor.ss_family) { +struct sockaddr_in *inet4; +struct sockaddr_in6 *inet6; + +if (virSocketAddrParseInternal(res, addr, AF_UNSPEC, false) 0) +return false; + 'res' allocates something that must be free'd +switch (res-ai_addr-sa_family) { case AF_INET: -return memcmp(addr-data.inet4.sin_addr.s_addr, tmp.s_addr, - sizeof(addr-data.inet4.sin_addr.s_addr)) == 0; +inet4 = (struct sockaddr_in*) res-ai_addr; Leak #1 +return memcmp(inet4-sin_addr.s_addr, tmp.s_addr, + sizeof(inet4-sin_addr.s_addr)) == 0; case AF_INET6: -return IN6_IS_ADDR_LOOPBACK(addr-data.inet6.sin6_addr); +inet6 = (struct sockaddr_in6*) res-ai_addr; Leak #2 +return IN6_IS_ADDR_LOOPBACK((inet6-sin6_addr)); } Leak #3 return false; Other callers will call 'freeaddrinfo(res);' In order to resolve - you probably need to create a local ret = false, then assign ret = to either memcmp/IN6_IS_ADDR_LOOPBACK return, then call freeaddrinfo() before return ret John -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] conf: fix an memory leak in virSocketAddrIsNumericLocalhost()
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/util/virsocketaddr.c | 15 ++- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 8c9f05f..5f54e68 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -894,19 +894,24 @@ virSocketAddrIsNumericLocalhost(const char *addr) struct in_addr tmp = { .s_addr = htonl(INADDR_LOOPBACK) }; struct sockaddr_in *inet4; struct sockaddr_in6 *inet6; +bool ret = false; if (virSocketAddrParseInternal(res, addr, AF_UNSPEC, false) 0) -return false; +return ret; switch (res-ai_addr-sa_family) { case AF_INET: inet4 = (struct sockaddr_in*) res-ai_addr; -return memcmp(inet4-sin_addr.s_addr, tmp.s_addr, - sizeof(inet4-sin_addr.s_addr)) == 0; +ret = memcmp(inet4-sin_addr.s_addr, tmp.s_addr, + sizeof(inet4-sin_addr.s_addr)) == 0; +break; case AF_INET6: inet6 = (struct sockaddr_in6*) res-ai_addr; -return IN6_IS_ADDR_LOOPBACK((inet6-sin6_addr)); +ret = IN6_IS_ADDR_LOOPBACK((inet6-sin6_addr)); +break; } -return false; + +freeaddrinfo(res); +return ret; } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 0/3] lxc: Implement emulator pin APIs to set/get cpuset
On Fri, 2014-10-10 at 13:58 +0800, Wang Rui wrote: Ping? I found some wrong indentation in the 3 patches. like following in patch 1/3: +static int virLXCCgroupSetupCpusetTuneForEmulator(virDomainDefPtr def, + virCgroupPtr cgroup, + virBitmapPtr nodemask) Thanks, Chen On 2014/9/4 15:52, Wang Rui wrote: We can specify cpuset for a container defined with the xml like vcpu placement='static' cpuset='0-3' to achieve cpu isolation. It works when container is started. But there is no implements we can use to either change or get cpuset. The following patches implement the lxc driver methods for virDomainPinEmulator and virDomainGetEmulatorPinInfo. Also support container startup with emulator affinity info in xml. After these patches, we can set and get libvirt_lxc cpuset. Yue Wenyuan (3): lxc: Implement pin emulator for container startup lxc: Implement emulator pin API in lxc driver lxc: Implement geting emulator pin info API in lxc driver src/lxc/lxc_cgroup.c | 88 src/lxc/lxc_cgroup.h | 7 ++ src/lxc/lxc_controller.c | 4 + src/lxc/lxc_driver.c | 206 +++ 4 files changed, 305 insertions(+) -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 0/3] Check migration configuration
On Thu, 2014-10-09 at 14:54 +0200, Ján Tomko wrote: On 10/07/2014 06:07 AM, Chen Fan wrote: add some check in migration configuration. Chen Fan (3): migration: add migration_host support for Ipv6 address without brackets conf: add check if migration_host is a localhost address conf: Check migration_address whether is localhost src/libvirt_private.syms | 3 +- src/qemu/qemu.conf | 2 +- src/qemu/qemu_conf.c | 58 ++ src/qemu/qemu_conf.h | 2 ++ src/qemu/qemu_migration.c | 49 src/qemu/test_libvirtd_qemu.aug.in | 2 +- src/util/virsocketaddr.c | 43 +--- src/util/virsocketaddr.h | 4 ++- tests/sockettest.c | 2 +- 9 files changed, 125 insertions(+), 40 deletions(-) Now pushed. Thanks, Chen Jan -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 2/3] conf: add check if migration_host is a localhost address
On Wed, 2014-10-08 at 12:33 +0200, Ján Tomko wrote: On 10/07/2014 06:07 AM, Chen Fan wrote: Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/libvirt_private.syms | 1 + src/qemu/qemu_conf.c | 50 src/qemu/qemu_conf.h | 2 ++ src/util/virsocketaddr.c | 24 +++ src/util/virsocketaddr.h | 2 ++ 5 files changed, 79 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 8ab1394..a104bc6 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1911,6 +1911,7 @@ virSocketAddrGetIpPrefix; virSocketAddrGetPort; virSocketAddrGetRange; virSocketAddrIsNetmask; +virSocketAddrIsNumericLocalhost; virSocketAddrIsPrivate; virSocketAddrIsWildcard; virSocketAddrMask; diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index adc6caf..6b0ac5c 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -707,6 +707,15 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_LONG(seccomp_sandbox, cfg-seccompSandbox); GET_VALUE_STR(migration_host, cfg-migrateHost); +if (cfg-migrateHost +qemuCheckLocalhost(cfg-migrateHost)) { +virReportError(VIR_ERR_CONF_SYNTAX, + _(migration_host must not be the address of + the local machine: %s), + cfg-migrateHost); +goto cleanup; +} + GET_VALUE_STR(migration_address, cfg-migrationAddress); GET_VALUE_BOOL(log_timestamp, cfg-logTimestamp); @@ -1371,3 +1380,44 @@ qemuGetDefaultHugepath(virHugeTLBFSPtr hugetlbfs, return qemuGetHugepagePath(hugetlbfs[i]); } + +bool +qemuCheckLocalhost(const char *addrStr) +{ +virSocketAddr addr; +char *hostname, *tmp; +bool encloseAddress = false; +int family; +bool ret = true; + +if (VIR_STRDUP(hostname, addrStr) 0) +return false; + +tmp = hostname; + +if (STRPREFIX(hostname, [)) { +char *end = strchr(hostname, ']'); +if (end) { +*end = '\0'; +hostname++; +encloseAddress = true; +} +} We don't format the qemu.conf back and we don't need the brackets for anything. We can just store the migration host without them in cfg-migrationHost + +if (STRPREFIX(hostname, localhost)) +goto cleanup; + +family = virSocketAddrNumericFamily(hostname); +if ((family == AF_INET !encloseAddress) || +family == AF_INET6) { +if (virSocketAddrParse(addr, hostname, family) 0 +virSocketAddrIsNumericLocalhost(addr)) { +goto cleanup; +} +} There's no need to check for family upfront. + +ret = false; +cleanup: +VIR_FREE(tmp); +return ret; +} diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index cb01fb6..c9ce53c 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -322,4 +322,6 @@ int qemuTranslateSnapshotDiskSourcePool(virConnectPtr conn, char * qemuGetHugepagePath(virHugeTLBFSPtr hugepage); char * qemuGetDefaultHugepath(virHugeTLBFSPtr hugetlbfs, size_t nhugetlbfs); + +bool qemuCheckLocalhost(const char *addrStr); #endif /* __QEMUD_CONF_H */ diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 7fe7a15..6d36689 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -878,3 +878,27 @@ virSocketAddrNumericFamily(const char *address) freeaddrinfo(res); return family; } + +/** + * virSocketAddrIsNumericLocalhost: + * @address: address to check + * + * Check if passed address is a numeric 'localhost' address. + * + * Returns: true if @address is a numeric 'localhost' address, + * false otherwise + */ +bool +virSocketAddrIsNumericLocalhost(const virSocketAddr *addr) I've rewritten this function to take a 'const char *' argument. Along with the virStringStripIPv6Brackets function I've sent for review separately, this removes the need for a separate qemuCheckLocalhost function and it can be inlined. +{ +struct in_addr tmp = { .s_addr = htonl(INADDR_LOOPBACK) }; +switch (addr-data.stor.ss_family) { +case AF_INET: +return memcmp(addr-data.inet4.sin_addr.s_addr, tmp.s_addr, + sizeof(addr-data.inet4.sin_addr.s_addr)) == 0; +case AF_INET6: +return IN6_IS_ADDR_LOOPBACK(addr-data.inet6.sin6_addr); +} +return false; + +} The diff I'll squash into this patch before pushing (after virStringStripIPv6Brackets is sorted out): I had tested this diff and it works fine. Thanks, Chen --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -707,8 +707,10 @@ int
Re: [libvirt] [PATCH v3 1/3] migration: add migration_host support for Ipv6 address without brackets
On Tue, 2014-10-07 at 11:08 +0200, Ján Tomko wrote: On 10/07/2014 06:07 AM, Chen Fan wrote: if specifying migration_host to an Ipv6 address without brackets, it was resolved to an incorrect address, such as: tcp:2001:0DB8::1428:, but the correct address should be: tcp:[2001:0DB8::1428]: so we should add brackets when parsing it. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/libvirt_private.syms | 2 +- src/qemu/qemu_migration.c | 49 +++ src/util/virsocketaddr.c | 19 +- src/util/virsocketaddr.h | 2 +- tests/sockettest.c| 2 +- 5 files changed, 36 insertions(+), 38 deletions(-) ACK Thanks. Jan -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 2/3] conf: add check if migration_host is a localhost address
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/libvirt_private.syms | 1 + src/qemu/qemu_conf.c | 50 src/qemu/qemu_conf.h | 2 ++ src/util/virsocketaddr.c | 24 +++ src/util/virsocketaddr.h | 2 ++ 5 files changed, 79 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 8ab1394..a104bc6 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1911,6 +1911,7 @@ virSocketAddrGetIpPrefix; virSocketAddrGetPort; virSocketAddrGetRange; virSocketAddrIsNetmask; +virSocketAddrIsNumericLocalhost; virSocketAddrIsPrivate; virSocketAddrIsWildcard; virSocketAddrMask; diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index adc6caf..6b0ac5c 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -707,6 +707,15 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_LONG(seccomp_sandbox, cfg-seccompSandbox); GET_VALUE_STR(migration_host, cfg-migrateHost); +if (cfg-migrateHost +qemuCheckLocalhost(cfg-migrateHost)) { +virReportError(VIR_ERR_CONF_SYNTAX, + _(migration_host must not be the address of + the local machine: %s), + cfg-migrateHost); +goto cleanup; +} + GET_VALUE_STR(migration_address, cfg-migrationAddress); GET_VALUE_BOOL(log_timestamp, cfg-logTimestamp); @@ -1371,3 +1380,44 @@ qemuGetDefaultHugepath(virHugeTLBFSPtr hugetlbfs, return qemuGetHugepagePath(hugetlbfs[i]); } + +bool +qemuCheckLocalhost(const char *addrStr) +{ +virSocketAddr addr; +char *hostname, *tmp; +bool encloseAddress = false; +int family; +bool ret = true; + +if (VIR_STRDUP(hostname, addrStr) 0) +return false; + +tmp = hostname; + +if (STRPREFIX(hostname, [)) { +char *end = strchr(hostname, ']'); +if (end) { +*end = '\0'; +hostname++; +encloseAddress = true; +} +} + +if (STRPREFIX(hostname, localhost)) +goto cleanup; + +family = virSocketAddrNumericFamily(hostname); +if ((family == AF_INET !encloseAddress) || +family == AF_INET6) { +if (virSocketAddrParse(addr, hostname, family) 0 +virSocketAddrIsNumericLocalhost(addr)) { +goto cleanup; +} +} + +ret = false; +cleanup: +VIR_FREE(tmp); +return ret; +} diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index cb01fb6..c9ce53c 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -322,4 +322,6 @@ int qemuTranslateSnapshotDiskSourcePool(virConnectPtr conn, char * qemuGetHugepagePath(virHugeTLBFSPtr hugepage); char * qemuGetDefaultHugepath(virHugeTLBFSPtr hugetlbfs, size_t nhugetlbfs); + +bool qemuCheckLocalhost(const char *addrStr); #endif /* __QEMUD_CONF_H */ diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 7fe7a15..6d36689 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -878,3 +878,27 @@ virSocketAddrNumericFamily(const char *address) freeaddrinfo(res); return family; } + +/** + * virSocketAddrIsNumericLocalhost: + * @address: address to check + * + * Check if passed address is a numeric 'localhost' address. + * + * Returns: true if @address is a numeric 'localhost' address, + * false otherwise + */ +bool +virSocketAddrIsNumericLocalhost(const virSocketAddr *addr) +{ +struct in_addr tmp = { .s_addr = htonl(INADDR_LOOPBACK) }; +switch (addr-data.stor.ss_family) { +case AF_INET: +return memcmp(addr-data.inet4.sin_addr.s_addr, tmp.s_addr, + sizeof(addr-data.inet4.sin_addr.s_addr)) == 0; +case AF_INET6: +return IN6_IS_ADDR_LOOPBACK(addr-data.inet6.sin6_addr); +} +return false; + +} diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h index 35c9c1a..fa9e98b 100644 --- a/src/util/virsocketaddr.h +++ b/src/util/virsocketaddr.h @@ -126,4 +126,6 @@ bool virSocketAddrIsPrivate(const virSocketAddr *addr); bool virSocketAddrIsWildcard(const virSocketAddr *addr); int virSocketAddrNumericFamily(const char *address); + +bool virSocketAddrIsNumericLocalhost(const virSocketAddr *addr); #endif /* __VIR_SOCKETADDR_H__ */ -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 1/3] migration: add migration_host support for Ipv6 address without brackets
if specifying migration_host to an Ipv6 address without brackets, it was resolved to an incorrect address, such as: tcp:2001:0DB8::1428:, but the correct address should be: tcp:[2001:0DB8::1428]: so we should add brackets when parsing it. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/libvirt_private.syms | 2 +- src/qemu/qemu_migration.c | 49 +++ src/util/virsocketaddr.c | 19 +- src/util/virsocketaddr.h | 2 +- tests/sockettest.c| 2 +- 5 files changed, 36 insertions(+), 38 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 7cbc35b..8ab1394 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1911,11 +1911,11 @@ virSocketAddrGetIpPrefix; virSocketAddrGetPort; virSocketAddrGetRange; virSocketAddrIsNetmask; -virSocketAddrIsNumeric; virSocketAddrIsPrivate; virSocketAddrIsWildcard; virSocketAddrMask; virSocketAddrMaskByPrefix; +virSocketAddrNumericFamily; virSocketAddrParse; virSocketAddrParseIPv4; virSocketAddrParseIPv6; diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 284cd5a..e135249 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2605,7 +2605,6 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, if (VIR_STRDUP(migrateFrom, stdio) 0) goto cleanup; } else { -virSocketAddr listenAddressSocket; bool encloseAddress = false; bool hostIPv6Capable = false; bool qemuIPv6Capable = false; @@ -2627,28 +2626,21 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, virObjectUnref(qemuCaps); if (listenAddress) { -if (virSocketAddrIsNumeric(listenAddress)) { -/* listenAddress is numeric IPv4 or IPv6 */ -if (virSocketAddrParse(listenAddressSocket, listenAddress, AF_UNSPEC) 0) +if (virSocketAddrNumericFamily(listenAddress) == AF_INET6) { +if (!qemuIPv6Capable) { +virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, %s, + _(qemu isn't capable of IPv6)); goto cleanup; - -/* address parsed successfully */ -if (VIR_SOCKET_ADDR_IS_FAMILY(listenAddressSocket, AF_INET6)) { -if (!qemuIPv6Capable) { -virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, %s, - _(qemu isn't capable of IPv6)); -goto cleanup; -} -if (!hostIPv6Capable) { -virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, %s, - _(host isn't capable of IPv6)); -goto cleanup; -} -/* IPv6 address must be escaped in brackets on the cmd line */ -encloseAddress = true; } +if (!hostIPv6Capable) { +virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, %s, + _(host isn't capable of IPv6)); +goto cleanup; +} +/* IPv6 address must be escaped in brackets on the cmd line */ +encloseAddress = true; } else { -/* listenAddress is a hostname */ +/* listenAddress is a hostname or IPv4 */ } } else if (qemuIPv6Capable hostIPv6Capable) { /* Listen on :: instead of 0.0.0.0 if QEMU understands it @@ -2950,15 +2942,17 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, * to be a correct hostname which refers to the target machine). */ if (uri_in == NULL) { +bool encloseAddress = false; +const char *incFormat; + if (virPortAllocatorAcquire(driver-migrationPorts, port) 0) goto cleanup; if (migrateHost != NULL) { -if (virSocketAddrIsNumeric(migrateHost) -virSocketAddrParse(NULL, migrateHost, AF_UNSPEC) 0) -goto cleanup; +if (virSocketAddrNumericFamily(migrateHost) == AF_INET6) +encloseAddress = true; - if (VIR_STRDUP(hostname, migrateHost) 0) +if (VIR_STRDUP(hostname, migrateHost) 0) goto cleanup; } else { if ((hostname = virGetHostname()) == NULL) @@ -2977,7 +2971,12 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, * compatibility with old targets. We at least make the * new targets accept both syntaxes though. */ -if (virAsprintf(uri_out, tcp:%s:%d, hostname, port) 0) +if (encloseAddress) +incFormat = %s:[%s]:%d; +else +incFormat = %s:%s:%d; + +if (virAsprintf(uri_out, incFormat, tcp, hostname, port) 0) goto cleanup
[libvirt] [PATCH v3 0/3] Check migration configuration
add some check in migration configuration. Chen Fan (3): migration: add migration_host support for Ipv6 address without brackets conf: add check if migration_host is a localhost address conf: Check migration_address whether is localhost src/libvirt_private.syms | 3 +- src/qemu/qemu.conf | 2 +- src/qemu/qemu_conf.c | 58 ++ src/qemu/qemu_conf.h | 2 ++ src/qemu/qemu_migration.c | 49 src/qemu/test_libvirtd_qemu.aug.in | 2 +- src/util/virsocketaddr.c | 43 +--- src/util/virsocketaddr.h | 4 ++- tests/sockettest.c | 2 +- 9 files changed, 125 insertions(+), 40 deletions(-) -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 3/3] conf: Check migration_address whether is localhost
When enabling the migration_address option, by default it is set to 127.0.0.1, but it's not a valid address for migration. so we should add verification and set the default migration_address to 0.0.0.0. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu.conf | 2 +- src/qemu/qemu_conf.c | 8 src/qemu/test_libvirtd_qemu.aug.in | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index 92ca715..c6db568 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -467,7 +467,7 @@ # Override the listen address for all incoming migrations. Defaults to # 0.0.0.0, or :: if both host and qemu are capable of IPv6. -#migration_address = 127.0.0.1 +#migration_address = 0.0.0.0 # The default hostname or IP address which will be used by a migration diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 6b0ac5c..f34fa06 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -717,6 +717,14 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, } GET_VALUE_STR(migration_address, cfg-migrationAddress); +if (cfg-migrationAddress +qemuCheckLocalhost(cfg-migrationAddress)) { +virReportError(VIR_ERR_CONF_SYNTAX, + _(migration_address must not be the address of + the local machine: %s), + cfg-migrationAddress); +goto cleanup; +} GET_VALUE_BOOL(log_timestamp, cfg-logTimestamp); diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in index d2bc2c0..30fd27e 100644 --- a/src/qemu/test_libvirtd_qemu.aug.in +++ b/src/qemu/test_libvirtd_qemu.aug.in @@ -69,7 +69,7 @@ module Test_libvirtd_qemu = { keepalive_interval = 5 } { keepalive_count = 5 } { seccomp_sandbox = 1 } -{ migration_address = 127.0.0.1 } +{ migration_address = 0.0.0.0 } { migration_host = host.example.com } { migration_port_min = 49152 } { migration_port_max = 49215 } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 3/4] conf: add virSocketAddrIsLocalhost to Check migration_host
On Fri, 2014-10-03 at 15:58 +0200, Ján Tomko wrote: On 09/23/2014 06:04 AM, Chen Fan wrote: Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/libvirt_private.syms | 1 + src/qemu/qemu_conf.c | 8 src/util/virsocketaddr.c | 35 +++ src/util/virsocketaddr.h | 3 +++ 4 files changed, 47 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 51a692b..f7172b0 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1885,6 +1885,7 @@ virSocketAddrGetPort; virSocketAddrGetRange; virSocketAddrIsNetmask; virSocketAddrIsNumeric; +virSocketAddrIsLocalhost; virSocketAddrIsPrivate; virSocketAddrIsWildcard; virSocketAddrMask; diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index adc6caf..30169cf 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -707,6 +707,14 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_LONG(seccomp_sandbox, cfg-seccompSandbox); GET_VALUE_STR(migration_host, cfg-migrateHost); +if (cfg-migrateHost +virSocketAddrIsLocalhost(cfg-migrateHost)) { +virReportError(VIR_ERR_CONF_SYNTAX, + _(migration_host must not be 'localhost' address: %s), + cfg-migrateHost); +goto cleanup; +} + GET_VALUE_STR(migration_address, cfg-migrationAddress); GET_VALUE_BOOL(log_timestamp, cfg-logTimestamp); diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 64409a6..dfcaf72 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -884,3 +884,38 @@ virSocketAddrIsNumeric(const char *address, int *family) } return sa_family == AF_INET || sa_family == AF_INET6; } + +/** + * virSocketAddrIsLocalhost: + * @address: address to check + * + * Check if passed address is a 'localhost' address. + * + * Returns: true if @address is 'localhost' address, + * false otherwise + */ +bool +virSocketAddrIsLocalhost(const char *address) I think this function should be named 'IsNumericLocalhost' and only check for the numeric representation of localhost. If the address is numeric, we can parse it and catch all the cases (like 127.0.0.1, 2130706433, 0177.0.0.1, 0:0:0::1). But we can't check if a hostname points to localhost without resolving it. +{ + int family; + + if (virSocketAddrIsNumeric(address, family)) { + if (family == AF_INET) { + if (STREQ(address, 127.0.0.1)) + return true; + } + This should do what virSocketAddrIsWildcard does, only using INADDR_LOOPBACK instead of INADDR_ANY and IN6_IS_ADDR_LOOPBACK instead of IN6_IS_ADDR_UNSPECIFIED. + if (family == AF_INET6) { + if (STREQ(address, ::1)) + return true; + } + } else { + if (STRPREFIX(address, localhost)) + return true; I'd put this check in qemu_conf.c. + + if (STREQ(address, [::1])) + return true; And strip the brackets before calling virSocketAddrParse. I had sent V3 patch that including the above solution. please help to review it. Thanks, Chen Jan + } + + return false; +} diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h index 7b11afb..5269f35 100644 --- a/src/util/virsocketaddr.h +++ b/src/util/virsocketaddr.h @@ -126,4 +126,7 @@ bool virSocketAddrIsPrivate(const virSocketAddr *addr); bool virSocketAddrIsWildcard(const virSocketAddr *addr); bool virSocketAddrIsNumeric(const char *address, int *family); + +bool virSocketAddrIsLocalhost(const char *address); + #endif /* __VIR_SOCKETADDR_H__ */ -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 2/4] migration: add migration_host support for Ipv6 address without brackets
On Fri, 2014-10-03 at 15:58 +0200, Ján Tomko wrote: On 09/23/2014 06:04 AM, Chen Fan wrote: if specifying migration_host to an Ipv6 address without brackets, it was resolved to an incorrect address, such as: tcp:2001:0DB8::1428:, but the correct address should be: tcp:[2001:0DB8::1428]: so we should add brackets when parsing it. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_migration.c | 24 +--- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 155f5b9..016d131 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2544,7 +2544,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, if (VIR_STRDUP(migrateFrom, stdio) 0) goto cleanup; } else { -virSocketAddr listenAddressSocket; +int listenAddressFamily; bool encloseAddress = false; bool hostIPv6Capable = false; bool qemuIPv6Capable = false; @@ -2565,13 +2565,9 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, virObjectUnref(qemuCaps); if (listenAddress) { -if (virSocketAddrIsNumeric(listenAddress, NULL)) { +if (virSocketAddrIsNumeric(listenAddress, listenAddressFamily)) { Both uses of this function are in this patch (I didn't realize that when reviewing v1). We can rename it to virSocketAddrNumericFamily and do if (virSocketAddrNumericFamily(listenAddress) == AF_INET6), removing the need for a temporary variable. Right, Agreed. /* listenAddress is numeric IPv4 or IPv6 */ -if (virSocketAddrParse(listenAddressSocket, listenAddress, AF_UNSPEC) 0) -goto cleanup; - -/* address parsed successfully */ -if (VIR_SOCKET_ADDR_IS_FAMILY(listenAddressSocket, AF_INET6)) { +if (listenAddressFamily == AF_INET6) { if (!qemuIPv6Capable) { virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, %s, _(qemu isn't capable of IPv6)); @@ -2850,11 +2846,17 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, goto cleanup; if (migrateHost != NULL) { -if (virSocketAddrIsNumeric(migrateHost, NULL) -virSocketAddrParse(NULL, migrateHost, AF_UNSPEC) 0) -goto cleanup; +int family; +bool migrateHostisIpv6Address = false; + +if (virSocketAddrIsNumeric(migrateHost, family) +(family == AF_INET6)) +migrateHostisIpv6Address = true; - if (VIR_STRDUP(hostname, migrateHost) 0) +if ((migrateHostisIpv6Address + virAsprintf(hostname, [%s], migrateHost) 0) || +(!migrateHostisIpv6Address + virAsprintf(hostname, %s, migrateHost) 0)) goto cleanup; In qemuMigrationPrepareAny, we have: if (encloseAddress) incFormat = %s:[%s]:%d; else incFormat = %s:%s:%d; if (virAsprintf(migrateFrom, incFormat, protocol, listenAddress, port) 0) goto cleanup; Using the same pattern here as well would make it more readable. Thanks, Chen Jan } else { if ((hostname = virGetHostname()) == NULL) -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 0/4] Check migration configuration
any feedback? Thanks, Chen On Thu, 2014-09-25 at 01:10 +, Chen, Fan wrote: ping? On Tue, 2014-09-23 at 12:04 +0800, Chen Fan wrote: add some check in migration configuration. Chen Fan (4): virsocketaddr: return address family in virSocketAddrIsNumeric migration: add migration_host support for Ipv6 address without brackets conf: add virSocketAddrIsLocalhost to Check migration_host conf: Check migration_address whether is localhost src/libvirt_private.syms | 1 + src/qemu/qemu.conf | 2 +- src/qemu/qemu_conf.c | 15 src/qemu/qemu_migration.c | 24 ++- src/qemu/test_libvirtd_qemu.aug.in | 2 +- src/util/virsocketaddr.c | 48 ++ src/util/virsocketaddr.h | 5 +++- tests/sockettest.c | 2 +- 8 files changed, 80 insertions(+), 19 deletions(-) -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 0/4] Check migration configuration
ping? On Tue, 2014-09-23 at 12:04 +0800, Chen Fan wrote: add some check in migration configuration. Chen Fan (4): virsocketaddr: return address family in virSocketAddrIsNumeric migration: add migration_host support for Ipv6 address without brackets conf: add virSocketAddrIsLocalhost to Check migration_host conf: Check migration_address whether is localhost src/libvirt_private.syms | 1 + src/qemu/qemu.conf | 2 +- src/qemu/qemu_conf.c | 15 src/qemu/qemu_migration.c | 24 ++- src/qemu/test_libvirtd_qemu.aug.in | 2 +- src/util/virsocketaddr.c | 48 ++ src/util/virsocketaddr.h | 5 +++- tests/sockettest.c | 2 +- 8 files changed, 80 insertions(+), 19 deletions(-) -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 1/2] numatune: add check for memnode.nodeset range
For memnode in numatune element, the range of attribute 'nodeset' was not validated. on my host maxnodes was 1, but when setting nodeset to '0-2' or more, guest also started succuss. there probably was qemu's bug too. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/numatune_conf.c | 29 + src/conf/numatune_conf.h | 4 2 files changed, 33 insertions(+) diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index 21d9a64..a9b20aa 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -183,6 +183,9 @@ virDomainNumatuneNodeParseXML(virDomainNumatunePtr *numatunePtr, VIR_DOMAIN_CPUMASK_LEN) 0) goto cleanup; VIR_FREE(tmp); + +if (!virDomainNumatuneNodeSetIsAvailable(numatune, cellid)) +goto cleanup; } ret = 0; @@ -612,3 +615,29 @@ virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune) return false; } + +bool +virDomainNumatuneNodeSetIsAvailable(virDomainNumatunePtr numatune, +int cellid) +{ +int maxnode; +int bit = -1; +virBitmapPtr nodemask = NULL; + +nodemask = virDomainNumatuneGetNodeset(numatune, NULL, cellid); +if (!nodemask) +return false; + +if ((maxnode = virNumaGetMaxNode()) 0) +return false; + +while ((bit = virBitmapNextSetBit(nodemask, bit)) = 0) { +if (bit maxnode) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(NUMA node %d is out of range), bit); +return false; +} +} + +return true; +} diff --git a/src/conf/numatune_conf.h b/src/conf/numatune_conf.h index 5254629..cab0b83 100644 --- a/src/conf/numatune_conf.h +++ b/src/conf/numatune_conf.h @@ -102,4 +102,8 @@ bool virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune); bool virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune); +extern int virNumaGetMaxNode(void); +bool virDomainNumatuneNodeSetIsAvailable(virDomainNumatunePtr numatune, + int cellid); + #endif /* __NUMATUNE_CONF_H__ */ -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 2/2] numatune: move up verification codes in virNumaSetupMemoryPolicy
use virDomainNumatuneNodeSetIsAvailable() to verify momory.nodeset whether is out of range. and move up the verification. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/numatune_conf.c | 3 +++ src/util/virnuma.c | 15 --- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index a9b20aa..8b43167 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -278,6 +278,9 @@ virDomainNumatuneParseXML(virDomainNumatunePtr *numatunePtr, nodeset) 0) goto cleanup; +if (!virDomainNumatuneNodeSetIsAvailable(*numatunePtr, -1)) +goto cleanup; + if (virDomainNumatuneNodeParseXML(numatunePtr, ncells, ctxt) 0) goto cleanup; diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 1a34398..4766f16 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -95,31 +95,16 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, int ret = -1; int bit = 0; size_t i; -int maxnode = 0; virBitmapPtr tmp_nodemask = NULL; tmp_nodemask = virDomainNumatuneGetNodeset(numatune, nodemask, -1); if (!tmp_nodemask) return 0; -if (numa_available() 0) { -virReportError(VIR_ERR_INTERNAL_ERROR, - %s, _(Host kernel is not aware of NUMA.)); -return -1; -} - -maxnode = numa_max_node(); -maxnode = maxnode NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; - /* Convert nodemask to NUMA bitmask. */ nodemask_zero(mask); bit = -1; while ((bit = virBitmapNextSetBit(tmp_nodemask, bit)) = 0) { -if (bit maxnode) { -virReportError(VIR_ERR_INTERNAL_ERROR, - _(NUMA node %d is out of range), bit); -return -1; -} nodemask_set(mask, bit); } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 0/2] add nodeset check in numatune
for memnode.nodeset in numatune, when setting it more than the host nodes, it should fail. Chen Fan (2): numatune: add check for memnode.nodeset range numatune: move up verification codes in virNumaSetupMemoryPolicy src/conf/numatune_conf.c | 32 src/conf/numatune_conf.h | 4 src/util/virnuma.c | 15 --- 3 files changed, 36 insertions(+), 15 deletions(-) -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 1/2] numatune: add check for memnode.nodeset range
On Tue, 2014-09-23 at 14:41 +0200, Michal Privoznik wrote: On 23.09.2014 11:34, Chen Fan wrote: For memnode in numatune element, the range of attribute 'nodeset' was not validated. on my host maxnodes was 1, but when setting nodeset to '0-2' or more, guest also started succuss. there probably was qemu's bug too. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/numatune_conf.c | 29 + src/conf/numatune_conf.h | 4 2 files changed, 33 insertions(+) diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index 21d9a64..a9b20aa 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -183,6 +183,9 @@ virDomainNumatuneNodeParseXML(virDomainNumatunePtr *numatunePtr, VIR_DOMAIN_CPUMASK_LEN) 0) goto cleanup; VIR_FREE(tmp); + +if (!virDomainNumatuneNodeSetIsAvailable(numatune, cellid)) +goto cleanup; Well, if there already exists such configuration within an existing domain, this will cause a failure on XML parsing when the daemon is starting and hence domain is lost. Right, I would move this check to VM start routine. } ret = 0; @@ -612,3 +615,29 @@ virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune) return false; } + +bool +virDomainNumatuneNodeSetIsAvailable(virDomainNumatunePtr numatune, +int cellid) +{ +int maxnode; +int bit = -1; +virBitmapPtr nodemask = NULL; + +nodemask = virDomainNumatuneGetNodeset(numatune, NULL, cellid); +if (!nodemask) +return false; + +if ((maxnode = virNumaGetMaxNode()) 0) +return false; This will work in real environment, but won't work in tests. You need to mock this to get predictable max numa node. I will add test case for this. Thanks, Chen + +while ((bit = virBitmapNextSetBit(nodemask, bit)) = 0) { +if (bit maxnode) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(NUMA node %d is out of range), bit); +return false; +} +} + +return true; +} diff --git a/src/conf/numatune_conf.h b/src/conf/numatune_conf.h index 5254629..cab0b83 100644 --- a/src/conf/numatune_conf.h +++ b/src/conf/numatune_conf.h @@ -102,4 +102,8 @@ bool virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune); bool virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune); +extern int virNumaGetMaxNode(void); +bool virDomainNumatuneNodeSetIsAvailable(virDomainNumatunePtr numatune, + int cellid); + #endif /* __NUMATUNE_CONF_H__ */ Michal -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/2] numatune: move up verification codes in virNumaSetupMemoryPolicy
On Tue, 2014-09-23 at 14:42 +0200, Michal Privoznik wrote: On 23.09.2014 11:34, Chen Fan wrote: use virDomainNumatuneNodeSetIsAvailable() to verify momory.nodeset whether is out of range. and move up the verification. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/numatune_conf.c | 3 +++ src/util/virnuma.c | 15 --- 2 files changed, 3 insertions(+), 15 deletions(-) I'd expect a test case for this. Ok, I will add it. thanks, Chen diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index a9b20aa..8b43167 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -278,6 +278,9 @@ virDomainNumatuneParseXML(virDomainNumatunePtr *numatunePtr, nodeset) 0) goto cleanup; +if (!virDomainNumatuneNodeSetIsAvailable(*numatunePtr, -1)) +goto cleanup; + if (virDomainNumatuneNodeParseXML(numatunePtr, ncells, ctxt) 0) goto cleanup; diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 1a34398..4766f16 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -95,31 +95,16 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, int ret = -1; int bit = 0; size_t i; -int maxnode = 0; virBitmapPtr tmp_nodemask = NULL; tmp_nodemask = virDomainNumatuneGetNodeset(numatune, nodemask, -1); if (!tmp_nodemask) return 0; -if (numa_available() 0) { -virReportError(VIR_ERR_INTERNAL_ERROR, - %s, _(Host kernel is not aware of NUMA.)); -return -1; -} - -maxnode = numa_max_node(); -maxnode = maxnode NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; - /* Convert nodemask to NUMA bitmask. */ nodemask_zero(mask); bit = -1; while ((bit = virBitmapNextSetBit(tmp_nodemask, bit)) = 0) { -if (bit maxnode) { -virReportError(VIR_ERR_INTERNAL_ERROR, - _(NUMA node %d is out of range), bit); -return -1; -} nodemask_set(mask, bit); } Yet again, this suffers the same problem that 1/2 does: domain may be lost. Michal -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v1 2/3] conf: Check migration_host is localhost or not during restart
On Mon, 2014-09-22 at 15:34 +0200, Ján Tomko wrote: On 09/12/2014 06:33 AM, Chen Fan wrote: Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_conf.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index ac10b64..013f3de 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -707,6 +707,17 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_LONG(seccomp_sandbox, cfg-seccompSandbox); GET_VALUE_STR(migration_host, cfg-migrateHost); +if (cfg-migrateHost) { +if (STRPREFIX(cfg-migrateHost, localhost) || +STREQ(cfg-migrateHost, 127.0.0.1) || +STREQ(cfg-migrateHost, ::1) || +STREQ(cfg-migrateHost, [::1])) {\ I think we need a 'virSocketAddrIsLocalhost' function similar to virSocketAddrIsWildcard, which would check any numeric represnation of the address: if (STRPREFIX(cfg-migrateHost, localhost) || virSocketAddrIsLocalhost(cfg-migrateHost)) It's a good point. +virReportError(VIR_ERR_CONF_SYNTAX, %s, + _(migration_host must be a valid address or hostname)); Something more specific, like: migration_host must not be localhost is more user-friendly. I will update the output. Thanks, Chen Jan +goto cleanup; +} +} + GET_VALUE_STR(migration_address, cfg-migrationAddress); GET_VALUE_BOOL(log_timestamp, cfg-logTimestamp); -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] cpu: fix wrong single quote mark
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/cpu_conf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index 6c454ee..116aa58 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -413,7 +413,7 @@ virCPUDefParseXML(xmlNodePtr node, for (j = 0; j i; j++) { if (STREQ(name, def-features[j].name)) { virReportError(VIR_ERR_XML_ERROR, - _(CPU feature `%s' specified more than once), + _(CPU feature '%s' specified more than once), name); VIR_FREE(name); goto error; @@ -731,7 +731,7 @@ virCPUDefUpdateFeatureInternal(virCPUDefPtr def, } virReportError(VIR_ERR_INTERNAL_ERROR, - _(CPU feature `%s' specified more than once), + _(CPU feature '%s' specified more than once), name); return -1; -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v1 1/3] migration: add migration_host support for Ipv6 address without brackets
On Mon, 2014-09-22 at 15:34 +0200, Ján Tomko wrote: On 09/12/2014 06:31 AM, Chen Fan wrote: when specifying migration_host to an Ipv6 address without brackets, it was resolved to an incorrect address, such as: tcp:2001:0DB8::1428:, but the correct address should be: tcp:[2001:0DB8::1428]: so we should add brackets when parsing it. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_migration.c | 19 +++ 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index e4b664b..c7eb305 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2850,11 +2850,22 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, goto cleanup; if (migrateHost != NULL) { -if (virSocketAddrIsNumeric(migrateHost) -virSocketAddrParse(NULL, migrateHost, AF_UNSPEC) 0) -goto cleanup; Hmm, I'm not sure what this check was doing - if the address was succesfully parsed in AddrIsNumeric, it should be parsed by virSocketAddrParse as well. agreed. +virSocketAddr migrateHostSocket; +bool migrateHostisIpv6Address = false; + +if (virSocketAddrIsNumeric(migrateHost)) { +if (virSocketAddrParse(migrateHostSocket, migrateHost, AF_UNSPEC) 0) +goto cleanup; + +if (VIR_SOCKET_ADDR_IS_FAMILY(migrateHostSocket, AF_INET6)) { +migrateHostisIpv6Address = true; +} +} We also do this parsing to chceck for numeric IPv6 addresses in qemuMigrationPrepareAny. It would be nicer to create a new 'virSocketAddrIsNumericIPv6' function and use it in both of them. I will follow this. Thanks, Chen Jan - if (VIR_STRDUP(hostname, migrateHost) 0) +if ((migrateHostisIpv6Address + virAsprintf(hostname, [%s], migrateHost) 0) || +(!migrateHostisIpv6Address + virAsprintf(hostname, %s, migrateHost) 0)) goto cleanup; } else { if ((hostname = virGetHostname()) == NULL) -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 2/4] migration: add migration_host support for Ipv6 address without brackets
if specifying migration_host to an Ipv6 address without brackets, it was resolved to an incorrect address, such as: tcp:2001:0DB8::1428:, but the correct address should be: tcp:[2001:0DB8::1428]: so we should add brackets when parsing it. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_migration.c | 24 +--- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 155f5b9..016d131 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2544,7 +2544,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, if (VIR_STRDUP(migrateFrom, stdio) 0) goto cleanup; } else { -virSocketAddr listenAddressSocket; +int listenAddressFamily; bool encloseAddress = false; bool hostIPv6Capable = false; bool qemuIPv6Capable = false; @@ -2565,13 +2565,9 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, virObjectUnref(qemuCaps); if (listenAddress) { -if (virSocketAddrIsNumeric(listenAddress, NULL)) { +if (virSocketAddrIsNumeric(listenAddress, listenAddressFamily)) { /* listenAddress is numeric IPv4 or IPv6 */ -if (virSocketAddrParse(listenAddressSocket, listenAddress, AF_UNSPEC) 0) -goto cleanup; - -/* address parsed successfully */ -if (VIR_SOCKET_ADDR_IS_FAMILY(listenAddressSocket, AF_INET6)) { +if (listenAddressFamily == AF_INET6) { if (!qemuIPv6Capable) { virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, %s, _(qemu isn't capable of IPv6)); @@ -2850,11 +2846,17 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, goto cleanup; if (migrateHost != NULL) { -if (virSocketAddrIsNumeric(migrateHost, NULL) -virSocketAddrParse(NULL, migrateHost, AF_UNSPEC) 0) -goto cleanup; +int family; +bool migrateHostisIpv6Address = false; + +if (virSocketAddrIsNumeric(migrateHost, family) +(family == AF_INET6)) +migrateHostisIpv6Address = true; - if (VIR_STRDUP(hostname, migrateHost) 0) +if ((migrateHostisIpv6Address + virAsprintf(hostname, [%s], migrateHost) 0) || +(!migrateHostisIpv6Address + virAsprintf(hostname, %s, migrateHost) 0)) goto cleanup; } else { if ((hostname = virGetHostname()) == NULL) -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 1/4] virsocketaddr: return address family in virSocketAddrIsNumeric
nowadays, virSocketAddrIsNumeric only validated the income address if numeric, but sometimes we need to know whether the address is an IPv4 or an IPv6 address. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_migration.c | 4 ++-- src/util/virsocketaddr.c | 13 + src/util/virsocketaddr.h | 2 +- tests/sockettest.c| 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index ce1a5cd..155f5b9 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2565,7 +2565,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, virObjectUnref(qemuCaps); if (listenAddress) { -if (virSocketAddrIsNumeric(listenAddress)) { +if (virSocketAddrIsNumeric(listenAddress, NULL)) { /* listenAddress is numeric IPv4 or IPv6 */ if (virSocketAddrParse(listenAddressSocket, listenAddress, AF_UNSPEC) 0) goto cleanup; @@ -2850,7 +2850,7 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, goto cleanup; if (migrateHost != NULL) { -if (virSocketAddrIsNumeric(migrateHost) +if (virSocketAddrIsNumeric(migrateHost, NULL) virSocketAddrParse(NULL, migrateHost, AF_UNSPEC) 0) goto cleanup; diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 7cc4bde..64409a6 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -858,6 +858,7 @@ virSocketAddrGetIpPrefix(const virSocketAddr *address, /** * virSocketAddrIsNumeric: * @address: address to check + * @family: where to store the address family, optional. * * Check if passed address is an IP address in numeric format. For * instance, for 0.0.0.0 true is returned, for 'examplehost @@ -867,15 +868,19 @@ virSocketAddrGetIpPrefix(const virSocketAddr *address, * false otherwise */ bool -virSocketAddrIsNumeric(const char *address) +virSocketAddrIsNumeric(const char *address, int *family) { struct addrinfo *res; -unsigned short family; +unsigned short sa_family; if (virSocketAddrParseInternal(res, address, AF_UNSPEC, false) 0) return false; -family = res-ai_addr-sa_family; +sa_family = res-ai_addr-sa_family; freeaddrinfo(res); -return family == AF_INET || family == AF_INET6; + +if (family != NULL) { +*family = sa_family; +} +return sa_family == AF_INET || sa_family == AF_INET6; } diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h index 27defa0..7b11afb 100644 --- a/src/util/virsocketaddr.h +++ b/src/util/virsocketaddr.h @@ -125,5 +125,5 @@ bool virSocketAddrIsPrivate(const virSocketAddr *addr); bool virSocketAddrIsWildcard(const virSocketAddr *addr); -bool virSocketAddrIsNumeric(const char *address); +bool virSocketAddrIsNumeric(const char *address, int *family); #endif /* __VIR_SOCKETADDR_H__ */ diff --git a/tests/sockettest.c b/tests/sockettest.c index 68b0536..dde0bb8 100644 --- a/tests/sockettest.c +++ b/tests/sockettest.c @@ -229,7 +229,7 @@ testIsNumericHelper(const void *opaque) { const struct testIsNumericData *data = opaque; -if (virSocketAddrIsNumeric(data-addr)) +if (virSocketAddrIsNumeric(data-addr, NULL)) return data-pass ? 0 : -1; return data-pass ? -1 : 0; } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 4/4] conf: Check migration_address whether is localhost
When enabling the migration_address option, by default it is set to 127.0.0.1, but it's not a valid address for migration. so we should add verification and set the default migration_address to 0.0.0.0. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu.conf | 2 +- src/qemu/qemu_conf.c | 7 +++ src/qemu/test_libvirtd_qemu.aug.in | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index 79bba36..666c303 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -459,7 +459,7 @@ # Override the listen address for all incoming migrations. Defaults to # 0.0.0.0, or :: if both host and qemu are capable of IPv6. -#migration_address = 127.0.0.1 +#migration_address = 0.0.0.0 # The default hostname or IP address which will be used by a migration diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 30169cf..65f98d7 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -716,6 +716,13 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, } GET_VALUE_STR(migration_address, cfg-migrationAddress); +if (cfg-migrationAddress +virSocketAddrIsLocalhost(cfg-migrationAddress)) { +virReportError(VIR_ERR_CONF_SYNTAX, + _(migration_address must not be 'localhost' address: %s), + cfg-migrationAddress); +goto cleanup; +} GET_VALUE_BOOL(log_timestamp, cfg-logTimestamp); diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in index d2bc2c0..30fd27e 100644 --- a/src/qemu/test_libvirtd_qemu.aug.in +++ b/src/qemu/test_libvirtd_qemu.aug.in @@ -69,7 +69,7 @@ module Test_libvirtd_qemu = { keepalive_interval = 5 } { keepalive_count = 5 } { seccomp_sandbox = 1 } -{ migration_address = 127.0.0.1 } +{ migration_address = 0.0.0.0 } { migration_host = host.example.com } { migration_port_min = 49152 } { migration_port_max = 49215 } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 0/4] Check migration configuration
add some check in migration configuration. Chen Fan (4): virsocketaddr: return address family in virSocketAddrIsNumeric migration: add migration_host support for Ipv6 address without brackets conf: add virSocketAddrIsLocalhost to Check migration_host conf: Check migration_address whether is localhost src/libvirt_private.syms | 1 + src/qemu/qemu.conf | 2 +- src/qemu/qemu_conf.c | 15 src/qemu/qemu_migration.c | 24 ++- src/qemu/test_libvirtd_qemu.aug.in | 2 +- src/util/virsocketaddr.c | 48 ++ src/util/virsocketaddr.h | 5 +++- tests/sockettest.c | 2 +- 8 files changed, 80 insertions(+), 19 deletions(-) -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 3/4] conf: add virSocketAddrIsLocalhost to Check migration_host
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/libvirt_private.syms | 1 + src/qemu/qemu_conf.c | 8 src/util/virsocketaddr.c | 35 +++ src/util/virsocketaddr.h | 3 +++ 4 files changed, 47 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 51a692b..f7172b0 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1885,6 +1885,7 @@ virSocketAddrGetPort; virSocketAddrGetRange; virSocketAddrIsNetmask; virSocketAddrIsNumeric; +virSocketAddrIsLocalhost; virSocketAddrIsPrivate; virSocketAddrIsWildcard; virSocketAddrMask; diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index adc6caf..30169cf 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -707,6 +707,14 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_LONG(seccomp_sandbox, cfg-seccompSandbox); GET_VALUE_STR(migration_host, cfg-migrateHost); +if (cfg-migrateHost +virSocketAddrIsLocalhost(cfg-migrateHost)) { +virReportError(VIR_ERR_CONF_SYNTAX, + _(migration_host must not be 'localhost' address: %s), + cfg-migrateHost); +goto cleanup; +} + GET_VALUE_STR(migration_address, cfg-migrationAddress); GET_VALUE_BOOL(log_timestamp, cfg-logTimestamp); diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 64409a6..dfcaf72 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -884,3 +884,38 @@ virSocketAddrIsNumeric(const char *address, int *family) } return sa_family == AF_INET || sa_family == AF_INET6; } + +/** + * virSocketAddrIsLocalhost: + * @address: address to check + * + * Check if passed address is a 'localhost' address. + * + * Returns: true if @address is 'localhost' address, + * false otherwise + */ +bool +virSocketAddrIsLocalhost(const char *address) +{ + int family; + + if (virSocketAddrIsNumeric(address, family)) { + if (family == AF_INET) { + if (STREQ(address, 127.0.0.1)) + return true; + } + + if (family == AF_INET6) { + if (STREQ(address, ::1)) + return true; + } + } else { + if (STRPREFIX(address, localhost)) + return true; + + if (STREQ(address, [::1])) + return true; + } + + return false; +} diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h index 7b11afb..5269f35 100644 --- a/src/util/virsocketaddr.h +++ b/src/util/virsocketaddr.h @@ -126,4 +126,7 @@ bool virSocketAddrIsPrivate(const virSocketAddr *addr); bool virSocketAddrIsWildcard(const virSocketAddr *addr); bool virSocketAddrIsNumeric(const char *address, int *family); + +bool virSocketAddrIsLocalhost(const char *address); + #endif /* __VIR_SOCKETADDR_H__ */ -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v1 0/3] Check migration configuration
Hi jiri, Please help to review this patches. Thanks, Chen On Fri, 2014-09-12 at 12:32 +0800, Chen Fan wrote: This version differs from the patch set conf: Check migration_host is valid or not during libvirt restarts I posted 2 weeks ago, I droped checking the migration_host on target host. and find an issue when setting migration_host. Chen Fan (3): migration: add migration_host support for Ipv6 address without brackets conf: Check migration_host is localhost or not during restart conf: Check migration_address is valid or not during restart src/qemu/qemu.conf | 2 +- src/qemu/qemu_conf.c | 21 + src/qemu/qemu_migration.c | 19 +++ src/qemu/test_libvirtd_qemu.aug.in | 2 +- 4 files changed, 38 insertions(+), 6 deletions(-) -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v1 1/3] migration: add migration_host support for Ipv6 address without brackets
when specifying migration_host to an Ipv6 address without brackets, it was resolved to an incorrect address, such as: tcp:2001:0DB8::1428:, but the correct address should be: tcp:[2001:0DB8::1428]: so we should add brackets when parsing it. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_migration.c | 19 +++ 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index e4b664b..c7eb305 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2850,11 +2850,22 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, goto cleanup; if (migrateHost != NULL) { -if (virSocketAddrIsNumeric(migrateHost) -virSocketAddrParse(NULL, migrateHost, AF_UNSPEC) 0) -goto cleanup; +virSocketAddr migrateHostSocket; +bool migrateHostisIpv6Address = false; + +if (virSocketAddrIsNumeric(migrateHost)) { +if (virSocketAddrParse(migrateHostSocket, migrateHost, AF_UNSPEC) 0) +goto cleanup; + +if (VIR_SOCKET_ADDR_IS_FAMILY(migrateHostSocket, AF_INET6)) { +migrateHostisIpv6Address = true; +} +} - if (VIR_STRDUP(hostname, migrateHost) 0) +if ((migrateHostisIpv6Address + virAsprintf(hostname, [%s], migrateHost) 0) || +(!migrateHostisIpv6Address + virAsprintf(hostname, %s, migrateHost) 0)) goto cleanup; } else { if ((hostname = virGetHostname()) == NULL) -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v1 0/3] Check migration configuration
This version differs from the patch set conf: Check migration_host is valid or not during libvirt restarts I posted 2 weeks ago, I droped checking the migration_host on target host. and find an issue when setting migration_host. Chen Fan (3): migration: add migration_host support for Ipv6 address without brackets conf: Check migration_host is localhost or not during restart conf: Check migration_address is valid or not during restart src/qemu/qemu.conf | 2 +- src/qemu/qemu_conf.c | 21 + src/qemu/qemu_migration.c | 19 +++ src/qemu/test_libvirtd_qemu.aug.in | 2 +- 4 files changed, 38 insertions(+), 6 deletions(-) -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v1 2/3] conf: Check migration_host is localhost or not during restart
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_conf.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index ac10b64..013f3de 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -707,6 +707,17 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_LONG(seccomp_sandbox, cfg-seccompSandbox); GET_VALUE_STR(migration_host, cfg-migrateHost); +if (cfg-migrateHost) { +if (STRPREFIX(cfg-migrateHost, localhost) || +STREQ(cfg-migrateHost, 127.0.0.1) || +STREQ(cfg-migrateHost, ::1) || +STREQ(cfg-migrateHost, [::1])) { +virReportError(VIR_ERR_CONF_SYNTAX, %s, + _(migration_host must be a valid address or hostname)); +goto cleanup; +} +} + GET_VALUE_STR(migration_address, cfg-migrationAddress); GET_VALUE_BOOL(log_timestamp, cfg-logTimestamp); -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v1 3/3] conf: Check migration_address is valid or not during restart
When enabling the migration_address option, by default it is set to 127.0.0.1, but it's not a valid address for migration. so we should add verification and set the default migration_address to 0.0.0.0. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu.conf | 2 +- src/qemu/qemu_conf.c | 10 ++ src/qemu/test_libvirtd_qemu.aug.in | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index 79bba36..666c303 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -459,7 +459,7 @@ # Override the listen address for all incoming migrations. Defaults to # 0.0.0.0, or :: if both host and qemu are capable of IPv6. -#migration_address = 127.0.0.1 +#migration_address = 0.0.0.0 # The default hostname or IP address which will be used by a migration diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 013f3de..2cbf2a6 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -719,6 +719,16 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, } GET_VALUE_STR(migration_address, cfg-migrationAddress); +if (cfg-migrationAddress) { +if (STRPREFIX(cfg-migrationAddress, localhost) || +STREQ(cfg-migrationAddress, 127.0.0.1) || +STREQ(cfg-migrationAddress, ::1) || +STREQ(cfg-migrationAddress, [::1])) { +virReportError(VIR_ERR_CONF_SYNTAX, %s, + _(migration_address must be a valid address or hostname)); +goto cleanup; +} +} GET_VALUE_BOOL(log_timestamp, cfg-logTimestamp); diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in index d2bc2c0..30fd27e 100644 --- a/src/qemu/test_libvirtd_qemu.aug.in +++ b/src/qemu/test_libvirtd_qemu.aug.in @@ -69,7 +69,7 @@ module Test_libvirtd_qemu = { keepalive_interval = 5 } { keepalive_count = 5 } { seccomp_sandbox = 1 } -{ migration_address = 127.0.0.1 } +{ migration_address = 0.0.0.0 } { migration_host = host.example.com } { migration_port_min = 49152 } { migration_port_max = 49215 } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] conf: Check migration_host is valid or not during libvirt restarts
if user specified an invalid strings as migration hostname, like setting: migration_host = XXX, libvirt should check it and return error during lbivirt restart. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/qemu/qemu_conf.c | 40 1 file changed, 40 insertions(+) diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index e2ec54f..450ac5b 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -33,6 +33,7 @@ #include fcntl.h #include sys/wait.h #include arpa/inet.h +#include netdb.h #include virerror.h #include qemu_conf.h @@ -650,6 +651,45 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_LONG(seccomp_sandbox, cfg-seccompSandbox); GET_VALUE_STR(migration_host, cfg-migrateHost); +if (cfg-migrateHost) { +struct addrinfo hints; +struct addrinfo *res; + +memset(hints, 0, sizeof(hints)); +hints.ai_flags = AI_ADDRCONFIG; +hints.ai_family = AF_UNSPEC; + +if (getaddrinfo(cfg-migrateHost, NULL, hints, res) != 0) { +virReportError(VIR_ERR_CONF_SYNTAX, + _(migration_host: '%s' is not a valid hostname), + cfg-migrateHost); +goto cleanup; +} + +if (res == NULL) { +virReportError(VIR_ERR_CONF_SYNTAX, + _(No IP address for host '%s' found), + cfg-migrateHost); +goto cleanup; +} + +freeaddrinfo(res); + +if (STRPREFIX(cfg-migrateHost, localhost)) { +virReportError(VIR_ERR_CONF_SYNTAX, %s, + _(setting migration_host to 'localhost' is not allowed)); +goto cleanup; +} + +if (STREQ(cfg-migrateHost, 127.0.0.1) || +STREQ(cfg-migrateHost, ::1)) { +virReportError(VIR_ERR_CONF_SYNTAX, %s, + _(setting migration_host to '127.0.0.1' or '::1' + is not allowed)); +goto cleanup; +} +} + GET_VALUE_STR(migration_address, cfg-migrationAddress); GET_VALUE_BOOL(log_timestamp, cfg-logTimestamp); -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] storage: remove unused 'canonPath' in virStorageFileGetMetadata
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/storage/storage_driver.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 3604613..5ddc23a 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -2892,7 +2892,6 @@ virStorageFileGetMetadata(virStorageSourcePtr src, src-path, src-format, (int)uid, (int)gid, allow_probe); virHashTablePtr cycle = NULL; -char *canonPath = NULL; int ret = -1; if (!(cycle = virHashCreate(5, NULL))) @@ -2904,7 +2903,6 @@ virStorageFileGetMetadata(virStorageSourcePtr src, ret = virStorageFileGetMetadataRecurse(src, uid, gid, allow_probe, cycle); -VIR_FREE(canonPath); virHashFree(cycle); return ret; } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 0/3] add binding guest numa nodes to host numa nodes support
Since qemu has supported numa option -memdev config: -object memory-backend-ram,size=1024M,policy=membind,host-nodes=0,id=ram-node0 \ -numa node,nodeid=0,cpus=0,memdev=ram-node0 \ for binding guest numa nodes to host numa nodes. So we introduce this capability in libvirt by configuration domain XML like: ... cpu numa cell cpus='0-1' memdev='ram0'/ /numa /cpu ... devices memdev type='ram' merge='yes' dump='yes' prealloc='yes' nameram0/name capacity unit='MiB'1000/capacity source host-nodes='0-1' policy='bind' / /memdev /devices Chen Fan (3): numa: add '-numa memdev=' support conf: add memdev device in devices XML tests: add numa -memdev testing and docs support docs/formatdomain.html.in | 71 ++- docs/schemas/domaincommon.rng | 76 +++- src/conf/cpu_conf.c| 73 ++-- src/conf/cpu_conf.h| 13 +- src/conf/domain_conf.c | 203 - src/conf/domain_conf.h | 42 + src/libvirt_private.syms | 4 + src/qemu/qemu_capabilities.c | 4 + src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_command.c| 84 - src/qemu/qemu_command.h| 4 + src/qemu/qemu_hotplug.c| 1 + tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.args | 9 + tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.xml | 35 tests/qemuxml2argvdata/qemuxml2argv-cpu-numa4.args | 10 + tests/qemuxml2argvdata/qemuxml2argv-cpu-numa4.xml | 35 tests/qemuxml2argvtest.c | 2 + 17 files changed, 644 insertions(+), 24 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-numa4.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-numa4.xml -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 1/3] numa: add '-numa memdev=' support
Since qemu has supported '-numa memdev=ram0' command option, so libvirt should add numa element to support specified memdev attrubute in XML. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/cpu_conf.c | 73 +++-- src/conf/cpu_conf.h | 13 - src/qemu/qemu_command.c | 10 +-- 3 files changed, 78 insertions(+), 18 deletions(-) diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index ebdaa19..2d0980e 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -29,6 +29,7 @@ #include cpu_conf.h #include domain_conf.h #include virstring.h +#include c-ctype.h #define VIR_FROM_THIS VIR_FROM_CPU @@ -84,6 +85,8 @@ virCPUDefFree(virCPUDefPtr def) for (i = 0; i def-ncells; i++) { virBitmapFree(def-cells[i].cpumask); VIR_FREE(def-cells[i].cpustr); +if (def-cells[i].memtype == VIR_CPU_CELL_MEMORY_DEV) +VIR_FREE(def-cells[i].data.memstr); } VIR_FREE(def-cells); VIR_FREE(def-vendor_id); @@ -153,7 +156,13 @@ virCPUDefCopy(const virCPUDef *cpu) for (i = 0; i cpu-ncells; i++) { copy-cells[i].cellid = cpu-cells[i].cellid; -copy-cells[i].mem = cpu-cells[i].mem; +copy-cells[i].memtype = cpu-cells[i].memtype; +if (cpu-cells[i].memtype == VIR_CPU_CELL_MEMORY_DEV) { +if (VIR_STRDUP(copy-cells[i].data.memstr, cpu-cells[i].data.memstr) 0) +goto error; +} else { +copy-cells[i].data.mem = cpu-cells[i].data.mem; +} copy-cells[i].cpumask = virBitmapNewCopy(cpu-cells[i].cpumask); @@ -436,7 +445,7 @@ virCPUDefParseXML(xmlNodePtr node, def-ncells = n; for (i = 0; i n; i++) { -char *cpus, *memory; +char *cpus, *memory, *memdev; int ret, ncpus = 0; def-cells[i].cellid = i; @@ -455,20 +464,52 @@ virCPUDefParseXML(xmlNodePtr node, def-cells_cpus += ncpus; memory = virXMLPropString(nodes[i], memory); -if (!memory) { -virReportError(VIR_ERR_XML_ERROR, %s, - _(Missing 'memory' attribute in NUMA cell)); -goto error; -} - -ret = virStrToLong_ui(memory, NULL, 10, def-cells[i].mem); -if (ret == -1) { +memdev = virXMLPropString(nodes[i], memdev); +if (memory || memdev) { +if (memory memdev) { +virReportError(VIR_ERR_XML_ERROR, %s, + _(Both 'memory' and 'memdev' attribute in NUMA cell is not allowed)); +goto error; +} + +if (memory) { +ret = virStrToLong_ui(memory, NULL, 10, def-cells[i].data.mem); +if (ret == -1) { +virReportError(VIR_ERR_XML_ERROR, %s, + _(Invalid 'memory' attribute in NUMA cell)); +VIR_FREE(memory); +goto error; +} +def-cells[i].memtype = VIR_CPU_CELL_MEMORY_SIZE; +VIR_FREE(memory); +} else { +if (strlen(memdev) 1) { +virReportError(VIR_ERR_XML_ERROR, %s, + _(Empty 'memdev' attribute in NUMA cell)); +VIR_FREE(memdev); +goto error; +} + +if (!c_isalpha(memdev[0])) { +virReportError(VIR_ERR_XML_ERROR, %s, + _(Invalid 'memdev' attribute name in NUMA cell, + it must begin with a letter)); +VIR_FREE(memdev); +goto error; +} + +if (VIR_STRDUP(def-cells[i].data.memstr, memdev) 0) { +VIR_FREE(memdev); +goto error; +} +def-cells[i].memtype = VIR_CPU_CELL_MEMORY_DEV; +VIR_FREE(memdev); +} +} else { virReportError(VIR_ERR_XML_ERROR, %s, - _(Invalid 'memory' attribute in NUMA cell)); -VIR_FREE(memory); + _(Missing 'memory' or 'memdev' attribute in NUMA cell)); goto error; } -VIR_FREE(memory); } } @@ -648,7 +689,11 @@ virCPUDefFormatBuf(virBufferPtr buf, for (i = 0; i def-ncells; i++) { virBufferAddLit(buf, cell); virBufferAsprintf(buf, cpus='%s', def-cells[i].cpustr); -virBufferAsprintf(buf, memory='%d', def-cells[i].mem); +if (def-cells[i].memtype
[libvirt] [PATCH 3/3] tests: add numa -memdev testing and docs support
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- docs/formatdomain.html.in | 71 +++- docs/schemas/domaincommon.rng | 76 +- tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.args | 9 +++ tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.xml | 35 ++ tests/qemuxml2argvdata/qemuxml2argv-cpu-numa4.args | 10 +++ tests/qemuxml2argvdata/qemuxml2argv-cpu-numa4.xml | 35 ++ tests/qemuxml2argvtest.c | 2 + 7 files changed, 233 insertions(+), 5 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-numa4.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-numa4.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 1b6ced8..5313c76 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1032,6 +1032,9 @@ lt;numagt; lt;cell cpus='0-3' memory='512000'/gt; lt;cell cpus='4-7' memory='512000'/gt; + lt;!-- OR --gt; + lt;cell cpus='0-3' memdev='ram0'/gt; + lt;cell cpus='4-7' memdev='ram1'/gt; lt;/numagt; ... lt;/cpugt; @@ -1041,8 +1044,11 @@ Each codecell/code element specifies a NUMA cell or a NUMA node. codecpus/code specifies the CPU or range of CPUs that are part of the node. codememory/code specifies the node memory in kibibytes - (i.e. blocks of 1024 bytes). Each cell or node is assigned cellid - or nodeid in the increasing order starting from 0. + (i.e. blocks of 1024 bytes). span class=sinceSince 2.1/span, + codememdev/code specifies the Host NUMA node that the Guest NUMA + node bind to. if codememdev/code specified for one node, it must + be specified for all nodes. Each cell or node is assigned cellid or + nodeid in the increasing order starting from 0. /p p @@ -5249,6 +5255,67 @@ qemu-kvm -net nic,model=? /dev/null /dd /dl +h4a name=elementsMemdevmemory device/a/h4 +p + A memory device can be added to guest via memdev element. + span class=sinceSince 2.1, QEMU and KVM only/span +/p +p + Example: usage of memory device configuration +/p +pre + ... + lt;devicesgt; +lt;memdev type='ram' merge='yes' dump='yes' prealloc='yes'gt; + lt;namegt;ram0lt;/namegt; + lt;capacity unit='KiB'gt;102400lt;/capacitygt; + lt;source host-nodes='0-1' policy='bind'/gt; +lt;/memdevgt; + lt;/devicesgt; + ... +/pre + dl +dtcodetype/code/dt +dd + p +The required type attribute specifies what type of memory device +is provided. Valid type are: + /p +ul + li'ram' mdash; memory ram backend./li + li'file' mdash; memory file backend./li +/ul +/dd +dtcodemerge/code/dt +dd + p +The optional merge attribute enables memory merge support. + /p +/dd +dtcodedump/code/dt +dd + p +The optional dump attribute enables to dump memory device's memory in a +core dump file. + /p +/dd +dtcodeprealloc/code/dt +dd + p +The optional prealloc attribute enables memory preallocation. + /p +/dd + dtcodesource/code/dt + ddThe source element describes the device as seen from the host. + the optional codemem-path/code element is required when specified type = 'file'. + the optional codehost-nodes/code element specified the Host nodes ids that the + Guest memory device binds to. the optional codepolicy/code element specified the + memory policy of memory device. the codepolicy/code is either default, preferred, + bind, interleave. defaults to default. + /dd + /dl + + h3a name=seclabelSecurity label/a/h3 p diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 6cc922c..0334b28 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3148,6 +3148,32 @@ /optional /element /define + define name=memdev +element name=memdev + attribute name=type +choice + valueram/value + valuefile/value +/choice + /attribute + optional +attribute name='merge' + valueyes/value +/attribute + /optional + optional +attribute name='dump' + valueyes/value +/attribute + /optional + optional +attribute name='prealloc' + valueyes/value +/attribute + /optional + ref name=memorybackend/ +/element + /define define name=parallel element name=parallel ref name=qemucdev/ @@ -3671,6 +3697,7 @@ ref name=redirfilter/ ref name=rng/ ref name=tpm/ +ref name=memdev
[libvirt] [PATCH 2/3] conf: add memdev device in devices XML
Since qemu has supported memory-backend-ram and memory-backend-file object, so we should add a new 'memdev' device type in devices XML to introduce the memory element, Its definition like the following: memdev type='ram' merge='yes' dump='yes' prealloc='yes' nameram0/name capacity unit='MiB'1000/capacity source host-nodes='0-1' policy='bind' / /memdev then we enable to support -numa memdev=ram0 command line for binding guest numa nodes to host numa nodes. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/domain_conf.c | 203 ++- src/conf/domain_conf.h | 42 + src/libvirt_private.syms | 4 + src/qemu/qemu_capabilities.c | 4 + src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_command.c | 74 src/qemu/qemu_command.h | 4 + src/qemu/qemu_hotplug.c | 1 + 8 files changed, 333 insertions(+), 1 deletion(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index be81dbe..c55bf47 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -204,7 +204,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST, chr, memballoon, nvram, - rng) + rng, + memdev) VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST, none, @@ -454,6 +455,16 @@ VIR_ENUM_IMPL(virDomainMemballoonModel, VIR_DOMAIN_MEMBALLOON_MODEL_LAST, xen, none) +VIR_ENUM_IMPL(virDomainMemDev, VIR_DOMAIN_MEMDEV_LAST, + ram, + file) + +VIR_ENUM_IMPL(virDomainHostNodePolicy, VIR_DOMAIN_HOST_NODE_POLICY_LAST, + default, + preferred, + bind, + interleave) + VIR_ENUM_IMPL(virDomainSmbiosMode, VIR_DOMAIN_SMBIOS_LAST, none, emulate, @@ -770,6 +781,10 @@ static void virDomainObjDispose(void *obj); static void virDomainObjListDispose(void *obj); static void virDomainXMLOptionClassDispose(void *obj); +static int +virDomainParseMemory(const char *xpath, xmlXPathContextPtr ctxt, + unsigned long long *mem, bool required); + static int virDomainObjOnceInit(void) { if (!(virDomainObjClass = virClassNew(virClassForObjectLockable(), @@ -1661,6 +1676,18 @@ void virDomainMemballoonDefFree(virDomainMemballoonDefPtr def) VIR_FREE(def); } +void virDomainMemDevDefFree(virDomainMemDevDefPtr def) +{ +if (!def) +return; + +VIR_FREE(def-name); +VIR_FREE(def-mempath); +VIR_FREE(def-hostnodes); +VIR_FREE(def); +} + + void virDomainNVRAMDefFree(virDomainNVRAMDefPtr def) { if (!def) @@ -1864,6 +1891,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def) case VIR_DOMAIN_DEVICE_NVRAM: virDomainNVRAMDefFree(def-data.nvram); break; +case VIR_DOMAIN_DEVICE_MEMDEV: +virDomainMemDevDefFree(def-data.memdev); +break; case VIR_DOMAIN_DEVICE_LAST: case VIR_DOMAIN_DEVICE_NONE: break; @@ -2543,6 +2573,7 @@ virDomainDeviceGetInfo(virDomainDeviceDefPtr device) /* The following devices do not contain virDomainDeviceInfo */ case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_GRAPHICS: +case VIR_DOMAIN_DEVICE_MEMDEV: case VIR_DOMAIN_DEVICE_LAST: case VIR_DOMAIN_DEVICE_NONE: break; @@ -2780,6 +2811,7 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def, case VIR_DOMAIN_DEVICE_NVRAM: case VIR_DOMAIN_DEVICE_LAST: case VIR_DOMAIN_DEVICE_RNG: +case VIR_DOMAIN_DEVICE_MEMDEV: break; } @@ -9192,6 +9224,104 @@ virDomainMemballoonDefParseXML(xmlNodePtr node, goto cleanup; } +static virDomainMemDevDefPtr +virDomainMemDevDefParseXML(xmlNodePtr node, + xmlXPathContextPtr ctxt) +{ +char *type; +virDomainMemDevDefPtr def; +xmlNodePtr save = ctxt-node; +char *tmp = NULL; +char *policy = NULL; + +if (VIR_ALLOC(def) 0) +return NULL; + +type = virXMLPropString(node, type); +if (type == NULL) { +virReportError(VIR_ERR_XML_ERROR, %s, + _(memory device must contain a type name)); +goto error; +} + +if ((def-type = virDomainMemDevTypeFromString(type)) 0) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _(unknown memory device type '%s'), type); +goto error; +} + +if ((tmp = virXMLPropString(node, merge)) != NULL) { +if (STREQ(tmp, yes)) +def-merge = true; +VIR_FREE(tmp); +} + +if ((tmp = virXMLPropString(node, dump)) != NULL) { +if (STREQ(tmp, yes)) +def-dump = true; +VIR_FREE(tmp); +} + +if ((tmp = virXMLPropString(node, prealloc)) != NULL) { +if (STREQ(tmp, yes)) +def-prealloc = true; +VIR_FREE(tmp); +} + +ctxt-node
[libvirt] [PATCH] domain conf: Fix whitespace around judgement operation when parsing 'managed' attribute.
Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/conf/domain_conf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 02c394f..b7aa4f5 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4261,7 +4261,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, * element that might be (pure hostdev, or higher level device * (e.g. interface) with type='hostdev') */ -if ((managed = virXMLPropString(node, managed))!= NULL) { +if ((managed = virXMLPropString(node, managed)) != NULL) { if (STREQ(managed, yes)) def-managed = true; } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [patch v2 1/1] manual: Add virsh manual about specified migration host
the 'migration_host' description maybe have a bit of difficulty to understand for user, so add this manual for them. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- tools/virsh.pod | 12 +++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/virsh.pod b/tools/virsh.pod index 02671b4..7b30292 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1208,7 +1208,8 @@ such as GFS2 or GPFS. If you are sure the migration is safe or you just do not care, use I--unsafe to force the migration. The Idesturi is the connection URI of the destination host, and -Imigrateuri is the migration URI, which usually can be omitted (see below). +Imigrateuri is the migration URI for specifying which IP address/URI of the +destination host to tansfer migration data, which usually can be omitted (see below). Idname is used for renaming the domain to new name during migration, which also usually can be omitted. Likewise, I--xml Bfile is usually omitted, but can be used to supply an alternative XML file for use on @@ -1238,6 +1239,15 @@ seen from the source machine. When Imigrateuri is not specified, libvirt will automatically determine the hypervisor specific URI, by looking up the target host's configured hostname. + +For QEMU/KVM hypervisor, when Imigrateuri is not specified, at first libvirt +will ask the destination side whether the optional migration_host is specified +or not, if the migration_host is specified, libvirt will use the specified +network for transferring migration data(the migrateion_host is useful when +hosts has multiple network interface). if the migrateion_host is not specified +too, libvirt will automatically determine the hypervisor specific URI, by looking +up the target host's configured hostname. + There are a few scenarios where specifying Imigrateuri may help: =over 4 -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] manual: Add virsh manual about specified migration host
the 'migration_host' description maybe have a bit of difficulty to understand for user, so add this manual for them. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- tools/virsh.pod | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/virsh.pod b/tools/virsh.pod index de9a4f7..8d77a2f 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1238,6 +1238,11 @@ seen from the source machine. When Imigrateuri is not specified, libvirt will automatically determine the hypervisor specific URI, by looking up the target host's configured hostname. +In particular, some hypervisors support having this migration hostname specified +separately by setting 'migration_host' in definition file, if 'migration_host' +is specified, the hostname or IP address will be used to as the default Imigrateuri +while running migration from source host. if 'migration_host' is not specified, +the migration hostname is set to the host's configured hostname by default. There are a few scenarios where specifying Imigrateuri may help: =over 4 @@ -1251,7 +1256,9 @@ explicitly specified, using an IP address, or a correct hostname. interfaces, it might be desirable for the migration data stream to be sent over a specific interface for either security or performance reasons. In this case Imigrateuri should be explicitly specified, using an IP address associated -with the network to be used. +with the network to be used. In particular, Some hypervisors could be easy to +specify the default network interface by setting 'migration_host'. then the +Imigrateuri can be omitted. =item * The firewall restricts what ports are available. When libvirt generates a migration URI, it will pick a port number using hypervisor specific rules. -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v5] migration: add support for migrateURI configuration
For now, we set the migration URI via command line '--migrate_uri' or construct the URI by looking up the dest host's hostname which could be solved by DNS automatically. But in cases the dest host have two or more NICs to reach, we may need to send the migration data over a specific NIC which is different from the automatically resloved one for some reason like performance, security, etc. thus we must explicitly specify the migrateuri in command line everytime, but it is too troublesome if there are many such hosts(and don't forget virt-manager). This patch adds a configuration file option on dest host to save the default value set which can be specified to a migration hostname or one of this host's addresses used for transferring data, thus user doesn't boring to specify it in command line everytime. Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- v4-v5: using migrate_host instead of migrate_uri configuration. src/qemu/qemu.conf| 7 ++- src/qemu/qemu_conf.c | 1 + src/qemu/qemu_conf.h | 1 + src/qemu/qemu_migration.c | 25 + 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index f0e802f..421efc4 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -449,7 +449,12 @@ # #seccomp_sandbox = 1 - +# Override the migration hostname for transfering the migration data. By +# default, the migrate hostname is set to the host's configured hostname. +# This can be used to override the default value set by a migration +# hostname or an IP address of the host machine. both IPv4 and IPv6 +# addresses are accepted. +#migrate_host = localhost # Override the listen address for all incoming migrations. Defaults to # 0.0.0.0, or :: if both host and qemu are capable of IPv6. diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 198ee2f..391fc57 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -574,6 +574,7 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_LONG(seccomp_sandbox, cfg-seccompSandbox); +GET_VALUE_STR(migrate_host, cfg-migrateHost); GET_VALUE_STR(migration_address, cfg-migrationAddress); ret = 0; diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index a36ea63..8e872b9 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -163,6 +163,7 @@ struct _virQEMUDriverConfig { int seccompSandbox; +char *migrateHost; /* The default for -incoming */ char *migrationAddress; int migrationPortMin; diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index a9f7fea..963d1ef 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2639,6 +2639,8 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, int ret = -1; virURIPtr uri = NULL; bool well_formed_uri = true; +virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); +const char *migrateHost = cfg-migrateHost; VIR_DEBUG(driver=%p, dconn=%p, cookiein=%s, cookieinlen=%d, cookieout=%p, cookieoutlen=%p, uri_in=%s, uri_out=%p, @@ -2652,8 +2654,9 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, /* The URI passed in may be NULL or a string tcp://somehostname:port. * * If the URI passed in is NULL then we allocate a port number - * from our pool of port numbers and return a URI of - * tcp://ourhostname:port. + * from our pool of port numbers, and if the migrateHost is configured, + * we return a URI of tcp://migrateHost:port, otherwise return a URI + * of tcp://ourhostname:port. * * If the URI passed in is not NULL then we try to parse out the * port number and use that (note that the hostname is assumed @@ -2663,8 +2666,21 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, if (virPortAllocatorAcquire(driver-migrationPorts, port) 0) goto cleanup; -if ((hostname = virGetHostname()) == NULL) -goto cleanup; +if (migrateHost != NULL) { +if (virSocketAddrIsNumeric(migrateHost)) { +/* migrateHost is numeric IPv4 or IPv6 */ +if (virSocketAddrParse(NULL, migrateHost, AF_UNSPEC) 0) +goto cleanup; +} else { +/* migrateHost is a hostname */ +} + + if (VIR_STRDUP(hostname, migrateHost) 0) +goto cleanup; +} else { +if ((hostname = virGetHostname()) == NULL) +goto cleanup; +} if (STRPREFIX(hostname, localhost)) { virReportError(VIR_ERR_INTERNAL_ERROR, %s, @@ -2746,6 +2762,7 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, cleanup: virURIFree(uri); VIR_FREE(hostname); +virObjectUnref(cfg); if (ret != 0) { VIR_FREE(*uri_out); if (autoPort) -- 1.8.1.4 -- libvir-list mailing list libvir-list@redhat.com https