[libvirt] [PATCH] build: hoist system-specific checks before library checks
by Eric Blake
Commit f92c7e3 fixed a regression for native builds, but introduced
a regression for cross-compilation builds; in particular,
./autobuild.sh on a Fedora system with mingw cross-compiler fails
with:
checking for qemu-kvm... /usr/bin/qemu-kvm
checking for yajl_parse_complete in -lyajl... no
checking for yajl_tree_parse in -lyajl... no
configure: error: You must install the libyajl library & headers to compile libvirt
Since we default $with_qemu to 'yes' rather than 'check', and then
flip that default based on platform-specific checks, those platform
specifics need to come prior to any library checks that depend on
the value of $with_qemu.
* configure.ac: Ensure system defaults are sane before checking
for things that make decisions based on system default.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
I'm tempted to push this under the build-breaker rule, so that
I can get a successful ./autobuild.sh run.
configure.ac | 85 +++++++++++++++++++++++++++++++-----------------------------
1 file changed, 44 insertions(+), 41 deletions(-)
diff --git a/configure.ac b/configure.ac
index 39b5fd5..69a01ae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -160,6 +160,50 @@ VERSION_SCRIPT_FLAGS=-Wl,--version-script=
VERSION_SCRIPT_FLAGS="-Wl,-M -Wl,"
AC_MSG_RESULT([$VERSION_SCRIPT_FLAGS])
+dnl Specify if we rely on ifconfig instead of iproute2 (e.g. in case
+dnl we're working on BSD)
+want_ifconfig=no
+
+dnl Make some notes about which OS we're compiling for, as the lxc and qemu
+dnl drivers require linux headers, and storage_mpath, dtrace, and nwfilter
+dnl are also linux specific. The "network" and storage_fs drivers are known
+dnl to not work on MacOS X presently, so we also make a note if compiling
+dnl for that
+
+with_linux=no with_osx=no with_freebsd=no
+case $host in
+ *-*-linux*) with_linux=yes ;;
+ *-*-darwin*) with_osx=yes ;;
+ *-*-freebsd*) with_freebsd=yes ;;
+esac
+
+if test $with_linux = no; then
+ if test "x$with_lxc" != xyes
+ then
+ with_lxc=no
+ fi
+ with_dtrace=no
+fi
+
+if test $with_freebsd = yes; then
+ want_ifconfig=yes
+
+ with_firewalld=no
+fi
+
+if test $with_osx = yes; then
+ with_qemu=no
+fi
+
+AM_CONDITIONAL([WITH_LINUX], [test "$with_linux" = "yes"])
+AM_CONDITIONAL([WITH_FREEBSD], [test "$with_freebsd" = "yes"])
+
+if test "$with_libvirtd" = "no" ; then
+ with_qemu=no
+fi
+
+# Check for compiler and library settings.
+
LIBVIRT_COMPILE_WARNINGS
LIBVIRT_COMPILE_PIE
LIBVIRT_LINKER_RELRO
@@ -391,44 +435,6 @@ if test "$prefix" = "/usr" && test "$sysconfdir" = '${prefix}/etc' ; then
sysconfdir='/etc'
fi
-dnl Specify if we rely on ifconfig instead of iproute2 (e.g. in case
-dnl we're working on BSD)
-want_ifconfig=no
-
-dnl Make some notes about which OS we're compiling for, as the lxc and qemu
-dnl drivers require linux headers, and storage_mpath, dtrace, and nwfilter
-dnl are also linux specific. The "network" and storage_fs drivers are known
-dnl to not work on MacOS X presently, so we also make a note if compiling
-dnl for that
-
-with_linux=no with_osx=no with_freebsd=no
-case $host in
- *-*-linux*) with_linux=yes ;;
- *-*-darwin*) with_osx=yes ;;
- *-*-freebsd*) with_freebsd=yes ;;
-esac
-
-if test $with_linux = no; then
- if test "x$with_lxc" != xyes
- then
- with_lxc=no
- fi
- with_dtrace=no
-fi
-
-if test $with_freebsd = yes; then
- want_ifconfig=yes
-
- with_firewalld=no
-fi
-
-if test $with_osx = yes; then
- with_qemu=no
-fi
-
-AM_CONDITIONAL([WITH_LINUX], [test "$with_linux" = "yes"])
-AM_CONDITIONAL([WITH_FREEBSD], [test "$with_freebsd" = "yes"])
-
dnl Allow to build without Xen, QEMU/KVM, test or remote driver
AC_ARG_WITH([xen],
[AS_HELP_STRING([--with-xen],
@@ -721,9 +727,6 @@ if test "x$with_vbox" = "xyes"; then
fi
AM_CONDITIONAL([WITH_VBOX], [test "$with_vbox" = "yes"])
-if test "$with_libvirtd" = "no" ; then
- with_qemu=no
-fi
if test "$with_qemu" = "yes" ; then
AC_DEFINE_UNQUOTED([WITH_QEMU], 1, [whether QEMU driver is enabled])
fi
--
1.8.3.1
11 years, 2 months
[libvirt] [PATCH] build: skip ld_preload tests on non-Linux systems
by Eric Blake
A cross build to mingw fails with:
CC virsystemdtest-virsystemdtest.o
../../tests/virsystemdtest.c: In function 'testCreateNoSystemd':
../../tests/virsystemdtest.c:97:9: error: implicit declaration of function 'unsetenv' [-Werror=implicit-function-declaration]
unsetenv("FAIL_NO_SERVICE");
^
../../tests/virsystemdtest.c:97:9: error: nested extern declaration of 'unsetenv' [-Werror=nested-externs]
We could cop out and pull in the gnulib unsetenv module. But when
you stop and think about it, this test requires LD_PRELOAD to work,
and systemd is a Linux-only concept anyways, both of which mean
the test could never work on mingw in the first place. Simpler is
to just fix the test to behave like our other LD_PRELOAD tests.
* tests/virsystemdtest.c: Provide non-Linux implementation.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
Pushing under the build-breaker rule.
tests/virsystemdtest.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/tests/virsystemdtest.c b/tests/virsystemdtest.c
index 7dc7520..e68b3ac 100644
--- a/tests/virsystemdtest.c
+++ b/tests/virsystemdtest.c
@@ -20,13 +20,16 @@
#include <config.h>
-#include <stdlib.h>
-
-#include "virsystemd.h"
-#include "virlog.h"
#include "testutils.h"
-#define VIR_FROM_THIS VIR_FROM_NONE
+#ifdef __linux__
+
+# include <stdlib.h>
+
+# include "virsystemd.h"
+# include "virlog.h"
+
+# define VIR_FROM_THIS VIR_FROM_NONE
static int testCreateContainer(const void *opaque ATTRIBUTE_UNUSED)
{
@@ -188,7 +191,7 @@ mymain(void)
if (virtTestRun("Test create bad systemd ", 1, testCreateBadSystemd, NULL) < 0)
ret = -1;
-#define TEST_SCOPE(name, partition, unitname) \
+# define TEST_SCOPE(name, partition, unitname) \
do { \
struct testScopeData data = { \
name, partition, unitname \
@@ -209,3 +212,11 @@ mymain(void)
}
VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virsystemdmock.so")
+
+#else
+int
+main(void)
+{
+ return EXIT_AM_SKIP;
+}
+#endif
--
1.8.3.1
11 years, 2 months
Re: [libvirt] openvswitch vlan support when not a forwarded network
by Ajith Antony
Thank you Laine, for your prompt reply. Adding the dev list to broaden the
audience.
On Mon, Sep 16, 2013 at 9:21 AM, Laine Stump <laine(a)laine.org> wrote:
On 09/16/2013 07:32 AM, Ajith Antony wrote:
>> Hi, I'm not sure what the best way to pursue this is, but since it
>> appears you authored the relevant code, you could advise of a good
>> next step.
>
> Kind of. I think I wrote code for hostdev networks, but the original was
> (if I remember correctly) written by Kyle Mestery with support only for
> openvswitch.
>
>> I'm trying to use libvirt to set up openvswitch vlans, but ran into a
>> problem where the libvirt code is precluding using vlans if the
>> network is not "Forwarded."[1] I don't think there is any technical
>> reason not to support vlans for non-forwarded networks. I verified
>> this by manually adding vlan tags to the ephemeral ports created by
>> the libvirt network definition. The tags worked as expected.
>> [1] http://libvirt.org/git/?p=libvirt.git;a=blob;f=src/network/bridge_driver....
>
> You're misunderstanding the intent (at least) of that if condition. The
> way that you configure a libvirt network to use openvswitch is with the
> following:
>
> <forward mode='bridge'/>
> <virtualport type='openvswitch'>
> <some other stuff I forget/>
> </virtualport>
>
> That condition is only checking if:
>
> vlanAllowed = ((def->forward.type == VIR_NETWORK_FORWARD_BRIDGE &&
>
>
> 1) forward mode is 'bridge' (this doesn't necessarily mean that anything
> will be forwarded beyond the bridge that the guest's network device is
> connected to, only that it is connected to a bridge, i.e. as far as
> libvirt is concerned any forwarding that *is* done will be L2
> forwarding. The specifics of how that happens are left up to the bridge.)
Yes, I think this the test that interests me. The key fact in my scenario is
that I'm not preconfiguring a bridge. I wouldn't be able to set the forward
mode as 'bridge' unless I already prepared a bridge. I recongize that if I
prepared a bridge that I could add more portgroups to it with thier unique vlan
tags and not expect anything to actually cross the physical interface. I think
this is what is is reccomended among the blogs when one searches for
"openvswitch fake bridge."
> You'll need to post a copy of your network config for me to understand
> for sure, but I'm guessing that you're missing one of the two items in
> your config, possibly indicating that you've misunderstood how to
> configure a libvirt network that uses an openvswitch bridge.
>
> So can you send a copy of your network XML?
The network that I'm trying to define is described as the following. Note
there there is no <forward> element as I'm not expcting there to be a *real*
bridge and I don't expect that I need to preconfigre explicit bridges. I
expect an ephemeral virtual bridge to be created.
<network>
<name>ajith-net1</name>
<virtualport type='openvswitch'/>
<portgroup name='client_lan'>
<vlan>
<tag id='1'/>
</vlan>
</portgroup>
<portgroup name='client_wan'>
<vlan>
<tag id='2'/>
</vlan>
</portgroup>
</network>
When I include the VLAN tags I get the error:
error: unsupported configuration: <vlan> element specified for network
ajith-net1, whose type doesn't support vlan configuration
When I omit the VLAN tags as follows I am able to create the network:
<network>
<name>ajith-net1</name>
<virtualport type='openvswitch'/>
<portgroup name='client_lan'>
</portgroup>
<portgroup name='client_wan'>
</portgroup>
</network>
In my domain configs I specify the network like so:
<interface type='network'>
<source network='ajith-net1' portgroup='client_lan'/>
<virtualport type='openvswitch'/>
<model type='virtio'/>
</interface>
The resulting ephemeral bridge(virbr1) looks like the following when my
network(w/o vlans) and two domains are started. I don't know if the portgroup
was meaningful, but it was accepted in the definition:
$ sudo ovs-vsctl show
<...>
Bridge "virbr1"
Port "vnet23"
Interface "vnet23"
Port "vnet25"
Interface "vnet25"
Port "virbr1"
Interface "virbr1"
type: internal
Port "virbr1-nic"
Interface "virbr1-nic"
ovs_version: "1.9.3"
My goal is assign unique vlan tags to the two portgroups. While the network
and the domains are started, I can manually add tags to the ports:
$ sudo ovs-vsctl set port vnet25 tag=2
$ sudo ovs-vsctl set port vnet23 tag=1
$ sudo ovs-vsctl show
Bridge "virbr1"
Port "vnet23"
tag: 1
Interface "vnet23"
Port "vnet25"
tag: 2
Interface "vnet25"
Port "virbr1"
Interface "virbr1"
type: internal
Port "virbr1-nic"
Interface "virbr1-nic"
ovs_version: "1.9.3"
This configuration behaves exactly as I want. I'm interested to learn how to
prepare this without the manual step of tagging the ports outside of the
libvirt operations.
Ultimately my goal is to prepare isolated test environments that consist of
several VM's attached to a similar qty of vlans. I intend to create many of
these environments per host. I also recongnize that instead of portgroups, I
could use separate networks altogether. From an administrative standpoint, I'd
prefer to have one "network" per test environment, with several portgroups,
instead of *many* networks.
FWIW, I'm doing something similar on ESX, where I create a "vSwitch" and then
create several "portgroups", each with its own vlan tag. These vSwitches are
not attached to any physical interfaces. (My esx work is directly against the
vsphere API, so I'm not sure if the same could be configured via libvirt) I'm
looking to port this work to KVM. It seems like a pretty natural thing to
support.
11 years, 2 months
[libvirt] [PATCH] maint: ignore recently-added test
by Eric Blake
* .gitignore: Ignore metadatatest.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
Pushing under the trivial rule.
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 2b8652f..d70d0dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -166,6 +166,7 @@
/tests/hashtest
/tests/jsontest
/tests/libvirtdconftest
+/tests/metadatatest
/tests/networkxml2argvtest
/tests/nodeinfotest
/tests/nwfilterxml2xmltest
--
1.8.3.1
11 years, 2 months
[libvirt] [PATCH libvirt-java] Set source and target version to Java 1.6
by Wido den Hollander
On platforms with Java 1.7 it will still produce compatible code
with Java 1.6 platforms
Java 1.6 is still out there and widely used.
Signed-off-by: Wido den Hollander <wido(a)widodh.nl>
---
build.properties | 2 ++
build.xml | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/build.properties b/build.properties
index 679a271..7721f90 100644
--- a/build.properties
+++ b/build.properties
@@ -2,5 +2,7 @@ version=0.5.0
release=1
libvirt.required=0.9.12
java.required=1:1.5.0
+java.target=1.6
+java.source=1.6
rpm.topdir=/home/veillard/rpms
jar.dir=/usr/share/java
diff --git a/build.xml b/build.xml
index 61b15bb..acd9c92 100644
--- a/build.xml
+++ b/build.xml
@@ -52,7 +52,7 @@
destdir="target/testclasses"
cache="target/cache"
closure="true" />
- <javac srcdir="src/test/java" debug="${javac.debug}" includes="**/*.java" classpathref="test.classpath" destdir="target/testclasses" includeAntRuntime="false" />
+ <javac srcdir="src/test/java" debug="${javac.debug}" source="${java.source}" target="${java.target}" includes="**/*.java" classpathref="test.classpath" destdir="target/testclasses" includeAntRuntime="false" />
</target>
<target name="build" depends="init" description="builds the code">
@@ -60,7 +60,7 @@
destdir="target/classes"
cache="target/cache"
closure="true" />
- <javac srcdir="src/main/java" debug="${javac.debug}" includes="**/*.java" classpathref="compile.classpath" destdir="target/classes" includeAntRuntime="false" />
+ <javac srcdir="src/main/java" debug="${javac.debug}" source="${java.source}" target="${java.target}" includes="**/*.java" classpathref="compile.classpath" destdir="target/classes" includeAntRuntime="false" />
</target>
<target name="test" depends="buildtests" description="tests the code">
--
1.7.9.5
11 years, 2 months
[libvirt] [PATCH 0/2] Add support for device blkio iops and bps throttle
by hzguanqiang@gmail.com
From: Guan Qiang <hzguanqiang(a)corp.netease.com>
The patches add support for setting/getting blkio read/write bps/iops
throttle per-device with blkio cgroup.
Guan Qiang (2):
blkiotune: add support for device iops and bps throttle
blkiotune: add virsh support for blkiotune.throttle.iops/bps
docs/formatdomain.html.in | 8 +
docs/schemas/domaincommon.rng | 28 +-
include/libvirt/libvirt.h.in | 40 ++
src/conf/domain_conf.c | 115 +++-
src/conf/domain_conf.h | 16 +-
src/libvirt_private.syms | 4 +-
src/lxc/lxc_cgroup.c | 9 +-
src/qemu/qemu_cgroup.c | 10 +-
src/qemu/qemu_driver.c | 579 ++++++++++++++++++--
src/util/vircgroup.c | 79 ++-
src/util/vircgroup.h | 8 +-
.../qemuxml2argv-blkiotune-device.xml | 4 +
tools/virsh-domain.c | 64 +++
tools/virsh.pod | 32 +-
14 files changed, 883 insertions(+), 113 deletions(-)
--
1.7.9.5
11 years, 2 months
[libvirt] [PATCH 2/2] blkiotune: add virsh support for blkiotune.throttle.iops/bps
by hzguanqiang@gmail.com
From: Guan Qiang <hzguanqiang(a)corp.netease.com>
This adds four parameters --device-read-bps, --device-write-bps, --device-read-iops
and --device-write-iops to virsh command blkiotune for setting/getting
blkiotune.throttle.{read/write}_{iops/bps}_device.
---
tools/virsh-domain.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
tools/virsh.pod | 32 +++++++++++++++++++++++--
2 files changed, 94 insertions(+), 2 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 49cd154..2830d6a 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -1252,6 +1252,22 @@ static const vshCmdOptDef opts_blkiotune[] = {
.type = VSH_OT_STRING,
.help = N_("per-device IO Weights, in the form of /path/to/device,weight,...")
},
+ {.name = "device-read-bps",
+ .type = VSH_OT_STRING,
+ .help = N_("per-device read throughput limit in bytes per second, in the form of /path/to/device,read_bps,...")
+ },
+ {.name = "device-write-bps",
+ .type = VSH_OT_STRING,
+ .help = N_("per-device write throughput limit in bytes per second, in the form of /path/to/device,write_bps,...")
+ },
+ {.name = "device-read-iops",
+ .type = VSH_OT_STRING,
+ .help = N_("per-device read I/O operations limit per second, in the form of /path/to/device,read_iops,...")
+ },
+ {.name = "device-write-iops",
+ .type = VSH_OT_STRING,
+ .help = N_("per-device write I/O operations limit per second, in the form of /path/to/device,write_iops,...")
+ },
{.name = "config",
.type = VSH_OT_BOOL,
.help = N_("affect next boot")
@@ -1272,6 +1288,10 @@ cmdBlkiotune(vshControl * ctl, const vshCmd * cmd)
{
virDomainPtr dom;
const char *device_weight = NULL;
+ const char *device_read_bps = NULL;
+ const char *device_write_bps = NULL;
+ const char *device_read_iops = NULL;
+ const char *device_write_iops = NULL;
int weight = 0;
int nparams = 0;
int maxparams = 0;
@@ -1319,6 +1339,50 @@ cmdBlkiotune(vshControl * ctl, const vshCmd * cmd)
goto save_error;
}
+ rv = vshCommandOptString(cmd, "device-read-bps", &device_read_bps);
+ if (rv < 0) {
+ vshError(ctl, "%s", _("Unable to parse string parameter"));
+ goto cleanup;
+ } else if (rv > 0) {
+ if (virTypedParamsAddString(¶ms, &nparams, &maxparams,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_BPS,
+ device_read_bps) < 0)
+ goto save_error;
+ }
+
+ rv = vshCommandOptString(cmd, "device-write-bps", &device_write_bps);
+ if (rv < 0) {
+ vshError(ctl, "%s", _("Unable to parse string parameter"));
+ goto cleanup;
+ } else if (rv > 0) {
+ if (virTypedParamsAddString(¶ms, &nparams, &maxparams,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_BPS,
+ device_write_bps) < 0)
+ goto save_error;
+ }
+
+ rv = vshCommandOptString(cmd, "device-read-iops", &device_read_iops);
+ if (rv < 0) {
+ vshError(ctl, "%s", _("Unable to parse string parameter"));
+ goto cleanup;
+ } else if (rv > 0) {
+ if (virTypedParamsAddString(¶ms, &nparams, &maxparams,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_IOPS,
+ device_read_iops) < 0)
+ goto save_error;
+ }
+
+ rv = vshCommandOptString(cmd, "device-write-iops", &device_write_iops);
+ if (rv < 0) {
+ vshError(ctl, "%s", _("Unable to parse string parameter"));
+ goto cleanup;
+ } else if (rv > 0) {
+ if (virTypedParamsAddString(¶ms, &nparams, &maxparams,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_IOPS,
+ device_write_iops) < 0)
+ goto save_error;
+ }
+
if (nparams == 0) {
/* get the number of blkio parameters */
if (virDomainGetBlkioParameters(dom, NULL, &nparams, flags) != 0) {
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 0ae5178..69829eb 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1611,8 +1611,12 @@ The guaranteed minimum memory allocation for the guest.
Specifying -1 as a value for these limits is interpreted as unlimited.
=item B<blkiotune> I<domain> [I<--weight> B<weight>]
-[I<--device-weights> B<device-weights>] [[I<--config>]
-[I<--live>] | [I<--current>]]
+[I<--device-weights> B<device-weights>]
+[I<--device-read-bps> B<device-read-bps>]
+[I<--device-write-bps> B<device-write-bps>]
+[I<--device-read-iops> B<device-read-iops>]
+[I<--device-write-iops> B<device-write-iops>]
+[[I<--config>] [I<--live>] | [I<--current>]]
Display or set the blkio parameters. QEMU/KVM supports I<--weight>.
I<--weight> is in range [100, 1000].
@@ -1624,6 +1628,30 @@ device from per-device listings. Only the devices listed in the string
are modified; any existing per-device weights for other devices remain
unchanged.
+B<device-read-bps> is a single string listing one or more device/read_bps
+pairs, in the format of /path/to/device,read_bps,/path/to/device,read_bps.
+Each read_bps is a postive number, or the value 0 to remove that device from
+per-device listings. Only the devices listed in the string are modified;
+any existing per-device read_bps for other devices remain unchanged.
+
+B<device-write-bps> is a single string listing one or more device/write_bps
+pairs, in the format of /path/to/device,write_bps,/path/to/device,write_bps.
+Each write_bps is a postive number, or the value 0 to remove that device from
+per-device listings. Only the devices listed in the string are modified;
+any existing per-device write_bps for other devices remain unchanged.
+
+B<device-read-iops> is a single string listing one or more device/read_iops
+pairs, in the format of /path/to/device,read_iops,/path/to/device,read_iops.
+Each read_iops is a postive number, or the value 0 to remove that device from
+per-device listings. Only the devices listed in the string are modified;
+any existing per-device read_iops for other devices remain unchanged.
+
+B<device-write-iops> is a single string listing one or more device/write_iops
+pairs, in the format of /path/to/device,write_iops,/path/to/device,write_iops.
+Each write_iops is a postive number, or the value 0 to remove that device from
+per-device listings. Only the devices listed in the string are modified;
+any existing per-device write_iops for other devices remain unchanged.
+
If I<--live> is specified, affect a running guest.
If I<--config> is specified, affect the next boot of a persistent guest.
If I<--current> is specified, affect the current guest state.
--
1.7.9.5
11 years, 2 months
[libvirt] [PATCH 1/2] blkiotune: add support for device iops and bps throttle
by hzguanqiang@gmail.com
From: Guan Qiang <hzguanqiang(a)corp.netease.com>
This adds per-device iops and bps throttle to <blkiotune>. By
extending the existed 'domainSetBlkioParameters' interface,
read/write iops and bps throttle for per-device can be set
with blkio cgroup. The blkiotune xml entry is now looked like:
<domain ...>
<blkiotune>
<device>
<path>/path/to/block</path>
<weight>1000</weight>
<read_bps>100000</read_bps>
<write_bps>100000</write_bps>
<read_iops>100000</read_iops>
<write_iops>1000000</write_iops>
</device>
</blkiotune>
..
Elments <weight>,<read_bps>,<write_bps>,<read_iops>,<write_iops>
are all optional, but must have one.
---
docs/formatdomain.html.in | 8 +
docs/schemas/domaincommon.rng | 28 +-
include/libvirt/libvirt.h.in | 40 ++
src/conf/domain_conf.c | 115 +++-
src/conf/domain_conf.h | 16 +-
src/libvirt_private.syms | 4 +-
src/lxc/lxc_cgroup.c | 9 +-
src/qemu/qemu_cgroup.c | 10 +-
src/qemu/qemu_driver.c | 579 ++++++++++++++++++--
src/util/vircgroup.c | 79 ++-
src/util/vircgroup.h | 8 +-
.../qemuxml2argv-blkiotune-device.xml | 4 +
12 files changed, 789 insertions(+), 111 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index a927643..daf4f7a 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -753,10 +753,18 @@
<device>
<path>/dev/sda</path>
<weight>1000</weight>
+ <read_bps>20000000</read_bps>
+ <write_bps>30000000</write_bps>
+ <read_iops>4000</read_iops>
+ <write_iops>5000</write_iops>
</device>
<device>
<path>/dev/sdb</path>
<weight>500</weight>
+ <read_bps>30000000</read_bps>
+ <write_bps>30000000</write_bps>
+ <read_iops>4300</read_iops>
+ <write_iops>6000</write_iops>
</device>
</blkiotune>
...
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 4d333a8..10553af 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -621,9 +621,31 @@
<element name="path">
<ref name="absFilePath"/>
</element>
- <element name="weight">
- <ref name="weight"/>
- </element>
+ <optional>
+ <element name="weight">
+ <ref name="weight"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="read_bps">
+ <data type="unsignedLong"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="write_bps">
+ <data type="unsignedLong"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="read_iops">
+ <data type="unsignedLong"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="write_iops">
+ <data type="unsignedLong"/>
+ </element>
+ </optional>
</interleave>
</element>
</zeroOrMore>
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index a47e33c..fd4a2e5 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1780,6 +1780,46 @@ char * virDomainGetSchedulerType(virDomainPtr domain,
#define VIR_DOMAIN_BLKIO_DEVICE_WEIGHT "device_weight"
+/**
+ * VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_BPS:
+ *
+ * Macro for the BLKIO tunable throttle.read_bps_device: it represents the read
+ * bytes per second permitted through a block device, as a string.
+ * The string is parsed as a series of /path/to/device,read_bps elements,
+ * separated by ',', with element read_bps as a ullong.
+ */
+#define VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_BPS "device_read_bps"
+
+/**
+ * VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_BPS:
+ *
+ * Macro for the BLKIO tunable throttle.write_bps_device: it represents the write
+ * bytes per second permitted through a block device, as a string.
+ * The string is parsed as a series of /path/to/device,write_bps elements,
+ * separated by ',', with element write_bps as a ullong.
+ */
+#define VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_BPS "device_write_bps"
+
+/**
+ * VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_IOPS:
+ *
+ * Macro for the BLKIO tunable throttle.read_iops_device: it represents the read
+ * I/O operations per second permitted through a block device, as a string.
+ * The string is parsed as a series of /path/to/device,read_iops elements,
+ * separated by ',', with element read_iops as a ullong.
+ */
+#define VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_IOPS "device_read_iops"
+
+/**
+ * VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_IOPS:
+ *
+ * Macro for the BLKIO tunable throttle.write_iops_device: it represents the write
+ * I/O operations per second permitted through a block device, as a string.
+ * The string is parsed as a series of /path/to/device,write_iops elements,
+ * separated by ',', with element write_iops as a ullong.
+ */
+#define VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_IOPS "device_write_iops"
+
/* Set Blkio tunables for the domain*/
int virDomainSetBlkioParameters(virDomainPtr domain,
virTypedParameterPtr params,
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 05c1de4..f9df10f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -880,47 +880,100 @@ virDomainXMLOptionGetNamespace(virDomainXMLOptionPtr xmlopt)
void
-virBlkioDeviceWeightArrayClear(virBlkioDeviceWeightPtr deviceWeights,
+virBlkioDeviceIoTuneInfoArrayClear(virBlkioDeviceIoTuneInfoPtr devices,
int ndevices)
{
size_t i;
for (i = 0; i < ndevices; i++)
- VIR_FREE(deviceWeights[i].path);
+ VIR_FREE(devices[i].path);
}
/**
- * virDomainBlkioDeviceWeightParseXML
+ * virDomainBlkioDeviceIoTuneInfoParseXML
*
* this function parses a XML node:
*
* <device>
* <path>/fully/qualified/device/path</path>
* <weight>weight</weight>
+ * <read_bps>read_bps</read_bps>
+ * <write_bps>write_bps</write_bps>
+ * <read_iops>read_iops</read_iops>
+ * <write_iops>write_iops</write_iops>
* </device>
*
- * and fills a virBlkioDeviceWeight struct.
+ * and fills a virBlkioDeviceIoTuneInfo struct.
*/
static int
-virDomainBlkioDeviceWeightParseXML(xmlNodePtr root,
- virBlkioDeviceWeightPtr dw)
+virDomainBlkioDeviceIoTuneInfoParseXML(xmlNodePtr root,
+ virBlkioDeviceIoTuneInfoPtr dio)
{
char *c;
xmlNodePtr node;
+ dio->read_bps = 0;
+ dio->write_bps = 0;
+ dio->read_iops = 0;
+ dio->write_iops = 0;
+
node = root->children;
while (node) {
if (node->type == XML_ELEMENT_NODE) {
- if (xmlStrEqual(node->name, BAD_CAST "path") && !dw->path) {
- dw->path = (char *)xmlNodeGetContent(node);
+ if (xmlStrEqual(node->name, BAD_CAST "path") && !dio->path) {
+ dio->path = (char *)xmlNodeGetContent(node);
} else if (xmlStrEqual(node->name, BAD_CAST "weight")) {
c = (char *)xmlNodeGetContent(node);
- if (virStrToLong_ui(c, NULL, 10, &dw->weight) < 0) {
+ if (virStrToLong_ui(c, NULL, 10, &dio->weight) < 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("could not parse weight %s"),
c);
VIR_FREE(c);
- VIR_FREE(dw->path);
+ VIR_FREE(dio->path);
+ return -1;
+ }
+ VIR_FREE(c);
+ } else if (xmlStrEqual(node->name, BAD_CAST "read_bps")) {
+ c = (char *)xmlNodeGetContent(node);
+ if (virStrToLong_ull(c, NULL, 10, &dio->read_bps) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not parse read_bps %s"),
+ c);
+ VIR_FREE(c);
+ VIR_FREE(dio->path);
+ return -1;
+ }
+ VIR_FREE(c);
+ } else if (xmlStrEqual(node->name, BAD_CAST "write_bps")) {
+ c = (char *)xmlNodeGetContent(node);
+ if (virStrToLong_ull(c, NULL, 10, &dio->write_bps) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not parse write_bps %s"),
+ c);
+ VIR_FREE(c);
+ VIR_FREE(dio->path);
+ return -1;
+ }
+ VIR_FREE(c);
+ } else if (xmlStrEqual(node->name, BAD_CAST "read_iops")) {
+ c = (char *)xmlNodeGetContent(node);
+ if (virStrToLong_ull(c, NULL, 10, &dio->read_iops) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not parse read_iops %s"),
+ c);
+ VIR_FREE(c);
+ VIR_FREE(dio->path);
+ return -1;
+ }
+ VIR_FREE(c);
+ } else if (xmlStrEqual(node->name, BAD_CAST "write_iops")) {
+ c = (char *)xmlNodeGetContent(node);
+ if (virStrToLong_ull(c, NULL, 10, &dio->write_iops) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not parse write_iops %s"),
+ c);
+ VIR_FREE(c);
+ VIR_FREE(dio->path);
return -1;
}
VIR_FREE(c);
@@ -928,7 +981,7 @@ virDomainBlkioDeviceWeightParseXML(xmlNodePtr root,
}
node = node->next;
}
- if (!dw->path) {
+ if (!dio->path) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("missing per-device path"));
return -1;
@@ -1988,8 +2041,8 @@ void virDomainDefFree(virDomainDefPtr def)
VIR_FREE(def->description);
VIR_FREE(def->title);
- virBlkioDeviceWeightArrayClear(def->blkio.devices,
- def->blkio.ndevices);
+ virBlkioDeviceIoTuneInfoArrayClear(def->blkio.devices,
+ def->blkio.ndevices);
VIR_FREE(def->blkio.devices);
virDomainWatchdogDefFree(def->watchdog);
@@ -10962,15 +11015,15 @@ virDomainDefParseXML(xmlDocPtr xml,
for (i = 0; i < n; i++) {
size_t j;
- if (virDomainBlkioDeviceWeightParseXML(nodes[i],
- &def->blkio.devices[i]) < 0)
+ if (virDomainBlkioDeviceIoTuneInfoParseXML(nodes[i],
+ &def->blkio.devices[i]) < 0)
goto error;
def->blkio.ndevices++;
for (j = 0; j < i; j++) {
if (STREQ(def->blkio.devices[j].path,
def->blkio.devices[i].path)) {
virReportError(VIR_ERR_XML_ERROR,
- _("duplicate device weight path '%s'"),
+ _("duplicate blkio device path '%s'"),
def->blkio.devices[i].path);
goto error;
}
@@ -16349,7 +16402,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
blkio = true;
} else {
for (n = 0; n < def->blkio.ndevices; n++) {
- if (def->blkio.devices[n].weight) {
+ if (def->blkio.devices[n].weight || def->blkio.devices[n].read_bps ||
+ def->blkio.devices[n].write_bps || def->blkio.devices[n].read_iops ||
+ def->blkio.devices[n].write_iops) {
blkio = true;
break;
}
@@ -16364,13 +16419,33 @@ virDomainDefFormatInternal(virDomainDefPtr def,
def->blkio.weight);
for (n = 0; n < def->blkio.ndevices; n++) {
- if (def->blkio.devices[n].weight == 0)
+ if (def->blkio.devices[n].weight == 0 && def->blkio.devices[n].read_bps == 0 &&
+ def->blkio.devices[n].write_bps == 0 && def->blkio.devices[n].read_iops == 0 &&
+ def->blkio.devices[n].write_iops == 0)
continue;
virBufferAddLit(buf, " <device>\n");
virBufferEscapeString(buf, " <path>%s</path>\n",
def->blkio.devices[n].path);
- virBufferAsprintf(buf, " <weight>%u</weight>\n",
- def->blkio.devices[n].weight);
+ if (def->blkio.devices[n].weight) {
+ virBufferAsprintf(buf, " <weight>%u</weight>\n",
+ def->blkio.devices[n].weight);
+ }
+ if (def->blkio.devices[n].read_bps) {
+ virBufferAsprintf(buf, " <read_bps>%llu</read_bps>\n",
+ def->blkio.devices[n].read_bps);
+ }
+ if (def->blkio.devices[n].write_bps) {
+ virBufferAsprintf(buf, " <write_bps>%llu</write_bps>\n",
+ def->blkio.devices[n].write_bps);
+ }
+ if (def->blkio.devices[n].read_iops) {
+ virBufferAsprintf(buf, " <read_iops>%llu</read_iops>\n",
+ def->blkio.devices[n].read_iops);
+ }
+ if (def->blkio.devices[n].write_iops) {
+ virBufferAsprintf(buf, " <write_iops>%llu</write_iops>\n",
+ def->blkio.devices[n].write_iops);
+ }
virBufferAddLit(buf, " </device>\n");
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 9414ebf..1f350ed 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1857,11 +1857,15 @@ virDomainVcpuPinDefPtr virDomainVcpuPinFindByVcpu(virDomainVcpuPinDefPtr *def,
int nvcpupin,
int vcpu);
-typedef struct _virBlkioDeviceWeight virBlkioDeviceWeight;
-typedef virBlkioDeviceWeight *virBlkioDeviceWeightPtr;
-struct _virBlkioDeviceWeight {
+typedef struct _virBlkioDeviceIoTuneInfo virBlkioDeviceIoTuneInfo;
+typedef virBlkioDeviceIoTuneInfo *virBlkioDeviceIoTuneInfoPtr;
+struct _virBlkioDeviceIoTuneInfo {
char *path;
unsigned int weight;
+ unsigned long long read_bps;
+ unsigned long long write_bps;
+ unsigned long long read_iops;
+ unsigned long long write_iops;
};
enum virDomainRNGModel {
@@ -1908,8 +1912,8 @@ struct _virDomainIdMapDef {
};
-void virBlkioDeviceWeightArrayClear(virBlkioDeviceWeightPtr deviceWeights,
- int ndevices);
+void virBlkioDeviceIoTuneInfoArrayClear(virBlkioDeviceIoTuneInfoPtr devices,
+ int ndevices);
typedef struct _virDomainResourceDef virDomainResourceDef;
typedef virDomainResourceDef *virDomainResourceDefPtr;
@@ -1937,7 +1941,7 @@ struct _virDomainDef {
unsigned int weight;
size_t ndevices;
- virBlkioDeviceWeightPtr devices;
+ virBlkioDeviceIoTuneInfoPtr devices;
} blkio;
struct {
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 50e2f48..e6259cf 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -103,7 +103,7 @@ virDomainAuditVcpu;
# conf/domain_conf.h
-virBlkioDeviceWeightArrayClear;
+virBlkioDeviceIoTuneInfoArrayClear;
virDiskNameToBusDeviceIndex;
virDiskNameToIndex;
virDomainActualNetDefFree;
@@ -1207,7 +1207,7 @@ virCgroupNewVcpu;
virCgroupPathOfController;
virCgroupRemove;
virCgroupRemoveRecursively;
-virCgroupSetBlkioDeviceWeight;
+virCgroupSetBlkioDeviceIoTune;
virCgroupSetBlkioWeight;
virCgroupSetCpuCfsPeriod;
virCgroupSetCpuCfsQuota;
diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c
index 0b0ca02..f2c32e7 100644
--- a/src/lxc/lxc_cgroup.c
+++ b/src/lxc/lxc_cgroup.c
@@ -112,10 +112,13 @@ static int virLXCCgroupSetupBlkioTune(virDomainDefPtr def,
if (def->blkio.ndevices) {
for (i = 0; i < def->blkio.ndevices; i++) {
- virBlkioDeviceWeightPtr dw = &def->blkio.devices[i];
- if (!dw->weight)
+ virBlkioDeviceIoTuneInfoPtr dio = &def->blkio.devices[i];
+ if (!dio->weight)
continue;
- if (virCgroupSetBlkioDeviceWeight(cgroup, dw->path, dw->weight) < 0)
+ if (virCgroupSetBlkioDeviceIoTune(cgroup,
+ dio->path, dio->weight,
+ dio->read_bps, dio->write_bps,
+ dio->read_iops, dio->write_iops) < 0)
return -1;
}
}
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index f95c7f2..20e700f 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -399,11 +399,13 @@ qemuSetupBlkioCgroup(virDomainObjPtr vm)
if (vm->def->blkio.ndevices) {
for (i = 0; i < vm->def->blkio.ndevices; i++) {
- virBlkioDeviceWeightPtr dw = &vm->def->blkio.devices[i];
- if (!dw->weight)
+ virBlkioDeviceIoTuneInfoPtr dio = &vm->def->blkio.devices[i];
+ if (!dio->weight)
continue;
- if (virCgroupSetBlkioDeviceWeight(priv->cgroup, dw->path,
- dw->weight) < 0)
+ if (virCgroupSetBlkioDeviceIoTune(priv->cgroup,
+ dio->path, dio->weight,
+ dio->read_bps, dio->write_bps,
+ dio->read_iops, dio->write_iops) < 0)
return -1;
}
}
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0763f9b..ff0ae98 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -131,7 +131,7 @@
# define KVM_CAP_NR_VCPUS 9 /* returns max vcpus per vm */
#endif
-#define QEMU_NB_BLKIO_PARAM 2
+#define QEMU_NB_BLKIO_PARAM 6
#define QEMU_NB_BANDWIDTH_PARAM 6
@@ -7388,26 +7388,26 @@ cleanup:
return ret;
}
-/* deviceWeightStr in the form of /device/path,weight,/device/path,weight
+/* deviceIoTuneStr in the form of /device/path,ioTuneValue,/device/path,ioTuneValue or
* for example, /dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0,800
+ * deviceIoTuneFiled represents the ioTune type to tune, including device weight,
+ * device read bps, device write bps, device read iops and device write iops.
*/
static int
-qemuDomainParseDeviceWeightStr(char *deviceWeightStr,
- virBlkioDeviceWeightPtr *dw, size_t *size)
+qemuDomainParseDeviceIoTuneInfoStr(char *deviceIoTuneStr,
+ const char *deviceIoTuneFiled,
+ virBlkioDeviceIoTuneInfoPtr *dio, size_t *size)
{
char *temp;
int ndevices = 0;
int nsep = 0;
- size_t i;
- virBlkioDeviceWeightPtr result = NULL;
-
- *dw = NULL;
- *size = 0;
+ size_t i, j, k;
+ virBlkioDeviceIoTuneInfoPtr result = NULL;
- if (STREQ(deviceWeightStr, ""))
+ if (STREQ(deviceIoTuneStr, ""))
return 0;
- temp = deviceWeightStr;
+ temp = deviceIoTuneStr;
while (temp) {
temp = strchr(temp, ',');
if (temp) {
@@ -7426,8 +7426,11 @@ qemuDomainParseDeviceWeightStr(char *deviceWeightStr,
if (VIR_ALLOC_N(result, ndevices) < 0)
return -1;
+ for (i = 0; i < ndevices; i++)
+ memset(&result[i], 0, sizeof(result[i]));
+
i = 0;
- temp = deviceWeightStr;
+ temp = deviceIoTuneStr;
while (temp) {
char *p = temp;
@@ -7439,11 +7442,25 @@ qemuDomainParseDeviceWeightStr(char *deviceWeightStr,
if (VIR_STRNDUP(result[i].path, temp, p - temp) < 0)
goto cleanup;
- /* weight */
+ /* device ioTune value */
temp = p + 1;
- if (virStrToLong_ui(temp, &p, 10, &result[i].weight) < 0)
- goto error;
+ if (STREQ(deviceIoTuneFiled, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
+ if (virStrToLong_ui(temp, &p, 10, &result[i].weight) < 0)
+ goto error;
+ } else if (STREQ(deviceIoTuneFiled, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_BPS)) {
+ if (virStrToLong_ull(temp, &p, 10, &result[i].read_bps) < 0)
+ goto error;
+ } else if (STREQ(deviceIoTuneFiled, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_BPS)) {
+ if (virStrToLong_ull(temp, &p, 10, &result[i].write_bps) < 0)
+ goto error;
+ } else if (STREQ(deviceIoTuneFiled, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_IOPS)) {
+ if (virStrToLong_ull(temp, &p, 10, &result[i].read_iops) < 0)
+ goto error;
+ } else if (STREQ(deviceIoTuneFiled, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_IOPS)) {
+ if (virStrToLong_ull(temp, &p, 10, &result[i].write_iops) < 0)
+ goto error;
+ }
i++;
@@ -7457,30 +7474,68 @@ qemuDomainParseDeviceWeightStr(char *deviceWeightStr,
if (!i)
VIR_FREE(result);
- *dw = result;
- *size = i;
+ for (j = 0; j < i; j++) {
+ bool found = false;
+ virBlkioDeviceIoTuneInfoPtr old, new;
+
+ new = &result[j];
+ for (k = 0; k < *size; k++) {
+ old = &(*dio)[k];
+ if (STREQ(new->path, old->path)) {
+ found = true;
+ if (STREQ(deviceIoTuneFiled, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT))
+ old->weight = new->weight;
+ else if (STREQ(deviceIoTuneFiled, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_BPS))
+ old->read_bps = new->read_bps;
+ else if (STREQ(deviceIoTuneFiled, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_BPS))
+ old->write_bps = new->write_bps;
+ else if (STREQ(deviceIoTuneFiled, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_IOPS))
+ old->read_iops = new->read_iops;
+ else if (STREQ(deviceIoTuneFiled, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_IOPS))
+ old->write_iops = new->write_iops;
+ break;
+ }
+ }
+ if (!found) {
+ if (!new->weight && !new->read_bps && !new->write_bps &&
+ !new->read_iops && !new->write_iops)
+ continue;
+ if (VIR_EXPAND_N(*dio, *size, 1) < 0)
+ goto cleanup;
+ old = &(*dio)[*size -1];
+ if (VIR_STRDUP(old->path, new->path) < 0)
+ goto cleanup;
+ old->weight = new->weight;
+ old->read_bps = new->read_bps;
+ old->write_bps = new->write_bps;
+ old->read_iops = new->read_iops;
+ old->write_iops = new->write_iops;
+ }
+ }
+ virBlkioDeviceIoTuneInfoArrayClear(result, ndevices);
+ VIR_FREE(result);
return 0;
error:
virReportError(VIR_ERR_INVALID_ARG,
- _("unable to parse device weight '%s'"), deviceWeightStr);
+ _("unable to parse device ioTune '%s'"), deviceIoTuneStr);
cleanup:
- virBlkioDeviceWeightArrayClear(result, ndevices);
+ virBlkioDeviceIoTuneInfoArrayClear(result, ndevices);
VIR_FREE(result);
return -1;
}
-/* Modify dest_array to reflect all device weight changes described in
+/* Modify dest_array to reflect all device Iotune info changes described in
* src_array. */
static int
-qemuDomainMergeDeviceWeights(virBlkioDeviceWeightPtr *dest_array,
- size_t *dest_size,
- virBlkioDeviceWeightPtr src_array,
- size_t src_size)
+qemuDomainMergeDeviceIoTuneInfos(virBlkioDeviceIoTuneInfoPtr *dest_array,
+ size_t *dest_size,
+ virBlkioDeviceIoTuneInfoPtr src_array,
+ size_t src_size)
{
size_t i, j;
- virBlkioDeviceWeightPtr dest, src;
+ virBlkioDeviceIoTuneInfoPtr dest, src;
for (i = 0; i < src_size; i++) {
bool found = false;
@@ -7491,18 +7546,27 @@ qemuDomainMergeDeviceWeights(virBlkioDeviceWeightPtr *dest_array,
if (STREQ(src->path, dest->path)) {
found = true;
dest->weight = src->weight;
+ dest->read_bps = src->read_bps;
+ dest->write_bps = src->write_bps;
+ dest->read_iops = src->read_iops;
+ dest->write_iops = src->write_iops;
break;
}
}
if (!found) {
- if (!src->weight)
+ if (!src->weight && !src->read_bps && !src->write_bps &&
+ !src->read_iops && !src->write_iops)
continue;
if (VIR_EXPAND_N(*dest_array, *dest_size, 1) < 0)
return -1;
dest = &(*dest_array)[*dest_size - 1];
- dest->path = src->path;
+ if (VIR_STRDUP(dest->path, src->path) < 0)
+ return -1;
dest->weight = src->weight;
- src->path = NULL;
+ dest->read_bps = src->read_bps;
+ dest->write_bps = src->write_bps;
+ dest->read_iops = src->read_iops;
+ dest->write_iops = src->write_iops;
}
}
@@ -7531,6 +7595,14 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
VIR_TYPED_PARAM_UINT,
VIR_DOMAIN_BLKIO_DEVICE_WEIGHT,
VIR_TYPED_PARAM_STRING,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_BPS,
+ VIR_TYPED_PARAM_STRING,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_BPS,
+ VIR_TYPED_PARAM_STRING,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_IOPS,
+ VIR_TYPED_PARAM_STRING,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_IOPS,
+ VIR_TYPED_PARAM_STRING,
NULL) < 0)
return -1;
@@ -7562,44 +7634,114 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
for (i = 0; i < nparams; i++) {
virTypedParameterPtr param = ¶ms[i];
+ size_t ndevices = 0;
+ virBlkioDeviceIoTuneInfoPtr devices = NULL;
+ size_t j;
+
+ if (qemuDomainMergeDeviceIoTuneInfos(&devices, &ndevices,
+ vm->def->blkio.devices,
+ vm->def->blkio.ndevices) < 0) {
+ ret = -1;
+ if (ndevices) {
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
+ }
+ continue;
+ }
if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
_("out of blkio weight range."));
ret = -1;
+ if (ndevices) {
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
+ }
continue;
}
if (virCgroupSetBlkioWeight(priv->cgroup, params[i].value.ui) < 0)
ret = -1;
} else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
- size_t ndevices;
- virBlkioDeviceWeightPtr devices = NULL;
- size_t j;
-
- if (qemuDomainParseDeviceWeightStr(params[i].value.s,
- &devices,
- &ndevices) < 0) {
+ if (qemuDomainParseDeviceIoTuneInfoStr(params[i].value.s,
+ VIR_DOMAIN_BLKIO_DEVICE_WEIGHT,
+ &devices,
+ &ndevices) < 0) {
ret = -1;
+ if (ndevices) {
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
+ }
continue;
}
- for (j = 0; j < ndevices; j++) {
- if (virCgroupSetBlkioDeviceWeight(priv->cgroup,
- devices[j].path,
- devices[j].weight) < 0) {
- ret = -1;
- break;
+ } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_IOPS)) {
+ if (qemuDomainParseDeviceIoTuneInfoStr(params[i].value.s,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_IOPS,
+ &devices,
+ &ndevices) < 0) {
+ ret = -1;
+ if (ndevices) {
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
}
+ continue;
}
- if (j != ndevices ||
- qemuDomainMergeDeviceWeights(&vm->def->blkio.devices,
- &vm->def->blkio.ndevices,
- devices, ndevices) < 0)
+ } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_IOPS)) {
+ if (qemuDomainParseDeviceIoTuneInfoStr(params[i].value.s,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_IOPS,
+ &devices,
+ &ndevices) < 0) {
+ ret = -1;
+ if (ndevices) {
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
+ }
+ continue;
+ }
+ } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_BPS)) {
+ if (qemuDomainParseDeviceIoTuneInfoStr(params[i].value.s,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_BPS,
+ &devices,
+ &ndevices) < 0) {
+ ret = -1;
+ if (ndevices) {
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
+ }
+ continue;
+ }
+ } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_BPS)) {
+ if (qemuDomainParseDeviceIoTuneInfoStr(params[i].value.s,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_BPS,
+ &devices,
+ &ndevices) < 0) {
+ ret = -1;
+ if (ndevices) {
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
+ }
+ continue;
+ }
+ }
+
+ for (j = 0; j < ndevices; j++) {
+ if (virCgroupSetBlkioDeviceIoTune(priv->cgroup,
+ devices[j].path, devices[j].weight,
+ devices[j].read_bps, devices[j].write_bps,
+ devices[j].read_iops, devices[j].write_iops) < 0) {
ret = -1;
- virBlkioDeviceWeightArrayClear(devices, ndevices);
- VIR_FREE(devices);
+ break;
+ }
}
+ if (j != ndevices ||
+ qemuDomainMergeDeviceIoTuneInfos(&vm->def->blkio.devices,
+ &vm->def->blkio.ndevices,
+ devices, ndevices) < 0)
+ ret = -1;
+
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
}
}
if (ret < 0)
@@ -7610,33 +7752,102 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
for (i = 0; i < nparams; i++) {
virTypedParameterPtr param = ¶ms[i];
+ virBlkioDeviceIoTuneInfoPtr devices = NULL;
+ size_t ndevices = 0;
+
+ if (qemuDomainMergeDeviceIoTuneInfos(&devices, &ndevices,
+ persistentDef->blkio.devices,
+ persistentDef->blkio.ndevices) < 0) {
+ ret = -1;
+ if (ndevices) {
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
+ }
+ continue;
+ }
if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
_("out of blkio weight range."));
ret = -1;
+ if (ndevices) {
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
+ }
continue;
}
persistentDef->blkio.weight = params[i].value.ui;
} else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
- virBlkioDeviceWeightPtr devices = NULL;
- size_t ndevices;
-
- if (qemuDomainParseDeviceWeightStr(params[i].value.s,
- &devices,
- &ndevices) < 0) {
+ if (qemuDomainParseDeviceIoTuneInfoStr(params[i].value.s,
+ VIR_DOMAIN_BLKIO_DEVICE_WEIGHT,
+ &devices,
+ &ndevices) < 0) {
ret = -1;
+ if (ndevices) {
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
+ }
continue;
}
- if (qemuDomainMergeDeviceWeights(&persistentDef->blkio.devices,
- &persistentDef->blkio.ndevices,
- devices, ndevices) < 0)
+ } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_IOPS)) {
+ if (qemuDomainParseDeviceIoTuneInfoStr(params[i].value.s,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_IOPS,
+ &devices,
+ &ndevices) < 0) {
ret = -1;
- virBlkioDeviceWeightArrayClear(devices, ndevices);
- VIR_FREE(devices);
+ if (ndevices) {
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
+ }
+ continue;
+ }
+ } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_IOPS)) {
+ if (qemuDomainParseDeviceIoTuneInfoStr(params[i].value.s,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_IOPS,
+ &devices,
+ &ndevices) < 0) {
+ ret = -1;
+ if (ndevices) {
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
+ }
+ continue;
+ }
+ } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_BPS)) {
+ if (qemuDomainParseDeviceIoTuneInfoStr(params[i].value.s,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_BPS,
+ &devices,
+ &ndevices) < 0) {
+ ret = -1;
+ if (ndevices) {
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
+ }
+ continue;
+ }
+ } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_BPS)) {
+ if (qemuDomainParseDeviceIoTuneInfoStr(params[i].value.s,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_BPS,
+ &devices,
+ &ndevices) < 0) {
+ ret = -1;
+ if (ndevices) {
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
+ }
+ continue;
+ }
}
+
+ if (qemuDomainMergeDeviceIoTuneInfos(&persistentDef->blkio.devices,
+ &persistentDef->blkio.ndevices,
+ devices, ndevices) < 0)
+ ret = -1;
+
+ virBlkioDeviceIoTuneInfoArrayClear(devices, ndevices);
+ VIR_FREE(devices);
}
if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
@@ -7747,6 +7958,122 @@ qemuDomainGetBlkioParameters(virDomainPtr dom,
goto cleanup;
break;
+ case 2: /* blkiotune.throttle.device_read_bps */
+ if (vm->def->blkio.ndevices > 0) {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ bool comma = false;
+
+ for (j = 0; j < vm->def->blkio.ndevices; j++) {
+ if (!vm->def->blkio.devices[j].read_bps)
+ continue;
+ if (comma)
+ virBufferAddChar(&buf, ',');
+ else
+ comma = true;
+ virBufferAsprintf(&buf, "%s,%llu",
+ vm->def->blkio.devices[j].path,
+ vm->def->blkio.devices[j].read_bps);
+ }
+ if (virBufferError(&buf)) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ param->value.s = virBufferContentAndReset(&buf);
+ }
+ if (virTypedParameterAssign(param,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_BPS,
+ VIR_TYPED_PARAM_STRING,
+ param->value.s) < 0)
+ goto cleanup;
+ break;
+
+ case 3: /* blkiotune.throttle.device_write_bps */
+ if (vm->def->blkio.ndevices > 0) {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ bool comma = false;
+
+ for (j = 0; j < vm->def->blkio.ndevices; j++) {
+ if (!vm->def->blkio.devices[j].write_bps)
+ continue;
+ if (comma)
+ virBufferAddChar(&buf, ',');
+ else
+ comma = true;
+ virBufferAsprintf(&buf, "%s,%llu",
+ vm->def->blkio.devices[j].path,
+ vm->def->blkio.devices[j].write_bps);
+ }
+ if (virBufferError(&buf)) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ param->value.s = virBufferContentAndReset(&buf);
+ }
+ if (virTypedParameterAssign(param,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_BPS,
+ VIR_TYPED_PARAM_STRING,
+ param->value.s) < 0)
+ goto cleanup;
+ break;
+
+ case 4: /* blkiotune.throttle.device_read_iops */
+ if (vm->def->blkio.ndevices > 0) {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ bool comma = false;
+
+ for (j = 0; j < vm->def->blkio.ndevices; j++) {
+ if (!vm->def->blkio.devices[j].read_iops)
+ continue;
+ if (comma)
+ virBufferAddChar(&buf, ',');
+ else
+ comma = true;
+ virBufferAsprintf(&buf, "%s,%llu",
+ vm->def->blkio.devices[j].path,
+ vm->def->blkio.devices[j].read_iops);
+ }
+ if (virBufferError(&buf)) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ param->value.s = virBufferContentAndReset(&buf);
+ }
+ if (virTypedParameterAssign(param,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_IOPS,
+ VIR_TYPED_PARAM_STRING,
+ param->value.s) < 0)
+ goto cleanup;
+ break;
+
+ case 5: /* blkiotune.throttle.device_write_iops */
+ if (vm->def->blkio.ndevices > 0) {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ bool comma = false;
+
+ for (j = 0; j < vm->def->blkio.ndevices; j++) {
+ if (!vm->def->blkio.devices[j].write_iops)
+ continue;
+ if (comma)
+ virBufferAddChar(&buf, ',');
+ else
+ comma = true;
+ virBufferAsprintf(&buf, "%s,%llu",
+ vm->def->blkio.devices[j].path,
+ vm->def->blkio.devices[j].write_iops);
+ }
+ if (virBufferError(&buf)) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ param->value.s = virBufferContentAndReset(&buf);
+ }
+ if (virTypedParameterAssign(param,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_IOPS,
+ VIR_TYPED_PARAM_STRING,
+ param->value.s) < 0)
+ goto cleanup;
+ break;
+
default:
break;
/* should not hit here */
@@ -7804,6 +8131,142 @@ qemuDomainGetBlkioParameters(virDomainPtr dom,
}
break;
+ case 2: /* blkiotune.device_read_bps */
+ if (persistentDef->blkio.ndevices > 0) {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ bool comma = false;
+
+ for (j = 0; j < persistentDef->blkio.ndevices; j++) {
+ if (!persistentDef->blkio.devices[j].read_bps)
+ continue;
+ if (comma)
+ virBufferAddChar(&buf, ',');
+ else
+ comma = true;
+ virBufferAsprintf(&buf, "%s,%llu",
+ persistentDef->blkio.devices[j].path,
+ persistentDef->blkio.devices[j].read_bps);
+ }
+ if (virBufferError(&buf)) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ param->value.s = virBufferContentAndReset(&buf);
+ }
+ if (!param->value.s && VIR_STRDUP(param->value.s, "") < 0)
+ goto cleanup;
+ param->type = VIR_TYPED_PARAM_STRING;
+ if (virStrcpyStatic(param->field,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_BPS) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Field name '%s' too long"),
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_BPS);
+ goto cleanup;
+ }
+ break;
+
+ case 3: /* blkiotune.device_write_bps */
+ if (persistentDef->blkio.ndevices > 0) {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ bool comma = false;
+
+ for (j = 0; j < persistentDef->blkio.ndevices; j++) {
+ if (!persistentDef->blkio.devices[j].write_bps)
+ continue;
+ if (comma)
+ virBufferAddChar(&buf, ',');
+ else
+ comma = true;
+ virBufferAsprintf(&buf, "%s,%llu",
+ persistentDef->blkio.devices[j].path,
+ persistentDef->blkio.devices[j].write_bps);
+ }
+ if (virBufferError(&buf)) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ param->value.s = virBufferContentAndReset(&buf);
+ }
+ if (!param->value.s && VIR_STRDUP(param->value.s, "") < 0)
+ goto cleanup;
+ param->type = VIR_TYPED_PARAM_STRING;
+ if (virStrcpyStatic(param->field,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_BPS) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Field name '%s' too long"),
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_BPS);
+ goto cleanup;
+ }
+ break;
+
+ case 4: /* blkiotune.device_read_iops */
+ if (persistentDef->blkio.ndevices > 0) {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ bool comma = false;
+
+ for (j = 0; j < persistentDef->blkio.ndevices; j++) {
+ if (!persistentDef->blkio.devices[j].read_iops)
+ continue;
+ if (comma)
+ virBufferAddChar(&buf, ',');
+ else
+ comma = true;
+ virBufferAsprintf(&buf, "%s,%llu",
+ persistentDef->blkio.devices[j].path,
+ persistentDef->blkio.devices[j].read_iops);
+ }
+ if (virBufferError(&buf)) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ param->value.s = virBufferContentAndReset(&buf);
+ }
+ if (!param->value.s && VIR_STRDUP(param->value.s, "") < 0)
+ goto cleanup;
+ param->type = VIR_TYPED_PARAM_STRING;
+ if (virStrcpyStatic(param->field,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_IOPS) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Field name '%s' too long"),
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_IOPS);
+ goto cleanup;
+ }
+ break;
+
+ case 5: /* blkiotune.device_write_iops */
+ if (persistentDef->blkio.ndevices > 0) {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ bool comma = false;
+
+ for (j = 0; j < persistentDef->blkio.ndevices; j++) {
+ if (!persistentDef->blkio.devices[j].write_iops)
+ continue;
+ if (comma)
+ virBufferAddChar(&buf, ',');
+ else
+ comma = true;
+ virBufferAsprintf(&buf, "%s,%llu",
+ persistentDef->blkio.devices[j].path,
+ persistentDef->blkio.devices[j].write_iops);
+ }
+ if (virBufferError(&buf)) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ param->value.s = virBufferContentAndReset(&buf);
+ }
+ if (!param->value.s && VIR_STRDUP(param->value.s, "") < 0)
+ goto cleanup;
+ param->type = VIR_TYPED_PARAM_STRING;
+ if (virStrcpyStatic(param->field,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_IOPS) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Field name '%s' too long"),
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_IOPS);
+ goto cleanup;
+ }
+ break;
+
default:
break;
/* should not hit here */
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index e99caf5..b506de5 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -1825,23 +1825,36 @@ virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight)
/**
- * virCgroupSetBlkioDeviceWeight:
+ * virCgroupSetBlkioDeviceIoTune:
*
- * @group: The cgroup to change io device weight device for
+ * @group: The cgroup to change io device iotune device for
* @path: The device with a weight to alter
* @weight: The new device weight (100-1000), or 0 to clear
+ * @read_bps: The new read bps throttle, or 0 to clear
+ * @write_bps: The new write bps throttle, or 0 to clear
+ * @read_iops: The new read iops throttle, or 0 to clear
+ * @write_iops: The new write iops throttle, or 0 to clear
*
- * device_weight is treated as a write-only parameter, so
- * there isn't a getter counterpart.
+ * paramters like device_weight, device_read_bps, device_write_bps,
+ * device_read_iops and device_write_iops are treated as write-only,
+ * so there isn't a getter counterpart.
*
* Returns: 0 on success, -1 on error
*/
int
-virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
+virCgroupSetBlkioDeviceIoTune(virCgroupPtr group,
const char *path,
- unsigned int weight)
-{
- char *str;
+ unsigned int weight,
+ unsigned long long read_bps,
+ unsigned long long write_bps,
+ unsigned long long read_iops,
+ unsigned long long write_iops)
+{
+ char *weight_str;
+ char *read_bps_str;
+ char *write_bps_str;
+ char *read_iops_str;
+ char *write_iops_str;
struct stat sb;
int ret;
@@ -1866,15 +1879,51 @@ virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
return -1;
}
- if (virAsprintf(&str, "%d:%d %d", major(sb.st_rdev), minor(sb.st_rdev),
+ if (virAsprintf(&weight_str, "%d:%d %d", major(sb.st_rdev), minor(sb.st_rdev),
weight) < 0)
return -1;
+ if (virAsprintf(&read_bps_str, "%d:%d %llu", major(sb.st_rdev), minor(sb.st_rdev),
+ read_bps) < 0)
+ return -1;
+
+ if (virAsprintf(&write_bps_str, "%d:%d %llu", major(sb.st_rdev), minor(sb.st_rdev),
+ write_bps) < 0)
+ return -1;
+
+ if (virAsprintf(&read_iops_str, "%d:%d %llu", major(sb.st_rdev), minor(sb.st_rdev),
+ read_iops) < 0)
+ return -1;
+
+ if (virAsprintf(&write_iops_str, "%d:%d %llu", major(sb.st_rdev), minor(sb.st_rdev),
+ write_iops) < 0)
+ return -1;
+
ret = virCgroupSetValueStr(group,
VIR_CGROUP_CONTROLLER_BLKIO,
"blkio.weight_device",
- str);
- VIR_FREE(str);
+ weight_str);
+ ret = virCgroupSetValueStr(group,
+ VIR_CGROUP_CONTROLLER_BLKIO,
+ "blkio.throttle.read_bps_device",
+ read_bps_str);
+ ret = virCgroupSetValueStr(group,
+ VIR_CGROUP_CONTROLLER_BLKIO,
+ "blkio.throttle.write_bps_device",
+ write_bps_str);
+ ret = virCgroupSetValueStr(group,
+ VIR_CGROUP_CONTROLLER_BLKIO,
+ "blkio.throttle.read_iops_device",
+ read_iops_str);
+ ret = virCgroupSetValueStr(group,
+ VIR_CGROUP_CONTROLLER_BLKIO,
+ "blkio.throttle.write_iops_device",
+ write_iops_str);
+ VIR_FREE(weight_str);
+ VIR_FREE(read_bps_str);
+ VIR_FREE(write_bps_str);
+ VIR_FREE(read_iops_str);
+ VIR_FREE(write_iops_str);
return ret;
}
@@ -3287,9 +3336,13 @@ virCgroupGetBlkioWeight(virCgroupPtr group ATTRIBUTE_UNUSED,
int
-virCgroupSetBlkioDeviceWeight(virCgroupPtr group ATTRIBUTE_UNUSED,
+virCgroupSetBlkioDeviceIoTune(virCgroupPtr group ATTRIBUTE_UNUSED,
const char *path ATTRIBUTE_UNUSED,
- unsigned int weight ATTRIBUTE_UNUSED)
+ unsigned int weight ATTRIBUTE_UNUSED,
+ unsigned long long read_bps ATTRIBUTE_UNUSED,
+ unsigned long long write_bps ATTRIBUTE_UNUSED,
+ unsigned long long read_iops ATTRIBUTE_UNUSED,
+ unsigned long long write_iops ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s",
_("Control groups not supported on this platform"));
diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
index 835eb30..21980da 100644
--- a/src/util/vircgroup.h
+++ b/src/util/vircgroup.h
@@ -122,9 +122,13 @@ int virCgroupMoveTask(virCgroupPtr src_group,
int virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight);
int virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight);
-int virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
+int virCgroupSetBlkioDeviceIoTune(virCgroupPtr group,
const char *path,
- unsigned int weight);
+ unsigned int weight,
+ unsigned long long read_bps,
+ unsigned long long write_bps,
+ unsigned long long read_iops,
+ unsigned long long write_iops);
int virCgroupSetMemory(virCgroupPtr group, unsigned long long kb);
int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb);
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-blkiotune-device.xml b/tests/qemuxml2argvdata/qemuxml2argv-blkiotune-device.xml
index 743cf29..9bd97fe 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-blkiotune-device.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-blkiotune-device.xml
@@ -8,6 +8,10 @@
<device>
<path>/dev/sda</path>
<weight>400</weight>
+ <read_bps>2000000000</read_bps>
+ <write_bps>1000000000</write_bps>
+ <read_iops>1000</read_iops>
+ <write_iops>2000</write_iops>
</device>
<device>
<path>/dev/sdb</path>
--
1.7.9.5
11 years, 2 months
[libvirt] [PATCH 1/5] Add https protocol support for cdrom disk
by hzguanqiang@gmail.com
From: Aline Manera <alinefm(a)br.ibm.com>
The https protocol is also accepted by qemu/KVM when specifying the cdrom ISO
image.
The xml should be as following:
<disk type='network' device='cdrom'>
<source protocol='https' name='/url/path'>
<host name='host.name' port='443'/>
</source>
</disk>
Signed-off-by: Aline Manera <alinefm(a)br.ibm.com>
---
docs/formatdomain.html.in | 8 +++++
docs/schemas/domaincommon.rng | 1 +
src/conf/domain_conf.c | 1 +
src/conf/domain_conf.h | 1 +
src/qemu/qemu_command.c | 6 ++++
.../qemuxml2argv-disk-cdrom-network-https.args | 8 +++++
.../qemuxml2argv-disk-cdrom-network-https.xml | 37 ++++++++++++++++++++
tests/qemuxml2argvtest.c | 2 ++
8 files changed, 64 insertions(+)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-cdrom-network-https.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-cdrom-network-https.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index f5a36d9..240571f 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1511,6 +1511,14 @@
</disk>
<disk type='network' device='cdrom'>
<driver name='qemu' type='raw'/>
+ <source protocol="https" name="url_path">
+ <host name="hostname" port="443"/>
+ </source>
+ <target dev='hdc' bus='ide' tray='open'/>
+ <readonly/>
+ </disk>
+ <disk type='network' device='cdrom'>
+ <driver name='qemu' type='raw'/>
<source protocol="ftp" name="url_path">
<host name="hostname" port="21"/>
</source>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index ecd3a42..2f91f0f 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1231,6 +1231,7 @@
<value>gluster</value>
<value>iscsi</value>
<value>http</value>
+ <value>https</value>
<value>ftp</value>
</choice>
</attribute>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e5fe900..04563f6 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -265,6 +265,7 @@ VIR_ENUM_IMPL(virDomainDiskProtocol, VIR_DOMAIN_DISK_PROTOCOL_LAST,
"gluster",
"iscsi",
"http",
+ "https",
"ftp")
VIR_ENUM_IMPL(virDomainDiskProtocolTransport, VIR_DOMAIN_DISK_PROTO_TRANS_LAST,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index e4dfee9..d54b29e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -543,6 +543,7 @@ enum virDomainDiskProtocol {
VIR_DOMAIN_DISK_PROTOCOL_GLUSTER,
VIR_DOMAIN_DISK_PROTOCOL_ISCSI,
VIR_DOMAIN_DISK_PROTOCOL_HTTP,
+ VIR_DOMAIN_DISK_PROTOCOL_HTTPS,
VIR_DOMAIN_DISK_PROTOCOL_FTP,
VIR_DOMAIN_DISK_PROTOCOL_LAST
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1521431..883b513 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3905,6 +3905,12 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED,
disk->hosts->port ? disk->hosts->port : "80");
virBufferEscape(&opt, ',', ",", "%s,", disk->src);
break;
+ case VIR_DOMAIN_DISK_PROTOCOL_HTTPS:
+ virBufferAsprintf(&opt, "file=https://%s:%s",
+ disk->hosts->name,
+ disk->hosts->port ? disk->hosts->port : "443");
+ virBufferEscape(&opt, ',', ",", "%s,", disk->src);
+ break;
case VIR_DOMAIN_DISK_PROTOCOL_FTP:
virBufferAsprintf(&opt, "file=ftp://%s:%s",
disk->hosts->name,
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-cdrom-network-https.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-cdrom-network-https.args
new file mode 100644
index 0000000..affa794
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-cdrom-network-https.args
@@ -0,0 +1,8 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/kvm -S \
+-M pc-1.2 -m 1024 -smp 1 -nographic -nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait -boot d -usb \
+-drive \
+file=https://host.name:443/url/path/file.iso,if=none,media=cdrom,id=drive-ide0-1-0 \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-cdrom-network-https.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-cdrom-network-https.xml
new file mode 100644
index 0000000..b8a60ed
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-cdrom-network-https.xml
@@ -0,0 +1,37 @@
+<domain type='kvm'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>1048576</memory>
+ <currentMemory unit='KiB'>1048576</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc-1.2'>hvm</type>
+ <boot dev='cdrom'/>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <pae/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <emulator>/usr/bin/kvm</emulator>
+ <disk type='network' device='cdrom'>
+ <driver name='qemu' type='raw'/>
+ <source protocol='https' name='/url/path/file.iso'>
+ <host name='host.name' port='443'/>
+ </source>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ <alias name='ide0-1-0'/>
+ <address type='drive' controller='0' bus='1' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <controller type='ide' index='0'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index fdf1d31..a11c9a8 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -445,6 +445,8 @@ mymain(void)
DO_TEST("disk-cdrom", NONE);
DO_TEST("disk-cdrom-network-http", QEMU_CAPS_KVM, QEMU_CAPS_DEVICE,
QEMU_CAPS_DRIVE);
+ DO_TEST("disk-cdrom-network-https", QEMU_CAPS_KVM, QEMU_CAPS_DEVICE,
+ QEMU_CAPS_DRIVE);
DO_TEST("disk-cdrom-network-ftp", QEMU_CAPS_KVM, QEMU_CAPS_DEVICE,
QEMU_CAPS_DRIVE);
DO_TEST("disk-cdrom-empty", QEMU_CAPS_DRIVE);
--
1.7.9.5
11 years, 2 months
[libvirt] [PATCH 2/2] blkiotune: add virsh support for blkiotune.throttle.iops/bps
by hzguanqiang@gmail.com
From: Guan Qiang <hzguanqiang(a)corp.netease.com>
This adds four parameters --device-read-bps, --device-write-bps, --device-read-iops
and --device-write-iops to virsh command blkiotune for setting/getting
blkiotune.throttle.{read/write}_{iops/bps}_device.
---
tools/virsh-domain.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
tools/virsh.pod | 32 +++++++++++++++++++++++--
2 files changed, 94 insertions(+), 2 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 49cd154..2830d6a 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -1252,6 +1252,22 @@ static const vshCmdOptDef opts_blkiotune[] = {
.type = VSH_OT_STRING,
.help = N_("per-device IO Weights, in the form of /path/to/device,weight,...")
},
+ {.name = "device-read-bps",
+ .type = VSH_OT_STRING,
+ .help = N_("per-device read throughput limit in bytes per second, in the form of /path/to/device,read_bps,...")
+ },
+ {.name = "device-write-bps",
+ .type = VSH_OT_STRING,
+ .help = N_("per-device write throughput limit in bytes per second, in the form of /path/to/device,write_bps,...")
+ },
+ {.name = "device-read-iops",
+ .type = VSH_OT_STRING,
+ .help = N_("per-device read I/O operations limit per second, in the form of /path/to/device,read_iops,...")
+ },
+ {.name = "device-write-iops",
+ .type = VSH_OT_STRING,
+ .help = N_("per-device write I/O operations limit per second, in the form of /path/to/device,write_iops,...")
+ },
{.name = "config",
.type = VSH_OT_BOOL,
.help = N_("affect next boot")
@@ -1272,6 +1288,10 @@ cmdBlkiotune(vshControl * ctl, const vshCmd * cmd)
{
virDomainPtr dom;
const char *device_weight = NULL;
+ const char *device_read_bps = NULL;
+ const char *device_write_bps = NULL;
+ const char *device_read_iops = NULL;
+ const char *device_write_iops = NULL;
int weight = 0;
int nparams = 0;
int maxparams = 0;
@@ -1319,6 +1339,50 @@ cmdBlkiotune(vshControl * ctl, const vshCmd * cmd)
goto save_error;
}
+ rv = vshCommandOptString(cmd, "device-read-bps", &device_read_bps);
+ if (rv < 0) {
+ vshError(ctl, "%s", _("Unable to parse string parameter"));
+ goto cleanup;
+ } else if (rv > 0) {
+ if (virTypedParamsAddString(¶ms, &nparams, &maxparams,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_BPS,
+ device_read_bps) < 0)
+ goto save_error;
+ }
+
+ rv = vshCommandOptString(cmd, "device-write-bps", &device_write_bps);
+ if (rv < 0) {
+ vshError(ctl, "%s", _("Unable to parse string parameter"));
+ goto cleanup;
+ } else if (rv > 0) {
+ if (virTypedParamsAddString(¶ms, &nparams, &maxparams,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_BPS,
+ device_write_bps) < 0)
+ goto save_error;
+ }
+
+ rv = vshCommandOptString(cmd, "device-read-iops", &device_read_iops);
+ if (rv < 0) {
+ vshError(ctl, "%s", _("Unable to parse string parameter"));
+ goto cleanup;
+ } else if (rv > 0) {
+ if (virTypedParamsAddString(¶ms, &nparams, &maxparams,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_READ_IOPS,
+ device_read_iops) < 0)
+ goto save_error;
+ }
+
+ rv = vshCommandOptString(cmd, "device-write-iops", &device_write_iops);
+ if (rv < 0) {
+ vshError(ctl, "%s", _("Unable to parse string parameter"));
+ goto cleanup;
+ } else if (rv > 0) {
+ if (virTypedParamsAddString(¶ms, &nparams, &maxparams,
+ VIR_DOMAIN_BLKIO_THROTTLE_DEVICE_WRITE_IOPS,
+ device_write_iops) < 0)
+ goto save_error;
+ }
+
if (nparams == 0) {
/* get the number of blkio parameters */
if (virDomainGetBlkioParameters(dom, NULL, &nparams, flags) != 0) {
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 0ae5178..69829eb 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1611,8 +1611,12 @@ The guaranteed minimum memory allocation for the guest.
Specifying -1 as a value for these limits is interpreted as unlimited.
=item B<blkiotune> I<domain> [I<--weight> B<weight>]
-[I<--device-weights> B<device-weights>] [[I<--config>]
-[I<--live>] | [I<--current>]]
+[I<--device-weights> B<device-weights>]
+[I<--device-read-bps> B<device-read-bps>]
+[I<--device-write-bps> B<device-write-bps>]
+[I<--device-read-iops> B<device-read-iops>]
+[I<--device-write-iops> B<device-write-iops>]
+[[I<--config>] [I<--live>] | [I<--current>]]
Display or set the blkio parameters. QEMU/KVM supports I<--weight>.
I<--weight> is in range [100, 1000].
@@ -1624,6 +1628,30 @@ device from per-device listings. Only the devices listed in the string
are modified; any existing per-device weights for other devices remain
unchanged.
+B<device-read-bps> is a single string listing one or more device/read_bps
+pairs, in the format of /path/to/device,read_bps,/path/to/device,read_bps.
+Each read_bps is a postive number, or the value 0 to remove that device from
+per-device listings. Only the devices listed in the string are modified;
+any existing per-device read_bps for other devices remain unchanged.
+
+B<device-write-bps> is a single string listing one or more device/write_bps
+pairs, in the format of /path/to/device,write_bps,/path/to/device,write_bps.
+Each write_bps is a postive number, or the value 0 to remove that device from
+per-device listings. Only the devices listed in the string are modified;
+any existing per-device write_bps for other devices remain unchanged.
+
+B<device-read-iops> is a single string listing one or more device/read_iops
+pairs, in the format of /path/to/device,read_iops,/path/to/device,read_iops.
+Each read_iops is a postive number, or the value 0 to remove that device from
+per-device listings. Only the devices listed in the string are modified;
+any existing per-device read_iops for other devices remain unchanged.
+
+B<device-write-iops> is a single string listing one or more device/write_iops
+pairs, in the format of /path/to/device,write_iops,/path/to/device,write_iops.
+Each write_iops is a postive number, or the value 0 to remove that device from
+per-device listings. Only the devices listed in the string are modified;
+any existing per-device write_iops for other devices remain unchanged.
+
If I<--live> is specified, affect a running guest.
If I<--config> is specified, affect the next boot of a persistent guest.
If I<--current> is specified, affect the current guest state.
--
1.7.9.5
11 years, 2 months