[libvirt] [PATCHv5 0/6] Add virNodeGetCPUTimeParameters() API
by Minoru Usui
Hi,
This is v5 of virNodeGetCPUTimeParameters() API.
It returns cpu utilization or
cumulative cpu time of the node from /proc/stat since node boots up.
This patch only supports linux host.
Changes
v4->v5
- Rebase latest libvirt GIT tree.
v3->v4
- Rebase this patch like virDomainGetMemoryParameters() from v2 patches.
(drop v3 patches except virsh subcommand)
- Rename API name to virNodeGetCPUTimeParameters()
v2->v3
- Change user I/F. It is able to request what the user want by the @flags.
- Minor change of virsh nodecputime I/F.
v1->v2
- Change user I/F like virDomainGetMemoryStats()
- It can return either cpu utilization or cumulative cpu time of the node
depends on each driver.
Minoru Usui (6):
[v5] virNodeGetCPUTimeParameters: Expose new API
[v5] virNodeGetCPUTimeParameters: Define internal driver API
[v5] virNodeGetCPUTimeParameters: Implement public API
[v5] virNodeGetCPUTimeParameters: Implement remote protocol
[v5] virNodeGetCPUTimeParameters: Implement virsh support
[v5] virNodeGetCPUTimeParameters: Implement linux support
daemon/remote.c | 76 +++++++++++++++++++++++++
include/libvirt/libvirt.h.in | 65 +++++++++++++++++++++
src/driver.h | 8 +++
src/libvirt.c | 87 ++++++++++++++++++++++++++++
src/libvirt_private.syms | 1 +
src/libvirt_public.syms | 1 +
src/lxc/lxc_driver.c | 1 +
src/nodeinfo.c | 127 ++++++++++++++++++++++++++++++++++++++++++
src/nodeinfo.h | 5 +-
src/qemu/qemu_driver.c | 1 +
src/remote/remote_driver.c | 65 +++++++++++++++++++++
src/remote/remote_protocol.x | 21 +++++++-
src/uml/uml_driver.c | 1 +
tools/virsh.c | 107 +++++++++++++++++++++++++++++++++++
tools/virsh.pod | 4 +
15 files changed, 568 insertions(+), 2 deletions(-)
--
Minoru Usui <usui(a)mxm.nes.nec.co.jp>
13 years, 11 months
[libvirt] [PATCH] python: Fix typo in bindings
by Michal Privoznik
This typo caused a bug in which we wanted to free() invalid pointer.
---
python/libvirt-override.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index 11e1d0c..a151e78 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -2945,7 +2945,7 @@ libvirt_virEventRegisterImpl(ATTRIBUTE_UNUSED PyObject * self,
return VIR_PY_INT_FAIL;
/* Get argument string representations (for error reporting) */
- addHandleName = py_str(addTimeoutObj);
+ addHandleName = py_str(addHandleObj);
updateHandleName = py_str(updateHandleObj);
removeHandleName = py_str(removeHandleObj);
addTimeoutName = py_str(addTimeoutObj);
--
1.7.5.rc3
13 years, 11 months
[libvirt] [RFC PATCH] support multifunction PCI device
by Wen Congyang
We want to use more than 200+ device. Libvirt does not use multi
function PCI device and PCI-to-PCI bridge. So we can not use more
than 200+ device if it's a PCI device or it's controller is a PCI
device.
This patch adds the support of multi function PCI device. It
does not support to hot plug/unplug multi function PCI device.
TODO:
1. support to hot plug multi function PCI device
We only can hot plug one device at one time. I think we should
introduce another command 'virsh attach-devices XXX' to support
hot plug more than one device at one time?
2. support to hot unplug multi function PCI device
hot unpluging multi function PCI device meas that all the other
devices on the same slot will be hot unpluged. So we should do
some cleanup and remove the other devices too. If the other
device on the same slot does not support hot unpluged, or it is a
a controller and some other devices still use this controller,
I think we should refuse to hot unplug this mutlti function PCI
device.
>From 85a14928f2d445012f293638b44dd476a15aac3c Mon Sep 17 00:00:00 2001
From: Wen Congyang <wency(a)cn.fujitsu.com>
Date: Mon, 9 May 2011 14:59:16 +0800
Subject: [PATCH] multifunction PCI device
---
src/conf/domain_conf.c | 3 +
src/qemu/qemu_capabilities.c | 5 +
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 339 ++++++++++++++++++++++++++++++++++++------
src/qemu/qemu_command.h | 13 ++-
src/qemu/qemu_hotplug.c | 76 +++++++++-
src/qemu/qemu_process.c | 6 +-
tests/qemuhelptest.c | 3 +-
tests/qemuxml2argvtest.c | 2 +-
9 files changed, 390 insertions(+), 58 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d3efec6..83fdfe8 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1237,6 +1237,9 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr)
{
+ /* PCI bus has 32 slots and 8 functions per slot */
+ if (addr->slot >= 32 || addr->function >= 8)
+ return 0;
return addr->domain || addr->bus || addr->slot;
}
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 620143e..5d0145d 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -119,6 +119,8 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
"device-spicevmc",
"virtio-tx-alg",
"device-qxl-vga",
+
+ "pci-multifunction", /* 60 */
);
struct qemu_feature_flags {
@@ -1024,6 +1026,9 @@ qemuCapsComputeCmdFlags(const char *help,
*/
if (version >= 13000)
qemuCapsSet(flags, QEMU_CAPS_MONITOR_JSON);
+
+ if (version >= 13000)
+ qemuCapsSet(flags, QEMU_CAPS_PCI_MULTIFUNCTION);
}
/* We parse the output of 'qemu -help' to get the QEMU
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index ab47f22..4691e90 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -95,6 +95,7 @@ enum qemuCapsFlags {
QEMU_CAPS_DEVICE_SPICEVMC = 57, /* older -device spicevmc*/
QEMU_CAPS_VIRTIO_TX_ALG = 58, /* -device virtio-net-pci,tx=string */
QEMU_CAPS_DEVICE_QXL_VGA = 59, /* Is the primary and vga campatible qxl device named qxl-vga? */
+ QEMU_CAPS_PCI_MULTIFUNCTION = 60, /* -device multifunction=on|off */
QEMU_CAPS_LAST, /* this must always be the last item */
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 22b2634..9ac438c 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -667,9 +667,15 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virBitmapPtr qemuCaps)
#define QEMU_PCI_ADDRESS_LAST_SLOT 31
+#define QEMU_PCI_ADDRESS_LAST_FUNCTION 7
+#define QEMU_PCI_ADDRESS_LAST_DEVFN 0xFF
+#define QEMU_PCI_ADDRESS_DEVFN(slot, function) (((slot) << 3) + (function))
+#define QEMU_PCI_ADDRESS_SLOT(devfn) (((devfn) >> 3) & 0x1f)
+#define QEMU_PCI_ADDRESS_FUNCTION(devfn) ((devfn) & 3)
struct _qemuDomainPCIAddressSet {
virHashTablePtr used;
int nextslot;
+ int nextfunction;
};
@@ -684,10 +690,11 @@ static char *qemuPCIAddressAsString(virDomainDeviceInfoPtr dev)
return NULL;
}
- if (virAsprintf(&addr, "%d:%d:%d",
+ if (virAsprintf(&addr, "%d:%d:%d.%d",
dev->addr.pci.domain,
dev->addr.pci.bus,
- dev->addr.pci.slot) < 0) {
+ dev->addr.pci.slot,
+ dev->addr.pci.function) < 0) {
virReportOOMError();
return NULL;
}
@@ -717,6 +724,29 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
return 0;
}
+static void qemuGotoNextFunction(qemuDomainPCIAddressSetPtr addrs,
+ int current_slot, int current_function)
+{
+ int current_devfn, next_devfn;
+
+ current_devfn = QEMU_PCI_ADDRESS_DEVFN(current_slot, current_function);
+ next_devfn = QEMU_PCI_ADDRESS_DEVFN(addrs->nextslot, addrs->nextfunction);
+
+ if (current_devfn >= next_devfn) {
+ next_devfn = (current_devfn + 1) % (QEMU_PCI_ADDRESS_LAST_DEVFN + 1);
+ addrs->nextslot = QEMU_PCI_ADDRESS_SLOT(next_devfn);
+ addrs->nextfunction = QEMU_PCI_ADDRESS_FUNCTION(next_devfn);
+ }
+}
+
+static void qemuGotoNextSlot(qemuDomainPCIAddressSetPtr addrs,
+ int current_slot)
+{
+ if (current_slot >= addrs->nextslot) {
+ addrs->nextslot = (current_slot + 1) % (QEMU_PCI_ADDRESS_LAST_SLOT +1);
+ addrs->nextfunction = 0;
+ }
+}
int
qemuDomainAssignPCIAddresses(virDomainDefPtr def)
@@ -734,7 +764,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def)
if (!(addrs = qemuDomainPCIAddressSetCreate(def)))
goto cleanup;
- if (qemuAssignDevicePCISlots(def, addrs) < 0)
+ if (qemuAssignDevicePCISlots(def, addrs, qemuCaps) < 0)
goto cleanup;
}
@@ -777,6 +807,35 @@ error:
return NULL;
}
+/* check whether the slot is used by the other device
+ * Return 0 if the slot is not used by the other device, or -1 if the slot
+ * is used by the other device.
+ */
+static int qemuDomainPCIAddressCheckSlot(qemuDomainPCIAddressSetPtr addrs,
+ virDomainDeviceInfoPtr dev)
+{
+ char *addr;
+ virDomainDeviceInfo temp_dev;
+ int function;
+
+ temp_dev = *dev;
+ for (function = 0; function < QEMU_PCI_ADDRESS_LAST_FUNCTION; function++) {
+ temp_dev.addr.pci.function = function;
+ addr = qemuPCIAddressAsString(&temp_dev);
+ if (!addr)
+ return -1;
+
+ if (virHashLookup(addrs->used, addr)) {
+ VIR_FREE(addr);
+ return -1;
+ }
+
+ VIR_FREE(addr);
+ }
+
+ return 0;
+}
+
int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
virDomainDeviceInfoPtr dev)
{
@@ -800,36 +859,61 @@ int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
return -1;
}
- if (dev->addr.pci.slot > addrs->nextslot) {
- addrs->nextslot = dev->addr.pci.slot + 1;
- if (QEMU_PCI_ADDRESS_LAST_SLOT < addrs->nextslot)
- addrs->nextslot = 0;
- }
+ qemuGotoNextFunction(addrs, dev->addr.pci.slot, dev->addr.pci.function);
return 0;
}
-int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
- int slot)
+int qemuDomainPCIAddressReserveFunction(qemuDomainPCIAddressSetPtr addrs,
+ int slot, int function)
{
virDomainDeviceInfo dev;
dev.addr.pci.domain = 0;
dev.addr.pci.bus = 0;
dev.addr.pci.slot = slot;
+ dev.addr.pci.function = function;
return qemuDomainPCIAddressReserveAddr(addrs, &dev);
}
+int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
+ int slot)
+{
+ int function;
+
+ for (function = 0; function <= QEMU_PCI_ADDRESS_LAST_FUNCTION; function++) {
+ if (qemuDomainPCIAddressReserveFunction(addrs, slot, function) < 0)
+ goto cleanup;
+ }
+
+ return 0;
+
+cleanup:
+ for (function--; function >= 0; function--) {
+ qemuDomainPCIAddressReleaseFunction(addrs, slot, function);
+ }
+ return -1;
+}
int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
virDomainDeviceInfoPtr dev)
{
int ret = 0;
- if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
- ret = qemuDomainPCIAddressReserveAddr(addrs, dev);
- else
- ret = qemuDomainPCIAddressSetNextAddr(addrs, dev);
+ if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+ /* We do not support hotplug multi-function PCI device now, so we should
+ * reserve the whole slot. The function of the PCI device must be 0.
+ */
+ if (dev->addr.pci.function != 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Only PCI device addresses with function=0"
+ " are supported"));
+ return -1;
+ }
+
+ ret = qemuDomainPCIAddressReserveSlot(addrs, dev->addr.pci.slot);
+ } else
+ ret = qemuDomainPCIAddressSetNextSlot(addrs, dev);
return ret;
}
@@ -851,6 +935,48 @@ int qemuDomainPCIAddressReleaseAddr(qemuDomainPCIAddressSetPtr addrs,
return ret;
}
+int qemuDomainPCIAddressReleaseFunction(qemuDomainPCIAddressSetPtr addrs,
+ int slot, int function)
+{
+ virDomainDeviceInfo dev;
+
+ dev.addr.pci.domain = 0;
+ dev.addr.pci.bus = 0;
+ dev.addr.pci.slot = slot;
+ dev.addr.pci.function = function;
+
+ return qemuDomainPCIAddressReleaseAddr(addrs, &dev);
+}
+
+int qemuDomainPCIAddressReleaseSlot(qemuDomainPCIAddressSetPtr addrs, int slot)
+{
+ virDomainDeviceInfo dev;
+ char *addr;
+ int function;
+ int ret = 0;
+
+ dev.addr.pci.domain = 0;
+ dev.addr.pci.bus = 0;
+ dev.addr.pci.slot = slot;
+
+ for (function = 0; function <= QEMU_PCI_ADDRESS_LAST_FUNCTION; function++) {
+ addr = qemuPCIAddressAsString(&dev);
+ if (!addr)
+ return -1;
+
+ if (!virHashLookup(addrs->used, addr)) {
+ VIR_FREE(addr);
+ continue;
+ }
+
+ VIR_FREE(addr);
+
+ if (qemuDomainPCIAddressReleaseFunction(addrs, slot, function) < 0)
+ ret = -1;
+ }
+
+ return ret;
+}
void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs)
{
@@ -861,8 +987,7 @@ void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs)
VIR_FREE(addrs);
}
-
-int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
+int qemuDomainPCIAddressSetNextSlot(qemuDomainPCIAddressSetPtr addrs,
virDomainDeviceInfoPtr dev)
{
int i;
@@ -879,6 +1004,56 @@ int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
maybe.addr.pci.domain = 0;
maybe.addr.pci.bus = 0;
maybe.addr.pci.slot = i;
+ maybe.addr.pci.function = 0;
+
+ if (!(addr = qemuPCIAddressAsString(&maybe)))
+ return -1;
+
+ if (qemuDomainPCIAddressCheckSlot(addrs, &maybe) < 0) {
+ VIR_DEBUG("PCI addr %s already in use", addr);
+ VIR_FREE(addr);
+ continue;
+ }
+
+ VIR_DEBUG("Allocating PCI addr %s", addr);
+ VIR_FREE(addr);
+
+ if (qemuDomainPCIAddressReserveSlot(addrs, i) < 0)
+ return -1;
+
+ dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+ dev->addr.pci = maybe.addr.pci;
+
+ qemuGotoNextSlot(addrs, maybe.addr.pci.slot);
+
+ return 0;
+ }
+
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("No more available PCI addresses"));
+ return -1;
+}
+
+int qemuDomainPCIAddressSetNextFunction(qemuDomainPCIAddressSetPtr addrs,
+ virDomainDeviceInfoPtr dev)
+{
+ int i;
+ int iteration;
+ int next_devfn;
+
+ next_devfn = QEMU_PCI_ADDRESS_DEVFN(addrs->nextslot, addrs->nextfunction);
+ for (i = next_devfn, iteration = 0;
+ iteration <= QEMU_PCI_ADDRESS_LAST_DEVFN; i++, iteration++) {
+ virDomainDeviceInfo maybe;
+ char *addr;
+
+ if (QEMU_PCI_ADDRESS_LAST_DEVFN < i)
+ i = 0;
+ memset(&maybe, 0, sizeof(maybe));
+ maybe.addr.pci.domain = 0;
+ maybe.addr.pci.bus = 0;
+ maybe.addr.pci.slot = QEMU_PCI_ADDRESS_SLOT(i);
+ maybe.addr.pci.function = QEMU_PCI_ADDRESS_FUNCTION(i);
if (!(addr = qemuPCIAddressAsString(&maybe)))
return -1;
@@ -899,9 +1074,8 @@ int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
dev->addr.pci = maybe.addr.pci;
- addrs->nextslot = i + 1;
- if (QEMU_PCI_ADDRESS_LAST_SLOT < addrs->nextslot)
- addrs->nextslot = 0;
+ qemuGotoNextFunction(addrs, maybe.addr.pci.slot,
+ maybe.addr.pci.function);
return 0;
}
@@ -944,7 +1118,8 @@ int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
* skip over info.type == PCI
*/
int
-qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
+qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs,
+ virBitmapPtr qemuCaps)
{
int i;
bool reservedIDE = false;
@@ -1021,16 +1196,28 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
/* Only support VirtIO-9p-pci so far. If that changes,
* we might need to skip devices here */
- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->fss[i]->info) < 0)
- goto error;
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION)) {
+ if (qemuDomainPCIAddressSetNextFunction(addrs,
+ &def->fss[i]->info) < 0)
+ goto error;
+ } else {
+ if (qemuDomainPCIAddressSetNextSlot(addrs, &def->fss[i]->info) < 0)
+ goto error;
+ }
}
/* Network interfaces */
for (i = 0; i < def->nnets ; i++) {
if (def->nets[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
continue;
- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->nets[i]->info) < 0)
- goto error;
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION)) {
+ if (qemuDomainPCIAddressSetNextFunction(addrs,
+ &def->nets[i]->info) < 0)
+ goto error;
+ } else {
+ if (qemuDomainPCIAddressSetNextSlot(addrs, &def->nets[i]->info) < 0)
+ goto error;
+ }
}
/* Sound cards */
@@ -1042,8 +1229,15 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_PCSPK)
continue;
- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->sounds[i]->info) < 0)
- goto error;
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION)) {
+ if (qemuDomainPCIAddressSetNextFunction(addrs,
+ &def->sounds[i]->info) < 0)
+ goto error;
+ } else {
+ if (qemuDomainPCIAddressSetNextSlot(addrs,
+ &def->sounds[i]->info) < 0)
+ goto error;
+ }
}
/* Disk controllers (SCSI only for now) */
@@ -1061,8 +1255,15 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
continue;
- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->controllers[i]->info) < 0)
- goto error;
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION)) {
+ if (qemuDomainPCIAddressSetNextFunction(addrs,
+ &def->controllers[i]->info) < 0)
+ goto error;
+ } else {
+ if (qemuDomainPCIAddressSetNextSlot(addrs,
+ &def->controllers[i]->info) < 0)
+ goto error;
+ }
}
/* Disks (VirtIO only for now */
@@ -1074,8 +1275,15 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
if (def->disks[i]->bus != VIR_DOMAIN_DISK_BUS_VIRTIO)
continue;
- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->disks[i]->info) < 0)
- goto error;
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION)) {
+ if (qemuDomainPCIAddressSetNextFunction(addrs,
+ &def->disks[i]->info) < 0)
+ goto error;
+ } else {
+ if (qemuDomainPCIAddressSetNextSlot(addrs,
+ &def->disks[i]->info) < 0)
+ goto error;
+ }
}
/* Host PCI devices */
@@ -1086,32 +1294,60 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
continue;
- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->hostdevs[i]->info) < 0)
- goto error;
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION)) {
+ if (qemuDomainPCIAddressSetNextFunction(addrs,
+ &def->hostdevs[i]->info) < 0)
+ goto error;
+ } else {
+ if (qemuDomainPCIAddressSetNextSlot(addrs,
+ &def->hostdevs[i]->info) < 0)
+ goto error;
+ }
}
/* VirtIO balloon */
if (def->memballoon &&
def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO &&
def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->memballoon->info) < 0)
- goto error;
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION)) {
+ if (qemuDomainPCIAddressSetNextFunction(addrs,
+ &def->memballoon->info) < 0)
+ goto error;
+ } else {
+ if (qemuDomainPCIAddressSetNextSlot(addrs,
+ &def->memballoon->info) < 0)
+ goto error;
+ }
}
/* A watchdog - skip IB700, it is not a PCI device */
if (def->watchdog &&
def->watchdog->model != VIR_DOMAIN_WATCHDOG_MODEL_IB700 &&
def->watchdog->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->watchdog->info) < 0)
- goto error;
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION)) {
+ if (qemuDomainPCIAddressSetNextFunction(addrs,
+ &def->watchdog->info) < 0)
+ goto error;
+ } else {
+ if (qemuDomainPCIAddressSetNextSlot(addrs,
+ &def->watchdog->info) < 0)
+ goto error;
+ }
}
/* Further non-primary video cards */
for (i = 1; i < def->nvideos ; i++) {
if (def->videos[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
continue;
- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->videos[i]->info) < 0)
- goto error;
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION)) {
+ if (qemuDomainPCIAddressSetNextFunction(addrs,
+ &def->videos[i]->info) < 0)
+ goto error;
+ } else {
+ if (qemuDomainPCIAddressSetNextSlot(addrs,
+ &def->videos[i]->info) < 0)
+ goto error;
+ }
}
for (i = 0; i < def->ninputs ; i++) {
/* Nada - none are PCI based (yet) */
@@ -1149,10 +1385,20 @@ qemuBuildDeviceAddressStr(virBufferPtr buf,
_("Only PCI device addresses with bus=0 are supported"));
return -1;
}
- if (info->addr.pci.function != 0) {
- qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Only PCI device addresses with function=0 are supported"));
- return -1;
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION)) {
+ if (info->addr.pci.function > 7) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("The function of PCI device addresses must "
+ "less than 8"));
+ return -1;
+ }
+ } else {
+ if (info->addr.pci.function != 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Only PCI device addresses with function=0 "
+ "are supported"));
+ return -1;
+ }
}
/* XXX
@@ -1162,9 +1408,14 @@ qemuBuildDeviceAddressStr(virBufferPtr buf,
* to pciNN.0 where NN is the domain number
*/
if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIBUS))
- virBufferAsprintf(buf, ",bus=pci.0,addr=0x%x", info->addr.pci.slot);
+ virBufferAsprintf(buf, ",bus=pci.0");
+ else
+ virBufferAsprintf(buf, ",bus=pci");
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION))
+ virBufferAsprintf(buf, ",multifunction=on,addr=0x%x.0x%x",
+ info->addr.pci.slot, info->addr.pci.function);
else
- virBufferAsprintf(buf, ",bus=pci,addr=0x%x", info->addr.pci.slot);
+ virBufferAsprintf(buf, ",addr=0x%x", info->addr.pci.slot);
}
return 0;
}
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 528031d..1a4f471 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -146,19 +146,28 @@ virDomainDefPtr qemuParseCommandLineString(virCapsPtr caps,
int qemuDomainAssignPCIAddresses(virDomainDefPtr def);
qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def);
+int qemuDomainPCIAddressReserveFunction(qemuDomainPCIAddressSetPtr addrs,
+ int slot, int function);
int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
int slot);
int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
virDomainDeviceInfoPtr dev);
-int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
+int qemuDomainPCIAddressSetNextSlot(qemuDomainPCIAddressSetPtr addrs,
virDomainDeviceInfoPtr dev);
+int qemuDomainPCIAddressSetNextFunction(qemuDomainPCIAddressSetPtr addrs,
+ virDomainDeviceInfoPtr dev);
int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
virDomainDeviceInfoPtr dev);
int qemuDomainPCIAddressReleaseAddr(qemuDomainPCIAddressSetPtr addrs,
virDomainDeviceInfoPtr dev);
+int qemuDomainPCIAddressReleaseFunction(qemuDomainPCIAddressSetPtr addrs,
+ int slot, int function);
+int qemuDomainPCIAddressReleaseSlot(qemuDomainPCIAddressSetPtr addrs, int slot);
void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs);
-int qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs);
+int qemuAssignDevicePCISlots(virDomainDefPtr def,
+ qemuDomainPCIAddressSetPtr addrs,
+ virBitmapPtr qemuCaps);
int qemuDomainNetVLAN(virDomainNetDefPtr def);
int qemuAssignDeviceNetAlias(virDomainDefPtr def, virDomainNetDefPtr net, int idx);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index dae2269..4731959 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -221,7 +221,8 @@ error:
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
(disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
releaseaddr &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &disk->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ disk->info.addr.pci.slot) < 0)
VIR_WARN("Unable to release PCI address on %s", disk->src);
if (virSecurityManagerRestoreImageLabel(driver->securityManager,
@@ -290,7 +291,8 @@ cleanup:
qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
(controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
releaseaddr &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &controller->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ controller->info.addr.pci.slot) < 0)
VIR_WARN0("Unable to release PCI address on controller");
VIR_FREE(devstr);
@@ -697,7 +699,8 @@ cleanup:
qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
(net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
releaseaddr &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &net->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ net->info.addr.pci.slot) < 0)
VIR_WARN0("Unable to release PCI address on NIC");
if (ret != 0)
@@ -828,7 +831,8 @@ error:
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
(hostdev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
releaseaddr &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &hostdev->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ hostdev->info.addr.pci.slot) < 0)
VIR_WARN0("Unable to release PCI address on host device");
qemuDomainReAttachHostdevDevices(driver, &hostdev, 1);
@@ -1100,6 +1104,30 @@ static inline int qemuFindDisk(virDomainDefPtr def, const char *dst)
return -1;
}
+static int qemuComparePCIDevice(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ virDomainDeviceInfoPtr dev1,
+ void *opaque)
+{
+ virDomainDeviceInfoPtr dev2 = opaque;
+
+ if (dev1->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
+ dev2->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
+ return 0;
+
+ if (dev1->addr.pci.slot == dev2->addr.pci.slot &&
+ dev1->addr.pci.function != dev2->addr.pci.function)
+ return -1;
+ return 0;
+}
+
+static bool qemuIsMultiFunctionDevice(virDomainDefPtr def,
+ virDomainDeviceInfoPtr dev)
+{
+ if (virDomainDeviceInfoIterate(def, qemuComparePCIDevice, dev) < 0)
+ return true;
+ return false;
+}
+
int qemuDomainDetachPciDiskDevice(struct qemud_driver *driver,
virDomainObjPtr vm,
@@ -1121,6 +1149,13 @@ int qemuDomainDetachPciDiskDevice(struct qemud_driver *driver,
detach = vm->def->disks[i];
+ if (qemuIsMultiFunctionDevice(vm->def, &detach->info)) {
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ _("cannot hot unplug multifunction PCI device: %s"),
+ dev->data.disk->dst);
+ goto cleanup;
+ }
+
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
@@ -1167,7 +1202,8 @@ int qemuDomainDetachPciDiskDevice(struct qemud_driver *driver,
qemuAuditDisk(vm, detach, NULL, "detach", ret >= 0);
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ detach->info.addr.pci.slot) < 0)
VIR_WARN("Unable to release PCI address on %s", dev->data.disk->src);
virDomainDiskRemove(vm->def, i);
@@ -1351,6 +1387,13 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver,
goto cleanup;
}
+ if (qemuIsMultiFunctionDevice(vm->def, &detach->info)) {
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ _("cannot hot unplug multifunction PCI device: %s"),
+ dev->data.disk->dst);
+ goto cleanup;
+ }
+
if (qemuDomainControllerIsBusy(vm, detach)) {
qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
_("device cannot be detached: device is busy"));
@@ -1392,7 +1435,8 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver,
}
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ detach->info.addr.pci.slot) < 0)
VIR_WARN0("Unable to release PCI address on controller");
virDomainControllerDefFree(detach);
@@ -1438,6 +1482,13 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver,
goto cleanup;
}
+ if (qemuIsMultiFunctionDevice(vm->def, &detach->info)) {
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ _("cannot hot unplug multifunction PCI device :%s"),
+ dev->data.disk->dst);
+ goto cleanup;
+ }
+
if ((vlan = qemuDomainNetVLAN(detach)) < 0) {
qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("unable to determine original VLAN"));
@@ -1484,7 +1535,8 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver,
qemuAuditNet(vm, detach, NULL, "detach", true);
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ detach->info.addr.pci.slot) < 0)
VIR_WARN0("Unable to release PCI address on NIC");
virDomainConfNWFilterTeardown(detach);
@@ -1567,6 +1619,13 @@ int qemuDomainDetachHostPciDevice(struct qemud_driver *driver,
return -1;
}
+ if (qemuIsMultiFunctionDevice(vm->def, &detach->info)) {
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ _("cannot hot unplug multifunction PCI device: %s"),
+ dev->data.disk->dst);
+ return -1;
+ }
+
if (!virDomainDeviceAddressIsValid(&detach->info,
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
qemuReportError(VIR_ERR_OPERATION_FAILED,
@@ -1601,7 +1660,8 @@ int qemuDomainDetachHostPciDevice(struct qemud_driver *driver,
}
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
- qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0)
+ qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ detach->info.addr.pci.slot) < 0)
VIR_WARN0("Unable to release PCI address on host device");
if (vm->def->nhostdevs > 1) {
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index bd7c932..f3fe78c 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1921,7 +1921,8 @@ qemuProcessReconnect(void *payload, const void *name ATTRIBUTE_UNUSED, void *opa
priv->persistentAddrs = 1;
if (!(priv->pciaddrs = qemuDomainPCIAddressSetCreate(obj->def)) ||
- qemuAssignDevicePCISlots(obj->def, priv->pciaddrs) < 0)
+ qemuAssignDevicePCISlots(obj->def, priv->pciaddrs,
+ priv->qemuCaps) < 0)
goto error;
}
@@ -2187,7 +2188,8 @@ int qemuProcessStart(virConnectPtr conn,
/* Assign any remaining addresses */
- if (qemuAssignDevicePCISlots(vm->def, priv->pciaddrs) < 0)
+ if (qemuAssignDevicePCISlots(vm->def, priv->pciaddrs,
+ priv->qemuCaps) < 0)
goto cleanup;
priv->persistentAddrs = 1;
diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c
index 2522396..2a0a923 100644
--- a/tests/qemuhelptest.c
+++ b/tests/qemuhelptest.c
@@ -430,7 +430,8 @@ mymain(void)
QEMU_CAPS_VGA_NONE,
QEMU_CAPS_MIGRATE_QEMU_FD,
QEMU_CAPS_DRIVE_AIO,
- QEMU_CAPS_DEVICE_SPICEVMC);
+ QEMU_CAPS_DEVICE_SPICEVMC,
+ QEMU_CAPS_PCI_MULTIFUNCTION);
DO_TEST("qemu-kvm-0.12.1.2-rhel61", 12001, 1, 0,
QEMU_CAPS_VNC_COLON,
QEMU_CAPS_NO_REBOOT,
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index a7e4cc0..04b8326 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -96,7 +96,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
if (!(pciaddrs = qemuDomainPCIAddressSetCreate(vmdef)))
goto fail;
- if (qemuAssignDevicePCISlots(vmdef, pciaddrs) < 0)
+ if (qemuAssignDevicePCISlots(vmdef, pciaddrs, extraFlags) < 0)
goto fail;
qemuDomainPCIAddressSetFree(pciaddrs);
--
1.7.1
13 years, 11 months
[libvirt] [PATCH 0/3] Fix some building errors
by Wen Congyang
Wen Congyang (3):
build: generate files when building without libvirtd
build: probes.d and libvirtd.stp should be part of tarball
test: all test_scripts should be part of tarball when building
without libvirtd
daemon/Makefile.am | 110 ++++++++++++++++++++++++++--------------------------
tests/Makefile.am | 18 ++++++++
2 files changed, 73 insertions(+), 55 deletions(-)
13 years, 11 months
[libvirt] [PATCH] docs: Fix error syntax of vcpupin example XML
by Osier Yang
Lacks of "/", push this directly in trivial rule.
---
docs/formatdomain.html.in | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index facdaf2..59c3d51 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -289,10 +289,10 @@
</memtune>
<vcpu cpuset="1-4,^3,6" current="1">2</vcpu>
<cputune>
- <vcpupin vcpu="0" cpuset="1-4,^2">
- <vcpupin vcpu="1" cpuset="0,1">
- <vcpupin vcpu="2" cpuset="2,3">
- <vcpupin vcpu="3" cpuset="0,4">
+ <vcpupin vcpu="0" cpuset="1-4,^2"/>
+ <vcpupin vcpu="1" cpuset="0,1"/>
+ <vcpupin vcpu="2" cpuset="2,3"/>
+ <vcpupin vcpu="3" cpuset="0,4"/>
<cpushares>2048</cpushares>
</cputune>
...</pre>
--
1.7.1
13 years, 11 months
[libvirt] vhost-net configuration
by Cal Heldenbrand
Hi everyone,
I'm trying to test out the virtio driver's "tx=bh" option, or iothread in
libvirt. When I create a machine, I get the "unsupported" error message:
# virsh create web101.xml
error: Failed to create domain from web101.xml
error: unsupported configuration: vhost-net is not supported with this QEMU
binary
My interface XML looks like this:
<interface type='bridge'>
<mac address='52:54:00:6f:51:43'/>
<source bridge='vnet0'/>
<model type='virtio'/>
<driver name='vhost' txmode='iothread'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03'
function='0x0'/>
</interface>
I've compiled libvirt (0.9.1) and QEMU (0.14.1) from source, but am still
using my distro's kernel, 2.6.32-71.29.1.el6.x86_64. (Scientific Linux 6)
Thanks, and please let me know if you need any more info!
--Cal
13 years, 11 months
[libvirt] [RFC][PATCH 0/7] interface: Transaction API
by Michal Privoznik
This is a RFC implementation of what some may call network transaction API.
The new interface driver functions now do not contain anything valuable,
they are just stub. Later on, a real netcf calls will be added. This should
only give us an image of whole thing. So any comments are more than welcome.
The new API is accessible via new virsh command: iface-change with 3 options:
start, commit, rollback. The test driver actually works, moreover it works
as expected later within real deployment.
Michal Privoznik (7):
interface: add new public API
interface: define internal driver API
interface: implement the public APIs
interface: implement the remote protocol
interface: expose to virsh
interface: Implement the driver methods
interface: implement test driver
configure.ac | 5 ++
include/libvirt/libvirt.h.in | 7 ++
src/driver.h | 12 ++++
src/esx/esx_interface_driver.c | 3 +
src/interface/netcf_driver.c | 39 ++++++++++++
src/libvirt.c | 129 ++++++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 7 ++
src/phyp/phyp_driver.c | 5 +-
src/remote/remote_driver.c | 3 +
src/remote/remote_protocol.x | 18 +++++-
src/remote_protocol-structs | 9 +++
src/test/test_driver.c | 113 +++++++++++++++++++++++++++++++++++
tools/virsh.c | 59 ++++++++++++++++++
13 files changed, 407 insertions(+), 2 deletions(-)
--
1.7.5.rc3
13 years, 11 months
[libvirt] [PATCH] qemudDomainMemoryPeek: chown temporary file to qemu.qemu.
by Richard W.M. Jones
This attached patch resolves a fairly obvious problem which stops
qemuDomainMemoryPeek from working at all.
However, it's not the whole story. Read on ...
(1) qemu still fails unless I manually set the mode of
/var/cache/libvirt to 0755 (it is normally 0700).
Owner Fails Works
/var/cache/libvirt root.root 0700 0755
/var/cache/libvirt/qemu qemu.qemu 0750 0750
qemu is doing:
open("/var/cache/libvirt/qemu/qemu.mem.fdVCod", O_WRONLY|O_CREAT|O_TRUNC, 0666)
It's kinda annoying that /etc/libvirt and /var/{cache,lib}/libvirt are
unreadable by other users. Is there some deep reason to do this?
(2) After applying this patch, using virDomainMemoryPeek causes
libvirtd to generate the following serious-looking warning. It
doesn't appear to crash or fail in any way that I can tell:
15:17:09.982: 7784: error : virDomainFree:2122 : invalid domain pointer in virDomainFree
I don't know where this is coming from. It only appears when my
program actually does virDomainMemoryPeek, not when I have the same
code with virDomainMemoryPeek commented out.
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
virt-top is 'top' for virtual machines. Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://et.redhat.com/~rjones/virt-top
13 years, 11 months
[libvirt] phy driver
by Serge Hallyn
Hi,
something like <disk type='block'> <driver name='phy'/> <source dev='%s'/>
<target dev='sdb'/> </disk> used to be allowed. But now it appears (looking at
git history) only <driver name='qemu'> is supported. Is that correct? Should
tools which are spitting out libvirt xml be updated to use 'qemu', or is there
something else going on?
thanks,
-serge
13 years, 11 months