Re: [libvirt] [PATCH 06/11] qemu: Add monitor functions to set IOThread params
On 10/22/18 5:16 AM, Michal Prívozník wrote: > On 10/19/2018 03:09 PM, John Ferlan wrote: >> >> >> On 10/19/18 7:06 AM, Michal Privoznik wrote: >>> On 10/07/2018 03:00 PM, John Ferlan wrote: Add functions to set the IOThreadInfo param data for the live guest. Based on code originally posted by Pavel Hrdina , but extracted into a separate patch. Note that qapi expects to receive integer parameters rather than unsigned long long or unsigned int's. QEMU does save the value in larger signed 64 bit values eventually. Signed-off-by: John Ferlan --- src/qemu/qemu_monitor.c | 19 +++ src/qemu/qemu_monitor.h | 2 ++ src/qemu/qemu_monitor_json.c | 33 + src/qemu/qemu_monitor_json.h | 4 4 files changed, 58 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 7f7013e115..a65d638ab8 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -4135,6 +4135,25 @@ qemuMonitorGetIOThreads(qemuMonitorPtr mon, } +/** + * qemuMonitorSetIOThread: + * @mon: Pointer to the monitor + * @iothreadInfo: filled IOThread info with data + * + * Alter the specified IOThread's IOThreadInfo values. + */ +int +qemuMonitorSetIOThread(qemuMonitorPtr mon, + qemuMonitorIOThreadInfoPtr iothreadInfo) +{ +VIR_DEBUG("iothread=%p", iothreadInfo); + +QEMU_CHECK_MONITOR(mon); + +return qemuMonitorJSONSetIOThread(mon, iothreadInfo); +} + + /** * qemuMonitorGetMemoryDeviceInfo: * @mon: pointer to the monitor diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index c2991e2b16..ef71fc6448 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1123,6 +1123,8 @@ struct _qemuMonitorIOThreadInfo { }; int qemuMonitorGetIOThreads(qemuMonitorPtr mon, qemuMonitorIOThreadInfoPtr **iothreads); +int qemuMonitorSetIOThread(qemuMonitorPtr mon, + qemuMonitorIOThreadInfoPtr iothreadInfo); typedef struct _qemuMonitorMemoryDeviceInfo qemuMonitorMemoryDeviceInfo; typedef qemuMonitorMemoryDeviceInfo *qemuMonitorMemoryDeviceInfoPtr; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 2e92984b44..bb1d62b844 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7474,6 +7474,39 @@ qemuMonitorJSONGetIOThreads(qemuMonitorPtr mon, } +int +qemuMonitorJSONSetIOThread(qemuMonitorPtr mon, + qemuMonitorIOThreadInfoPtr iothreadInfo) +{ +int ret = -1; +char *path = NULL; +qemuMonitorJSONObjectProperty prop; + +if (virAsprintf(&path, "/objects/iothread%u", +iothreadInfo->iothread_id) < 0) +goto cleanup; + +#define VIR_IOTHREAD_SET_PROP(propName, propVal) \ +memset(&prop, 0, sizeof(qemuMonitorJSONObjectProperty)); \ +prop.type = QEMU_MONITOR_OBJECT_PROPERTY_INT; \ +prop.val.iv = propVal; \ +if (qemuMonitorJSONSetObjectProperty(mon, path, propName, &prop) < 0) \ +goto cleanup; + +VIR_IOTHREAD_SET_PROP("poll-max-ns", iothreadInfo->poll_max_ns) +VIR_IOTHREAD_SET_PROP("poll-grow", iothreadInfo->poll_grow) +VIR_IOTHREAD_SET_PROP("poll-shrink", iothreadInfo->poll_shrink) >>> >>> So this is all or nothing approach. All values are set - even though >>> user might request through public API to change just one. I don't think >>> it is a good design. Either we need a monitor API that changes just one >>> value and call it for every typed parameter that user sends to us, or >>> public API implementation must copy the old values into this struct >>> (even though it would be ugly). >>> >>> Michal >>> >> >> Fair complaint - I tried to reuse as much as possible from the initial >> series so that I didn't "waste" time implementing something that in the >> long run wasn't desired. Originally there were lots of checks about what >> was or wasn't set - I just took the path of least resistance. >> >> It should be simple to add flag for each to determine which was set >> before setting them in the object path. >> >> IOW: >> >> #define VIR_IOTHREAD_SET_PROP(propName, propVal) \ >> if (iothreadInfo->set_##propVal) { \ > > This will fly iff zero value can't be set on the monitor. I have no idea > whether it can or can not. If it can be set, then we have to go with > something more clever. > > Michal > Not 100% sure what you meant... The point of the bools is to indicate when the value was set, doesn't matter if it's zero. From: $QEMU.GIT/qapi/misc.json: # @poll-max
Re: [libvirt] [jenkins-ci PATCH 3/3] projects: add libvirt-ocaml project
On Friday, 19 October 2018 11:37:17 CEST Daniel P. Berrangé wrote: > On Thu, Oct 11, 2018 at 11:19:54AM +0200, Pino Toscano wrote: > > Not built on Debian 8, as the version of OCaml is not new enough. > > > > Signed-off-by: Pino Toscano > > --- > > jobs/defaults.yaml | 2 ++ > > projects/libvirt-ocaml.yaml | 23 +++ > > 2 files changed, 25 insertions(+) > > create mode 100644 projects/libvirt-ocaml.yaml > > > > diff --git a/jobs/defaults.yaml b/jobs/defaults.yaml > > index 5cf84dc..13cc443 100644 > > --- a/jobs/defaults.yaml > > +++ b/jobs/defaults.yaml > > @@ -51,6 +51,8 @@ > > default: https://github.com/libvirt/libvirt-go-xml.git > >libvirt-go: > > default: https://github.com/libvirt/libvirt-go.git > > + libvirt-ocaml: > > +default: https://github.com/libvirt/libvirt-ocaml.git > >libvirt-perl: > > default: https://github.com/libvirt/libvirt-perl.git > >libvirt-python: > > diff --git a/projects/libvirt-ocaml.yaml b/projects/libvirt-ocaml.yaml > > new file mode 100644 > > index 000..efea09b > > --- /dev/null > > +++ b/projects/libvirt-ocaml.yaml > > @@ -0,0 +1,23 @@ > > + > > +- project: > > +name: libvirt-ocaml > > +# Debian 8 doesn't have a recent enough OCaml > > +machines: > > + - libvirt-centos-7 > > + - libvirt-debian-9 > > + - libvirt-fedora-27 > > + - libvirt-fedora-28 > > + - libvirt-fedora-rawhide > > + - libvirt-freebsd-10 > > + - libvirt-freebsd-11 > > +title: Libvirt OCaml > > +archive_format: xz > > +git_url: '{git_urls[libvirt-ocaml][default]}' > > +jobs: > > + - generic-build-job: > > + parent_jobs: 'libvirt-build' > > + command: | > > +autoreconf -vfi > > +./configure --prefix=$VIRT_PREFIX --with-libvirt=$VIRT_PREFIX > > +$MAKE > > +$MAKE opt > > Since this is using autotools, how about tweaking it to follow the normal > pattern for autotools jobs, so we can use the standard job defintion. Technically, it does not use autotools, but only autoconf. > It looks like it would need > > - An autogen.sh script It can be added, but it would just call autoreconf. > - Fixed VPATH build Slightly more complicated to fix, and not a priority for now. > - Have 'make opt' be part of the default target 'opt' builds the library, and the examples as native using the ocamlopt compiler. ocamlopt is not available on all the architecture (since it requires an ELF generator in the OCaml compiler), and you can choose which flavour of build you want (i.e. native/optimized, or bytecode). -- Pino Toscano signature.asc Description: This is a digitally signed message part. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [jenkins-ci PATCH v2 3/3] Add libvirt-ocaml project
Not built on Debian 8, as the version of OCaml is not new enough. Signed-off-by: Pino Toscano --- guests/playbooks/build/jobs/defaults.yml | 2 ++ .../build/projects/libvirt-ocaml.yml | 27 +++ jobs/defaults.yaml| 2 ++ projects/libvirt-ocaml.yaml | 23 4 files changed, 54 insertions(+) create mode 100644 guests/playbooks/build/projects/libvirt-ocaml.yml create mode 100644 projects/libvirt-ocaml.yaml diff --git a/guests/playbooks/build/jobs/defaults.yml b/guests/playbooks/build/jobs/defaults.yml index 522dd83..81c5fab 100644 --- a/guests/playbooks/build/jobs/defaults.yml +++ b/guests/playbooks/build/jobs/defaults.yml @@ -52,6 +52,8 @@ git_urls: default: https://github.com/libvirt/libvirt-go-xml.git libvirt-go: default: https://github.com/libvirt/libvirt-go.git + libvirt-ocaml: +default: https://github.com/libvirt/libvirt-ocaml.git libvirt-perl: default: https://github.com/libvirt/libvirt-perl.git libvirt-python: diff --git a/guests/playbooks/build/projects/libvirt-ocaml.yml b/guests/playbooks/build/projects/libvirt-ocaml.yml new file mode 100644 index 000..f0dec8b --- /dev/null +++ b/guests/playbooks/build/projects/libvirt-ocaml.yml @@ -0,0 +1,27 @@ +--- +- set_fact: +name: libvirt-ocaml +# Debian 8 doesn't have a recent enough OCaml +machines: + - libvirt-centos-7 + - libvirt-debian-9 + - libvirt-debian-sid + - libvirt-fedora-27 + - libvirt-fedora-28 + - libvirt-fedora-rawhide + - libvirt-freebsd-10 + - libvirt-freebsd-11 + - libvirt-freebsd-current + - libvirt-ubuntu-16 + - libvirt-ubuntu-18 +archive_format: xz +git_url: '{{ git_urls["libvirt-ocaml"][git_remote] }}' + +- include: '{{ playbook_base }}/jobs/prepare.yml' +- include: '{{ playbook_base }}/jobs/generic-build-job.yml' + vars: +command: | + autoreconf -vfi + ./configure --prefix=$VIRT_PREFIX + $MAKE + $MAKE opt diff --git a/jobs/defaults.yaml b/jobs/defaults.yaml index 5cf84dc..13cc443 100644 --- a/jobs/defaults.yaml +++ b/jobs/defaults.yaml @@ -51,6 +51,8 @@ default: https://github.com/libvirt/libvirt-go-xml.git libvirt-go: default: https://github.com/libvirt/libvirt-go.git + libvirt-ocaml: +default: https://github.com/libvirt/libvirt-ocaml.git libvirt-perl: default: https://github.com/libvirt/libvirt-perl.git libvirt-python: diff --git a/projects/libvirt-ocaml.yaml b/projects/libvirt-ocaml.yaml new file mode 100644 index 000..e9e3837 --- /dev/null +++ b/projects/libvirt-ocaml.yaml @@ -0,0 +1,23 @@ + +- project: +name: libvirt-ocaml +# Debian 8 doesn't have a recent enough OCaml +machines: + - libvirt-centos-7 + - libvirt-debian-9 + - libvirt-fedora-27 + - libvirt-fedora-28 + - libvirt-fedora-rawhide + - libvirt-freebsd-10 + - libvirt-freebsd-11 +title: Libvirt OCaml +archive_format: xz +git_url: '{git_urls[libvirt-ocaml][default]}' +jobs: + - generic-build-job: + parent_jobs: 'libvirt-build' + command: | +autoreconf -vfi +./configure --prefix=$VIRT_PREFIX +$MAKE +$MAKE opt -- 2.17.2 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [jenkins-ci PATCH v2 1/3] guests: add mappings for OCaml components
Soon to be used by libvirt-ocaml. Signed-off-by: Pino Toscano --- guests/vars/mappings.yml | 6 ++ 1 file changed, 6 insertions(+) diff --git a/guests/vars/mappings.yml b/guests/vars/mappings.yml index 5df918f..cd92bd8 100644 --- a/guests/vars/mappings.yml +++ b/guests/vars/mappings.yml @@ -501,6 +501,12 @@ mappings: FreeBSD: Debian8: + ocaml: +default: ocaml + + ocaml-findlib: +default: ocaml-findlib + openwsman: rpm: libwsman-devel Ubuntu: libopenwsman-dev -- 2.17.2 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [jenkins-ci PATCH v2 2/3] guests: pull dependencies for libvirt-ocaml
Install the packages needed for building libvirt-ocaml; not on Debian 8 though, as the version of OCaml is not new enough there. Signed-off-by: Pino Toscano --- guests/host_vars/libvirt-centos-7/main.yml| 1 + guests/host_vars/libvirt-debian-9/main.yml| 1 + guests/host_vars/libvirt-debian-sid/main.yml | 1 + guests/host_vars/libvirt-fedora-27/main.yml | 1 + guests/host_vars/libvirt-fedora-28/main.yml | 1 + guests/host_vars/libvirt-fedora-rawhide/main.yml | 1 + guests/host_vars/libvirt-freebsd-10/main.yml | 1 + guests/host_vars/libvirt-freebsd-11/main.yml | 1 + guests/host_vars/libvirt-freebsd-current/main.yml | 1 + guests/host_vars/libvirt-ubuntu-16/main.yml | 1 + guests/host_vars/libvirt-ubuntu-18/main.yml | 1 + guests/vars/projects/libvirt-ocaml.yml| 5 + 12 files changed, 16 insertions(+) create mode 100644 guests/vars/projects/libvirt-ocaml.yml diff --git a/guests/host_vars/libvirt-centos-7/main.yml b/guests/host_vars/libvirt-centos-7/main.yml index e220849..8be54b6 100644 --- a/guests/host_vars/libvirt-centos-7/main.yml +++ b/guests/host_vars/libvirt-centos-7/main.yml @@ -7,6 +7,7 @@ projects: - libvirt-glib - libvirt-go - libvirt-go-xml + - libvirt-ocaml - libvirt-perl - libvirt-python - osinfo-db diff --git a/guests/host_vars/libvirt-debian-9/main.yml b/guests/host_vars/libvirt-debian-9/main.yml index cdc5a57..33476ad 100644 --- a/guests/host_vars/libvirt-debian-9/main.yml +++ b/guests/host_vars/libvirt-debian-9/main.yml @@ -6,6 +6,7 @@ projects: - libvirt-glib - libvirt-go - libvirt-go-xml + - libvirt-ocaml - libvirt-perl - libvirt-python - libvirt-sandbox diff --git a/guests/host_vars/libvirt-debian-sid/main.yml b/guests/host_vars/libvirt-debian-sid/main.yml index 5dd887b..f2594e7 100644 --- a/guests/host_vars/libvirt-debian-sid/main.yml +++ b/guests/host_vars/libvirt-debian-sid/main.yml @@ -6,6 +6,7 @@ projects: - libvirt-glib - libvirt-go - libvirt-go-xml + - libvirt-ocaml - libvirt-perl - libvirt-python - libvirt-sandbox diff --git a/guests/host_vars/libvirt-fedora-27/main.yml b/guests/host_vars/libvirt-fedora-27/main.yml index f131953..0b4ec2b 100644 --- a/guests/host_vars/libvirt-fedora-27/main.yml +++ b/guests/host_vars/libvirt-fedora-27/main.yml @@ -7,6 +7,7 @@ projects: - libvirt-glib - libvirt-go - libvirt-go-xml + - libvirt-ocaml - libvirt-perl - libvirt-python - libvirt-sandbox diff --git a/guests/host_vars/libvirt-fedora-28/main.yml b/guests/host_vars/libvirt-fedora-28/main.yml index f115598..13555af 100644 --- a/guests/host_vars/libvirt-fedora-28/main.yml +++ b/guests/host_vars/libvirt-fedora-28/main.yml @@ -7,6 +7,7 @@ projects: - libvirt-glib - libvirt-go - libvirt-go-xml + - libvirt-ocaml - libvirt-perl - libvirt-python - libvirt-sandbox diff --git a/guests/host_vars/libvirt-fedora-rawhide/main.yml b/guests/host_vars/libvirt-fedora-rawhide/main.yml index 4318653..604f57f 100644 --- a/guests/host_vars/libvirt-fedora-rawhide/main.yml +++ b/guests/host_vars/libvirt-fedora-rawhide/main.yml @@ -13,6 +13,7 @@ projects: - libvirt-glib+mingw64 - libvirt-go - libvirt-go-xml + - libvirt-ocaml - libvirt-perl - libvirt-python - libvirt-sandbox diff --git a/guests/host_vars/libvirt-freebsd-10/main.yml b/guests/host_vars/libvirt-freebsd-10/main.yml index 005acb4..6547ab4 100644 --- a/guests/host_vars/libvirt-freebsd-10/main.yml +++ b/guests/host_vars/libvirt-freebsd-10/main.yml @@ -8,6 +8,7 @@ projects: - libvirt-glib - libvirt-go - libvirt-go-xml + - libvirt-ocaml - libvirt-perl - libvirt-python - libvirt-tck diff --git a/guests/host_vars/libvirt-freebsd-11/main.yml b/guests/host_vars/libvirt-freebsd-11/main.yml index dd06fc5..887c9e6 100644 --- a/guests/host_vars/libvirt-freebsd-11/main.yml +++ b/guests/host_vars/libvirt-freebsd-11/main.yml @@ -8,6 +8,7 @@ projects: - libvirt-glib - libvirt-go - libvirt-go-xml + - libvirt-ocaml - libvirt-perl - libvirt-python - libvirt-tck diff --git a/guests/host_vars/libvirt-freebsd-current/main.yml b/guests/host_vars/libvirt-freebsd-current/main.yml index 07f3f25..1f3e911 100644 --- a/guests/host_vars/libvirt-freebsd-current/main.yml +++ b/guests/host_vars/libvirt-freebsd-current/main.yml @@ -8,6 +8,7 @@ projects: - libvirt-glib - libvirt-go - libvirt-go-xml + - libvirt-ocaml - libvirt-perl - libvirt-python - libvirt-tck diff --git a/guests/host_vars/libvirt-ubuntu-16/main.yml b/guests/host_vars/libvirt-ubuntu-16/main.yml index 4d9914a..6ec1df8 100644 --- a/guests/host_vars/libvirt-ubuntu-16/main.yml +++ b/guests/host_vars/libvirt-ubuntu-16/main.yml @@ -6,6 +6,7 @@ projects: - libvirt-glib - libvirt-go - libvirt-go-xml + - libvirt-ocaml - libvirt-perl - libvirt-python - libvirt-sandbox diff --git a/guests/host_vars/libvirt-ubuntu-18/main.yml b/guests/host_vars/libvirt-ubuntu-
[libvirt] [jenkins-ci PATCH v2 0/3] Add libvirt-ocaml
Now that the libvirt-ocaml repository is fixed, let's build it in CI. Changes from v1 to v2: - split according to Andrea's hints - removed --with-libvirt as argument for configure, no more needed after upstream changes Pino Toscano (3): guests: add mappings for OCaml components guests: pull dependencies for libvirt-ocaml Add libvirt-ocaml project guests/host_vars/libvirt-centos-7/main.yml| 1 + guests/host_vars/libvirt-debian-9/main.yml| 1 + guests/host_vars/libvirt-debian-sid/main.yml | 1 + guests/host_vars/libvirt-fedora-27/main.yml | 1 + guests/host_vars/libvirt-fedora-28/main.yml | 1 + .../host_vars/libvirt-fedora-rawhide/main.yml | 1 + guests/host_vars/libvirt-freebsd-10/main.yml | 1 + guests/host_vars/libvirt-freebsd-11/main.yml | 1 + .../libvirt-freebsd-current/main.yml | 1 + guests/host_vars/libvirt-ubuntu-16/main.yml | 1 + guests/host_vars/libvirt-ubuntu-18/main.yml | 1 + guests/playbooks/build/jobs/defaults.yml | 2 ++ .../build/projects/libvirt-ocaml.yml | 27 +++ guests/vars/mappings.yml | 6 + guests/vars/projects/libvirt-ocaml.yml| 5 jobs/defaults.yaml| 2 ++ projects/libvirt-ocaml.yaml | 23 17 files changed, 76 insertions(+) create mode 100644 guests/playbooks/build/projects/libvirt-ocaml.yml create mode 100644 guests/vars/projects/libvirt-ocaml.yml create mode 100644 projects/libvirt-ocaml.yaml -- 2.17.2 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [Qemu-devel] [PULL 00/45] Machine queue, 2018-10-18
Igor Mammedov writes: > On Fri, 19 Oct 2018 17:23:21 -0300 > Eduardo Habkost wrote: > >> On Fri, Oct 19, 2018 at 09:53:45PM +0200, Igor Mammedov wrote: >> > On Fri, 19 Oct 2018 15:44:08 -0300 >> > Eduardo Habkost wrote: >> > >> > > On Fri, Oct 19, 2018 at 03:12:31PM +0100, Peter Maydell wrote: >> > > > On 18 October 2018 at 21:03, Eduardo Habkost >> > > > wrote: >> > > > > The following changes since commit >> > > > > 09558375a634e17cea6cfbfec883ac2376d2dc7f: >> > > > > >> > > > > Merge remote-tracking branch >> > > > > 'remotes/pmaydell/tags/pull-target-arm-20181016-1' into staging >> > > > > (2018-10-16 17:42:56 +0100) >> > > > > >> > > > > are available in the Git repository at: >> > > > > >> > > > > git://github.com/ehabkost/qemu.git tags/machine-next-pull-request >> > > > > >> > > > > for you to fetch changes up to >> > > > > 6d8e1bcc7dd5e819ce81e6a87fffe23e39c700cc: >> > > > > >> > > > > numa: Clean up error reporting in parse_numa() (2018-10-17 >> > > > > 16:33:40 -0300) >> > > > > >> > > > > >> > > > > Machine queue, 2018-10-18 >> > > > > >> > > > > * sysbus init/realize cleanups >> > > > > (Cédric Le Goater, Philippe Mathieu-Daudé) >> > > > > * memory-device refactoring (David Hildenbrand) >> > > > > * -smp: deprecate incorrect CPUs topology (Igor Mammedov) >> > > > > * -numa parsing cleanups (Markus Armbruster) >> > > > > * Fix hostmem-file memory leak (Zhang Yi) >> > > > > * Typo fix (Li Qiang) >> > > > > >> > > > > >> > > > > >> > > > >> > > > Hi. This had some problems in merge testing, I'm afraid: >> > > > >> > > > On aarch64 host, warnings running tests/cpu-plug-test for i386 and >> > > > s390 targets: >> > > > >> > > > TEST: tests/cpu-plug-test... (pid=12602) >> > > > /i386/cpu-plug/pc-i440fx-3.0/cpu-add/1x3x2&maxcpus=12: >> > > > qemu-system-i386: warning: Invalid CPU topology deprecated: sockets >> > > > (1) * cores (3) * threads (2) != maxcpus (12) >> > > [...] >> > > > >> > > > (plus similar ppc64, x86_64 targets) >> > > >> > > Ouch. Apologies. >> > > >> > > Can we please do something make sure "make check" will fail on >> > > these cases? I'd like to be able to trust CI systems like >> > > travis-ci. >> > > >> > >> > we probably don't want make check fail on warning. >> >> I disagree. If a warning is blocking a pull request from being >> merged, it must make CI systems fail too. Otherwise we're >> defeating the purpose of CI systems. > > When we deprecate options we are bound to trigger warning which are not errors > and are meant to be there until deprecated options are removed/tested by make > check. > So what would you suggest to do wrt tests that use deprecated features, > drop testing for it? We commonly suppress the warning when testing. Search for 'if (qtest_enabled())'. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] util: Fix typo vcups -> vcpus
Signed-off-by: Martin Kletzander --- Pushed as trivial src/util/virnuma.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/virnuma.h b/src/util/virnuma.h index a3ffb6d6c7c9..edc206100f78 100644 --- a/src/util/virnuma.h +++ b/src/util/virnuma.h @@ -27,7 +27,7 @@ # include "virutil.h" -char *virNumaGetAutoPlacementAdvice(unsigned short vcups, +char *virNumaGetAutoPlacementAdvice(unsigned short vcpus, unsigned long long balloon); int virNumaSetupMemoryPolicy(virDomainNumatuneMemMode mode, -- 2.19.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] BugFix - Libvirt Ruby Binding Memory Stats Val Method
Hi libvirt comuninty’s developers. I will try the fast explain. We’re working on kvm for a project and we tried get current machine’s memory usages. The code we tried to use for this operation is as shown in the below. irb(main):002:0> conn = Libvirt::open("qemu:///system")=> #irb(main):003:0> domain = conn.lookup_domain_by_name("2_2").memory_stats=> [#, #]irb(main):004:0> domain.first.valTraceback (most recent call last):16: from /root/.rbenv/versions/2.5.1/bin/bundle:23:in `load'15: from /root/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.6/exe/bundle:22:in `'14: from /root/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.6/lib/bundler/friendly_errors.rb:124:in `with_friendly_errors'13: from /root/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.6/exe/bundle:30:in `block in '12: from /root/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.6/lib/bundler/cli.rb:18:in `start'11: from /root/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.6/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start'10: from /root/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.6/lib/bundler/cli.rb:27:in `dispatch'9: from /root/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.6/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'8: from /root/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.6/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'7: from /root/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.6/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'6: from /root/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.6/lib/bundler/cli.rb:424:in `exec'5: from /root/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.6/lib/bundler/cli/exec.rb:28:in `run'4: from /root/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.6/lib/bundler/cli/exec.rb:74:in `kernel_load'3: from /root/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.6/lib/bundler/cli/exec.rb:74:in `load'2: from bin/console:13:in `'1: from (irb):4NoMethodError (undefined method `val' for #)Did you mean? valueirb(main):005:0> domain.first.value=> nil As you see, when we want the use memory_usage’s val parameter but Libvirt throwing up undefined method error. Our fix proffer is memory_stats function's return @val parameter enough be update as shown in the below.diff --git a/ext/libvirt/domain.c b/ext/libvirt/domain.cindex d665907..d458e98 100644--- a/ext/libvirt/domain.c+++ b/ext/libvirt/domain.c@@ -675,7 +675,7 @@ static VALUE libvirt_domain_memory_stats(int argc, VALUE *argv, VALUE d)for (i = 0; i < r; i++) {tmp = rb_class_new_instance(0, NULL, c_domain_memory_stats);rb_iv_set(tmp, "@tag", INT2NUM(stats[i].tag));- rb_iv_set(tmp, "@val", ULL2NUM(stats[i].val));+ rb_iv_set(tmp, "@value", ULL2NUM(stats[i].val)); rb_ary_store(result, i, tmp);} After that change memory_stats method’s val error will solved as shown in the below. irb(main):002:0> conn = Libvirt::open("qemu:///system")=> #irb(main):003:0> memory_stats = conn.lookup_domain_by_name("2_2").memory_stats=> [#, #]irb(main):004:0> memory_stats.first.value=> 1048576-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 1/2] syntax-check: revert indentation checks
On 10/19/2018 10:03 AM, Erik Skultety wrote: > On Fri, Oct 05, 2018 at 01:48:06PM +0200, Ján Tomko wrote: >> Recent patches added indentation checks that discovered some cosmetic >> issues at the cost of making this check last as long as the rest of >> syntax-check combined on my system. Also, they're moving closer >> to us implementing yet another C parser (docs/apibuild.py being the >> other one). >> >> Revert the following commits: >> commit 11e1f11dd34f2688169c63c13ea8d99a64724369 >> syntax-check: Check for incorrect indentation in function body >> commit 2585a79e32e8b0d994ab35fd7c641eb9b96632e3 >> build-aux:check-spacing: Introduce a new rule to check misaligned stuff >> in parenthesises >> commit a033182f042a07ffbd4b9a50418670778ceddbf3 >> build-aux:check-spacing: Add wrapper function of CheckCurlyBrackets >> commit 6225626b6f0a4817d1f17de0bc5200c5d7986a3e >> build-aux:check-spacing: Add wrapper function of CheckWhiteSpaces >> commit c3875129d9bd094ffe90d54fbec86624ae88c40b >> build-aux:check-spacing: Add wrapper function of KillComments >> commit e995904c5691be3c21f4c6dbc1f067fe0c8e8515 >> build-aux:check-spacing: Add wrapper function of CheckFunctionBody >> commit 11e1f11dd34f2688169c63c13ea8d99a64724369 >> syntax-check: Check for incorrect indentation in function body >> >> This brings the speed of the script to a tolerable level and lets it >> focus on the more visible issues. >> >> Signed-off-by: Ján Tomko > Reviewed-by: Erik Skultety > So what alternative do we have? Obviously, we fail at honoring our formatting rules. Having a check that would fail at `synax-check' time would help us. Okay, implementing new C parser might not be the best solution, but it's at least something. Michal -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 06/11] qemu: Add monitor functions to set IOThread params
On 10/19/2018 03:09 PM, John Ferlan wrote: > > > On 10/19/18 7:06 AM, Michal Privoznik wrote: >> On 10/07/2018 03:00 PM, John Ferlan wrote: >>> Add functions to set the IOThreadInfo param data for the live guest. >>> >>> Based on code originally posted by Pavel Hrdina , >>> but extracted into a separate patch. Note that qapi expects to receive >>> integer parameters rather than unsigned long long or unsigned int's. >>> QEMU does save the value in larger signed 64 bit values eventually. >>> >>> Signed-off-by: John Ferlan >>> --- >>> src/qemu/qemu_monitor.c | 19 +++ >>> src/qemu/qemu_monitor.h | 2 ++ >>> src/qemu/qemu_monitor_json.c | 33 + >>> src/qemu/qemu_monitor_json.h | 4 >>> 4 files changed, 58 insertions(+) >>> >>> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c >>> index 7f7013e115..a65d638ab8 100644 >>> --- a/src/qemu/qemu_monitor.c >>> +++ b/src/qemu/qemu_monitor.c >>> @@ -4135,6 +4135,25 @@ qemuMonitorGetIOThreads(qemuMonitorPtr mon, >>> } >>> >>> >>> +/** >>> + * qemuMonitorSetIOThread: >>> + * @mon: Pointer to the monitor >>> + * @iothreadInfo: filled IOThread info with data >>> + * >>> + * Alter the specified IOThread's IOThreadInfo values. >>> + */ >>> +int >>> +qemuMonitorSetIOThread(qemuMonitorPtr mon, >>> + qemuMonitorIOThreadInfoPtr iothreadInfo) >>> +{ >>> +VIR_DEBUG("iothread=%p", iothreadInfo); >>> + >>> +QEMU_CHECK_MONITOR(mon); >>> + >>> +return qemuMonitorJSONSetIOThread(mon, iothreadInfo); >>> +} >>> + >>> + >>> /** >>> * qemuMonitorGetMemoryDeviceInfo: >>> * @mon: pointer to the monitor >>> diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h >>> index c2991e2b16..ef71fc6448 100644 >>> --- a/src/qemu/qemu_monitor.h >>> +++ b/src/qemu/qemu_monitor.h >>> @@ -1123,6 +1123,8 @@ struct _qemuMonitorIOThreadInfo { >>> }; >>> int qemuMonitorGetIOThreads(qemuMonitorPtr mon, >>> qemuMonitorIOThreadInfoPtr **iothreads); >>> +int qemuMonitorSetIOThread(qemuMonitorPtr mon, >>> + qemuMonitorIOThreadInfoPtr iothreadInfo); >>> >>> typedef struct _qemuMonitorMemoryDeviceInfo qemuMonitorMemoryDeviceInfo; >>> typedef qemuMonitorMemoryDeviceInfo *qemuMonitorMemoryDeviceInfoPtr; >>> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c >>> index 2e92984b44..bb1d62b844 100644 >>> --- a/src/qemu/qemu_monitor_json.c >>> +++ b/src/qemu/qemu_monitor_json.c >>> @@ -7474,6 +7474,39 @@ qemuMonitorJSONGetIOThreads(qemuMonitorPtr mon, >>> } >>> >>> >>> +int >>> +qemuMonitorJSONSetIOThread(qemuMonitorPtr mon, >>> + qemuMonitorIOThreadInfoPtr iothreadInfo) >>> +{ >>> +int ret = -1; >>> +char *path = NULL; >>> +qemuMonitorJSONObjectProperty prop; >>> + >>> +if (virAsprintf(&path, "/objects/iothread%u", >>> +iothreadInfo->iothread_id) < 0) >>> +goto cleanup; >>> + >>> +#define VIR_IOTHREAD_SET_PROP(propName, propVal) \ >>> +memset(&prop, 0, sizeof(qemuMonitorJSONObjectProperty)); \ >>> +prop.type = QEMU_MONITOR_OBJECT_PROPERTY_INT; \ >>> +prop.val.iv = propVal; \ >>> +if (qemuMonitorJSONSetObjectProperty(mon, path, propName, &prop) < 0) \ >>> +goto cleanup; >>> + >>> +VIR_IOTHREAD_SET_PROP("poll-max-ns", iothreadInfo->poll_max_ns) >>> +VIR_IOTHREAD_SET_PROP("poll-grow", iothreadInfo->poll_grow) >>> +VIR_IOTHREAD_SET_PROP("poll-shrink", iothreadInfo->poll_shrink) >> >> So this is all or nothing approach. All values are set - even though >> user might request through public API to change just one. I don't think >> it is a good design. Either we need a monitor API that changes just one >> value and call it for every typed parameter that user sends to us, or >> public API implementation must copy the old values into this struct >> (even though it would be ugly). >> >> Michal >> > > Fair complaint - I tried to reuse as much as possible from the initial > series so that I didn't "waste" time implementing something that in the > long run wasn't desired. Originally there were lots of checks about what > was or wasn't set - I just took the path of least resistance. > > It should be simple to add flag for each to determine which was set > before setting them in the object path. > > IOW: > > #define VIR_IOTHREAD_SET_PROP(propName, propVal) \ > if (iothreadInfo->set_##propVal) { \ This will fly iff zero value can't be set on the monitor. I have no idea whether it can or can not. If it can be set, then we have to go with something more clever. Michal -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [Qemu-devel] [PULL 00/45] Machine queue, 2018-10-18
On Fri, 19 Oct 2018 17:23:21 -0300 Eduardo Habkost wrote: > On Fri, Oct 19, 2018 at 09:53:45PM +0200, Igor Mammedov wrote: > > On Fri, 19 Oct 2018 15:44:08 -0300 > > Eduardo Habkost wrote: > > > > > On Fri, Oct 19, 2018 at 03:12:31PM +0100, Peter Maydell wrote: > > > > On 18 October 2018 at 21:03, Eduardo Habkost > > > > wrote: > > > > > The following changes since commit > > > > > 09558375a634e17cea6cfbfec883ac2376d2dc7f: > > > > > > > > > > Merge remote-tracking branch > > > > > 'remotes/pmaydell/tags/pull-target-arm-20181016-1' into staging > > > > > (2018-10-16 17:42:56 +0100) > > > > > > > > > > are available in the Git repository at: > > > > > > > > > > git://github.com/ehabkost/qemu.git tags/machine-next-pull-request > > > > > > > > > > for you to fetch changes up to > > > > > 6d8e1bcc7dd5e819ce81e6a87fffe23e39c700cc: > > > > > > > > > > numa: Clean up error reporting in parse_numa() (2018-10-17 16:33:40 > > > > > -0300) > > > > > > > > > > > > > > > Machine queue, 2018-10-18 > > > > > > > > > > * sysbus init/realize cleanups > > > > > (Cédric Le Goater, Philippe Mathieu-Daudé) > > > > > * memory-device refactoring (David Hildenbrand) > > > > > * -smp: deprecate incorrect CPUs topology (Igor Mammedov) > > > > > * -numa parsing cleanups (Markus Armbruster) > > > > > * Fix hostmem-file memory leak (Zhang Yi) > > > > > * Typo fix (Li Qiang) > > > > > > > > > > > > > > > > > > > > > > > Hi. This had some problems in merge testing, I'm afraid: > > > > > > > > On aarch64 host, warnings running tests/cpu-plug-test for i386 and s390 > > > > targets: > > > > > > > > TEST: tests/cpu-plug-test... (pid=12602) > > > > /i386/cpu-plug/pc-i440fx-3.0/cpu-add/1x3x2&maxcpus=12: > > > > qemu-system-i386: warning: Invalid CPU topology deprecated: sockets > > > > (1) * cores (3) * threads (2) != maxcpus (12) > > > [...] > > > > > > > > (plus similar ppc64, x86_64 targets) > > > > > > Ouch. Apologies. > > > > > > Can we please do something make sure "make check" will fail on > > > these cases? I'd like to be able to trust CI systems like > > > travis-ci. > > > > > > > we probably don't want make check fail on warning. > > I disagree. If a warning is blocking a pull request from being > merged, it must make CI systems fail too. Otherwise we're > defeating the purpose of CI systems. When we deprecate options we are bound to trigger warning which are not errors and are meant to be there until deprecated options are removed/tested by make check. So what would you suggest to do wrt tests that use deprecated features, drop testing for it? [...] -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 2/3] qemu: vfio-ap device support
On 10/19/18 1:56 PM, Thomas Huth wrote: On 2018-10-18 16:54, Boris Fiuczynski wrote: Adjusting domain format documentation, adding device address support and adding command line generation for vfio-ap. Since only one mediated hostdev with model vfio-ap is supported a check disallows to define domains with more than one such hostdev device. Signed-off-by: Boris Fiuczynski Reviewed-by: Bjoern Walk [...] +static int +virDomainDefPostParseHostdev(virDomainDefPtr def) +{ +size_t i; +bool vfioap_found = false; + +/* verify settings of hostdevs vfio-ap */ +for (i = 0; i < def->nhostdevs; i++) { +virDomainHostdevDefPtr hostdev = def->hostdevs[i]; + +if (virHostdevIsMdevDevice(hostdev) && +hostdev->source.subsys.u.mdev.model == VIR_MDEV_MODEL_TYPE_VFIO_AP) { +if (vfioap_found) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Only one hostdev of model vfio-ap is " + "support")); s/support/supported/ ? It should be "supported"... :-) I hope whoever is going to push this series can fix it before pushing. If not please let me know and I am going to send a v3. Thomas, thanks for your review. Thomas -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list -- Mit freundlichen Grüßen/Kind regards Boris Fiuczynski IBM Deutschland Research & Development GmbH Vorsitzender des Aufsichtsrats: Martina Köderitz Geschäftsführung: Dirk Wittkopp Sitz der Gesellschaft: Böblingen Registergericht: Amtsgericht Stuttgart, HRB 243294 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 14/18] util: Add function for checking if monitor is running
Check whether monitor is running by checking the monitor's PIDs status. Monitor is looked as running normally if the vcpu PID list matches with the content of monitor's 'tasks' file. Signed-off-by: Wang Huaqiang --- src/libvirt_private.syms | 1 + src/util/virresctrl.c| 102 ++- src/util/virresctrl.h| 3 ++ 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d59ac86..91801ed 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2684,6 +2684,7 @@ virResctrlMonitorAddPID; virResctrlMonitorCreate; virResctrlMonitorDeterminePath; virResctrlMonitorGetID; +virResctrlMonitorIsRunning; virResctrlMonitorNew; virResctrlMonitorRemove; virResctrlMonitorSetAlloc; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index b0205bc..fa3e6e9 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -359,6 +359,9 @@ struct _virResctrlMonitor { /* libvirt-generated path in /sys/fs/resctrl for this particular * monitor */ char *path; +/* Tracking the tasks' PID associated with this monitor */ +pid_t *pids; +size_t npids; }; @@ -418,6 +421,7 @@ virResctrlMonitorDispose(void *obj) virObjectUnref(monitor->alloc); VIR_FREE(monitor->id); VIR_FREE(monitor->path); +VIR_FREE(monitor->pids); } @@ -2540,7 +2544,20 @@ int virResctrlMonitorAddPID(virResctrlMonitorPtr monitor, pid_t pid) { -return virResctrlAddPID(monitor->path, pid); +size_t i = 0; + +if (virResctrlAddPID(monitor->path, pid) < 0) +return -1; + +for (i = 0; i < monitor->npids; i++) { +if (pid == monitor->pids[i]) +return 0; +} + +if (VIR_APPEND_ELEMENT(monitor->pids, monitor->npids, pid) < 0) +return -1; + +return 0; } @@ -2613,3 +2630,86 @@ virResctrlMonitorRemove(virResctrlMonitorPtr monitor) return ret; } + + +static int +virResctrlPIDSorter(const void *pida, const void *pidb) +{ +return *(pid_t*)pida - *(pid_t*)pidb; +} + + +bool +virResctrlMonitorIsRunning(virResctrlMonitorPtr monitor) +{ +char *pidstr = NULL; +char **spids = NULL; +size_t nspids = 0; +pid_t *pids = NULL; +size_t npids = 0; +size_t i = 0; +int rv = -1; +bool ret = false; + +/* path is not determined yet, monitor is not running*/ +if (!monitor->path) +return false; + +/* No vcpu PID filled, regard monitor as not running */ +if (monitor->npids == 0) +return false; + +/* If no 'tasks' file found, underlying resctrl directory is not + * ready, regard monitor as not running */ +rv = virFileReadValueString(&pidstr, "%s/tasks", monitor->path); +if (rv < 0) +goto cleanup; + +/* no PID in task file, monitor is not running */ +if (!*pidstr) +goto cleanup; + +/* The tracking monitor PID list is not identical to the + * list in current resctrl directory. monitor is corrupted, + * report error and un-running state */ +spids = virStringSplitCount(pidstr, "\n", 0, &nspids); +if (nspids != monitor->npids) { +VIR_ERROR(_("Monitor %s PID list mismatch in length"), monitor->path); +goto cleanup; +} + +for (i = 0; i < nspids; i++) { +unsigned int val = 0; +pid_t pid = 0; + +if (virStrToLong_uip(spids[i], NULL, 0, &val) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Monitor %s failed in parse PID list"), + monitor->path); +goto cleanup; +} + +pid = (pid_t)val; + +if (VIR_APPEND_ELEMENT(pids, npids, pid) < 0) +goto cleanup; +} + +qsort(pids, npids, sizeof(pid_t), virResctrlPIDSorter); +qsort(monitor->pids, monitor->npids, sizeof(pid_t), virResctrlPIDSorter); + +for (i = 0; i < monitor->npids; i++) { +if (monitor->pids[i] != pids[i]) { +VIR_ERROR(_("Monitor %s PID list corrupted"), monitor->path); +goto cleanup; +} +} + +ret = true; + cleanup: +virStringListFree(spids); +VIR_FREE(pids); +VIR_FREE(pidstr); + +return ret; +} diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 804d6f5..8d8fdc2 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -219,4 +219,7 @@ virResctrlMonitorSetAlloc(virResctrlMonitorPtr monitor, int virResctrlMonitorRemove(virResctrlMonitorPtr monitor); + +bool +virResctrlMonitorIsRunning(virResctrlMonitorPtr monitor); #endif /* __VIR_RESCTRL_H__ */ -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 18/18] qemu: Setting up vcpu and adding pids to resctrl monitor groups during reconnection
Invoking qemuProcessSetupVcpus in process of VM reconnection. The vcpu pid information need to be refilled to resctrl monitor after a VM reconnection./ Signed-off-by: Wang Huaqiang --- src/qemu/qemu_process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index fba4fb4..ed0330b 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -8008,6 +8008,9 @@ qemuProcessReconnect(void *opaque) } } +if (qemuProcessSetupVcpus(obj) < 0) +goto error; + /* update domain state XML with possibly updated state in virDomainObj */ if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, obj, driver->caps) < 0) goto error; -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 09/18] util: Add more interfaces for resctrl monitor
Add interfaces monitor group to support operations such as add PID, set ID, remove group ... etc. Signed-off-by: Wang Huaqiang --- src/libvirt_private.syms | 5 + src/util/virresctrl.c| 47 +++ src/util/virresctrl.h| 14 ++ 3 files changed, 66 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index a878083..d59ac86 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2683,7 +2683,12 @@ virResctrlInfoNew; virResctrlMonitorAddPID; virResctrlMonitorCreate; virResctrlMonitorDeterminePath; +virResctrlMonitorGetID; virResctrlMonitorNew; +virResctrlMonitorRemove; +virResctrlMonitorSetAlloc; +virResctrlMonitorSetID; + # util/virrotatingfile.h diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 9f42065..b0205bc 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -2566,3 +2566,50 @@ virResctrlMonitorCreate(virResctrlMonitorPtr monitor, virResctrlUnlock(lockfd); return ret; } + + +int +virResctrlMonitorSetID(virResctrlMonitorPtr monitor, + const char *id) +{ +if (!id) { +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Resctrl monitor 'id' cannot be NULL")); +return -1; +} + +return VIR_STRDUP(monitor->id, id); +} + + +const char * +virResctrlMonitorGetID(virResctrlMonitorPtr monitor) +{ +return monitor->id; +} + + +void +virResctrlMonitorSetAlloc(virResctrlMonitorPtr monitor, + virResctrlAllocPtr alloc) +{ +monitor->alloc = virObjectRef(alloc); +} + + +int +virResctrlMonitorRemove(virResctrlMonitorPtr monitor) +{ +int ret = 0; + +if (!monitor->path) +return 0; + +VIR_DEBUG("Removing resctrl monitor%s", monitor->path); +if (rmdir(monitor->path) != 0 && errno != ENOENT) { +ret = -errno; +VIR_ERROR(_("Unable to remove %s (%d)"), monitor->path, errno); +} + +return ret; +} diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 76e40a2..804d6f5 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -205,4 +205,18 @@ virResctrlMonitorAddPID(virResctrlMonitorPtr monitor, int virResctrlMonitorCreate(virResctrlMonitorPtr monitor, const char *machinename); + +int +virResctrlMonitorSetID(virResctrlMonitorPtr monitor, + const char *id); + +const char * +virResctrlMonitorGetID(virResctrlMonitorPtr monitor); + +void +virResctrlMonitorSetAlloc(virResctrlMonitorPtr monitor, + virResctrlAllocPtr alloc); + +int +virResctrlMonitorRemove(virResctrlMonitorPtr monitor); #endif /* __VIR_RESCTRL_H__ */ -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 12/18] conf: Introduce cache monitor element in cachetune
Introducing element under to represent a cache monitor. Signed-off-by: Wang Huaqiang --- docs/formatdomain.html.in | 26 +++ docs/schemas/domaincommon.rng | 10 + src/conf/domain_conf.c | 234 - src/conf/domain_conf.h | 11 + tests/genericxml2xmlindata/cachetune-cdp.xml | 3 + .../cachetune-colliding-monitor.xml| 30 +++ tests/genericxml2xmlindata/cachetune-small.xml | 7 + tests/genericxml2xmltest.c | 2 + 8 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 tests/genericxml2xmlindata/cachetune-colliding-monitor.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index b1651e3..2fd665c 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -759,6 +759,12 @@+ + + + + + @@ -978,6 +984,26 @@ + monitor + +The optional element monitor creates the cache +monitor(s) for current cache allocation and has the following +required attributes: + + level + +Host cache level the monitor belongs to. + + vcpus + +vCPU list the monitor applies to. A monitor's vCPU list +can only be the member(s) of the vCPU list of associating +allocation. The default monitor has the same vCPU list as the +associating allocation. For non-default monitors, there +are no vCPU overlap permitted. + + + diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 5c533d6..7ce49d3 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -981,6 +981,16 @@ + + + + + + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index a068d4d..01f795f 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2955,13 +2955,31 @@ virDomainLoaderDefFree(virDomainLoaderDefPtr loader) static void +virDomainResctrlMonDefFree(virDomainResctrlMonDefPtr domresmon) +{ +if (!domresmon) +return; + +virBitmapFree(domresmon->vcpus); +virObjectUnref(domresmon->instance); +VIR_FREE(domresmon); +} + + +static void virDomainResctrlDefFree(virDomainResctrlDefPtr resctrl) { +size_t i = 0; + if (!resctrl) return; +for (i = 0; i < resctrl->nmonitors; i++) +virDomainResctrlMonDefFree(resctrl->monitors[i]); + virObjectUnref(resctrl->alloc); virBitmapFree(resctrl->vcpus); +VIR_FREE(resctrl->monitors); VIR_FREE(resctrl); } @@ -18920,6 +18938,177 @@ virDomainCachetuneDefParseCache(xmlXPathContextPtr ctxt, } +/* Checking if the monitor's vcpus is conflicted with existing allocation + * and monitors. + * + * Returns 1 if @vcpus equals to @resctrl->vcpus, then the monitor will + * share the underlying resctrl group with @resctrl->alloc. Returns - 1 + * if any conflict found. Returns 0 if no conflict and @vcpus is not equal + * to @resctrl->vcpus. + */ +static int +virDomainResctrlMonValidateVcpus(virDomainResctrlDefPtr resctrl, +virBitmapPtr vcpus) +{ +size_t i = 0; +int vcpu = -1; +size_t mons_same_alloc_vcpus = 0; + +if (virBitmapIsAllClear(vcpus)) { +virReportError(VIR_ERR_INVALID_ARG, "%s", + _("vcpus is empty")); +return -1; +} + +while ((vcpu = virBitmapNextSetBit(vcpus, vcpu)) >= 0) { +if (!virBitmapIsBitSet(resctrl->vcpus, vcpu)) { +virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Monitor vcpus conflicts with allocation")); +return -1; +} +} + +if (virBitmapEqual(vcpus, resctrl->vcpus)) +return 1; + +for (i = 0; i < resctrl->nmonitors; i++) { +if (virBitmapEqual(resctrl->vcpus, resctrl->monitors[i]->vcpus)) { +mons_same_alloc_vcpus++; +continue; +} + +if (virBitmapOverlaps(vcpus, resctrl->monitors[i]->vcpus)) { +virReportError(VIR_ERR_INVALID_ARG, "%s", +
[libvirt] [PATCHv7 08/18] util: Add interface for creating monitor group
Add interface for creating the resource monitoring group according to '@virResctrlMonitor->path'. Signed-off-by: Wang Huaqiang --- src/libvirt_private.syms | 1 + src/util/virresctrl.c| 24 src/util/virresctrl.h| 4 3 files changed, 29 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e175c8b..a878083 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2681,6 +2681,7 @@ virResctrlInfoGetMonitorPrefix; virResctrlInfoMonFree; virResctrlInfoNew; virResctrlMonitorAddPID; +virResctrlMonitorCreate; virResctrlMonitorDeterminePath; virResctrlMonitorNew; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 5b984d9..9f42065 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -2542,3 +2542,27 @@ virResctrlMonitorAddPID(virResctrlMonitorPtr monitor, { return virResctrlAddPID(monitor->path, pid); } + + +int +virResctrlMonitorCreate(virResctrlMonitorPtr monitor, +const char *machinename) +{ +int lockfd = -1; +int ret = -1; + +if (!monitor) +return 0; + +if (virResctrlMonitorDeterminePath(monitor, machinename) < 0) +return -1; + +lockfd = virResctrlLockWrite(); +if (lockfd < 0) +return -1; + +ret = virResctrlCreateGroupPath(monitor->path); + +virResctrlUnlock(lockfd); +return ret; +} diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 52d283a..76e40a2 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -201,4 +201,8 @@ virResctrlMonitorDeterminePath(virResctrlMonitorPtr monitor, int virResctrlMonitorAddPID(virResctrlMonitorPtr monitor, pid_t pid); + +int +virResctrlMonitorCreate(virResctrlMonitorPtr monitor, +const char *machinename); #endif /* __VIR_RESCTRL_H__ */ -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 16/18] qemu: refactor qemuDomainGetStatsCpu
Refactoring qemuDomainGetStatsCpu, make it possible to add more CPU statistics. Signed-off-by: Wang Huaqiang --- src/qemu/qemu_driver.c | 45 ++--- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a52e249..12a5f8f 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19711,30 +19711,29 @@ qemuDomainGetStatsCpu(virQEMUDriverPtr driver ATTRIBUTE_UNUSED, 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; +if (priv->cgroup) { +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; +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; } -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 10/18] conf: Remove virDomainResctrlAppend and introduce virDomainResctrlNew
Introduced virDomainResctrlNew to do the most part of virDomainResctrlAppend and move the operation of appending resctrl to @def->resctrls out of function. Rather than rely on virDomainResctrlAppend to perform the allocation, move the onus to the caller and make use of virBitmapNewCopy for @vcpus and virObjectRef for @alloc, thus removing the need to set each to NULL after the call. Signed-off-by: Wang Huaqiang --- src/conf/domain_conf.c | 60 +- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e8e0adc..39bd396 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -18920,26 +18920,22 @@ virDomainCachetuneDefParseCache(xmlXPathContextPtr ctxt, } -static int -virDomainResctrlAppend(virDomainDefPtr def, - xmlNodePtr node, - virResctrlAllocPtr alloc, - virBitmapPtr vcpus, - unsigned int flags) +static virDomainResctrlDefPtr +virDomainResctrlNew(xmlNodePtr node, +virResctrlAllocPtr *alloc, +virBitmapPtr *vcpus, +unsigned int flags) { char *vcpus_str = NULL; char *alloc_id = NULL; -virDomainResctrlDefPtr tmp_resctrl = NULL; -int ret = -1; - -if (VIR_ALLOC(tmp_resctrl) < 0) -goto cleanup; +virDomainResctrlDefPtr resctrl = NULL; +virDomainResctrlDefPtr ret = NULL; /* We need to format it back because we need to be consistent in the naming * even when users specify some "sub-optimal" string there. */ -vcpus_str = virBitmapFormat(vcpus); +vcpus_str = virBitmapFormat(*vcpus); if (!vcpus_str) -goto cleanup; +return NULL; if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) alloc_id = virXMLPropString(node, "id"); @@ -18954,18 +18950,23 @@ virDomainResctrlAppend(virDomainDefPtr def, goto cleanup; } -if (virResctrlAllocSetID(alloc, alloc_id) < 0) +if (virResctrlAllocSetID(*alloc, alloc_id) < 0) goto cleanup; -tmp_resctrl->vcpus = vcpus; -tmp_resctrl->alloc = alloc; +if (VIR_ALLOC(resctrl) < 0) +goto cleanup; -if (VIR_APPEND_ELEMENT(def->resctrls, def->nresctrls, tmp_resctrl) < 0) +if (!(resctrl->vcpus = virBitmapNewCopy(*vcpus))) { +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to copy 'vcpus'")); goto cleanup; +} -ret = 0; +resctrl->alloc = virObjectRef(*alloc); + +VIR_STEAL_PTR(ret, resctrl); cleanup: -virDomainResctrlDefFree(tmp_resctrl); +virDomainResctrlDefFree(resctrl); VIR_FREE(alloc_id); VIR_FREE(vcpus_str); return ret; @@ -18982,6 +18983,7 @@ virDomainCachetuneDefParse(virDomainDefPtr def, xmlNodePtr *nodes = NULL; virBitmapPtr vcpus = NULL; virResctrlAllocPtr alloc = NULL; +virDomainResctrlDefPtr resctrl = NULL; ssize_t i = 0; int n; int ret = -1; @@ -19025,14 +19027,17 @@ virDomainCachetuneDefParse(virDomainDefPtr def, goto cleanup; } -if (virDomainResctrlAppend(def, node, alloc, vcpus, flags) < 0) +resctrl = virDomainResctrlNew(node, &alloc, &vcpus, flags); +if (!resctrl) +goto cleanup; + +if (VIR_APPEND_ELEMENT(def->resctrls, def->nresctrls, resctrl) < 0) goto cleanup; -vcpus = NULL; -alloc = NULL; ret = 0; cleanup: ctxt->node = oldnode; +virDomainResctrlDefFree(resctrl); virObjectUnref(alloc); virBitmapFree(vcpus); VIR_FREE(nodes); @@ -19190,6 +19195,8 @@ virDomainMemorytuneDefParse(virDomainDefPtr def, xmlNodePtr *nodes = NULL; virBitmapPtr vcpus = NULL; virResctrlAllocPtr alloc = NULL; +virDomainResctrlDefPtr resctrl = NULL; + ssize_t i = 0; int n; int ret = -1; @@ -19234,15 +19241,18 @@ virDomainMemorytuneDefParse(virDomainDefPtr def, * just update the existing alloc information, which is done in above * virDomainMemorytuneDefParseMemory */ if (new_alloc) { -if (virDomainResctrlAppend(def, node, alloc, vcpus, flags) < 0) +resctrl = virDomainResctrlNew(node, &alloc, &vcpus, flags); +if (!resctrl) +goto cleanup; + +if (VIR_APPEND_ELEMENT(def->resctrls, def->nresctrls, resctrl) < 0) goto cleanup; -vcpus = NULL; -alloc = NULL; } ret = 0; cleanup: ctxt->node = oldnode; +virDomainResctrlDefFree(resctrl); virObjectUnref(alloc); virBitmapFree(vcpus); VIR_FREE(nodes); -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 11/18] conf: move virResctrlAllocIsEmpty to a place a litter lower
This refactor allows to add some code between virDomainResctrlNew and virResctrlAllocIsEmpty to extend the scope of resctrl. Signed-off-by: Wang Huaqiang --- src/conf/domain_conf.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 39bd396..a068d4d 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -19022,15 +19022,15 @@ virDomainCachetuneDefParse(virDomainDefPtr def, goto cleanup; } +resctrl = virDomainResctrlNew(node, &alloc, &vcpus, flags); +if (!resctrl) +goto cleanup; + if (virResctrlAllocIsEmpty(alloc)) { ret = 0; goto cleanup; } -resctrl = virDomainResctrlNew(node, &alloc, &vcpus, flags); -if (!resctrl) -goto cleanup; - if (VIR_APPEND_ELEMENT(def->resctrls, def->nresctrls, resctrl) < 0) goto cleanup; -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 13/18] qemu: enable resctrl monitor in qemu
Add functions for creating, destroying, reconnecting resctrl monitor in qemu according to the configuration in domain XML. Signed-off-by: Wang Huaqiang --- src/qemu/qemu_process.c | 66 - 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index e9c7618..fba4fb4 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2611,10 +2611,21 @@ qemuProcessResctrlCreate(virQEMUDriverPtr driver, return -1; for (i = 0; i < vm->def->nresctrls; i++) { +size_t j = 0; if (virResctrlAllocCreate(caps->host.resctrl, vm->def->resctrls[i]->alloc, priv->machineName) < 0) goto cleanup; + +for (j = 0; j < vm->def->resctrls[i]->nmonitors; j++) { +virDomainResctrlMonDefPtr mon = NULL; + +mon = vm->def->resctrls[i]->monitors[j]; +if (virResctrlMonitorCreate(mon->instance, +priv->machineName) < 0) +goto cleanup; + +} } ret = 0; @@ -5430,6 +5441,7 @@ qemuProcessSetupVcpu(virDomainObjPtr vm, { pid_t vcpupid = qemuDomainGetVcpuPid(vm, vcpuid); virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(vm->def, vcpuid); +virDomainResctrlMonDefPtr mon = NULL; size_t i = 0; if (qemuProcessSetupPid(vm, vcpupid, VIR_CGROUP_THREAD_VCPU, @@ -5440,11 +5452,42 @@ qemuProcessSetupVcpu(virDomainObjPtr vm, return -1; for (i = 0; i < vm->def->nresctrls; i++) { +size_t j = 0; virDomainResctrlDefPtr ct = vm->def->resctrls[i]; if (virBitmapIsBitSet(ct->vcpus, vcpuid)) { if (virResctrlAllocAddPID(ct->alloc, vcpupid) < 0) return -1; + +/* The order of invoking virResctrlMonitorAddPID matters, it is + * required to invoke this function first for monitor that has + * the same vcpus setting as the allocation in same def->resctrl. + * Otherwise, some other monitor's pid may be removed from its + * resource group's 'tasks' file.*/ +for (j = 0; j < vm->def->resctrls[i]->nmonitors; j++) { +mon = vm->def->resctrls[i]->monitors[j]; + +if (!virBitmapEqual(ct->vcpus, mon->vcpus)) +continue; + +if (virBitmapIsBitSet(mon->vcpus, vcpuid)) { +if (virResctrlMonitorAddPID(mon->instance, vcpupid) < 0) +return -1; +} +break; +} + +for (j = 0; j < vm->def->resctrls[i]->nmonitors; j++) { +mon = vm->def->resctrls[i]->monitors[j]; + +if (virBitmapEqual(ct->vcpus, mon->vcpus)) +continue; + +if (virBitmapIsBitSet(mon->vcpus, vcpuid)) { +if (virResctrlMonitorAddPID(mon->instance, vcpupid) < 0) +return -1; +} +} break; } } @@ -7207,8 +7250,18 @@ void qemuProcessStop(virQEMUDriverPtr driver, /* Remove resctrl allocation after cgroups are cleaned up which makes it * kind of safer (although removing the allocation should work even with * pids in tasks file */ -for (i = 0; i < vm->def->nresctrls; i++) +for (i = 0; i < vm->def->nresctrls; i++) { +size_t j = 0; + +for (j = 0; j < vm->def->resctrls[i]->nmonitors; j++) { +virDomainResctrlMonDefPtr mon = NULL; + +mon = vm->def->resctrls[i]->monitors[j]; +virResctrlMonitorRemove(mon->instance); +} + virResctrlAllocRemove(vm->def->resctrls[i]->alloc); +} qemuProcessRemoveDomainStatus(driver, vm); @@ -7939,9 +7992,20 @@ qemuProcessReconnect(void *opaque) goto error; for (i = 0; i < obj->def->nresctrls; i++) { +size_t j = 0; + if (virResctrlAllocDeterminePath(obj->def->resctrls[i]->alloc, priv->machineName) < 0) goto error; + +for (j = 0; j < obj->def->resctrls[i]->nmonitors; j++) { +virDomainResctrlMonDefPtr mon = NULL; + +mon = obj->def->resctrls[i]->monitors[j]; +if (virResctrlMonitorDeterminePath(mon->instance, + priv->machineName) < 0) +goto error; +} } /* update domain state XML with possibly updated state in virDomainObj */ -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 04/18] util: Add interface to determine monitor path
Add interface for resctrl monitor to determine the path. Signed-off-by: Wang Huaqiang --- src/libvirt_private.syms | 1 + src/util/virresctrl.c| 55 src/util/virresctrl.h| 5 - 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d2573c5..5235046 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2680,6 +2680,7 @@ virResctrlInfoGetCache; virResctrlInfoGetMonitorPrefix; virResctrlInfoMonFree; virResctrlInfoNew; +virResctrlMonitorDeterminePath; virResctrlMonitorNew; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 956aca8..1d0eb01 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -2462,3 +2462,58 @@ virResctrlMonitorNew(void) return virObjectNew(virResctrlMonitorClass); } + + +/* + * virResctrlMonitorDeterminePath + * + * @monitor: Pointer to a resctrl monitor + * @machinename: Name string of the VM + * + * Determines the directory path that the underlying resctrl group will be + * created with. + * + * A monitor represents a directory under resource control file system, + * its directory path could be the same path as @monitor->alloc, could be a + * path of directory under 'mon_groups' of @monitor->alloc, or a path of + * directory under '/sys/fs/resctrl/mon_groups' if @monitor->alloc is NULL. + * + * Returns 0 on success, -1 on error. + */ +int +virResctrlMonitorDeterminePath(virResctrlMonitorPtr monitor, + const char *machinename) +{ +VIR_AUTOFREE(char *) parentpath = NULL; + +if (!monitor) { +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Invalid resctrl monitor")); +return -1; +} + +if (monitor->path) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Resctrl monitor path is already set to '%s'"), + monitor->path); +return -1; +} + +if (monitor->id && monitor->alloc && monitor->alloc->id) { +if (STREQ(monitor->id, monitor->alloc->id)) { +if (VIR_STRDUP(monitor->path, monitor->alloc->path) < 0) +return -1; +return 0; +} +} + +if (virAsprintf(&parentpath, "%s/mon_groups", monitor->alloc->path) < 0) +return -1; + +monitor->path = virResctrlDeterminePath(parentpath, machinename, +monitor->id); +if (!monitor->path) +return -1; + +return 0; +} diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index eaa077d..baae554 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -191,7 +191,10 @@ virResctrlInfoGetMonitorPrefix(virResctrlInfoPtr resctrl, typedef struct _virResctrlMonitor virResctrlMonitor; typedef virResctrlMonitor *virResctrlMonitorPtr; - virResctrlMonitorPtr virResctrlMonitorNew(void); + +int +virResctrlMonitorDeterminePath(virResctrlMonitorPtr monitor, + const char *machinename); #endif /* __VIR_RESCTRL_H__ */ -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 05/18] util: Refactor code for adding PID to the resource group
The code of adding PID to the allocation could be reused, refactor it for later reuse. Signed-off-by: Wang Huaqiang --- src/util/virresctrl.c | 30 +++--- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 1d0eb01..5fc8772 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -2390,26 +2390,21 @@ virResctrlAllocCreate(virResctrlInfoPtr resctrl, } -int -virResctrlAllocAddPID(virResctrlAllocPtr alloc, - pid_t pid) +static int +virResctrlAddPID(const char *path, + pid_t pid) { char *tasks = NULL; char *pidstr = NULL; int ret = 0; -/* If the allocation is empty, then it is impossible to add a PID to - * allocation due to lacking of its 'tasks' file. Just return */ -if (virResctrlAllocIsEmpty(alloc)) -return 0; - -if (!alloc->path) { +if (!path) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot add pid to non-existing resctrl allocation")); + _("Cannot add pid to non-existing resctrl group")); return -1; } -if (virAsprintf(&tasks, "%s/tasks", alloc->path) < 0) +if (virAsprintf(&tasks, "%s/tasks", path) < 0) return -1; if (virAsprintf(&pidstr, "%lld", (long long int) pid) < 0) @@ -2431,6 +2426,19 @@ virResctrlAllocAddPID(virResctrlAllocPtr alloc, int +virResctrlAllocAddPID(virResctrlAllocPtr alloc, + pid_t pid) +{ +/* If allocation is empty, then no resctrl directory and the 'tasks' file + * exists, just return */ +if (virResctrlAllocIsEmpty(alloc)) +return 0; + +return virResctrlAddPID(alloc->path, pid); +} + + +int virResctrlAllocRemove(virResctrlAllocPtr alloc) { int ret = 0; -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 06/18] util: Add interface for adding PID to the monitor
Add interface for adding task PID to the monitor. Signed-off-by: Wang Huaqiang --- src/libvirt_private.syms | 1 + src/util/virresctrl.c| 8 src/util/virresctrl.h| 4 3 files changed, 13 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5235046..e175c8b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2680,6 +2680,7 @@ virResctrlInfoGetCache; virResctrlInfoGetMonitorPrefix; virResctrlInfoMonFree; virResctrlInfoNew; +virResctrlMonitorAddPID; virResctrlMonitorDeterminePath; virResctrlMonitorNew; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 5fc8772..93b5e70 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -2525,3 +2525,11 @@ virResctrlMonitorDeterminePath(virResctrlMonitorPtr monitor, return 0; } + + +int +virResctrlMonitorAddPID(virResctrlMonitorPtr monitor, +pid_t pid) +{ +return virResctrlAddPID(monitor->path, pid); +} diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index baae554..52d283a 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -197,4 +197,8 @@ virResctrlMonitorNew(void); int virResctrlMonitorDeterminePath(virResctrlMonitorPtr monitor, const char *machinename); + +int +virResctrlMonitorAddPID(virResctrlMonitorPtr monitor, +pid_t pid); #endif /* __VIR_RESCTRL_H__ */ -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 00/18] Introduce x86 Cache Monitoring Technology (CMT)
This series of patches and the series already been merged introduce the x86 Cache Monitoring Technology (CMT) to libvirt by interacting with kernel resource control (resctrl) interface. CMT is one of the Intel(R) x86 CPU feature which belongs to the Resource Director Technology (RDT). CMT reports the occupancy of the last level cache, which is shared by all CPU cores. In the v1 series, an original and complete feature for CMT was introduced The v2 and v3 patches address the feature for the host capability of CMT. v4 is addressing the feature for monitoring VM vcpu thread set cache occupancy and reporting it through a virsh command. We have serval discussion about the enabling of CMT, please refer to following links for the RFCs. RFCv3 https://www.redhat.com/archives/libvir-list/2018-August/msg01213.html RFCv2 https://www.redhat.com/archives/libvir-list/2018-July/msg00409.html https://www.redhat.com/archives/libvir-list/2018-July/msg01241.html RFCv1 https://www.redhat.com/archives/libvir-list/2018-June/msg00674.html And the merged commits are list as below, for host capability of CMT. 6af8417415508c31f8ce71234b573b4999f35980 8f6887998bf63594ae26e3db18d4d5896c5f2cb4 58fcee6f3a2b7e89c21c1fb4ec21429c31a0c5b8 12093f1feaf8f5023dcd9d65dff111022842183d a5d293c18831dcf69ec6195798387fbb70c9f461 1. About reason why CMT is necessary in libvirt? The perf events of 'CMT, MBML, MBMT' have been phased out since Linux kernel commit c39a0e2c8850f08249383f2425dbd8dbe4baad69, in libvirt the perf based cmt,mbm will not work with the latest linux kernel. These patches add CMT feature to libvirt through kernel resctrlfs interface. 2 Create cache monitoring group (cache monitor). The main interface for creating monitoring group is through XML file. The proposed configuration is like: + + In above XML, created 2 cache resctrl allocation groups and 2 resctrl monitoring groups. The changes of cache monitor will be effective in next booting of VM. 2 Show CMT result through command 'domstats' Adding the interface in qemu to report this information for resource monitor group through command 'virsh domstats --cpu-total'. Below is a typical output: # virsh domstats 1 --cpu-total Domain: 'ubuntu16.04-base' ... cpu.cache.monitor.count=2 cpu.cache.monitor.0.name=vcpus_1 cpu.cache.monitor.0.vcpus=1 cpu.cache.monitor.0.bank.count=2 cpu.cache.monitor.0.bank.0.id=0 cpu.cache.monitor.0.bank.0.bytes=4505600 cpu.cache.monitor.0.bank.1.id=1 cpu.cache.monitor.0.bank.1.bytes=5586944 cpu.cache.monitor.1.name=vcpus_4-6 cpu.cache.monitor.1.vcpus=4,5,6 cpu.cache.monitor.1.bank.count=2 cpu.cache.monitor.1.bank.0.id=0 cpu.cache.monitor.1.bank.0.bytes=17571840 cpu.cache.monitor.1.bank.1.id=1 cpu.cache.monitor.1.bank.1.bytes=29106176 Changes in v7: - Add several lines removed by mistake. Changes in v6: - Addressing John's review comments for v5. - Removed and cleaned the concepts of 'default allocation' and 'default monitor'. - qemu: virsh domstats --cpu-total output for CMT, add identifier 'monitor' for each itm. Changes in v5: - qemu: Setting up vcpu and adding pids to resctrl monitor groups during re-connection. - Add the document for domain configuration related to resctrl monitor. Changes in v4: v4 is addressing the feature for monitoring VM vcpu thread set cache occupancy and reporting it through a virsh command. - Introduced resctrl default allocation - Introduced resctrl monitor and default monitor Changes in v3: - Addressed John Ferlan's review. - Typo fixed. - Removed VIR_ENUM_DECL(virMonitor); Changes in v2: - Introduced MBM capability. - Capability layout changed * Moved from cahe to * Renamed to - Document for 'reuseThreshold' changed. - Introduced API virResctrlInfoGetMonitorPrefix - Added more tests, covering standalone CMT, fake new feature. - Creating CMT resource control group will be subsequent job. Wang Huaqiang (18): docs,util: Refactor schemas and virresctrl to support optional cache util: Introduce resctrl monitor for CMT util: Refactor code for determining allocation path util: Add interface to determine monitor path util: Refactor code for adding PID to the resource group util: Add interface for adding PID to the monitor util: Refactor code for creating resctrl group util: Add interface for creating monitor group util: Add more interfaces for resctrl monitor conf: Remove virDomainResctrlAppend and introduce virDomainResctrlNew conf: move virResctrlAllocIsEmpty to a place a litter lower conf: Introduce cache monitor element in cachetune qemu: enable resctrl monitor in qemu util: Add function for checking if monitor is running conf: Add 'id' to virDomainResctrlDef qemu: refactor qemuDomainGetStatsCpu qemu: Report cache occupancy (CMT) with domstats qemu:
[libvirt] [PATCHv7 02/18] util: Introduce resctrl monitor for CMT
Cache Monitoring Technology (aka CMT) provides the capability to report cache utilization information of system task. This patch introduces the concept of resctrl monitor through data structure virResctrlMonitor. Signed-off-by: Wang Huaqiang --- src/libvirt_private.syms | 1 + src/util/virresctrl.c| 79 src/util/virresctrl.h| 9 ++ 3 files changed, 83 insertions(+), 6 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 335210c..d2573c5 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2680,6 +2680,7 @@ virResctrlInfoGetCache; virResctrlInfoGetMonitorPrefix; virResctrlInfoMonFree; virResctrlInfoNew; +virResctrlMonitorNew; # util/virrotatingfile.h diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 91bd341..6530801 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -36,9 +36,9 @@ VIR_LOG_INIT("util.virresctrl") /* Resctrl is short for Resource Control. It might be implemented for various - * resources. Currently this supports cache allocation technology (aka CAT) and - * memory bandwidth allocation (aka MBA). More resources technologies may be - * added in the future. + * resources. Currently this supports cache allocation technology (aka CAT), + * memory bandwidth allocation (aka MBA) and cache monitoring technology (aka + * CMT). More resources technologies may be added in the future. */ @@ -105,6 +105,7 @@ typedef virResctrlAllocMemBW *virResctrlAllocMemBWPtr; /* Class definitions and initializations */ static virClassPtr virResctrlInfoClass; static virClassPtr virResctrlAllocClass; +static virClassPtr virResctrlMonitorClass; /* virResctrlInfo */ @@ -224,11 +225,16 @@ virResctrlInfoMonFree(virResctrlInfoMonPtr mon) } -/* virResctrlAlloc */ +/* virResctrlAlloc and virResctrlMonitor*/ /* - * virResctrlAlloc represents one allocation (in XML under cputune/cachetune and - * consequently a directory under /sys/fs/resctrl). Since it can have multiple + * virResctrlAlloc and virResctrlMonitor are representing a resource control + * group (in XML under cputune/cachetune and consequently a directory under + * /sys/fs/resctrl). virResctrlAlloc is the data structure for resource + * allocation, while the virResctrlMonitor represents the resource monitoring + * part. + * + * virResctrlAlloc represents one allocation. Since it can have multiple * parts of multiple caches allocated it is represented as bunch of nested * sparse arrays (by sparse I mean array of pointers so that each might be NULL * in case there is no allocation for that particular cache allocation (level, @@ -275,6 +281,18 @@ virResctrlInfoMonFree(virResctrlInfoMonPtr mon) * a sparse array to represent whether a memory bandwidth allocation happens * on corresponding node. The available memory controller number is collected * in 'virResctrlInfo'. + * + * =Cache monitoring technology (CMT)= + * + * Cache monitoring technology is used to perceive how many cache the process + * is using actually. virResctrlMonitor represents the resource control + * monitoring group, it is supported to monitor resource utilization + * information on granularity of vcpu. + * + * From hardware perspective, cache monitoring technology (CMT), memory + * bandwidth technology (MBM), as well as the CAT and MBA, are all orthogonal + * features. The monitor will be created under the scope of default resctl + * group if no specific CAT or MBA entries are provided for the guest." */ struct _virResctrlAllocPerType { /* There could be bool saying whether this is set or not, but since everything @@ -320,6 +338,29 @@ struct _virResctrlAlloc { char *path; }; +/* + * virResctrlMonitor is the data structure for resctrl monitor. Resctrl + * monitor represents a resctrl monitoring group, which can be used to + * monitor the resource utilization information for either cache or + * memory bandwidth. + */ +struct _virResctrlMonitor { +virObject parent; + +/* In resctrl, each monitor is associated with one specific allocation, + * either the allocation under / sys / fs / resctrl or allocation of the + * root directory itself. This pointer points to the allocation + * this monitor associated with. */ +virResctrlAllocPtr alloc; +/* The monitor identifier. For a monitor has the same @path name as its + * @alloc, the @id will be set to the same value as it is in @alloc->id. + */ +char *id; +/* libvirt-generated path in /sys/fs/resctrl for this particular + * monitor */ +char *path; +}; + static void virResctrlAllocDispose(void *obj) @@ -369,6 +410,17 @@ virResctrlAllocDispose(void *obj) } +static void +virResctrlMonitorDispose(void *obj) +{ +virResctrlMonitorPtr monitor = obj; + +virObjectUnref(monitor->alloc); +VIR_FREE(monitor->id); +VIR_FREE(monitor->path); +} + + /* Global initialization for classe
[libvirt] [PATCHv7 01/18] docs, util: Refactor schemas and virresctrl to support optional cache
Refactor schemas and virresctrl to support optional element in . Later, the monitor entry will be introduced and to be placed under . Either cache entry or monitor entry is an optional element of . An cachetune has no element is taking the default resource allocating policy defined in '/sys/fs/resctrl/schemata'. Signed-off-by: Wang Huaqiang --- docs/formatdomain.html.in | 4 ++-- docs/schemas/domaincommon.rng | 4 ++-- src/util/virresctrl.c | 28 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 8189959..b1651e3 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -943,8 +943,8 @@ cache -This element controls the allocation of CPU cache and has the -following attributes: +This optional element controls the allocation of CPU cache and has +the following attributes: level diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 099a949..5c533d6 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -956,7 +956,7 @@ - + @@ -980,7 +980,7 @@ - + diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 5d811a2..91bd341 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -234,6 +234,11 @@ virResctrlInfoMonFree(virResctrlInfoMonPtr mon) * in case there is no allocation for that particular cache allocation (level, * cache, ...) or memory allocation for particular node). * + * Allocation corresponding to root directory, /sys/fs/sysctrl/, defines the + * default resource allocating policy, which is created immediately after + * mounting, and owns all the tasks and cpus in the system. Cache or memory + * bandwidth resource will be shared for tasks in this allocation. + * * =Cache allocation technology (CAT)= * * Since one allocation can be made for caches on different levels, the first @@ -2215,6 +2220,15 @@ virResctrlAllocDeterminePath(virResctrlAllocPtr alloc, return -1; } +/* If the allocation is empty, then the path will be SYSFS_RESCTRL_PATH */ +if (virResctrlAllocIsEmpty(alloc)) { +if (!alloc->path && +VIR_STRDUP(alloc->path, SYSFS_RESCTRL_PATH) < 0) +return -1; + +return 0; +} + if (!alloc->path && virAsprintf(&alloc->path, "%s/%s-%s", SYSFS_RESCTRL_PATH, machinename, alloc->id) < 0) @@ -2248,6 +2262,11 @@ virResctrlAllocCreate(virResctrlInfoPtr resctrl, if (virResctrlAllocDeterminePath(alloc, machinename) < 0) return -1; +/* If the allocation is empty, then do not create directory in underlying + * resctrl file system */ +if (virResctrlAllocIsEmpty(alloc)) +return 0; + if (virFileExists(alloc->path)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Path '%s' for resctrl allocation exists"), @@ -2302,6 +2321,11 @@ virResctrlAllocAddPID(virResctrlAllocPtr alloc, char *pidstr = NULL; int ret = 0; +/* If the allocation is empty, then it is impossible to add a PID to + * allocation due to lacking of its 'tasks' file. Just return */ +if (virResctrlAllocIsEmpty(alloc)) +return 0; + if (!alloc->path) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Cannot add pid to non-existing resctrl allocation")); @@ -2334,6 +2358,10 @@ virResctrlAllocRemove(virResctrlAllocPtr alloc) { int ret = 0; +/* No directory have ever been created. Just return */ +if (virResctrlAllocIsEmpty(alloc)) +return 0; + if (!alloc->path) return 0; -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 17/18] qemu: Report cache occupancy (CMT) with domstats
Adding the interface in qemu to report CMT statistic information through command 'virsh domstats --cpu-total'. Below is a typical output: # virsh domstats 1 --cpu-total Domain: 'ubuntu16.04-base' ... cpu.cache.monitor.count=2 cpu.cache.monitor.0.name=vcpus_1 cpu.cache.monitor.0.vcpus=1 cpu.cache.monitor.0.bank.count=2 cpu.cache.monitor.0.bank.0.id=0 cpu.cache.monitor.0.bank.0.bytes=4505600 cpu.cache.monitor.0.bank.1.id=1 cpu.cache.monitor.0.bank.1.bytes=5586944 cpu.cache.monitor.1.name=vcpus_4-6 cpu.cache.monitor.1.vcpus=4,5,6 cpu.cache.monitor.1.bank.count=2 cpu.cache.monitor.1.bank.0.id=0 cpu.cache.monitor.1.bank.0.bytes=17571840 cpu.cache.monitor.1.bank.1.id=1 cpu.cache.monitor.1.bank.1.bytes=29106176 Signed-off-by: Wang Huaqiang --- src/libvirt-domain.c | 9 ++ src/libvirt_private.syms | 1 + src/qemu/qemu_driver.c | 229 +++ src/util/virresctrl.c| 130 +++ src/util/virresctrl.h| 12 +++ 5 files changed, 381 insertions(+) diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 7690339..4895f9f 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11345,6 +11345,15 @@ virConnectGetDomainCapabilities(virConnectPtr conn, * "cpu.user" - user cpu time spent in nanoseconds as unsigned long long. * "cpu.system" - system cpu time spent in nanoseconds as unsigned long *long. + * "cpu.cache.monitor.count" - tocal cache monitoring groups + * "cpu.cache.monitor.M.name" - name of cache monitoring group 'M' + * "cpu.cache.monitor.M.vcpus" - vcpus for cache monitoring group 'M' + * "cpu.cache.monitor.M.bank.count" - total bank number of cache monitoring + *group 'M' + * "cpu.cache.monitor.M.bank.N.id" - OS assigned cache bank id for cache + *'N' in cache monitoring group 'M' + * "cpu.cache.monitor.M.bank.N.bytes" - monitor's cache occupancy of cache + *bank 'N' in cache monitoring group 'M' * * VIR_DOMAIN_STATS_BALLOON: * Return memory balloon device information. diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 91801ed..4551767 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2683,6 +2683,7 @@ virResctrlInfoNew; virResctrlMonitorAddPID; virResctrlMonitorCreate; virResctrlMonitorDeterminePath; +virResctrlMonitorGetCacheOccupancy; virResctrlMonitorGetID; virResctrlMonitorIsRunning; virResctrlMonitorNew; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 12a5f8f..9828118 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -102,6 +102,7 @@ #include "virnuma.h" #include "dirname.h" #include "netdev_bandwidth_conf.h" +#include "c-ctype.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -19698,6 +19699,230 @@ typedef enum { #define HAVE_JOB(flags) ((flags) & QEMU_DOMAIN_STATS_HAVE_JOB) +/* In terms of the output of virBitmapFormat, both '1-3' and '1,3' are valid + * outputs and represent different vcpu set. But it is not easy to + * differentiate these two vcpu set formats at first glance. + * + * This function could be used to clear this ambiguity, it substitutes all '-' + * with ',' while generates semantically correct vcpu set. + * e.g. vcpu set string '1-3' will be replaced by string '1,2,3'. */ +static char * +qemuDomainVcpuFormatHelper(const char *vcpus) +{ +size_t i = 0; +int last = 0; +int start = 0; +char * tmp = NULL; +bool firstnum = true; +const char *cur = vcpus; +virBuffer buf = VIR_BUFFER_INITIALIZER; +char *ret = NULL; + +if (virStringIsEmpty(cur)) +return NULL; + +while (*cur != '\0') { +if (!c_isdigit(*cur)) +goto cleanup; + +if (virStrToLong_i(cur, &tmp, 10, &start) < 0) +goto cleanup; +if (start < 0) +goto cleanup; + +cur = tmp; + +virSkipSpaces(&cur); + +if (*cur == ',' || *cur == 0) { +if (!firstnum) +virBufferAddChar(&buf, ','); +virBufferAsprintf(&buf, "%d", start); +firstnum = false; +} else if (*cur == '-') { +cur++; +virSkipSpaces(&cur); + +if (virStrToLong_i(cur, &tmp, 10, &last) < 0) +goto cleanup; + +if (last < start) +goto cleanup; +cur = tmp; + +for (i = start; i <= last; i++) { +if (!firstnum) + +virBufferAddChar(&buf, ','); +virBufferAsprintf(&buf, "%ld", i); +firstnum = 0; +} + +virSkipSpaces(&cur); +} + +if (*cur == ',') { +cur++; +virSkipSpaces(&cur); +
[libvirt] [PATCHv7 15/18] conf: Add 'id' to virDomainResctrlDef
Adding element 'id' to virDomainResctrlDef tracking resource group id, it reflects the attribute 'id' of of element in XML. virResctrlAlloc.id is a copy from virDomanResctrlDef.id. Signed-off-by: Wang Huaqiang --- src/conf/domain_conf.c | 20 src/conf/domain_conf.h | 1 + 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 01f795f..1aecd8c 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2980,6 +2980,7 @@ virDomainResctrlDefFree(virDomainResctrlDefPtr resctrl) virObjectUnref(resctrl->alloc); virBitmapFree(resctrl->vcpus); VIR_FREE(resctrl->monitors); +VIR_FREE(resctrl->id); VIR_FREE(resctrl); } @@ -19145,6 +19146,9 @@ virDomainResctrlNew(xmlNodePtr node, if (VIR_ALLOC(resctrl) < 0) goto cleanup; +if (VIR_STRDUP(resctrl->id, alloc_id) < 0) +goto cleanup; + if (!(resctrl->vcpus = virBitmapNewCopy(*vcpus))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("failed to copy 'vcpus'")); @@ -27323,13 +27327,9 @@ virDomainCachetuneDefFormat(virBufferPtr buf, virBufferAsprintf(buf, "alloc); -if (!alloc_id) -goto cleanup; +if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) +virBufferAsprintf(buf, " id='%s'", resctrl->id); -virBufferAsprintf(buf, " id='%s'", alloc_id); -} virBufferAddLit(buf, ">\n"); virBufferAddBuffer(buf, &childrenBuf); @@ -27386,13 +27386,9 @@ virDomainMemorytuneDefFormat(virBufferPtr buf, virBufferAsprintf(buf, "alloc); -if (!alloc_id) -goto cleanup; +if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) +virBufferAsprintf(buf, " id='%s'", resctrl->id); -virBufferAsprintf(buf, " id='%s'", alloc_id); -} virBufferAddLit(buf, ">\n"); virBufferAddBuffer(buf, &childrenBuf); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 60f6464..e190aa2 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2248,6 +2248,7 @@ typedef struct _virDomainResctrlDef virDomainResctrlDef; typedef virDomainResctrlDef *virDomainResctrlDefPtr; struct _virDomainResctrlDef { +char *id; virBitmapPtr vcpus; virResctrlAllocPtr alloc; -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 07/18] util: Refactor code for creating resctrl group
The code for creating resctrl allocation group could be reused for monitoring group, refactor it for reuse in the later patch. Signed-off-by: Wang Huaqiang --- src/util/virresctrl.c | 37 +++-- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 93b5e70..5b984d9 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -2315,6 +2315,26 @@ virResctrlAllocDeterminePath(virResctrlAllocPtr alloc, } +/* This function creates a resctrl directory in resource control file system, + * and the directory path is specified by @path. */ +static int +virResctrlCreateGroupPath(const char *path) +{ +/* Directory exists, return */ +if (virFileExists(path)) +return 0; + +if (virFileMakePath(path) < 0) { +virReportSystemError(errno, + _("Cannot create resctrl directory '%s'"), + path); +return -1; +} + +return 0; +} + + /* This checks if the directory for the alloc exists. If not it tries to create * it and apply appropriate alloc settings. */ int @@ -2344,13 +2364,6 @@ virResctrlAllocCreate(virResctrlInfoPtr resctrl, if (virResctrlAllocIsEmpty(alloc)) return 0; -if (virFileExists(alloc->path)) { -virReportError(VIR_ERR_INTERNAL_ERROR, - _("Path '%s' for resctrl allocation exists"), - alloc->path); -goto cleanup; -} - lockfd = virResctrlLockWrite(); if (lockfd < 0) goto cleanup; @@ -2358,6 +2371,9 @@ virResctrlAllocCreate(virResctrlInfoPtr resctrl, if (virResctrlAllocAssign(resctrl, alloc) < 0) goto cleanup; +if (virResctrlCreateGroupPath(alloc->path) < 0) +goto cleanup; + alloc_str = virResctrlAllocFormat(alloc); if (!alloc_str) goto cleanup; @@ -2365,13 +2381,6 @@ virResctrlAllocCreate(virResctrlInfoPtr resctrl, if (virAsprintf(&schemata_path, "%s/schemata", alloc->path) < 0) goto cleanup; -if (virFileMakePath(alloc->path) < 0) { -virReportSystemError(errno, - _("Cannot create resctrl directory '%s'"), - alloc->path); -goto cleanup; -} - VIR_DEBUG("Writing resctrl schemata '%s' into '%s'", alloc_str, schemata_path); if (virFileWriteStr(schemata_path, alloc_str, 0) < 0) { rmdir(alloc->path); -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv7 03/18] util: Refactor code for determining allocation path
The code for determining resctrl allocation path could be reused for monitor. Refactor it for reuse. Signed-off-by: Wang Huaqiang --- src/util/virresctrl.c | 38 ++ 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 6530801..956aca8 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -2265,28 +2265,50 @@ virResctrlAllocAssign(virResctrlInfoPtr resctrl, } +static char * +virResctrlDeterminePath(const char *parentpath, +const char *prefix, +const char *id) +{ +char *path = NULL; + +if (!id) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Resctrl ID must be set before determining resctrl " + "parentpath='%s'"), parentpath); +return NULL; +} + +if (virAsprintf(&path, "%s/%s-%s", parentpath, prefix, id) < 0) +return NULL; + +return path; +} + + int virResctrlAllocDeterminePath(virResctrlAllocPtr alloc, const char *machinename) { -if (!alloc->id) { -virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Resctrl Allocation ID must be set before creation")); +if (alloc->path) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Resctrl allocation path is already set to '%s'"), + alloc->path); return -1; } /* If the allocation is empty, then the path will be SYSFS_RESCTRL_PATH */ if (virResctrlAllocIsEmpty(alloc)) { -if (!alloc->path && -VIR_STRDUP(alloc->path, SYSFS_RESCTRL_PATH) < 0) +if (VIR_STRDUP(alloc->path, SYSFS_RESCTRL_PATH) < 0) return -1; return 0; } -if (!alloc->path && -virAsprintf(&alloc->path, "%s/%s-%s", -SYSFS_RESCTRL_PATH, machinename, alloc->id) < 0) +alloc->path = virResctrlDeterminePath(SYSFS_RESCTRL_PATH, + machinename, alloc->id); + +if (!alloc->path) return -1; return 0; -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] qemu: Restore lost shutdown reason
On 18.10.2018 18:28, John Ferlan wrote: > When qemuProcessReconnectHelper was introduced (commit d38897a5d) > reconnection failure used VIR_DOMAIN_SHUTOFF_FAILED; however, that > was changed in commit bda2f17d to either VIR_DOMAIN_SHUTOFF_CRASHED > or VIR_DOMAIN_SHUTOFF_UNKNOWN. > > When QEMU_CAPS_NO_SHUTDOWN checking was removed in commit fe35b1ad6 > the conditional state was just left at VIR_DOMAIN_SHUTOFF_CRASHED. > > Restore the logic adjustment using the same conditions as command > line building and alter the comment to describe the reasoning. > > Signed-off-by: John Ferlan > --- > > This was "discovered" while reviewing Nikolay's patch related > to adding "DAEMON" as the shutdown reason: > > https://www.redhat.com/archives/libvir-list/2018-October/msg00493.html > > While working through the iterations of that - figured I'd at > least post this. > > > src/qemu/qemu_process.c | 15 ++- > 1 file changed, 10 insertions(+), 5 deletions(-) > > diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c > index 3955eda17c..4a39111d51 100644 > --- a/src/qemu/qemu_process.c > +++ b/src/qemu/qemu_process.c > @@ -7985,11 +7985,16 @@ qemuProcessReconnect(void *opaque) > if (virDomainObjIsActive(obj)) { > /* We can't get the monitor back, so must kill the VM > * to remove danger of it ending up running twice if > - * user tries to start it again later > - * If we couldn't get the monitor since QEMU supports > - * no-shutdown, we can safely say that the domain > - * crashed ... */ > -state = VIR_DOMAIN_SHUTOFF_CRASHED; > + * user tries to start it again later. > + * > + * If we cannot get to the monitor when the QEMU command > + * line used -no-shutdown, then we can safely say that the > + * domain crashed; otherwise we don't really know. */ > +if (priv->monJSON && priv->allowReboot == VIR_TRISTATE_BOOL_YES) > +state = VIR_DOMAIN_SHUTOFF_CRASHED; > +else > +state = VIR_DOMAIN_SHUTOFF_UNKNOWN; > + > /* If BeginJob failed, we jumped here without a job, let's hope > another > * thread didn't have a chance to start playing with the domain yet > * (it's all we can do anyway). > This is reasonable but not complete. This is only applied to case when we do connect(2) to qemu and it is failed with ECONNREFUSED which means qemu process does not exists (in which case it is either crashed if was configured with -no-shutdown or terminated for unknown reason) or just closed monitor connection (in this case we are going to terminate it by ourselves). But there are other cases. For example we can jump to error path even before connect(2) or after successfull connect. See discussion of such cases in [1]. [1] https://www.redhat.com/archives/libvir-list/2018-October/msg01031.html Nikolay -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 1/4] nwfilter: add nwfilter hash
On 19.10.2018 18:33, Laine Stump wrote: > On 10/18/18 2:49 AM, Nikolay Shirokovskiy wrote: >> For filter without references to other filters hash is just sha-256 of >> filter's >> xml. For filters with references hash is sha-256 of string consisting of >> filter's self hash and hashes of directly referenced filters. > > > I didn't read the entire patch, but if you're just comparing hashes of > the filters' XML, then you aren't actually checking to see if *someone > else* outside libvirt has modified the actual rules in ebtables/iptables > (and someday not *too* far away nbtables, or maybe firewalld "rich > rules"). That is the really important thing we need to check for. One of > the reasons for a libvirtd restart to delete and reload all the rules is > to clean up after some third party has "moved our cheese" and our filter > rules no longer work as expected, and just checking that our own > internal data is unchanged doesn't help that problem. Agree. I mentioned the same issue in the cover letter. Need to rework series) > > > (BTW, on a slightly related topic - since I've lately been thinking > about making libvirt work properly on systems with nbtables and in > particular firewalld with an nbtables backend, I've been wondering if > our whole model of "deleting old rules" based on our current idea of the > libvirt xml ==> eb/iptables backend isn't improper. Maybe we should be > saving the actual rules that we sent out in the status, and undoing > those. The rules we need to delete could be *very* different from what > the new libvirtd is generating (e.g. we decided we didn't need one of > the rules anymore so it's no longer generated, or we're now using > nbtables/ebpf/sub-etha-senso-tables or whatever). The approach of not keeping firewall rules status is that libvirt keeps all rules in 4 chains: libvirt-O-$IFACE, libvirt-I-$IFACE, libvirt-J-$IFACE, libvirt-O-$IFACE (the last two are temporary) and their subchains. This names are fixed so we can always cleanup all rules installed by libvirt. Not sure of nbtables though - can we clean chains installed thru iptables/ebtables thru nbtables. Nikolay > > >> >> If filter is not complete that is some of filters it's referencing directly >> or >> indirectly are missing the hash is set to NULL as well as if there was OOM on >> hash caculation. So having NULL hash is regular situation. >> >> Signed-off-by: Nikolay Shirokovskiy >> --- >> src/conf/virnwfilterobj.c | 145 >> + >> src/conf/virnwfilterobj.h | 9 ++ >> src/libvirt_private.syms | 3 + >> src/nwfilter/nwfilter_driver.c | 3 + >> src/nwfilter/nwfilter_gentech_driver.c | 2 + >> 5 files changed, 162 insertions(+) >> >> diff --git a/src/conf/virnwfilterobj.c b/src/conf/virnwfilterobj.c >> index 0136a0d..4cc81df 100644 >> --- a/src/conf/virnwfilterobj.c >> +++ b/src/conf/virnwfilterobj.c >> @@ -28,6 +28,7 @@ >> #include "virlog.h" >> #include "virnwfilterobj.h" >> #include "virstring.h" >> +#include "vircrypto.h" >> >> #define VIR_FROM_THIS VIR_FROM_NWFILTER >> >> @@ -40,6 +41,8 @@ struct _virNWFilterObj { >> >> virNWFilterDefPtr def; >> virNWFilterDefPtr newDef; >> + >> +char *hash; >> }; >> >> struct _virNWFilterObjList { >> @@ -82,6 +85,13 @@ virNWFilterObjGetNewDef(virNWFilterObjPtr obj) >> } >> >> >> +char* >> +virNWFilterObjGetHash(virNWFilterObjPtr obj) >> +{ >> +return obj->hash; >> +} >> + >> + >> bool >> virNWFilterObjWantRemoved(virNWFilterObjPtr obj) >> { >> @@ -307,6 +317,139 @@ virNWFilterDefEqual(const virNWFilterDef *def1, >> } >> >> >> +static void >> +virNWFilterObjInvalidateHash(virNWFilterObjListPtr nwfilters, >> + virNWFilterObjPtr obj) >> +{ >> +virNWFilterDefPtr def = obj->def; >> +size_t i; >> + >> +if (!obj->hash) >> +return; >> + >> +if (obj->newDef) { >> +VIR_FREE(obj->hash); >> +return; >> +} >> + >> +for (i = 0; i < def->nentries; i++) { >> +virNWFilterObjPtr child; >> +char *filterref; >> + >> +if (def->filterEntries[i]->rule || >> +!def->filterEntries[i]->include) >> +continue; >> + >> +filterref = def->filterEntries[i]->include->filterref; >> + >> +if (!(child = virNWFilterObjListFindByName(nwfilters, filterref))) { >> +VIR_FREE(obj->hash); >> +return; >> +} >> + >> +virNWFilterObjInvalidateHash(nwfilters, child); >> + >> +if (!child->hash) { >> +VIR_FREE(obj->hash); >> +virNWFilterObjUnlock(child); >> +return; >> +} >> + >> +virNWFilterObjUnlock(child); >> +} >> +} >> + >> + >> +void >> +virNWFilterObjListInvalidateHash(virNWFilterObjListPtr nwfilters) >> +{ >> +size_t i; >> +virNWFilterObjPtr obj; >> + >> +for (i = 0; i < nwfilters->count; i++) { >> +obj = nwfilters
[libvirt] [PATCHv6 14/18] util: Add function for checking if monitor is running
Check whether monitor is running by checking the monitor's PIDs status. Monitor is looked as running normally if the vcpu PID list matches with the content of monitor's 'tasks' file. Signed-off-by: Wang Huaqiang --- src/libvirt_private.syms | 1 + src/util/virresctrl.c| 102 ++- src/util/virresctrl.h| 3 ++ 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 239b979..cbc86ce 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2684,6 +2684,7 @@ virResctrlMonitorAddPID; virResctrlMonitorCreate; virResctrlMonitorDeterminePath; virResctrlMonitorGetID; +virResctrlMonitorIsRunning; virResctrlMonitorNew; virResctrlMonitorRemove; virResctrlMonitorSetAlloc; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index b4b63b6..fa4c05e 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -359,6 +359,9 @@ struct _virResctrlMonitor { /* libvirt-generated path in /sys/fs/resctrl for this particular * monitor */ char *path; +/* Tracking the tasks' PID associated with this monitor */ +pid_t *pids; +size_t npids; }; @@ -418,6 +421,7 @@ virResctrlMonitorDispose(void *obj) virObjectUnref(monitor->alloc); VIR_FREE(monitor->id); VIR_FREE(monitor->path); +VIR_FREE(monitor->pids); } @@ -2537,7 +2541,20 @@ int virResctrlMonitorAddPID(virResctrlMonitorPtr monitor, pid_t pid) { -return virResctrlAddPID(monitor->path, pid); +size_t i = 0; + +if (virResctrlAddPID(monitor->path, pid) < 0) +return -1; + +for (i = 0; i < monitor->npids; i++) { +if (pid == monitor->pids[i]) +return 0; +} + +if (VIR_APPEND_ELEMENT(monitor->pids, monitor->npids, pid) < 0) +return -1; + +return 0; } @@ -2610,3 +2627,86 @@ virResctrlMonitorRemove(virResctrlMonitorPtr monitor) return ret; } + + +static int +virResctrlPIDSorter(const void *pida, const void *pidb) +{ +return *(pid_t*)pida - *(pid_t*)pidb; +} + + +bool +virResctrlMonitorIsRunning(virResctrlMonitorPtr monitor) +{ +char *pidstr = NULL; +char **spids = NULL; +size_t nspids = 0; +pid_t *pids = NULL; +size_t npids = 0; +size_t i = 0; +int rv = -1; +bool ret = false; + +/* path is not determined yet, monitor is not running*/ +if (!monitor->path) +return false; + +/* No vcpu PID filled, regard monitor as not running */ +if (monitor->npids == 0) +return false; + +/* If no 'tasks' file found, underlying resctrl directory is not + * ready, regard monitor as not running */ +rv = virFileReadValueString(&pidstr, "%s/tasks", monitor->path); +if (rv < 0) +goto cleanup; + +/* no PID in task file, monitor is not running */ +if (!*pidstr) +goto cleanup; + +/* The tracking monitor PID list is not identical to the + * list in current resctrl directory. monitor is corrupted, + * report error and un-running state */ +spids = virStringSplitCount(pidstr, "\n", 0, &nspids); +if (nspids != monitor->npids) { +VIR_ERROR(_("Monitor %s PID list mismatch in length"), monitor->path); +goto cleanup; +} + +for (i = 0; i < nspids; i++) { +unsigned int val = 0; +pid_t pid = 0; + +if (virStrToLong_uip(spids[i], NULL, 0, &val) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Monitor %s failed in parse PID list"), + monitor->path); +goto cleanup; +} + +pid = (pid_t)val; + +if (VIR_APPEND_ELEMENT(pids, npids, pid) < 0) +goto cleanup; +} + +qsort(pids, npids, sizeof(pid_t), virResctrlPIDSorter); +qsort(monitor->pids, monitor->npids, sizeof(pid_t), virResctrlPIDSorter); + +for (i = 0; i < monitor->npids; i++) { +if (monitor->pids[i] != pids[i]) { +VIR_ERROR(_("Monitor %s PID list corrupted"), monitor->path); +goto cleanup; +} +} + +ret = true; + cleanup: +virStringListFree(spids); +VIR_FREE(pids); +VIR_FREE(pidstr); + +return ret; +} diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 804d6f5..8d8fdc2 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -219,4 +219,7 @@ virResctrlMonitorSetAlloc(virResctrlMonitorPtr monitor, int virResctrlMonitorRemove(virResctrlMonitorPtr monitor); + +bool +virResctrlMonitorIsRunning(virResctrlMonitorPtr monitor); #endif /* __VIR_RESCTRL_H__ */ -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 04/18] util: Add interface to determine monitor path
Add interface for resctrl monitor to determine the path. Signed-off-by: Wang Huaqiang --- src/libvirt_private.syms | 1 + src/util/virresctrl.c| 55 src/util/virresctrl.h| 5 - 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 9577b70..19004bb 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2680,6 +2680,7 @@ virResctrlInfoGetCache; virResctrlInfoGetMonitorPrefix; virResctrlInfoMonFree; virResctrlInfoNew; +virResctrlMonitorDeterminePath; virResctrlMonitorNew; # util/virrotatingfile.h diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 404b26c..794de87 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -2459,3 +2459,58 @@ virResctrlMonitorNew(void) return virObjectNew(virResctrlMonitorClass); } + + +/* + * virResctrlMonitorDeterminePath + * + * @monitor: Pointer to a resctrl monitor + * @machinename: Name string of the VM + * + * Determines the directory path that the underlying resctrl group will be + * created with. + * + * A monitor represents a directory under resource control file system, + * its directory path could be the same path as @monitor->alloc, could be a + * path of directory under 'mon_groups' of @monitor->alloc, or a path of + * directory under '/sys/fs/resctrl/mon_groups' if @monitor->alloc is NULL. + * + * Returns 0 on success, -1 on error. + */ +int +virResctrlMonitorDeterminePath(virResctrlMonitorPtr monitor, + const char *machinename) +{ +VIR_AUTOFREE(char *) parentpath = NULL; + +if (!monitor) { +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Invalid resctrl monitor")); +return -1; +} + +if (monitor->path) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Resctrl monitor path is already set to '%s'"), + monitor->path); +return -1; +} + +if (monitor->id && monitor->alloc && monitor->alloc->id) { +if (STREQ(monitor->id, monitor->alloc->id)) { +if (VIR_STRDUP(monitor->path, monitor->alloc->path) < 0) +return -1; +return 0; +} +} + +if (virAsprintf(&parentpath, "%s/mon_groups", monitor->alloc->path) < 0) +return -1; + +monitor->path = virResctrlDeterminePath(parentpath, machinename, +monitor->id); +if (!monitor->path) +return -1; + +return 0; +} diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index eaa077d..baae554 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -191,7 +191,10 @@ virResctrlInfoGetMonitorPrefix(virResctrlInfoPtr resctrl, typedef struct _virResctrlMonitor virResctrlMonitor; typedef virResctrlMonitor *virResctrlMonitorPtr; - virResctrlMonitorPtr virResctrlMonitorNew(void); + +int +virResctrlMonitorDeterminePath(virResctrlMonitorPtr monitor, + const char *machinename); #endif /* __VIR_RESCTRL_H__ */ -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 11/18] conf: move virResctrlAllocIsEmpty to a place a litter lower
This refactor allows to add some code between virDomainResctrlNew and virResctrlAllocIsEmpty to extend the scope of resctrl. Signed-off-by: Wang Huaqiang --- src/conf/domain_conf.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 39bd396..a068d4d 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -19022,15 +19022,15 @@ virDomainCachetuneDefParse(virDomainDefPtr def, goto cleanup; } +resctrl = virDomainResctrlNew(node, &alloc, &vcpus, flags); +if (!resctrl) +goto cleanup; + if (virResctrlAllocIsEmpty(alloc)) { ret = 0; goto cleanup; } -resctrl = virDomainResctrlNew(node, &alloc, &vcpus, flags); -if (!resctrl) -goto cleanup; - if (VIR_APPEND_ELEMENT(def->resctrls, def->nresctrls, resctrl) < 0) goto cleanup; -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 16/18] qemu: refactor qemuDomainGetStatsCpu
Refactoring qemuDomainGetStatsCpu, make it possible to add more CPU statistics. Signed-off-by: Wang Huaqiang --- src/qemu/qemu_driver.c | 45 ++--- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a52e249..12a5f8f 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19711,30 +19711,29 @@ qemuDomainGetStatsCpu(virQEMUDriverPtr driver ATTRIBUTE_UNUSED, 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; +if (priv->cgroup) { +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; +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; } -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 13/18] qemu: enable resctrl monitor in qemu
Add functions for creating, destroying, reconnecting resctrl monitor in qemu according to the configuration in domain XML. Signed-off-by: Wang Huaqiang --- src/qemu/qemu_process.c | 66 - 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index e9c7618..fba4fb4 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2611,10 +2611,21 @@ qemuProcessResctrlCreate(virQEMUDriverPtr driver, return -1; for (i = 0; i < vm->def->nresctrls; i++) { +size_t j = 0; if (virResctrlAllocCreate(caps->host.resctrl, vm->def->resctrls[i]->alloc, priv->machineName) < 0) goto cleanup; + +for (j = 0; j < vm->def->resctrls[i]->nmonitors; j++) { +virDomainResctrlMonDefPtr mon = NULL; + +mon = vm->def->resctrls[i]->monitors[j]; +if (virResctrlMonitorCreate(mon->instance, +priv->machineName) < 0) +goto cleanup; + +} } ret = 0; @@ -5430,6 +5441,7 @@ qemuProcessSetupVcpu(virDomainObjPtr vm, { pid_t vcpupid = qemuDomainGetVcpuPid(vm, vcpuid); virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(vm->def, vcpuid); +virDomainResctrlMonDefPtr mon = NULL; size_t i = 0; if (qemuProcessSetupPid(vm, vcpupid, VIR_CGROUP_THREAD_VCPU, @@ -5440,11 +5452,42 @@ qemuProcessSetupVcpu(virDomainObjPtr vm, return -1; for (i = 0; i < vm->def->nresctrls; i++) { +size_t j = 0; virDomainResctrlDefPtr ct = vm->def->resctrls[i]; if (virBitmapIsBitSet(ct->vcpus, vcpuid)) { if (virResctrlAllocAddPID(ct->alloc, vcpupid) < 0) return -1; + +/* The order of invoking virResctrlMonitorAddPID matters, it is + * required to invoke this function first for monitor that has + * the same vcpus setting as the allocation in same def->resctrl. + * Otherwise, some other monitor's pid may be removed from its + * resource group's 'tasks' file.*/ +for (j = 0; j < vm->def->resctrls[i]->nmonitors; j++) { +mon = vm->def->resctrls[i]->monitors[j]; + +if (!virBitmapEqual(ct->vcpus, mon->vcpus)) +continue; + +if (virBitmapIsBitSet(mon->vcpus, vcpuid)) { +if (virResctrlMonitorAddPID(mon->instance, vcpupid) < 0) +return -1; +} +break; +} + +for (j = 0; j < vm->def->resctrls[i]->nmonitors; j++) { +mon = vm->def->resctrls[i]->monitors[j]; + +if (virBitmapEqual(ct->vcpus, mon->vcpus)) +continue; + +if (virBitmapIsBitSet(mon->vcpus, vcpuid)) { +if (virResctrlMonitorAddPID(mon->instance, vcpupid) < 0) +return -1; +} +} break; } } @@ -7207,8 +7250,18 @@ void qemuProcessStop(virQEMUDriverPtr driver, /* Remove resctrl allocation after cgroups are cleaned up which makes it * kind of safer (although removing the allocation should work even with * pids in tasks file */ -for (i = 0; i < vm->def->nresctrls; i++) +for (i = 0; i < vm->def->nresctrls; i++) { +size_t j = 0; + +for (j = 0; j < vm->def->resctrls[i]->nmonitors; j++) { +virDomainResctrlMonDefPtr mon = NULL; + +mon = vm->def->resctrls[i]->monitors[j]; +virResctrlMonitorRemove(mon->instance); +} + virResctrlAllocRemove(vm->def->resctrls[i]->alloc); +} qemuProcessRemoveDomainStatus(driver, vm); @@ -7939,9 +7992,20 @@ qemuProcessReconnect(void *opaque) goto error; for (i = 0; i < obj->def->nresctrls; i++) { +size_t j = 0; + if (virResctrlAllocDeterminePath(obj->def->resctrls[i]->alloc, priv->machineName) < 0) goto error; + +for (j = 0; j < obj->def->resctrls[i]->nmonitors; j++) { +virDomainResctrlMonDefPtr mon = NULL; + +mon = obj->def->resctrls[i]->monitors[j]; +if (virResctrlMonitorDeterminePath(mon->instance, + priv->machineName) < 0) +goto error; +} } /* update domain state XML with possibly updated state in virDomainObj */ -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 03/18] util: Refactor code for determining allocation path
The code for determining resctrl allocation path could be reused for monitor. Refactor it for reuse. Signed-off-by: Wang Huaqiang --- src/util/virresctrl.c | 38 ++ 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 578a52c..404b26c 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -2265,28 +2265,50 @@ virResctrlAllocAssign(virResctrlInfoPtr resctrl, } +static char * +virResctrlDeterminePath(const char *parentpath, +const char *prefix, +const char *id) +{ +char *path = NULL; + +if (!id) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Resctrl ID must be set before determining resctrl " + "parentpath='%s'"), parentpath); +return NULL; +} + +if (virAsprintf(&path, "%s/%s-%s", parentpath, prefix, id) < 0) +return NULL; + +return path; +} + + int virResctrlAllocDeterminePath(virResctrlAllocPtr alloc, const char *machinename) { -if (!alloc->id) { -virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Resctrl Allocation ID must be set before creation")); +if (alloc->path) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Resctrl allocation path is already set to '%s'"), + alloc->path); return -1; } /* If the allocation is empty, then the path will be SYSFS_RESCTRL_PATH */ if (virResctrlAllocIsEmpty(alloc)) { -if (!alloc->path && -VIR_STRDUP(alloc->path, SYSFS_RESCTRL_PATH) < 0) +if (VIR_STRDUP(alloc->path, SYSFS_RESCTRL_PATH) < 0) return -1; return 0; } -if (!alloc->path && -virAsprintf(&alloc->path, "%s/%s-%s", -SYSFS_RESCTRL_PATH, machinename, alloc->id) < 0) +alloc->path = virResctrlDeterminePath(SYSFS_RESCTRL_PATH, + machinename, alloc->id); + +if (!alloc->path) return -1; return 0; -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 10/18] conf: Remove virDomainResctrlAppend and introduce virDomainResctrlNew
Introduced virDomainResctrlNew to do the most part of virDomainResctrlAppend and move the operation of appending resctrl to @def->resctrls out of function. Rather than rely on virDomainResctrlAppend to perform the allocation, move the onus to the caller and make use of virBitmapNewCopy for @vcpus and virObjectRef for @alloc, thus removing the need to set each to NULL after the call. Signed-off-by: Wang Huaqiang --- src/conf/domain_conf.c | 60 +- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e8e0adc..39bd396 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -18920,26 +18920,22 @@ virDomainCachetuneDefParseCache(xmlXPathContextPtr ctxt, } -static int -virDomainResctrlAppend(virDomainDefPtr def, - xmlNodePtr node, - virResctrlAllocPtr alloc, - virBitmapPtr vcpus, - unsigned int flags) +static virDomainResctrlDefPtr +virDomainResctrlNew(xmlNodePtr node, +virResctrlAllocPtr *alloc, +virBitmapPtr *vcpus, +unsigned int flags) { char *vcpus_str = NULL; char *alloc_id = NULL; -virDomainResctrlDefPtr tmp_resctrl = NULL; -int ret = -1; - -if (VIR_ALLOC(tmp_resctrl) < 0) -goto cleanup; +virDomainResctrlDefPtr resctrl = NULL; +virDomainResctrlDefPtr ret = NULL; /* We need to format it back because we need to be consistent in the naming * even when users specify some "sub-optimal" string there. */ -vcpus_str = virBitmapFormat(vcpus); +vcpus_str = virBitmapFormat(*vcpus); if (!vcpus_str) -goto cleanup; +return NULL; if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) alloc_id = virXMLPropString(node, "id"); @@ -18954,18 +18950,23 @@ virDomainResctrlAppend(virDomainDefPtr def, goto cleanup; } -if (virResctrlAllocSetID(alloc, alloc_id) < 0) +if (virResctrlAllocSetID(*alloc, alloc_id) < 0) goto cleanup; -tmp_resctrl->vcpus = vcpus; -tmp_resctrl->alloc = alloc; +if (VIR_ALLOC(resctrl) < 0) +goto cleanup; -if (VIR_APPEND_ELEMENT(def->resctrls, def->nresctrls, tmp_resctrl) < 0) +if (!(resctrl->vcpus = virBitmapNewCopy(*vcpus))) { +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to copy 'vcpus'")); goto cleanup; +} -ret = 0; +resctrl->alloc = virObjectRef(*alloc); + +VIR_STEAL_PTR(ret, resctrl); cleanup: -virDomainResctrlDefFree(tmp_resctrl); +virDomainResctrlDefFree(resctrl); VIR_FREE(alloc_id); VIR_FREE(vcpus_str); return ret; @@ -18982,6 +18983,7 @@ virDomainCachetuneDefParse(virDomainDefPtr def, xmlNodePtr *nodes = NULL; virBitmapPtr vcpus = NULL; virResctrlAllocPtr alloc = NULL; +virDomainResctrlDefPtr resctrl = NULL; ssize_t i = 0; int n; int ret = -1; @@ -19025,14 +19027,17 @@ virDomainCachetuneDefParse(virDomainDefPtr def, goto cleanup; } -if (virDomainResctrlAppend(def, node, alloc, vcpus, flags) < 0) +resctrl = virDomainResctrlNew(node, &alloc, &vcpus, flags); +if (!resctrl) +goto cleanup; + +if (VIR_APPEND_ELEMENT(def->resctrls, def->nresctrls, resctrl) < 0) goto cleanup; -vcpus = NULL; -alloc = NULL; ret = 0; cleanup: ctxt->node = oldnode; +virDomainResctrlDefFree(resctrl); virObjectUnref(alloc); virBitmapFree(vcpus); VIR_FREE(nodes); @@ -19190,6 +19195,8 @@ virDomainMemorytuneDefParse(virDomainDefPtr def, xmlNodePtr *nodes = NULL; virBitmapPtr vcpus = NULL; virResctrlAllocPtr alloc = NULL; +virDomainResctrlDefPtr resctrl = NULL; + ssize_t i = 0; int n; int ret = -1; @@ -19234,15 +19241,18 @@ virDomainMemorytuneDefParse(virDomainDefPtr def, * just update the existing alloc information, which is done in above * virDomainMemorytuneDefParseMemory */ if (new_alloc) { -if (virDomainResctrlAppend(def, node, alloc, vcpus, flags) < 0) +resctrl = virDomainResctrlNew(node, &alloc, &vcpus, flags); +if (!resctrl) +goto cleanup; + +if (VIR_APPEND_ELEMENT(def->resctrls, def->nresctrls, resctrl) < 0) goto cleanup; -vcpus = NULL; -alloc = NULL; } ret = 0; cleanup: ctxt->node = oldnode; +virDomainResctrlDefFree(resctrl); virObjectUnref(alloc); virBitmapFree(vcpus); VIR_FREE(nodes); -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 07/18] util: Refactor code for creating resctrl group
The code for creating resctrl allocation group could be reused for monitoring group, refactor it for reuse in the later patch. Signed-off-by: Wang Huaqiang --- src/util/virresctrl.c | 37 +++-- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 4489ef9..cffacd3 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -2315,6 +2315,26 @@ virResctrlAllocDeterminePath(virResctrlAllocPtr alloc, } +/* This function creates a resctrl directory in resource control file system, + * and the directory path is specified by @path. */ +static int +virResctrlCreateGroupPath(const char *path) +{ +/* Directory exists, return */ +if (virFileExists(path)) +return 0; + +if (virFileMakePath(path) < 0) { +virReportSystemError(errno, + _("Cannot create resctrl directory '%s'"), + path); +return -1; +} + +return 0; +} + + /* This checks if the directory for the alloc exists. If not it tries to create * it and apply appropriate alloc settings. */ int @@ -2341,13 +2361,6 @@ virResctrlAllocCreate(virResctrlInfoPtr resctrl, if (virResctrlAllocIsEmpty(alloc)) return 0; -if (virFileExists(alloc->path)) { -virReportError(VIR_ERR_INTERNAL_ERROR, - _("Path '%s' for resctrl allocation exists"), - alloc->path); -goto cleanup; -} - lockfd = virResctrlLockWrite(); if (lockfd < 0) goto cleanup; @@ -2355,6 +2368,9 @@ virResctrlAllocCreate(virResctrlInfoPtr resctrl, if (virResctrlAllocAssign(resctrl, alloc) < 0) goto cleanup; +if (virResctrlCreateGroupPath(alloc->path) < 0) +goto cleanup; + alloc_str = virResctrlAllocFormat(alloc); if (!alloc_str) goto cleanup; @@ -2362,13 +2378,6 @@ virResctrlAllocCreate(virResctrlInfoPtr resctrl, if (virAsprintf(&schemata_path, "%s/schemata", alloc->path) < 0) goto cleanup; -if (virFileMakePath(alloc->path) < 0) { -virReportSystemError(errno, - _("Cannot create resctrl directory '%s'"), - alloc->path); -goto cleanup; -} - VIR_DEBUG("Writing resctrl schemata '%s' into '%s'", alloc_str, schemata_path); if (virFileWriteStr(schemata_path, alloc_str, 0) < 0) { rmdir(alloc->path); -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 08/18] util: Add interface for creating monitor group
Add interface for creating the resource monitoring group according to '@virResctrlMonitor->path'. Signed-off-by: Wang Huaqiang --- src/libvirt_private.syms | 1 + src/util/virresctrl.c| 24 src/util/virresctrl.h| 4 3 files changed, 29 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 01cd155..b47b60d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2681,6 +2681,7 @@ virResctrlInfoGetMonitorPrefix; virResctrlInfoMonFree; virResctrlInfoNew; virResctrlMonitorAddPID; +virResctrlMonitorCreate; virResctrlMonitorDeterminePath; virResctrlMonitorNew; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index cffacd3..e97127c 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -2539,3 +2539,27 @@ virResctrlMonitorAddPID(virResctrlMonitorPtr monitor, { return virResctrlAddPID(monitor->path, pid); } + + +int +virResctrlMonitorCreate(virResctrlMonitorPtr monitor, +const char *machinename) +{ +int lockfd = -1; +int ret = -1; + +if (!monitor) +return 0; + +if (virResctrlMonitorDeterminePath(monitor, machinename) < 0) +return -1; + +lockfd = virResctrlLockWrite(); +if (lockfd < 0) +return -1; + +ret = virResctrlCreateGroupPath(monitor->path); + +virResctrlUnlock(lockfd); +return ret; +} diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 52d283a..76e40a2 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -201,4 +201,8 @@ virResctrlMonitorDeterminePath(virResctrlMonitorPtr monitor, int virResctrlMonitorAddPID(virResctrlMonitorPtr monitor, pid_t pid); + +int +virResctrlMonitorCreate(virResctrlMonitorPtr monitor, +const char *machinename); #endif /* __VIR_RESCTRL_H__ */ -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 09/18] util: Add more interfaces for resctrl monitor
Add interfaces monitor group to support operations such as add PID, set ID, remove group ... etc. Signed-off-by: Wang Huaqiang --- src/libvirt_private.syms | 5 + src/util/virresctrl.c| 47 +++ src/util/virresctrl.h| 14 ++ 3 files changed, 66 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b47b60d..239b979 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2683,7 +2683,12 @@ virResctrlInfoNew; virResctrlMonitorAddPID; virResctrlMonitorCreate; virResctrlMonitorDeterminePath; +virResctrlMonitorGetID; virResctrlMonitorNew; +virResctrlMonitorRemove; +virResctrlMonitorSetAlloc; +virResctrlMonitorSetID; + # util/virrotatingfile.h virRotatingFileReaderConsume; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index e97127c..b4b63b6 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -2563,3 +2563,50 @@ virResctrlMonitorCreate(virResctrlMonitorPtr monitor, virResctrlUnlock(lockfd); return ret; } + + +int +virResctrlMonitorSetID(virResctrlMonitorPtr monitor, + const char *id) +{ +if (!id) { +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Resctrl monitor 'id' cannot be NULL")); +return -1; +} + +return VIR_STRDUP(monitor->id, id); +} + + +const char * +virResctrlMonitorGetID(virResctrlMonitorPtr monitor) +{ +return monitor->id; +} + + +void +virResctrlMonitorSetAlloc(virResctrlMonitorPtr monitor, + virResctrlAllocPtr alloc) +{ +monitor->alloc = virObjectRef(alloc); +} + + +int +virResctrlMonitorRemove(virResctrlMonitorPtr monitor) +{ +int ret = 0; + +if (!monitor->path) +return 0; + +VIR_DEBUG("Removing resctrl monitor%s", monitor->path); +if (rmdir(monitor->path) != 0 && errno != ENOENT) { +ret = -errno; +VIR_ERROR(_("Unable to remove %s (%d)"), monitor->path, errno); +} + +return ret; +} diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 76e40a2..804d6f5 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -205,4 +205,18 @@ virResctrlMonitorAddPID(virResctrlMonitorPtr monitor, int virResctrlMonitorCreate(virResctrlMonitorPtr monitor, const char *machinename); + +int +virResctrlMonitorSetID(virResctrlMonitorPtr monitor, + const char *id); + +const char * +virResctrlMonitorGetID(virResctrlMonitorPtr monitor); + +void +virResctrlMonitorSetAlloc(virResctrlMonitorPtr monitor, + virResctrlAllocPtr alloc); + +int +virResctrlMonitorRemove(virResctrlMonitorPtr monitor); #endif /* __VIR_RESCTRL_H__ */ -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 00/18] Introduce x86 Cache Monitoring Technology (CMT)
This series of patches and the series already been merged introduce the x86 Cache Monitoring Technology (CMT) to libvirt by interacting with kernel resource control (resctrl) interface. CMT is one of the Intel(R) x86 CPU feature which belongs to the Resource Director Technology (RDT). CMT reports the occupancy of the last level cache, which is shared by all CPU cores. In the v1 series, an original and complete feature for CMT was introduced The v2 and v3 patches address the feature for the host capability of CMT. v4 is addressing the feature for monitoring VM vcpu thread set cache occupancy and reporting it through a virsh command. We have serval discussion about the enabling of CMT, please refer to following links for the RFCs. RFCv3 https://www.redhat.com/archives/libvir-list/2018-August/msg01213.html RFCv2 https://www.redhat.com/archives/libvir-list/2018-July/msg00409.html https://www.redhat.com/archives/libvir-list/2018-July/msg01241.html RFCv1 https://www.redhat.com/archives/libvir-list/2018-June/msg00674.html And the merged commits are list as below, for host capability of CMT. 6af8417415508c31f8ce71234b573b4999f35980 8f6887998bf63594ae26e3db18d4d5896c5f2cb4 58fcee6f3a2b7e89c21c1fb4ec21429c31a0c5b8 12093f1feaf8f5023dcd9d65dff111022842183d a5d293c18831dcf69ec6195798387fbb70c9f461 1. About reason why CMT is necessary in libvirt? The perf events of 'CMT, MBML, MBMT' have been phased out since Linux kernel commit c39a0e2c8850f08249383f2425dbd8dbe4baad69, in libvirt the perf based cmt,mbm will not work with the latest linux kernel. These patches add CMT feature to libvirt through kernel resctrlfs interface. 2 Create cache monitoring group (cache monitor). The main interface for creating monitoring group is through XML file. The proposed configuration is like: + + In above XML, created 2 cache resctrl allocation groups and 2 resctrl monitoring groups. The changes of cache monitor will be effective in next booting of VM. 2 Show CMT result through command 'domstats' Adding the interface in qemu to report this information for resource monitor group through command 'virsh domstats --cpu-total'. Below is a typical output: # virsh domstats 1 --cpu-total Domain: 'ubuntu16.04-base' ... cpu.cache.monitor.count=2 cpu.cache.monitor.0.name=vcpus_1 cpu.cache.monitor.0.vcpus=1 cpu.cache.monitor.0.bank.count=2 cpu.cache.monitor.0.bank.0.id=0 cpu.cache.monitor.0.bank.0.bytes=4505600 cpu.cache.monitor.0.bank.1.id=1 cpu.cache.monitor.0.bank.1.bytes=5586944 cpu.cache.monitor.1.name=vcpus_4-6 cpu.cache.monitor.1.vcpus=4,5,6 cpu.cache.monitor.1.bank.count=2 cpu.cache.monitor.1.bank.0.id=0 cpu.cache.monitor.1.bank.0.bytes=17571840 cpu.cache.monitor.1.bank.1.id=1 cpu.cache.monitor.1.bank.1.bytes=29106176 Changes in v6: - Addressing John's review comments for v5. - Removed and cleaned the concepts of 'default allocation' and 'default monitor'. - qemu: virsh domstats --cpu-total output for CMT, add identifier 'monitor' for each itm. Changes in v5: - qemu: Setting up vcpu and adding pids to resctrl monitor groups during re-connection. - Add the document for domain configuration related to resctrl monitor. Changes in v4: v4 is addressing the feature for monitoring VM vcpu thread set cache occupancy and reporting it through a virsh command. - Introduced resctrl default allocation - Introduced resctrl monitor and default monitor Changes in v3: - Addressed John Ferlan's review. - Typo fixed. - Removed VIR_ENUM_DECL(virMonitor); Changes in v2: - Introduced MBM capability. - Capability layout changed * Moved from cahe to * Renamed to - Document for 'reuseThreshold' changed. - Introduced API virResctrlInfoGetMonitorPrefix - Added more tests, covering standalone CMT, fake new feature. - Creating CMT resource control group will be subsequent job. Wang Huaqiang (18): docs,util: Refactor schemas and virresctrl to support optional cache util: Introduce resctrl monitor for CMT util: Refactor code for determining allocation path util: Add interface to determine monitor path util: Refactor code for adding PID to the resource group util: Add interface for adding PID to the monitor util: Refactor code for creating resctrl group util: Add interface for creating monitor group util: Add more interfaces for resctrl monitor conf: Remove virDomainResctrlAppend and introduce virDomainResctrlNew conf: move virResctrlAllocIsEmpty to a place a litter lower conf: Introduce cache monitor element in cachetune qemu: enable resctrl monitor in qemu util: Add function for checking if monitor is running conf: Add 'id' to virDomainResctrlDef qemu: refactor qemuDomainGetStatsCpu qemu: Report cache occupancy (CMT) with domstats qemu: Setting up vcpu and adding pids to resctrl monitor gro
[libvirt] [PATCHv6 06/18] util: Add interface for adding PID to the monitor
Add interface for adding task PID to the monitor. Signed-off-by: Wang Huaqiang --- src/libvirt_private.syms | 1 + src/util/virresctrl.c| 8 src/util/virresctrl.h| 4 3 files changed, 13 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 19004bb..01cd155 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2680,6 +2680,7 @@ virResctrlInfoGetCache; virResctrlInfoGetMonitorPrefix; virResctrlInfoMonFree; virResctrlInfoNew; +virResctrlMonitorAddPID; virResctrlMonitorDeterminePath; virResctrlMonitorNew; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 014c2fc..4489ef9 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -2522,3 +2522,11 @@ virResctrlMonitorDeterminePath(virResctrlMonitorPtr monitor, return 0; } + + +int +virResctrlMonitorAddPID(virResctrlMonitorPtr monitor, +pid_t pid) +{ +return virResctrlAddPID(monitor->path, pid); +} diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index baae554..52d283a 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -197,4 +197,8 @@ virResctrlMonitorNew(void); int virResctrlMonitorDeterminePath(virResctrlMonitorPtr monitor, const char *machinename); + +int +virResctrlMonitorAddPID(virResctrlMonitorPtr monitor, +pid_t pid); #endif /* __VIR_RESCTRL_H__ */ -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 15/18] conf: Add 'id' to virDomainResctrlDef
Adding element 'id' to virDomainResctrlDef tracking resource group id, it reflects the attribute 'id' of of element in XML. virResctrlAlloc.id is a copy from virDomanResctrlDef.id. Signed-off-by: Wang Huaqiang --- src/conf/domain_conf.c | 20 src/conf/domain_conf.h | 1 + 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 01f795f..1aecd8c 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2980,6 +2980,7 @@ virDomainResctrlDefFree(virDomainResctrlDefPtr resctrl) virObjectUnref(resctrl->alloc); virBitmapFree(resctrl->vcpus); VIR_FREE(resctrl->monitors); +VIR_FREE(resctrl->id); VIR_FREE(resctrl); } @@ -19145,6 +19146,9 @@ virDomainResctrlNew(xmlNodePtr node, if (VIR_ALLOC(resctrl) < 0) goto cleanup; +if (VIR_STRDUP(resctrl->id, alloc_id) < 0) +goto cleanup; + if (!(resctrl->vcpus = virBitmapNewCopy(*vcpus))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("failed to copy 'vcpus'")); @@ -27323,13 +27327,9 @@ virDomainCachetuneDefFormat(virBufferPtr buf, virBufferAsprintf(buf, "alloc); -if (!alloc_id) -goto cleanup; +if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) +virBufferAsprintf(buf, " id='%s'", resctrl->id); -virBufferAsprintf(buf, " id='%s'", alloc_id); -} virBufferAddLit(buf, ">\n"); virBufferAddBuffer(buf, &childrenBuf); @@ -27386,13 +27386,9 @@ virDomainMemorytuneDefFormat(virBufferPtr buf, virBufferAsprintf(buf, "alloc); -if (!alloc_id) -goto cleanup; +if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) +virBufferAsprintf(buf, " id='%s'", resctrl->id); -virBufferAsprintf(buf, " id='%s'", alloc_id); -} virBufferAddLit(buf, ">\n"); virBufferAddBuffer(buf, &childrenBuf); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 60f6464..e190aa2 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2248,6 +2248,7 @@ typedef struct _virDomainResctrlDef virDomainResctrlDef; typedef virDomainResctrlDef *virDomainResctrlDefPtr; struct _virDomainResctrlDef { +char *id; virBitmapPtr vcpus; virResctrlAllocPtr alloc; -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 18/18] qemu: Setting up vcpu and adding pids to resctrl monitor groups during reconnection
Invoking qemuProcessSetupVcpus in process of VM reconnection. The vcpu pid information need to be refilled to resctrl monitor after a VM reconnection./ Signed-off-by: Wang Huaqiang --- src/qemu/qemu_process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index fba4fb4..ed0330b 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -8008,6 +8008,9 @@ qemuProcessReconnect(void *opaque) } } +if (qemuProcessSetupVcpus(obj) < 0) +goto error; + /* update domain state XML with possibly updated state in virDomainObj */ if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, obj, driver->caps) < 0) goto error; -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 17/18] qemu: Report cache occupancy (CMT) with domstats
Adding the interface in qemu to report CMT statistic information through command 'virsh domstats --cpu-total'. Below is a typical output: # virsh domstats 1 --cpu-total Domain: 'ubuntu16.04-base' ... cpu.cache.monitor.count=2 cpu.cache.monitor.0.name=vcpus_1 cpu.cache.monitor.0.vcpus=1 cpu.cache.monitor.0.bank.count=2 cpu.cache.monitor.0.bank.0.id=0 cpu.cache.monitor.0.bank.0.bytes=4505600 cpu.cache.monitor.0.bank.1.id=1 cpu.cache.monitor.0.bank.1.bytes=5586944 cpu.cache.monitor.1.name=vcpus_4-6 cpu.cache.monitor.1.vcpus=4,5,6 cpu.cache.monitor.1.bank.count=2 cpu.cache.monitor.1.bank.0.id=0 cpu.cache.monitor.1.bank.0.bytes=17571840 cpu.cache.monitor.1.bank.1.id=1 cpu.cache.monitor.1.bank.1.bytes=29106176 Signed-off-by: Wang Huaqiang --- src/libvirt-domain.c | 9 ++ src/libvirt_private.syms | 1 + src/qemu/qemu_driver.c | 229 +++ src/util/virresctrl.c| 130 +++ src/util/virresctrl.h| 12 +++ 5 files changed, 381 insertions(+) diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 7690339..4895f9f 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11345,6 +11345,15 @@ virConnectGetDomainCapabilities(virConnectPtr conn, * "cpu.user" - user cpu time spent in nanoseconds as unsigned long long. * "cpu.system" - system cpu time spent in nanoseconds as unsigned long *long. + * "cpu.cache.monitor.count" - tocal cache monitoring groups + * "cpu.cache.monitor.M.name" - name of cache monitoring group 'M' + * "cpu.cache.monitor.M.vcpus" - vcpus for cache monitoring group 'M' + * "cpu.cache.monitor.M.bank.count" - total bank number of cache monitoring + *group 'M' + * "cpu.cache.monitor.M.bank.N.id" - OS assigned cache bank id for cache + *'N' in cache monitoring group 'M' + * "cpu.cache.monitor.M.bank.N.bytes" - monitor's cache occupancy of cache + *bank 'N' in cache monitoring group 'M' * * VIR_DOMAIN_STATS_BALLOON: * Return memory balloon device information. diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index cbc86ce..64ff1d0 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2683,6 +2683,7 @@ virResctrlInfoNew; virResctrlMonitorAddPID; virResctrlMonitorCreate; virResctrlMonitorDeterminePath; +virResctrlMonitorGetCacheOccupancy; virResctrlMonitorGetID; virResctrlMonitorIsRunning; virResctrlMonitorNew; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 12a5f8f..9828118 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -102,6 +102,7 @@ #include "virnuma.h" #include "dirname.h" #include "netdev_bandwidth_conf.h" +#include "c-ctype.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -19698,6 +19699,230 @@ typedef enum { #define HAVE_JOB(flags) ((flags) & QEMU_DOMAIN_STATS_HAVE_JOB) +/* In terms of the output of virBitmapFormat, both '1-3' and '1,3' are valid + * outputs and represent different vcpu set. But it is not easy to + * differentiate these two vcpu set formats at first glance. + * + * This function could be used to clear this ambiguity, it substitutes all '-' + * with ',' while generates semantically correct vcpu set. + * e.g. vcpu set string '1-3' will be replaced by string '1,2,3'. */ +static char * +qemuDomainVcpuFormatHelper(const char *vcpus) +{ +size_t i = 0; +int last = 0; +int start = 0; +char * tmp = NULL; +bool firstnum = true; +const char *cur = vcpus; +virBuffer buf = VIR_BUFFER_INITIALIZER; +char *ret = NULL; + +if (virStringIsEmpty(cur)) +return NULL; + +while (*cur != '\0') { +if (!c_isdigit(*cur)) +goto cleanup; + +if (virStrToLong_i(cur, &tmp, 10, &start) < 0) +goto cleanup; +if (start < 0) +goto cleanup; + +cur = tmp; + +virSkipSpaces(&cur); + +if (*cur == ',' || *cur == 0) { +if (!firstnum) +virBufferAddChar(&buf, ','); +virBufferAsprintf(&buf, "%d", start); +firstnum = false; +} else if (*cur == '-') { +cur++; +virSkipSpaces(&cur); + +if (virStrToLong_i(cur, &tmp, 10, &last) < 0) +goto cleanup; + +if (last < start) +goto cleanup; +cur = tmp; + +for (i = start; i <= last; i++) { +if (!firstnum) + +virBufferAddChar(&buf, ','); +virBufferAsprintf(&buf, "%ld", i); +firstnum = 0; +} + +virSkipSpaces(&cur); +} + +if (*cur == ',') { +cur++; +virSkipSpaces(&cur); +
[libvirt] [PATCHv6 05/18] util: Refactor code for adding PID to the resource group
The code of adding PID to the allocation could be reused, refactor it for later reuse. Signed-off-by: Wang Huaqiang --- src/util/virresctrl.c | 30 +++--- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 794de87..014c2fc 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -2387,26 +2387,21 @@ virResctrlAllocCreate(virResctrlInfoPtr resctrl, } -int -virResctrlAllocAddPID(virResctrlAllocPtr alloc, - pid_t pid) +static int +virResctrlAddPID(const char *path, + pid_t pid) { char *tasks = NULL; char *pidstr = NULL; int ret = 0; -/* If the allocation is empty, then it is impossible to add a PID to - * allocation due to lacking of its 'tasks' file. Just return */ -if (virResctrlAllocIsEmpty(alloc)) -return 0; - -if (!alloc->path) { +if (!path) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot add pid to non-existing resctrl allocation")); + _("Cannot add pid to non-existing resctrl group")); return -1; } -if (virAsprintf(&tasks, "%s/tasks", alloc->path) < 0) +if (virAsprintf(&tasks, "%s/tasks", path) < 0) return -1; if (virAsprintf(&pidstr, "%lld", (long long int) pid) < 0) @@ -2428,6 +2423,19 @@ virResctrlAllocAddPID(virResctrlAllocPtr alloc, int +virResctrlAllocAddPID(virResctrlAllocPtr alloc, + pid_t pid) +{ +/* If allocation is empty, then no resctrl directory and the 'tasks' file + * exists, just return */ +if (virResctrlAllocIsEmpty(alloc)) +return 0; + +return virResctrlAddPID(alloc->path, pid); +} + + +int virResctrlAllocRemove(virResctrlAllocPtr alloc) { int ret = 0; -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 01/18] docs, util: Refactor schemas and virresctrl to support optional cache
Refactor schemas and virresctrl to support optional element in . Later, the monitor entry will be introduced and to be placed under . Either cache entry or monitor entry is an optional element of . An cachetune has no element is taking the default resource allocating policy defined in '/sys/fs/resctrl/schemata'. Signed-off-by: Wang Huaqiang --- docs/formatdomain.html.in | 4 ++-- docs/schemas/domaincommon.rng | 4 ++-- src/util/virresctrl.c | 31 --- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 8189959..b1651e3 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -943,8 +943,8 @@ cache -This element controls the allocation of CPU cache and has the -following attributes: +This optional element controls the allocation of CPU cache and has +the following attributes: level diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 099a949..5c533d6 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -956,7 +956,7 @@ - + @@ -980,7 +980,7 @@ - + diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 5d811a2..d54d85f 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -234,6 +234,11 @@ virResctrlInfoMonFree(virResctrlInfoMonPtr mon) * in case there is no allocation for that particular cache allocation (level, * cache, ...) or memory allocation for particular node). * + * Allocation corresponding to root directory, /sys/fs/sysctrl/, defines the + * default resource allocating policy, which is created immediately after + * mounting, and owns all the tasks and cpus in the system. Cache or memory + * bandwidth resource will be shared for tasks in this allocation. + * * =Cache allocation technology (CAT)= * * Since one allocation can be made for caches on different levels, the first @@ -2215,6 +2220,15 @@ virResctrlAllocDeterminePath(virResctrlAllocPtr alloc, return -1; } +/* If the allocation is empty, then the path will be SYSFS_RESCTRL_PATH */ +if (virResctrlAllocIsEmpty(alloc)) { +if (!alloc->path && +VIR_STRDUP(alloc->path, SYSFS_RESCTRL_PATH) < 0) +return -1; + +return 0; +} + if (!alloc->path && virAsprintf(&alloc->path, "%s/%s-%s", SYSFS_RESCTRL_PATH, machinename, alloc->id) < 0) @@ -2236,9 +2250,6 @@ virResctrlAllocCreate(virResctrlInfoPtr resctrl, int ret = -1; int lockfd = -1; -if (!alloc) -return 0; - if (virResctrlInfoIsEmpty(resctrl)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Resource control is not supported on this host")); @@ -2248,6 +2259,11 @@ virResctrlAllocCreate(virResctrlInfoPtr resctrl, if (virResctrlAllocDeterminePath(alloc, machinename) < 0) return -1; +/* If the allocation is empty, then do not create directory in underlying + * resctrl file system */ +if (virResctrlAllocIsEmpty(alloc)) +return 0; + if (virFileExists(alloc->path)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Path '%s' for resctrl allocation exists"), @@ -2302,6 +2318,11 @@ virResctrlAllocAddPID(virResctrlAllocPtr alloc, char *pidstr = NULL; int ret = 0; +/* If the allocation is empty, then it is impossible to add a PID to + * allocation due to lacking of its 'tasks' file. Just return */ +if (virResctrlAllocIsEmpty(alloc)) +return 0; + if (!alloc->path) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Cannot add pid to non-existing resctrl allocation")); @@ -2334,6 +2355,10 @@ virResctrlAllocRemove(virResctrlAllocPtr alloc) { int ret = 0; +/* No directory have ever been created. Just return */ +if (virResctrlAllocIsEmpty(alloc)) +return 0; + if (!alloc->path) return 0; -- 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv6 12/18] conf: Introduce cache monitor element in cachetune
Introducing element under to represent a cache monitor. Signed-off-by: Wang Huaqiang --- docs/formatdomain.html.in | 26 +++ docs/schemas/domaincommon.rng | 10 + src/conf/domain_conf.c | 234 - src/conf/domain_conf.h | 11 + tests/genericxml2xmlindata/cachetune-cdp.xml | 3 + .../cachetune-colliding-monitor.xml| 30 +++ tests/genericxml2xmlindata/cachetune-small.xml | 7 + tests/genericxml2xmltest.c | 2 + 8 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 tests/genericxml2xmlindata/cachetune-colliding-monitor.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index b1651e3..2fd665c 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -759,6 +759,12 @@+ + + + + + @@ -978,6 +984,26 @@ + monitor + +The optional element monitor creates the cache +monitor(s) for current cache allocation and has the following +required attributes: + + level + +Host cache level the monitor belongs to. + + vcpus + +vCPU list the monitor applies to. A monitor's vCPU list +can only be the member(s) of the vCPU list of associating +allocation. The default monitor has the same vCPU list as the +associating allocation. For non-default monitors, there +are no vCPU overlap permitted. + + + diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 5c533d6..7ce49d3 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -981,6 +981,16 @@ + + + + + + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index a068d4d..01f795f 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2955,13 +2955,31 @@ virDomainLoaderDefFree(virDomainLoaderDefPtr loader) static void +virDomainResctrlMonDefFree(virDomainResctrlMonDefPtr domresmon) +{ +if (!domresmon) +return; + +virBitmapFree(domresmon->vcpus); +virObjectUnref(domresmon->instance); +VIR_FREE(domresmon); +} + + +static void virDomainResctrlDefFree(virDomainResctrlDefPtr resctrl) { +size_t i = 0; + if (!resctrl) return; +for (i = 0; i < resctrl->nmonitors; i++) +virDomainResctrlMonDefFree(resctrl->monitors[i]); + virObjectUnref(resctrl->alloc); virBitmapFree(resctrl->vcpus); +VIR_FREE(resctrl->monitors); VIR_FREE(resctrl); } @@ -18920,6 +18938,177 @@ virDomainCachetuneDefParseCache(xmlXPathContextPtr ctxt, } +/* Checking if the monitor's vcpus is conflicted with existing allocation + * and monitors. + * + * Returns 1 if @vcpus equals to @resctrl->vcpus, then the monitor will + * share the underlying resctrl group with @resctrl->alloc. Returns - 1 + * if any conflict found. Returns 0 if no conflict and @vcpus is not equal + * to @resctrl->vcpus. + */ +static int +virDomainResctrlMonValidateVcpus(virDomainResctrlDefPtr resctrl, +virBitmapPtr vcpus) +{ +size_t i = 0; +int vcpu = -1; +size_t mons_same_alloc_vcpus = 0; + +if (virBitmapIsAllClear(vcpus)) { +virReportError(VIR_ERR_INVALID_ARG, "%s", + _("vcpus is empty")); +return -1; +} + +while ((vcpu = virBitmapNextSetBit(vcpus, vcpu)) >= 0) { +if (!virBitmapIsBitSet(resctrl->vcpus, vcpu)) { +virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Monitor vcpus conflicts with allocation")); +return -1; +} +} + +if (virBitmapEqual(vcpus, resctrl->vcpus)) +return 1; + +for (i = 0; i < resctrl->nmonitors; i++) { +if (virBitmapEqual(resctrl->vcpus, resctrl->monitors[i]->vcpus)) { +mons_same_alloc_vcpus++; +continue; +} + +if (virBitmapOverlaps(vcpus, resctrl->monitors[i]->vcpus)) { +virReportError(VIR_ERR_INVALID_ARG, "%s", +
[libvirt] [PATCHv6 02/18] util: Introduce resctrl monitor for CMT
Cache Monitoring Technology (aka CMT) provides the capability to report cache utilization information of system task. This patch introduces the concept of resctrl monitor through data structure virResctrlMonitor. Signed-off-by: Wang Huaqiang --- src/libvirt_private.syms | 2 +- src/util/virresctrl.c| 79 src/util/virresctrl.h| 9 ++ 3 files changed, 83 insertions(+), 7 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 335210c..9577b70 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2680,7 +2680,7 @@ virResctrlInfoGetCache; virResctrlInfoGetMonitorPrefix; virResctrlInfoMonFree; virResctrlInfoNew; - +virResctrlMonitorNew; # util/virrotatingfile.h virRotatingFileReaderConsume; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index d54d85f..578a52c 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -36,9 +36,9 @@ VIR_LOG_INIT("util.virresctrl") /* Resctrl is short for Resource Control. It might be implemented for various - * resources. Currently this supports cache allocation technology (aka CAT) and - * memory bandwidth allocation (aka MBA). More resources technologies may be - * added in the future. + * resources. Currently this supports cache allocation technology (aka CAT), + * memory bandwidth allocation (aka MBA) and cache monitoring technology (aka + * CMT). More resources technologies may be added in the future. */ @@ -105,6 +105,7 @@ typedef virResctrlAllocMemBW *virResctrlAllocMemBWPtr; /* Class definitions and initializations */ static virClassPtr virResctrlInfoClass; static virClassPtr virResctrlAllocClass; +static virClassPtr virResctrlMonitorClass; /* virResctrlInfo */ @@ -224,11 +225,16 @@ virResctrlInfoMonFree(virResctrlInfoMonPtr mon) } -/* virResctrlAlloc */ +/* virResctrlAlloc and virResctrlMonitor*/ /* - * virResctrlAlloc represents one allocation (in XML under cputune/cachetune and - * consequently a directory under /sys/fs/resctrl). Since it can have multiple + * virResctrlAlloc and virResctrlMonitor are representing a resource control + * group (in XML under cputune/cachetune and consequently a directory under + * /sys/fs/resctrl). virResctrlAlloc is the data structure for resource + * allocation, while the virResctrlMonitor represents the resource monitoring + * part. + * + * virResctrlAlloc represents one allocation. Since it can have multiple * parts of multiple caches allocated it is represented as bunch of nested * sparse arrays (by sparse I mean array of pointers so that each might be NULL * in case there is no allocation for that particular cache allocation (level, @@ -275,6 +281,18 @@ virResctrlInfoMonFree(virResctrlInfoMonPtr mon) * a sparse array to represent whether a memory bandwidth allocation happens * on corresponding node. The available memory controller number is collected * in 'virResctrlInfo'. + * + * =Cache monitoring technology (CMT)= + * + * Cache monitoring technology is used to perceive how many cache the process + * is using actually. virResctrlMonitor represents the resource control + * monitoring group, it is supported to monitor resource utilization + * information on granularity of vcpu. + * + * From hardware perspective, cache monitoring technology (CMT), memory + * bandwidth technology (MBM), as well as the CAT and MBA, are all orthogonal + * features. The monitor will be created under the scope of default resctl + * group if no specific CAT or MBA entries are provided for the guest." */ struct _virResctrlAllocPerType { /* There could be bool saying whether this is set or not, but since everything @@ -320,6 +338,29 @@ struct _virResctrlAlloc { char *path; }; +/* + * virResctrlMonitor is the data structure for resctrl monitor. Resctrl + * monitor represents a resctrl monitoring group, which can be used to + * monitor the resource utilization information for either cache or + * memory bandwidth. + */ +struct _virResctrlMonitor { +virObject parent; + +/* In resctrl, each monitor is associated with one specific allocation, + * either the allocation under / sys / fs / resctrl or allocation of the + * root directory itself. This pointer points to the allocation + * this monitor associated with. */ +virResctrlAllocPtr alloc; +/* The monitor identifier. For a monitor has the same @path name as its + * @alloc, the @id will be set to the same value as it is in @alloc->id. + */ +char *id; +/* libvirt-generated path in /sys/fs/resctrl for this particular + * monitor */ +char *path; +}; + static void virResctrlAllocDispose(void *obj) @@ -369,6 +410,17 @@ virResctrlAllocDispose(void *obj) } +static void +virResctrlMonitorDispose(void *obj) +{ +virResctrlMonitorPtr monitor = obj; + +virObjectUnref(monitor->alloc); +VIR_FREE(monitor->id); +VIR_FREE(monitor->path); +} + + /*