[libvirt] RFC regarding libvirtd deadlock
by Jim Fehlig
Doing something foolish like
# while true; do killall -HUP libvirtd; sleep 1; done
# virsh create vm.xml
can deadlock libvirtd. Threads of interest are
Thread 4 (Thread 0x7fc13b53e700 (LWP 64084)):
#0 0x00007fc13fba10bf in pthread_cond_wait@(a)GLIBC_2.3.2 () from
/lib64/libpthread.so.0
#1 0x00007fc14310213c in virCondWait (c=0x7fc110017fa8, m=0x7fc110017f80)
at util/virthread.c:154
#2 0x00007fc1280244e9 in qemuMonitorSend (mon=0x7fc110017f70, msg=0x7fc13b53d240)
at qemu/qemu_monitor.c:1083
#3 0x00007fc12803bf5a in qemuMonitorJSONCommandWithFd (mon=0x7fc110017f70,
cmd=0x7fc110017700, scm_fd=-1, reply=0x7fc13b53d318) at
qemu/qemu_monitor_json.c:305
#4 0x00007fc12803c09c in qemuMonitorJSONCommand (mon=0x7fc110017f70,
cmd=0x7fc110017700,
reply=0x7fc13b53d318) at qemu/qemu_monitor_json.c:335
---Type <return> to continue, or q <return> to quit---
#5 0x00007fc12803f116 in qemuMonitorJSONSetCapabilities (mon=0x7fc110017f70)
at qemu/qemu_monitor_json.c:1298
#6 0x00007fc128026e14 in qemuMonitorSetCapabilities (mon=0x7fc110017f70)
at qemu/qemu_monitor.c:1697
#7 0x00007fc127ffe250 in qemuProcessInitMonitor (driver=0x7fc12004e1e0,
vm=0x7fc110003d00, asyncJob=QEMU_ASYNC_JOB_START) at qemu/qemu_process.c:1763
#8 0x00007fc127ffe564 in qemuConnectMonitor (driver=0x7fc12004e1e0,
vm=0x7fc110003d00,
asyncJob=6, logCtxt=0x7fc1100089c0) at qemu/qemu_process.c:1835
#9 0x00007fc127fff386 in qemuProcessWaitForMonitor (driver=0x7fc12004e1e0,
vm=0x7fc110003d00, asyncJob=6, logCtxt=0x7fc1100089c0) at
qemu/qemu_process.c:2180
#10 0x00007fc128009269 in qemuProcessLaunch (conn=0x7fc1100009a0,
driver=0x7fc12004e1e0,
vm=0x7fc110003d00, asyncJob=QEMU_ASYNC_JOB_START, incoming=0x0, snapshot=0x0,
vmop=VIR_NETDEV_VPORT_PROFILE_OP_CREATE, flags=17) at qemu/qemu_process.c:6111
#11 0x00007fc128009e85 in qemuProcessStart (conn=0x7fc1100009a0,
driver=0x7fc12004e1e0,
vm=0x7fc110003d00, updatedCPU=0x0, asyncJob=QEMU_ASYNC_JOB_START,
migrateFrom=0x0,
migrateFd=-1, migratePath=0x0, snapshot=0x0,
vmop=VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
flags=17) at qemu/qemu_process.c:6334
#12 0x00007fc1280552f1 in qemuDomainCreateXML (conn=0x7fc1100009a0,
xml=0x7fc110000ed0 "<!--\nWARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES
TO IT ARE LIKELY TO BE\nOVERWRITTEN AND LOST. Changes to this xml configuration
should be made using:\n virsh edit sles12sp2-kvm\nor other applicati"...,
flags=0) at qemu/qemu_driver.c:1776
...
Thread 1 (Thread 0x7fc143c66880 (LWP 64081)):
#0 0x00007fc13fb9aac8 in __pthread_rwlock_wrlock_slow () from
/lib64/libpthread.so.0
#1 0x00007fc143101ffa in virRWLockWrite (m=0x7fc143678cc0 <updateLock>)
at util/virthread.c:122
#2 0x00007fc1431a394f in virNWFilterWriteLockFilterUpdates () at
conf/nwfilter_conf.c:159
#3 0x00007fc12a5230a0 in nwfilterStateReload () at nwfilter/nwfilter_driver.c:299
#4 0x00007fc1433170c2 in virStateReload () at libvirt.c:829
#5 0x0000558c522d5686 in daemonReloadHandler (dmn=0x558c5328b230,
sig=0x7ffe0a831e30,
opaque=0x0) at remote/remote_daemon.c:724
#6 0x00007fc14321e3c7 in virNetDaemonSignalEvent (watch=2, fd=9, events=1,
opaque=0x558c5328b230) at rpc/virnetdaemon.c:654
#7 0x00007fc143085cc7 in virEventPollDispatchHandles (nfds=11, fds=0x558c532cd930)
at util/vireventpoll.c:508
#8 0x00007fc143086586 in virEventPollRunOnce () at util/vireventpoll.c:657
#9 0x00007fc143084312 in virEventRunDefaultImpl () at util/virevent.c:327
#10 0x00007fc14321ecb8 in virNetDaemonRun (dmn=0x558c5328b230) at
rpc/virnetdaemon.c:858
#11 0x0000558c522d7add in main (argc=3, argv=0x7ffe0a832758) at
remote/remote_daemon.c:1496
(gdb) thr 1
[Switching to thread 1 (Thread 0x7fc143c66880 (LWP 64081))]
#0 0x00007fc13fb9aac8 in __pthread_rwlock_wrlock_slow () from
/lib64/libpthread.so.0
(gdb) f 1
#1 0x00007fc143101ffa in virRWLockWrite (m=0x7fc143678cc0 <updateLock>)
at util/virthread.c:122
122 pthread_rwlock_wrlock(&m->lock);
(gdb) p updateLock
$1 = {lock = {__data = {__lock = 0, __nr_readers = 1, __readers_wakeup = 0,
__writer_wakeup = 0, __nr_readers_queued = 0, __nr_writers_queued = 1,
__writer = 0,
__shared = 0, __rwelision = 0 '\000', __pad1 = "\000\000\000\000\000\000",
__pad2 = 0, __flags = 0},
__size = "\000\000\000\000\001", '\000' <repeats 15 times>, "\001", '\000'
<repeats 34 times>, __align = 4294967296}}
Reloading of the nwfilter driver is stuck waiting for a write lock, which
already has a reader (from qemuDomainCreateXML) in the critical section.
I'm not really sure how to best fix this deadlock. One hack that avoids the
deadlock is to load the nwfilter driver after the hypervisor drivers, as the
below patch does. This is obviously problematic if loading a hypervisor driver
requires the nwfilter one.
Any suggestions on better fixes for this issue?
Regards,
Jim
diff --git a/src/remote/remote_daemon.c b/src/remote/remote_daemon.c
index f8082f62f..7a6655a23 100644
--- a/src/remote/remote_daemon.c
+++ b/src/remote/remote_daemon.c
@@ -327,9 +327,6 @@ static void daemonInitialize(void)
#ifdef WITH_SECRETS
VIR_DAEMON_LOAD_MODULE(secretRegister, "secret");
#endif
-#ifdef WITH_NWFILTER
- VIR_DAEMON_LOAD_MODULE(nwfilterRegister, "nwfilter");
-#endif
#ifdef WITH_XEN
VIR_DAEMON_LOAD_MODULE(xenRegister, "xen");
#endif
@@ -354,6 +351,9 @@ static void daemonInitialize(void)
#ifdef WITH_VZ
VIR_DAEMON_LOAD_MODULE(vzRegister, "vz");
#endif
+#ifdef WITH_NWFILTER
+ VIR_DAEMON_LOAD_MODULE(nwfilterRegister, "nwfilter");
+#endif
}
#undef VIR_DAEMON_LOAD_MODULE
6 years, 9 months
[libvirt] [PATCH] virt-aa-helper: resolve yet to be created paths
by Christian Ehrhardt
In certain cases a xml contains paths that do not yet exist, but
are valid as qemu will create them later on - for example
vhostuser mode=server sockets.
In any such cases so far the check to virFileExists failed and due to
that the paths stayed non-resolved in regard to symlinks.
But for apparmor those non-resolved rules are non functional as they
are evaluated after resolving any symlinks.
Therefore for non-existent files and partially non-existent paths
resolve as much as possible to get valid rules.
Example:
<interface type='vhostuser'>
<model type='virtio'/>
<source type='unix'
path='/var/run/symlinknet'
mode='server'/>
</interface>
Got rendered as:
"/var/run/symlinknet" rw,
But correct with "/var/run" being a symlink to "/run" is:
"/run/symlinknet" rw,
Signed-off-by: Christian Ehrhardt <christian.ehrhardt(a)canonical.com>
---
src/security/virt-aa-helper.c | 45 ++++++++++++++++++++++++++++++++++++-------
1 file changed, 38 insertions(+), 7 deletions(-)
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index ff0068c..91bc339 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -41,6 +41,7 @@
#include "viralloc.h"
#include "vircommand.h"
#include "virlog.h"
+#include "dirname.h"
#include "driver.h"
#include "security_driver.h"
@@ -752,6 +753,9 @@ vah_add_path(virBufferPtr buf, const char *path, const char *perms, bool recursi
bool explicit_deny_rule = true;
char *sub = NULL;
char *perms_new = NULL;
+ char *pathdir = NULL;
+ char *pathtmp = NULL;
+ char *pathreal = NULL;
if (path == NULL)
return rc;
@@ -766,14 +770,38 @@ vah_add_path(virBufferPtr buf, const char *path, const char *perms, bool recursi
return 0;
}
- if (virFileExists(path)) {
- if ((tmp = realpath(path, NULL)) == NULL) {
- vah_error(NULL, 0, path);
- vah_error(NULL, 0, _("could not find realpath for disk"));
- return rc;
+ /* files might be created by qemu later on and not exist right now.
+ * But realpath needs a valid path to work on, therefore:
+ * 1. walk the path to find longest valid path
+ * 2. get the realpath of that valid path
+ * 3. re-combine the realpath with the remaining suffix
+ * Note: A totally non existent path is used as-is
+ */
+ if ((pathdir = mdir_name(path)) == NULL)
+ goto cleanup;
+ while (!virFileExists(pathdir)) {
+ if (VIR_STRDUP_QUIET(pathtmp, pathdir) < 0)
+ goto cleanup;
+ VIR_FREE(pathdir);
+ if ((pathdir = mdir_name(pathtmp)) == NULL)
+ goto cleanup;
+ VIR_FREE(pathtmp);
+ }
+
+ if (strlen(pathdir) == 1) {
+ /* nothing of the path does exist yet */
+ if (VIR_STRDUP_QUIET(tmp, path) < 0)
+ goto cleanup;
+ } else {
+ if (VIR_STRDUP_QUIET(pathtmp, path+strlen(pathdir)) < 0)
+ goto cleanup;
+ if ((pathreal = realpath(pathdir, NULL)) == NULL) {
+ vah_error(NULL, 0, pathdir);
+ vah_error(NULL, 0, _("could not find realpath"));
+ goto cleanup;
}
- } else if (VIR_STRDUP_QUIET(tmp, path) < 0) {
- return rc;
+ if (virAsprintfQuiet(&tmp, "%s%s", pathreal, pathtmp) < 0)
+ goto cleanup;
}
if (VIR_STRDUP_QUIET(perms_new, perms) < 0)
@@ -814,6 +842,9 @@ vah_add_path(virBufferPtr buf, const char *path, const char *perms, bool recursi
}
cleanup:
+ VIR_FREE(pathdir);
+ VIR_FREE(pathtmp);
+ VIR_FREE(pathreal);
VIR_FREE(perms_new);
VIR_FREE(tmp);
--
2.7.4
6 years, 9 months
[libvirt] [PATCH] util: mdev: Treat the 'name' sysfs attribute as optional
by Erik Skultety
When commit 3545cbef moved the sysfs attribute reading logic from
_udev.c module to virmdev.c, it had to replace our udev read wrappers
with the ones available from virfile.c. The problem is that the original
logic worked correctly with udev read wrappers which don't return an
error code for a missing attribute, virfile.c readers however - not so
much. Therefore add another parameter to the macro, so we can again
accept the fact that optional attributes may be missing.
Signed-off-by: Erik Skultety <eskultet(a)redhat.com>
---
src/util/virmdev.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/src/util/virmdev.c b/src/util/virmdev.c
index 124933506..688f2efb5 100644
--- a/src/util/virmdev.c
+++ b/src/util/virmdev.c
@@ -505,10 +505,13 @@ virMediatedDeviceTypeReadAttrs(const char *sysfspath,
int ret = -1;
virMediatedDeviceTypePtr tmp = NULL;
-#define MDEV_GET_SYSFS_ATTR(attr, dst, cb) \
+#define MDEV_GET_SYSFS_ATTR(attr, dst, cb, optional) \
do { \
- if (cb(dst, "%s/%s", sysfspath, attr) < 0) \
- goto cleanup; \
+ errno = 0; \
+ if (cb(dst, "%s/%s", sysfspath, attr) < 0) { \
+ if (errno != ENOENT || !optional) \
+ goto cleanup; \
+ } \
} while (0)
if (VIR_ALLOC(tmp) < 0)
@@ -517,10 +520,12 @@ virMediatedDeviceTypeReadAttrs(const char *sysfspath,
if (VIR_STRDUP(tmp->id, last_component(sysfspath)) < 0)
goto cleanup;
- MDEV_GET_SYSFS_ATTR("name", &tmp->name, virFileReadValueString);
- MDEV_GET_SYSFS_ATTR("device_api", &tmp->device_api, virFileReadValueString);
+ /* @name sysfs attribute is optional, so getting ENOENT is fine */
+ MDEV_GET_SYSFS_ATTR("name", &tmp->name, virFileReadValueString, true);
+ MDEV_GET_SYSFS_ATTR("device_api", &tmp->device_api,
+ virFileReadValueString, false);
MDEV_GET_SYSFS_ATTR("available_instances", &tmp->available_instances,
- virFileReadValueUint);
+ virFileReadValueUint, false);
#undef MDEV_GET_SYSFS_ATTR
--
2.13.6
6 years, 9 months
[libvirt] [PATCH v5 00/12] qemu: Validate PCI controller options
by Andrea Bolognani
Applies cleanly on top of 328b8dbe8bee9939c7108fdec4fda05fd02511f6.
Changes from [v4]:
* patch 1/12 is new;
* use virReportEnumRangeError(), as suggested by laine.
Changes from [v3]:
* don't introduce new test cases that won't be able to provide
full test coverage anyway, as suggested by laine.
Changes from [v2]:
* replace the old implementation bit by bit using a clever trick
suggested by pkrempa;
* don't move QEMU capability validation;
* add a default: label to all switch statements as recommended
by danpb.
Changes from [v1]:
* error out instead of silently accept invalid options;
* shave quite a lot of yaks.
[v4] https://www.redhat.com/archives/libvir-list/2018-February/msg01232.html
[v3] https://www.redhat.com/archives/libvir-list/2018-February/msg00996.html
[v2] https://www.redhat.com/archives/libvir-list/2018-February/msg00813.html
[v1] https://www.redhat.com/archives/libvir-list/2018-February/msg00244.html
Andrea Bolognani (12):
conf: Assign explicit value to
VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE
qemu: Create new qemuDomainDeviceDefValidateControllerPCI()
qemu: Validate PCI controller options (modelName)
qemu: Validate PCI controller options (index)
qemu: Validate PCI controller options (targetIndex)
qemu: Validate PCI controller options (pcihole64)
qemu: Validate PCI controller options (busNr)
qemu: Validate PCI controller options (numaNode)
qemu: Validate PCI controller options (chassisNr)
qemu: Validate PCI controller options (chassis and port)
qemu: Validate PCI controllers (QEMU capabilities)
qemu: Remove old qemuDomainDeviceDefValidateControllerPCI()
src/conf/domain_conf.h | 2 +-
src/qemu/qemu_domain.c | 571 ++++++++++++++++++-------
tests/qemuxml2argvdata/pcie-expander-bus.xml | 3 -
tests/qemuxml2xmloutdata/pcie-expander-bus.xml | 4 +-
4 files changed, 418 insertions(+), 162 deletions(-)
--
2.14.3
6 years, 9 months
[libvirt] [PATCH] qemu: Fix memory leak in qemuConnectGetAllDomainStats error path
by John Ferlan
If we return -1 on VIR_ALLOC_N failure, we leaked @vms, so
goto cleanup instead.
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/qemu/qemu_driver.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 9e715e7a0..e13544f83 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -20348,7 +20348,7 @@ qemuConnectGetAllDomainStats(virConnectPtr conn,
}
if (VIR_ALLOC_N(tmpstats, nvms + 1) < 0)
- return -1;
+ goto cleanup;
if (qemuDomainGetStatsNeedMonitor(stats))
privflags |= QEMU_DOMAIN_STATS_HAVE_JOB;
--
2.13.6
6 years, 9 months
[libvirt] [PATCH 3/3] lxc: implement connectGetAllDomainStats
by Cédric Bosdonnat
LXC containers can also provide some statistics. Allow users to fetch
them using the existing API.
---
src/lxc/lxc_driver.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 203 insertions(+)
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index a16dbcc96..c357df927 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -80,6 +80,7 @@
#include "viraccessapichecklxc.h"
#include "virhostdev.h"
#include "netdev_bandwidth_conf.h"
+#include "domain_stats.h"
#define VIR_FROM_THIS VIR_FROM_LXC
@@ -5483,6 +5484,207 @@ lxcDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
return ret;
}
+static int
+lxcDomainGetStatsState(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
+ virDomainObjPtr dom,
+ virDomainStatsRecordPtr record,
+ int *maxparams)
+{
+ return virDomainStatsGetState(dom, record, maxparams);
+}
+
+static int
+lxcDomainGetStatsCpu(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
+ virDomainObjPtr dom,
+ virDomainStatsRecordPtr record,
+ int *maxparams)
+{
+ virLXCDomainObjPrivatePtr priv = dom->privateData;
+ return virCgroupGetStatsCpu(priv->cgroup, record, maxparams);
+}
+
+static int
+lxcDomainGetStatsInterface(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
+ virDomainObjPtr dom,
+ virDomainStatsRecordPtr record,
+ int *maxparams)
+{
+ return virDomainStatsGetInterface(dom, record, maxparams);
+}
+
+/* expects a LL, but typed parameter must be ULL */
+#define LXC_ADD_BLOCK_PARAM_LL(record, maxparams, name, value) \
+do { \
+ char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
+ snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
+ "block.cgroup.%s", name); \
+ if (virTypedParamsAddULLong(&(record)->params, \
+ &(record)->nparams, \
+ maxparams, \
+ param_name, \
+ value) < 0) \
+ goto cleanup; \
+} while (0)
+
+static int
+lxcDomainGetStatsBlock(virLXCDriverPtr driver,
+ virDomainObjPtr dom,
+ virDomainStatsRecordPtr record,
+ int *maxparams)
+{
+ long long rd_req, rd_bytes, wr_req, wr_bytes;
+
+ int ret = lxcDomainBlockStatsInternal(driver, dom, "",
+ &rd_bytes,
+ &wr_bytes,
+ &rd_req,
+ &wr_req);
+
+ LXC_ADD_BLOCK_PARAM_LL(record, maxparams,
+ "rd.reqs", rd_req);
+ LXC_ADD_BLOCK_PARAM_LL(record, maxparams,
+ "rd.bytes", rd_bytes);
+ LXC_ADD_BLOCK_PARAM_LL(record, maxparams,
+ "wr.reqs", wr_req);
+ LXC_ADD_BLOCK_PARAM_LL(record, maxparams,
+ "wr.bytes", wr_bytes);
+
+ cleanup:
+ return ret;
+}
+
+#undef LXC_ADD_BLOCK_PARAM_ULL
+
+typedef int
+(*lxcDomainGetStatsFunc)(virLXCDriverPtr driver,
+ virDomainObjPtr dom,
+ virDomainStatsRecordPtr record,
+ int *maxparams);
+
+struct lxcDomainGetStatsWorker {
+ lxcDomainGetStatsFunc func;
+ unsigned int stats;
+};
+
+static struct lxcDomainGetStatsWorker lxcDomainGetStatsWorkers[] = {
+ { lxcDomainGetStatsState, VIR_DOMAIN_STATS_STATE },
+ { lxcDomainGetStatsCpu, VIR_DOMAIN_STATS_CPU_TOTAL },
+ { lxcDomainGetStatsInterface, VIR_DOMAIN_STATS_INTERFACE },
+ { lxcDomainGetStatsBlock, VIR_DOMAIN_STATS_BLOCK },
+ { NULL, 0 }
+};
+
+static int
+lxcDomainGetStats(virConnectPtr conn,
+ virDomainObjPtr dom,
+ unsigned int stats,
+ virDomainStatsRecordPtr *record)
+{
+ virLXCDriverPtr driver = conn->privateData;
+ int maxparams = 0;
+ virDomainStatsRecordPtr tmp;
+ size_t i;
+ int ret = -1;
+
+ if (VIR_ALLOC(tmp) < 0)
+ goto cleanup;
+
+ for (i = 0; lxcDomainGetStatsWorkers[i].func; i++) {
+ if (stats & lxcDomainGetStatsWorkers[i].stats) {
+ if (lxcDomainGetStatsWorkers[i].func(driver, dom, tmp, &maxparams) < 0)
+ goto cleanup;
+ }
+ }
+
+ if (!(tmp->dom = virGetDomain(conn, dom->def->name,
+ dom->def->uuid, dom->def->id)))
+ goto cleanup;
+
+ *record = tmp;
+ tmp = NULL;
+ ret = 0;
+
+ cleanup:
+ if (tmp) {
+ virTypedParamsFree(tmp->params, tmp->nparams);
+ VIR_FREE(tmp);
+ }
+
+ return ret;
+}
+
+static int
+lxcConnectGetAllDomainStats(virConnectPtr conn,
+ virDomainPtr *doms,
+ unsigned int ndoms,
+ unsigned int stats,
+ virDomainStatsRecordPtr **retStats,
+ unsigned int flags)
+{
+ virLXCDriverPtr driver = conn->privateData;
+ virDomainObjPtr *vms = NULL;
+ virDomainObjPtr vm;
+ size_t nvms;
+ virDomainStatsRecordPtr *tmpstats = NULL;
+ int nstats = 0;
+ size_t i;
+ int ret = -1;
+ unsigned int lflags = flags & (VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE |
+ VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT |
+ VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE);
+
+ virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE |
+ VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT |
+ VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE, -1);
+
+ if (virConnectGetAllDomainStatsEnsureACL(conn) < 0)
+ return -1;
+
+ /* TODO Check stats support */
+
+ if (ndoms) {
+ if (virDomainObjListConvert(driver->domains, conn, doms, ndoms, &vms,
+ &nvms, virConnectGetAllDomainStatsCheckACL,
+ lflags, true) < 0)
+ return -1;
+ } else {
+ if (virDomainObjListCollect(driver->domains, conn, &vms, &nvms,
+ virConnectGetAllDomainStatsCheckACL,
+ lflags) < 0)
+ return -1;
+ }
+
+ if (VIR_ALLOC_N(tmpstats, nvms + 1) < 0)
+ return -1;
+
+ for (i = 0; i < nvms; i++) {
+ virDomainStatsRecordPtr tmp = NULL;
+ vm = vms[i];
+
+ virObjectLock(vm);
+
+ if (lxcDomainGetStats(conn, vm, stats, &tmp) < 0) {
+ virObjectUnlock(vm);
+ goto cleanup;
+ }
+
+ if (tmp)
+ tmpstats[nstats++] = tmp;
+
+ virObjectUnlock(vm);
+ }
+
+ *retStats = tmpstats;
+ tmpstats = NULL;
+
+ ret = nstats;
+
+ cleanup:
+ virDomainStatsRecordListFree(tmpstats);
+ virObjectListFreeCount(vms, nvms);
+
+ return ret;
+}
/* Function Tables */
static virHypervisorDriver lxcHypervisorDriver = {
@@ -5577,6 +5779,7 @@ static virHypervisorDriver lxcHypervisorDriver = {
.nodeGetFreePages = lxcNodeGetFreePages, /* 1.2.6 */
.nodeAllocPages = lxcNodeAllocPages, /* 1.2.9 */
.domainHasManagedSaveImage = lxcDomainHasManagedSaveImage, /* 1.2.13 */
+ .connectGetAllDomainStats = lxcConnectGetAllDomainStats, /* 4.2.0 */
};
static virConnectDriver lxcConnectDriver = {
--
2.16.1
6 years, 9 months
[libvirt] [PATCH 1/3] Extract stats functions from the qemu driver
by Cédric Bosdonnat
Some of the qemu functions getting statistics can easily be reused in
other drivers. Create a conf/domain_stats.[ch] pair to host some of
them.
---
src/Makefile.am | 1 +
src/conf/domain_stats.c | 139 +++++++++++++++++++++++++++++++++++++++++
src/conf/domain_stats.h | 64 +++++++++++++++++++
src/libvirt_private.syms | 4 ++
src/qemu/qemu_driver.c | 158 +++--------------------------------------------
src/util/vircgroup.c | 46 ++++++++++++++
src/util/vircgroup.h | 4 ++
7 files changed, 265 insertions(+), 151 deletions(-)
create mode 100644 src/conf/domain_stats.c
create mode 100644 src/conf/domain_stats.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 3bf2da543..3952a6d2c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -441,6 +441,7 @@ DOMAIN_CONF_SOURCES = \
conf/domain_conf.c conf/domain_conf.h \
conf/domain_audit.c conf/domain_audit.h \
conf/domain_nwfilter.c conf/domain_nwfilter.h \
+ conf/domain_stats.c conf/domain_stats.h \
conf/virsavecookie.c conf/virsavecookie.h \
conf/snapshot_conf.c conf/snapshot_conf.h \
conf/numa_conf.c conf/numa_conf.h \
diff --git a/src/conf/domain_stats.c b/src/conf/domain_stats.c
new file mode 100644
index 000000000..beb3c09d5
--- /dev/null
+++ b/src/conf/domain_stats.c
@@ -0,0 +1,139 @@
+/*
+ * domain_stats.c: domain stats extraction helpers
+ *
+ * Copyright (C) 2006-2016 Red Hat, Inc.
+ * Copyright (C) 2006-2008 Daniel P. Berrange
+ * Copyright (c) 2018 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include "virlog.h"
+#include "domain_stats.h"
+#include "virtypedparam.h"
+#include "virnetdevtap.h"
+#include "virnetdevopenvswitch.h"
+
+#define VIR_FROM_THIS VIR_FROM_DOMAIN
+
+VIR_LOG_INIT("conf.domain_stats");
+
+int
+virDomainStatsGetState(virDomainObjPtr dom,
+ virDomainStatsRecordPtr record,
+ int *maxparams)
+{
+ if (virTypedParamsAddInt(&record->params,
+ &record->nparams,
+ maxparams,
+ "state.state",
+ dom->state.state) < 0)
+ return -1;
+
+ if (virTypedParamsAddInt(&record->params,
+ &record->nparams,
+ maxparams,
+ "state.reason",
+ dom->state.reason) < 0)
+ return -1;
+
+ return 0;
+}
+
+#define STATS_ADD_NET_PARAM(record, maxparams, num, name, value) \
+do { \
+ char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
+ snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
+ "net.%zu.%s", num, name); \
+ if (value >= 0 && virTypedParamsAddULLong(&(record)->params, \
+ &(record)->nparams, \
+ maxparams, \
+ param_name, \
+ value) < 0) \
+ return -1; \
+} while (0)
+
+int
+virDomainStatsGetInterface(virDomainObjPtr dom,
+ virDomainStatsRecordPtr record,
+ int *maxparams)
+{
+ size_t i;
+ struct _virDomainInterfaceStats tmp;
+ int ret = -1;
+
+ if (!virDomainObjIsActive(dom))
+ return 0;
+
+ VIR_DOMAIN_STATS_ADD_COUNT_PARAM(record, maxparams, "net", dom->def->nnets);
+
+ /* Check the path is one of the domain's network interfaces. */
+ for (i = 0; i < dom->def->nnets; i++) {
+ virDomainNetDefPtr net = dom->def->nets[i];
+ virDomainNetType actualType;
+
+ if (!net->ifname)
+ continue;
+
+ memset(&tmp, 0, sizeof(tmp));
+
+ actualType = virDomainNetGetActualType(net);
+
+ VIR_DOMAIN_STATS_ADD_NAME_PARAM(record, maxparams,
+ "net", "name", i, net->ifname);
+
+ if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
+ if (virNetDevOpenvswitchInterfaceStats(net->ifname, &tmp) < 0) {
+ virResetLastError();
+ continue;
+ }
+ } else {
+ if (virNetDevTapInterfaceStats(net->ifname, &tmp,
+ !virDomainNetTypeSharesHostView(net)) < 0) {
+ virResetLastError();
+ continue;
+ }
+ }
+
+ STATS_ADD_NET_PARAM(record, maxparams, i,
+ "rx.bytes", tmp.rx_bytes);
+ STATS_ADD_NET_PARAM(record, maxparams, i,
+ "rx.pkts", tmp.rx_packets);
+ STATS_ADD_NET_PARAM(record, maxparams, i,
+ "rx.errs", tmp.rx_errs);
+ STATS_ADD_NET_PARAM(record, maxparams, i,
+ "rx.drop", tmp.rx_drop);
+ STATS_ADD_NET_PARAM(record, maxparams, i,
+ "tx.bytes", tmp.tx_bytes);
+ STATS_ADD_NET_PARAM(record, maxparams, i,
+ "tx.pkts", tmp.tx_packets);
+ STATS_ADD_NET_PARAM(record, maxparams, i,
+ "tx.errs", tmp.tx_errs);
+ STATS_ADD_NET_PARAM(record, maxparams, i,
+ "tx.drop", tmp.tx_drop);
+ }
+
+ ret = 0;
+ cleanup:
+ return ret;
+}
+
+#undef STATS_ADD_NET_PARAM
diff --git a/src/conf/domain_stats.h b/src/conf/domain_stats.h
new file mode 100644
index 000000000..42f8cb6d3
--- /dev/null
+++ b/src/conf/domain_stats.h
@@ -0,0 +1,64 @@
+/*
+ * domain_stats.h: domain stats extraction helpers
+ *
+ * Copyright (C) 2006-2016 Red Hat, Inc.
+ * Copyright (C) 2006-2008 Daniel P. Berrange
+ * Copyright (c) 2018 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+#ifndef __DOMAIN_STATS_H
+# define __DOMAIN_STATS_H
+
+# include "internal.h"
+# include "domain_conf.h"
+
+
+# define VIR_DOMAIN_STATS_ADD_COUNT_PARAM(record, maxparams, type, count) \
+do { \
+ char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
+ snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "%s.count", type); \
+ if (virTypedParamsAddUInt(&(record)->params, \
+ &(record)->nparams, \
+ maxparams, \
+ param_name, \
+ count) < 0) \
+ goto cleanup; \
+} while (0)
+
+# define VIR_DOMAIN_STATS_ADD_NAME_PARAM(record, maxparams, type, subtype, num, name) \
+do { \
+ char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
+ snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
+ "%s.%zu.%s", type, num, subtype); \
+ if (virTypedParamsAddString(&(record)->params, \
+ &(record)->nparams, \
+ maxparams, \
+ param_name, \
+ name) < 0) \
+ goto cleanup; \
+} while (0)
+
+int virDomainStatsGetState(virDomainObjPtr dom,
+ virDomainStatsRecordPtr record,
+ int *maxparams);
+
+int virDomainStatsGetInterface(virDomainObjPtr dom,
+ virDomainStatsRecordPtr record,
+ int *maxparams);
+
+#endif /* __DOMAIN_STATS_H */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 8a62ea159..6fb5b6945 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -644,6 +644,9 @@ virDomainConfNWFilterRegister;
virDomainConfNWFilterTeardown;
virDomainConfVMNWFilterTeardown;
+# conf/domain_stats.h
+virDomainStatsGetInterface;
+virDomainStatsGetState;
# conf/interface_conf.h
virInterfaceDefFormat;
@@ -1500,6 +1503,7 @@ virCgroupGetMemoryUsage;
virCgroupGetMemSwapHardLimit;
virCgroupGetMemSwapUsage;
virCgroupGetPercpuStats;
+virCgroupGetStatsCpu;
virCgroupHasController;
virCgroupHasEmptyTasks;
virCgroupKill;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 96454c17c..d2e6c0ebe 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -72,6 +72,7 @@
#include "viralloc.h"
#include "viruuid.h"
#include "domain_conf.h"
+#include "domain_stats.h"
#include "domain_audit.h"
#include "node_device_conf.h"
#include "virpci.h"
@@ -19510,21 +19511,7 @@ qemuDomainGetStatsState(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
int *maxparams,
unsigned int privflags ATTRIBUTE_UNUSED)
{
- if (virTypedParamsAddInt(&record->params,
- &record->nparams,
- maxparams,
- "state.state",
- dom->state.state) < 0)
- return -1;
-
- if (virTypedParamsAddInt(&record->params,
- &record->nparams,
- maxparams,
- "state.reason",
- dom->state.reason) < 0)
- return -1;
-
- return 0;
+ return virDomainStatsGetState(dom, record, maxparams);
}
@@ -19547,37 +19534,7 @@ qemuDomainGetStatsCpu(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
unsigned int privflags ATTRIBUTE_UNUSED)
{
qemuDomainObjPrivatePtr priv = dom->privateData;
- unsigned long long cpu_time = 0;
- unsigned long long user_time = 0;
- unsigned long long sys_time = 0;
- int err = 0;
-
- if (!priv->cgroup)
- return 0;
-
- err = virCgroupGetCpuacctUsage(priv->cgroup, &cpu_time);
- if (!err && virTypedParamsAddULLong(&record->params,
- &record->nparams,
- maxparams,
- "cpu.time",
- cpu_time) < 0)
- return -1;
-
- err = virCgroupGetCpuacctStat(priv->cgroup, &user_time, &sys_time);
- if (!err && virTypedParamsAddULLong(&record->params,
- &record->nparams,
- maxparams,
- "cpu.user",
- user_time) < 0)
- return -1;
- if (!err && virTypedParamsAddULLong(&record->params,
- &record->nparams,
- maxparams,
- "cpu.system",
- sys_time) < 0)
- return -1;
-
- return 0;
+ return virCgroupGetStatsCpu(priv->cgroup, record, maxparams);
}
static int
@@ -19756,44 +19713,6 @@ qemuDomainGetStatsVcpu(virQEMUDriverPtr driver,
return ret;
}
-#define QEMU_ADD_COUNT_PARAM(record, maxparams, type, count) \
-do { \
- char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
- snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "%s.count", type); \
- if (virTypedParamsAddUInt(&(record)->params, \
- &(record)->nparams, \
- maxparams, \
- param_name, \
- count) < 0) \
- goto cleanup; \
-} while (0)
-
-#define QEMU_ADD_NAME_PARAM(record, maxparams, type, subtype, num, name) \
-do { \
- char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
- snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
- "%s.%zu.%s", type, num, subtype); \
- if (virTypedParamsAddString(&(record)->params, \
- &(record)->nparams, \
- maxparams, \
- param_name, \
- name) < 0) \
- goto cleanup; \
-} while (0)
-
-#define QEMU_ADD_NET_PARAM(record, maxparams, num, name, value) \
-do { \
- char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
- snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
- "net.%zu.%s", num, name); \
- if (value >= 0 && virTypedParamsAddULLong(&(record)->params, \
- &(record)->nparams, \
- maxparams, \
- param_name, \
- value) < 0) \
- return -1; \
-} while (0)
-
static int
qemuDomainGetStatsInterface(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
virDomainObjPtr dom,
@@ -19801,68 +19720,9 @@ qemuDomainGetStatsInterface(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
int *maxparams,
unsigned int privflags ATTRIBUTE_UNUSED)
{
- size_t i;
- struct _virDomainInterfaceStats tmp;
- int ret = -1;
-
- if (!virDomainObjIsActive(dom))
- return 0;
-
- QEMU_ADD_COUNT_PARAM(record, maxparams, "net", dom->def->nnets);
-
- /* Check the path is one of the domain's network interfaces. */
- for (i = 0; i < dom->def->nnets; i++) {
- virDomainNetDefPtr net = dom->def->nets[i];
- virDomainNetType actualType;
-
- if (!net->ifname)
- continue;
-
- memset(&tmp, 0, sizeof(tmp));
-
- actualType = virDomainNetGetActualType(net);
-
- QEMU_ADD_NAME_PARAM(record, maxparams,
- "net", "name", i, net->ifname);
-
- if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
- if (virNetDevOpenvswitchInterfaceStats(net->ifname, &tmp) < 0) {
- virResetLastError();
- continue;
- }
- } else {
- if (virNetDevTapInterfaceStats(net->ifname, &tmp,
- !virDomainNetTypeSharesHostView(net)) < 0) {
- virResetLastError();
- continue;
- }
- }
-
- QEMU_ADD_NET_PARAM(record, maxparams, i,
- "rx.bytes", tmp.rx_bytes);
- QEMU_ADD_NET_PARAM(record, maxparams, i,
- "rx.pkts", tmp.rx_packets);
- QEMU_ADD_NET_PARAM(record, maxparams, i,
- "rx.errs", tmp.rx_errs);
- QEMU_ADD_NET_PARAM(record, maxparams, i,
- "rx.drop", tmp.rx_drop);
- QEMU_ADD_NET_PARAM(record, maxparams, i,
- "tx.bytes", tmp.tx_bytes);
- QEMU_ADD_NET_PARAM(record, maxparams, i,
- "tx.pkts", tmp.tx_packets);
- QEMU_ADD_NET_PARAM(record, maxparams, i,
- "tx.errs", tmp.tx_errs);
- QEMU_ADD_NET_PARAM(record, maxparams, i,
- "tx.drop", tmp.tx_drop);
- }
-
- ret = 0;
- cleanup:
- return ret;
+ return virDomainStatsGetInterface(dom, record, maxparams);
}
-#undef QEMU_ADD_NET_PARAM
-
#define QEMU_ADD_BLOCK_PARAM_UI(record, maxparams, num, name, value) \
do { \
char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
@@ -19984,10 +19844,10 @@ qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver,
if (disk->info.alias)
alias = qemuDomainStorageAlias(disk->info.alias, backing_idx);
- QEMU_ADD_NAME_PARAM(record, maxparams, "block", "name", block_idx,
+ VIR_DOMAIN_STATS_ADD_NAME_PARAM(record, maxparams, "block", "name", block_idx,
disk->dst);
if (virStorageSourceIsLocalStorage(src) && src->path)
- QEMU_ADD_NAME_PARAM(record, maxparams, "block", "path",
+ VIR_DOMAIN_STATS_ADD_NAME_PARAM(record, maxparams, "block", "path",
block_idx, src->path);
if (backing_idx)
QEMU_ADD_BLOCK_PARAM_UI(record, maxparams, block_idx, "backingIndex",
@@ -20103,7 +19963,7 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
* after the iteration than it is to iterate twice; but we still
* want count listed first. */
count_index = record->nparams;
- QEMU_ADD_COUNT_PARAM(record, maxparams, "block", 0);
+ VIR_DOMAIN_STATS_ADD_COUNT_PARAM(record, maxparams, "block", 0);
for (i = 0; i < dom->def->ndisks; i++) {
virDomainDiskDefPtr disk = dom->def->disks[i];
@@ -20137,10 +19997,6 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
#undef QEMU_ADD_BLOCK_PARAM_ULL
-#undef QEMU_ADD_NAME_PARAM
-
-#undef QEMU_ADD_COUNT_PARAM
-
static int
qemuDomainGetStatsPerfOneEvent(virPerfPtr perf,
virPerfEventType type,
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index 0a31947b0..04ef4c1a7 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -4122,6 +4122,44 @@ virCgroupControllerAvailable(int controller)
return ret;
}
+int
+virCgroupGetStatsCpu(virCgroupPtr cgroup,
+ virDomainStatsRecordPtr record,
+ int *maxparams)
+{
+ unsigned long long cpu_time = 0;
+ unsigned long long user_time = 0;
+ unsigned long long sys_time = 0;
+ int err = 0;
+
+ if (!cgroup)
+ return 0;
+
+ err = virCgroupGetCpuacctUsage(cgroup, &cpu_time);
+ if (!err && virTypedParamsAddULLong(&record->params,
+ &record->nparams,
+ maxparams,
+ "cpu.time",
+ cpu_time) < 0)
+ return -1;
+
+ err = virCgroupGetCpuacctStat(cgroup, &user_time, &sys_time);
+ if (!err && virTypedParamsAddULLong(&record->params,
+ &record->nparams,
+ maxparams,
+ "cpu.user",
+ user_time) < 0)
+ return -1;
+ if (!err && virTypedParamsAddULLong(&record->params,
+ &record->nparams,
+ maxparams,
+ "cpu.system",
+ sys_time) < 0)
+ return -1;
+
+ return 0;
+}
+
#else /* !VIR_CGROUP_SUPPORTED */
bool
@@ -4899,6 +4937,14 @@ virCgroupControllerAvailable(int controller ATTRIBUTE_UNUSED)
{
return false;
}
+
+int
+virCgroupGetStatsCpu(virCgroupPtr cgroup,
+ virDomainStatsRecordPtr record,
+ int *maxparams)
+{
+ return 0;
+}
#endif /* !VIR_CGROUP_SUPPORTED */
diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
index d83392767..2ebdf9505 100644
--- a/src/util/vircgroup.h
+++ b/src/util/vircgroup.h
@@ -297,4 +297,8 @@ int virCgroupSetOwner(virCgroupPtr cgroup,
int virCgroupHasEmptyTasks(virCgroupPtr cgroup, int controller);
bool virCgroupControllerAvailable(int controller);
+
+int virCgroupGetStatsCpu(virCgroupPtr cgroup,
+ virDomainStatsRecordPtr record,
+ int *maxparams);
#endif /* __VIR_CGROUP_H__ */
--
2.16.1
6 years, 9 months
[libvirt] [PATCH 2/3] lxc: factorize code for block stats
by Cédric Bosdonnat
lxcDomainBlockStats and lxcDomainBlockStatsFlags were both using very
similar code. This commit factorizes them into a
lxcDomainBlockStatsInternal.
---
src/lxc/lxc_driver.c | 131 ++++++++++++++++++++-------------------------------
1 file changed, 50 insertions(+), 81 deletions(-)
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index fa6fc4643..a16dbcc96 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -2348,28 +2348,22 @@ lxcDomainMergeBlkioDevice(virBlkioDevicePtr *dest_array,
return 0;
}
-
-static int
-lxcDomainBlockStats(virDomainPtr dom,
- const char *path,
- virDomainBlockStatsPtr stats)
+static int lxcDomainBlockStatsInternal(virLXCDriverPtr driver,
+ virDomainObjPtr vm,
+ const char *path,
+ long long *rd_bytes,
+ long long *wr_bytes,
+ long long *rd_req,
+ long long *wr_req)
{
- virLXCDriverPtr driver = dom->conn->privateData;
int ret = -1;
- virDomainObjPtr vm;
virDomainDiskDefPtr disk = NULL;
virLXCDomainObjPrivatePtr priv;
- if (!(vm = lxcDomObjFromDomain(dom)))
- return ret;
-
priv = vm->privateData;
- if (virDomainBlockStatsEnsureACL(dom->conn, vm->def) < 0)
- goto cleanup;
-
if (virLXCDomainObjBeginJob(driver, vm, LXC_JOB_QUERY) < 0)
- goto cleanup;
+ return -1;
if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_OPERATION_INVALID,
@@ -2386,10 +2380,10 @@ lxcDomainBlockStats(virDomainPtr dom,
if (!*path) {
/* empty path - return entire domain blkstats instead */
ret = virCgroupGetBlkioIoServiced(priv->cgroup,
- &stats->rd_bytes,
- &stats->wr_bytes,
- &stats->rd_req,
- &stats->wr_req);
+ rd_bytes,
+ wr_bytes,
+ rd_req,
+ wr_req);
goto endjob;
}
@@ -2407,13 +2401,36 @@ lxcDomainBlockStats(virDomainPtr dom,
ret = virCgroupGetBlkioIoDeviceServiced(priv->cgroup,
disk->info.alias,
- &stats->rd_bytes,
- &stats->wr_bytes,
- &stats->rd_req,
- &stats->wr_req);
+ rd_bytes,
+ wr_bytes,
+ rd_req,
+ wr_req);
endjob:
virLXCDomainObjEndJob(driver, vm);
+ return ret;
+}
+
+static int
+lxcDomainBlockStats(virDomainPtr dom,
+ const char *path,
+ virDomainBlockStatsPtr stats)
+{
+ virLXCDriverPtr driver = dom->conn->privateData;
+ virDomainObjPtr vm;
+ int ret = -1;
+
+ if (!(vm = lxcDomObjFromDomain(dom)))
+ return -1;
+
+ if (virDomainBlockStatsEnsureACL(dom->conn, vm->def) < 0)
+ goto cleanup;
+
+ ret = lxcDomainBlockStatsInternal(driver, vm, path,
+ &stats->rd_bytes,
+ &stats->wr_bytes,
+ &stats->rd_req,
+ &stats->wr_req);
cleanup:
virDomainObjEndAPI(&vm);
@@ -2431,8 +2448,6 @@ lxcDomainBlockStatsFlags(virDomainPtr dom,
virLXCDriverPtr driver = dom->conn->privateData;
int tmp, ret = -1;
virDomainObjPtr vm;
- virDomainDiskDefPtr disk = NULL;
- virLXCDomainObjPrivatePtr priv;
long long rd_req, rd_bytes, wr_req, wr_bytes;
virTypedParameterPtr param;
@@ -2449,60 +2464,17 @@ lxcDomainBlockStatsFlags(virDomainPtr dom,
if (!(vm = lxcDomObjFromDomain(dom)))
return ret;
- priv = vm->privateData;
-
if (virDomainBlockStatsFlagsEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
- if (virLXCDomainObjBeginJob(driver, vm, LXC_JOB_QUERY) < 0)
+ if (lxcDomainBlockStatsInternal(driver, vm, path,
+ &rd_bytes,
+ &wr_bytes,
+ &rd_req,
+ &wr_req) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("domain stats query failed"));
goto cleanup;
-
- if (!virDomainObjIsActive(vm)) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("domain is not running"));
- goto endjob;
- }
-
- if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("blkio cgroup isn't mounted"));
- goto endjob;
- }
-
- if (!*path) {
- /* empty path - return entire domain blkstats instead */
- if (virCgroupGetBlkioIoServiced(priv->cgroup,
- &rd_bytes,
- &wr_bytes,
- &rd_req,
- &wr_req) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain stats query failed"));
- goto endjob;
- }
- } else {
- if (!(disk = virDomainDiskByName(vm->def, path, false))) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("invalid path: %s"), path);
- goto endjob;
- }
-
- if (!disk->info.alias) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("missing disk device alias name for %s"), disk->dst);
- goto endjob;
- }
-
- if (virCgroupGetBlkioIoDeviceServiced(priv->cgroup,
- disk->info.alias,
- &rd_bytes,
- &wr_bytes,
- &rd_req,
- &wr_req) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain stats query failed"));
- goto endjob;
- }
}
tmp = 0;
@@ -2512,7 +2484,7 @@ lxcDomainBlockStatsFlags(virDomainPtr dom,
param = ¶ms[tmp];
if (virTypedParameterAssign(param, VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES,
VIR_TYPED_PARAM_LLONG, wr_bytes) < 0)
- goto endjob;
+ goto cleanup;
tmp++;
}
@@ -2520,7 +2492,7 @@ lxcDomainBlockStatsFlags(virDomainPtr dom,
param = ¶ms[tmp];
if (virTypedParameterAssign(param, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ,
VIR_TYPED_PARAM_LLONG, wr_req) < 0)
- goto endjob;
+ goto cleanup;
tmp++;
}
@@ -2528,7 +2500,7 @@ lxcDomainBlockStatsFlags(virDomainPtr dom,
param = ¶ms[tmp];
if (virTypedParameterAssign(param, VIR_DOMAIN_BLOCK_STATS_READ_BYTES,
VIR_TYPED_PARAM_LLONG, rd_bytes) < 0)
- goto endjob;
+ goto cleanup;
tmp++;
}
@@ -2536,16 +2508,13 @@ lxcDomainBlockStatsFlags(virDomainPtr dom,
param = ¶ms[tmp];
if (virTypedParameterAssign(param, VIR_DOMAIN_BLOCK_STATS_READ_REQ,
VIR_TYPED_PARAM_LLONG, rd_req) < 0)
- goto endjob;
+ goto cleanup;
tmp++;
}
ret = 0;
*nparams = tmp;
- endjob:
- virLXCDomainObjEndJob(driver, vm);
-
cleanup:
virDomainObjEndAPI(&vm);
return ret;
--
2.16.1
6 years, 9 months
[libvirt] [PATCH] qemuDomainObjBeginJob: Don't account DESTROY job to maxQueuedJobs
by Michal Privoznik
When trying to destroy a domain (e.g. because we've seen EOF on
the monitor) we try to acquire QEMU_JOB_DESTROY. However, if
max_queued is set in qemu.conf this may fail and since our code
doesn't count on that we will still report domain as active even
though the qemu process is long gone. More specifically, if we've
seen EOF on the monitor, qemuProcessHandleMonitorEOF() is called
which sends MONITOR_EOF job to the event worker pool and
unregisters monitor from the event loop. The worker pool calls
processMonitorEOFEvent() which tries to set job which may fail
due to the limit as described above.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/qemu/qemu_domain.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 8b4efc82d..ee02ecd0c 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -5401,7 +5401,8 @@ qemuDomainObjBeginJobInternal(virQEMUDriverPtr driver,
then = now + QEMU_JOB_WAIT_TIME;
retry:
- if (cfg->maxQueuedJobs &&
+ if ((!async && job != QEMU_JOB_DESTROY) &&
+ cfg->maxQueuedJobs &&
priv->jobs_queued > cfg->maxQueuedJobs) {
goto error;
}
--
2.16.1
6 years, 9 months
[libvirt] [perl PATCH 0/3] Make the perl documentation less confusing
by Laine Stump
I encountered several examples that assigned a network, an nwfilter,
or just about anything to a variable called $dom, and called
connections $vmm. This seemed confusing, so...
Laine Stump (3):
docs: replace $vmm with $conn
docs: replace VMM with hypervisor
docs: fix other assorted example variable names
lib/Sys/Virt.pm | 280 ++++++++++++++++++++++++++++----------------------------
1 file changed, 140 insertions(+), 140 deletions(-)
--
2.14.3
6 years, 9 months