[libvirt] [PATCH] lxc: Fix suspend/resume with freezer cgroup
by Jiri Denemark
---
src/util/cgroup.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/util/cgroup.c b/src/util/cgroup.c
index c8d1f33..71dedeb 100644
--- a/src/util/cgroup.c
+++ b/src/util/cgroup.c
@@ -1474,14 +1474,14 @@ int virCgroupGetCpuacctUsage(virCgroupPtr group, unsigned long long *usage)
int virCgroupSetFreezerState(virCgroupPtr group, const char *state)
{
return virCgroupSetValueStr(group,
- VIR_CGROUP_CONTROLLER_CPU,
+ VIR_CGROUP_CONTROLLER_FREEZER,
"freezer.state", state);
}
int virCgroupGetFreezerState(virCgroupPtr group, char **state)
{
return virCgroupGetValueStr(group,
- VIR_CGROUP_CONTROLLER_CPU,
+ VIR_CGROUP_CONTROLLER_FREEZER,
"freezer.state", state);
}
--
1.7.8.rc4
12 years, 12 months
[libvirt] [PATCH] examples: Correct the example command to use testnode.xml
by Osier Yang
* s/-connection/-c/
* Removes the redundant '/'.
* Add "absolute" so that it's more clear.
Pushed under trivial rule.
---
examples/xml/test/testnode.xml | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/examples/xml/test/testnode.xml b/examples/xml/test/testnode.xml
index adc5440..001e353 100644
--- a/examples/xml/test/testnode.xml
+++ b/examples/xml/test/testnode.xml
@@ -4,7 +4,7 @@
of applications using libvirt. To use this with virsh, run something
like:
- virsh -connect test:////path/to/this/dir/testnode.xml nodeinfo
+ virsh -c test://absolute/path/to/this/dir/testnode.xml nodeinfo
-->
<domain file="testdomfv0.xml"/>
--
1.7.7.3
12 years, 12 months
[libvirt] [ PATCH v5 0/4] API to invoke S3/S4 on a host and also resume from within libvirt
by Srivatsa S. Bhat
This patchset adds a new API to put a host to a suspended state
(Suspend-to-RAM, Suspend-to-Disk or Hybrid-Suspend) and setup a timed resume
to get the host back online, from within libvirt.
This uses the RTC wakeup mechanism to set up a timer alarm before suspending
the host, so that in-band resume is facilitated by the firing of the RTC
alarm, which wakes up the host.
This patch applies on top of the Hybrid-Suspend patch posted in [1].
v5:
* Added MIN_TIME_REQ_FOR_SUSPEND.
* Incorporated the review comments in [3].
v4:
* Applies on top of the Hybrid-Suspend patch posted in [1].
* Incorporated the review comments in [2].
v3:
* Rebased to libvirt 0.9.7
* Added a check to see if alarmTime (suspend duration) is within an
acceptable range.
v2:
* Added an init function which finds out if S3/S4 is supported by the host,
upon the first request to suspend/hibernate.
* Added synchronization/locking to ensure that only one suspend operation
is active at a time.
v1: http://www.redhat.com/archives/libvir-list/2011-September/msg00830.html
v2: http://comments.gmane.org/gmane.comp.emulators.libvirt/46729
References:
[1]. http://www.redhat.com/archives/libvir-list/2011-November/msg01407.html
[2]. http://thread.gmane.org/gmane.comp.emulators.libvirt/47950
[3]. http://thread.gmane.org/gmane.comp.emulators.libvirt/49054
Srivatsa S. Bhat (4):
Add a public API to invoke suspend/resume on the host
Add the remote protocol implementation for virNodeSuspendForDuration
Implement the core API to suspend/resume the host
Add virsh command to initiate suspend on the host
include/libvirt/libvirt.h.in | 16 ++
src/Makefile.am | 1
src/driver.h | 6 +
src/libvirt.c | 65 ++++++++++
src/libvirt_private.syms | 5 +
src/libvirt_public.syms | 5 +
src/lxc/lxc_driver.c | 2
src/qemu/qemu_driver.c | 2
src/remote/remote_driver.c | 1
src/remote/remote_protocol.x | 10 +-
src/uml/uml_driver.c | 2
src/util/virnodesuspend.c | 269 ++++++++++++++++++++++++++++++++++++++++++
src/util/virnodesuspend.h | 36 ++++++
src/xen/xen_driver.c | 2
tools/virsh.c | 64 ++++++++++
tools/virsh.pod | 7 +
16 files changed, 491 insertions(+), 2 deletions(-)
create mode 100644 src/util/virnodesuspend.c
create mode 100644 src/util/virnodesuspend.h
12 years, 12 months
[libvirt] [PATCH] Add 'Hybrid-Suspend' power management discovery for the host
by Srivatsa S. Bhat
Some systems support a feature known as 'Hybrid-Suspend', apart from the
usual system-wide sleep states such as Suspend-to-RAM (S3) or Suspend-to-Disk
(S4). Add the functionality to discover this power management feature and
export it in the capabilities XML under the <power_management> tag.
This addition was suggested in [1].
References:
1. http://www.redhat.com/archives/libvir-list/2011-November/msg01298.html
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat(a)linux.vnet.ibm.com>
---
docs/formatcaps.html.in | 12 +++--
docs/schemas/capability.rng | 5 ++
src/conf/capabilities.c | 2 -
src/util/util.c | 99 ++++++++++++++++++++++++++++++-------------
src/util/util.h | 8 ++-
5 files changed, 88 insertions(+), 38 deletions(-)
diff --git a/docs/formatcaps.html.in b/docs/formatcaps.html.in
index ce6f9a6..c5fb925 100644
--- a/docs/formatcaps.html.in
+++ b/docs/formatcaps.html.in
@@ -31,6 +31,7 @@ BIOS you will see</p>
<power_management>
<S3/>
<S4/>
+ <Hybrid-Suspend/>
<power_management/>
</host></span>
@@ -70,11 +71,12 @@ the host platform, but other information may be available, it shows the CPU arch
topology, model name, and additional features which are not included in the model but the
CPU provides them. Features of the chip are shown within the feature block (the block is
similar to what you will find in a Xen fully virtualized domain description). Further,
-the power management features supported by the host are shown, such as Suspend-to-RAM (S3)
-and Suspend-to-Disk (S4). In case the query for power management features succeeded but the
-host does not support any such feature, then an empty <power_management/>
-tag will be shown. Otherwise, if the query itself failed, no such tag will
-be displayed (i.e., there will not be any power_management block or empty tag in the XML).</p>
+the power management features supported by the host are shown, such as Suspend-to-RAM (S3),
+Suspend-to-Disk (S4) and Hybrid-Suspend (a combination of S3 and S4).
+In case the query for power management features succeeded but the host does not support
+any such feature, then an empty <power_management/> tag will be shown. Otherwise,
+if the query itself failed, no such tag will be displayed (i.e., there will not be any
+power_management block or empty tag in the XML).</p>
<p>The second block (in blue) indicates the paravirtualization support of the
Xen support, you will see the os_type of xen to indicate a paravirtual
kernel, then architecture information and potential features.</p>
diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng
index 645769e..6cf2188 100644
--- a/docs/schemas/capability.rng
+++ b/docs/schemas/capability.rng
@@ -121,6 +121,11 @@
<empty/>
</element>
</optional>
+ <optional>
+ <element name='Hybrid-Suspend'>
+ <empty/>
+ </element>
+ </optional>
</interleave>
</element>
</define>
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
index 87b60b0..8468861 100644
--- a/src/conf/capabilities.c
+++ b/src/conf/capabilities.c
@@ -35,7 +35,7 @@
#define VIR_FROM_THIS VIR_FROM_CAPABILITIES
VIR_ENUM_IMPL(virHostPMCapability, VIR_HOST_PM_LAST,
- "S3", "S4")
+ "S3", "S4", "Hybrid-Suspend")
/**
* virCapabilitiesNew:
diff --git a/src/util/util.c b/src/util/util.c
index ce697fb..ccd1a0e 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -2623,47 +2623,50 @@ virTypedParameterArrayClear(virTypedParameterPtr params, int nparams)
}
/**
- * Get the Power Management Capabilities of the host system.
- * The script 'pm-is-supported' (from the pm-utils package) is run
- * to find out all the power management features supported by the host,
- * such as Suspend-to-RAM (S3) and Suspend-to-Disk (S4).
+ * virDiscoverHostPMFeature:
+ * @bitmask: The bitmask which should be populated with the result of
+ * the query
+ * @feature: The power management feature to check whether it is supported
+ * by the host. Values could be:
+ * VIR_HOST_PM_S3 for Suspend-to-RAM
+ * VIR_HOST_PM_S4 for Suspend-to-Disk
+ * VIR_HOST_PM_HYBRID_SUSPEND for Hybrid-Suspend
*
- * @bitmask: Pointer to the bitmask which will be set appropriately to
- * indicate all the supported host power management features.
+ * Run the script 'pm-is-supported' (from the pm-utils package)
+ * to find out if @feature is supported by the host.
*
- * Returns 0 if the query was successful, -1 upon failure.
+ * Returns 0 if the query was successful, -1 on failure.
*/
int
-virGetPMCapabilities(unsigned int *bitmask)
+virDiscoverHostPMFeature(unsigned int *bitmask, unsigned int feature)
{
- int ret = -1;
- int status;
virCommandPtr cmd;
+ int status;
+ int ret = -1;
- *bitmask = 0;
-
- /* Check support for Suspend-to-RAM (S3) */
- cmd = virCommandNewArgList("pm-is-supported", "--suspend", NULL);
- if (virCommandRun(cmd, &status) < 0)
- goto cleanup;
-
- /* Check return code of command == 0 for success
- * (i.e., the PM capability is supported)
- */
- if (status == 0)
- *bitmask |= 1U << VIR_HOST_PM_S3;
- virCommandFree(cmd);
+ switch (feature) {
+ case VIR_HOST_PM_S3:
+ cmd = virCommandNewArgList("pm-is-supported", "--suspend", NULL);
+ break;
+ case VIR_HOST_PM_S4:
+ cmd = virCommandNewArgList("pm-is-supported", "--hibernate", NULL);
+ break;
+ case VIR_HOST_PM_HYBRID_SUSPEND:
+ cmd = virCommandNewArgList("pm-is-supported", "--suspend-hybrid", NULL);
+ break;
+ default:
+ return ret;
+ }
- /* Check support for Suspend-to-Disk (S4) */
- cmd = virCommandNewArgList("pm-is-supported", "--hibernate", NULL);
if (virCommandRun(cmd, &status) < 0)
goto cleanup;
- /* Check return code of command == 0 for success
- * (i.e., the PM capability is supported)
- */
+ /*
+ * Check return code of command == 0 for success
+ * (i.e., the PM capability is supported)
+ */
if (status == 0)
- *bitmask |= 1U << VIR_HOST_PM_S4;
+ *bitmask |= 1U << feature;
ret = 0;
@@ -2671,3 +2674,41 @@ cleanup:
virCommandFree(cmd);
return ret;
}
+
+/**
+ * virGetPMCapabilities:
+ *
+ * Get the Power Management Capabilities that the host system supports,
+ * such as Suspend-to-RAM (S3), Suspend-to-Disk (S4) and Hybrid-Suspend
+ * (a combination of S3 and S4).
+ *
+ * @bitmask: Pointer to the bitmask which will be set appropriately to
+ * indicate all the supported host power management features.
+ *
+ * Returns 0 if the query was successful, -1 on failure.
+ */
+int
+virGetPMCapabilities(unsigned int *bitmask)
+{
+ int ret;
+
+ *bitmask = 0;
+
+ /* Check support for Suspend-to-RAM (S3) */
+ ret = virDiscoverHostPMFeature(bitmask, VIR_HOST_PM_S3);
+ if (ret < 0)
+ return -1;
+
+ /* Check support for Suspend-to-Disk (S4) */
+ ret = virDiscoverHostPMFeature(bitmask, VIR_HOST_PM_S4);
+ if (ret < 0)
+ return -1;
+
+ /* Check support for Hybrid-Suspend */
+ ret = virDiscoverHostPMFeature(bitmask, VIR_HOST_PM_HYBRID_SUSPEND);
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
diff --git a/src/util/util.h b/src/util/util.h
index 5afcf58..eda60d2 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -264,14 +264,16 @@ void virTypedParameterArrayClear(virTypedParameterPtr params, int nparams);
/* Power Management Capabilities of the host system */
enum virHostPMCapability {
- VIR_HOST_PM_S3, /* Suspend-to-RAM */
- VIR_HOST_PM_S4, /* Suspend-to-Disk */
+ VIR_HOST_PM_S3, /* Suspend-to-RAM */
+ VIR_HOST_PM_S4, /* Suspend-to-Disk */
+ VIR_HOST_PM_HYBRID_SUSPEND, /* Hybrid-Suspend */
VIR_HOST_PM_LAST
};
VIR_ENUM_DECL(virHostPMCapability)
-int virGetPMCapabilities(unsigned int *);
+int virDiscoverHostPMFeature(unsigned int *bitmask, unsigned int feature);
+int virGetPMCapabilities(unsigned int *bitmask);
#endif /* __VIR_UTIL_H__ */
12 years, 12 months
[libvirt] [PATCH] rpc: Really send non-blocking calls while waiting for another call
by Jiri Denemark
When another thread was dispatching while we wanted to send a
non-blocking call, we correctly queued the call and woke up the thread
but the thread just threw the call away since it forgot to recheck if
its socket was writable.
---
src/rpc/virnetclient.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c
index aad7f5d..a738129 100644
--- a/src/rpc/virnetclient.c
+++ b/src/rpc/virnetclient.c
@@ -1381,6 +1381,16 @@ static int virNetClientIOEventLoop(virNetClientPtr client,
_("read on wakeup fd failed"));
goto error;
}
+
+ /* If we were woken up because a new non-blocking call was queued,
+ * we need to re-poll to check if we can send it.
+ */
+ if (virNetClientCallMatchPredicate(client->waitDispatch,
+ virNetClientIOEventLoopWantNonBlock,
+ NULL)) {
+ VIR_DEBUG("New non-blocking call arrived; repolling");
+ continue;
+ }
}
if (ret < 0) {
--
1.7.8.rc3
12 years, 12 months
[libvirt] [PATCH 3/8] Implement virDomain{Set, Get}BlockIoTune for the qemu driver
by Lei Li
Implement the block I/O throttle setting and getting support to qemu
driver.
Signed-off-by: Lei Li <lilei(a)linux.vnet.ibm.com>
Signed-off-by: Zhi Yong Wu <wuzhy(a)linux.vnet.ibm.com>
---
src/qemu/qemu_driver.c | 342 ++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor.c | 37 +++++
src/qemu/qemu_monitor.h | 22 +++
src/qemu/qemu_monitor_json.c | 186 +++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 10 ++
src/qemu/qemu_monitor_text.c | 165 ++++++++++++++++++++
src/qemu/qemu_monitor_text.h | 10 ++
7 files changed, 772 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 5f4a18d..0a4eaa9 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -94,6 +94,8 @@
#define QEMU_NB_MEM_PARAM 3
+#define QEMU_NB_BLKIOTHROTTLE_PARAM 6
+
#if HAVE_LINUX_KVM_H
# include <linux/kvm.h>
#endif
@@ -10775,6 +10777,344 @@ cleanup:
return ret;
}
+static int
+qemuDomainSetBlockIoTune(virDomainPtr dom,
+ const char *disk,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags)
+{
+ struct qemud_driver *driver = dom->conn->privateData;
+ virDomainObjPtr vm = NULL;
+ qemuDomainObjPrivatePtr priv;
+ virDomainDefPtr persistentDef = NULL;
+ virDomainBlockIoTuneInfo info;
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ const char *device = NULL;
+ int ret = -1;
+ int i;
+ bool isActive;
+
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+ VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+ memset(&info, 0, sizeof(info));
+
+ qemuDriverLock(driver);
+ virUUIDFormat(dom->uuid, uuidstr);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ if (!vm) {
+ qemuReportError(VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+
+ device = qemuDiskPathToAlias(vm, disk);
+ if (!device) {
+ goto cleanup;
+ }
+
+ if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
+ goto cleanup;
+
+ isActive = virDomainObjIsActive(vm);
+
+ if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
+ if (isActive)
+ flags = VIR_DOMAIN_AFFECT_LIVE;
+ else
+ flags = VIR_DOMAIN_AFFECT_CONFIG;
+ }
+
+ if (!isActive && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain is not running"));
+ goto endjob;
+ }
+
+ if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+ if (!vm->persistent) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("cannot change persistent config of a transient domain"));
+ goto endjob;
+ }
+ if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
+ goto endjob;
+ }
+
+ for (i = 0; i < nparams; i++) {
+ virTypedParameterPtr param = ¶ms[i];
+
+ if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC)) {
+
+ info.total_bytes_sec = params[i].value.ul;
+ } else if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC)) {
+ info.read_bytes_sec = params[i].value.ul;
+ } else if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC)) {
+ info.write_bytes_sec = params[i].value.ul;
+ } else if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC)) {
+ info.total_iops_sec = params[i].value.ul;
+ } else if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC)) {
+ info.read_iops_sec = params[i].value.ul;
+ } else if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC)) {
+ info.write_iops_sec = params[i].value.ul;
+ } else {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("Unrecognized parameter"));
+ goto endjob;
+ }
+ }
+
+ if ((info.total_bytes_sec && info.read_bytes_sec) ||
+ (info.total_bytes_sec && info.write_bytes_sec)) {
+ qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("total and read/write of bytes_sec cannot be set at the same time"));
+ goto endjob;
+ }
+
+ if ((info.total_iops_sec && info.read_iops_sec) ||
+ (info.total_iops_sec && info.write_iops_sec)) {
+ qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("total and read/write of iops_sec cannot be set at the same time"));
+ goto endjob;
+ }
+
+ if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+ priv = vm->privateData;
+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ ret = qemuMonitorSetBlockIoThrottle(priv->mon, device, &info, 1);
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+ }
+
+ if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+ sa_assert(persistentDef);
+ int idx = virDomainDiskIndexByName(vm->def, disk, true);
+ if (i < 0)
+ goto endjob;
+ persistentDef->disks[idx]->blkdeviotune.total_bytes_sec = info.total_bytes_sec;
+ persistentDef->disks[idx]->blkdeviotune.read_bytes_sec = info.read_bytes_sec;
+ persistentDef->disks[idx]->blkdeviotune.write_bytes_sec = info.write_bytes_sec;
+ persistentDef->disks[idx]->blkdeviotune.total_iops_sec = info.total_iops_sec;
+ persistentDef->disks[idx]->blkdeviotune.read_iops_sec = info.read_iops_sec;
+ persistentDef->disks[idx]->blkdeviotune.write_iops_sec = info.write_iops_sec;
+ persistentDef->disks[idx]->blkdeviotune.mark = 1;
+ }
+
+ if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+ ret = virDomainSaveConfig(driver->configDir, persistentDef);
+ if (ret < 0) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("Write to config file failed"));
+ goto endjob;
+ }
+ }
+
+endjob:
+ if (qemuDomainObjEndJob(driver, vm) == 0)
+ vm = NULL;
+
+cleanup:
+ VIR_FREE(device);
+ if (vm)
+ virDomainObjUnlock(vm);
+ qemuDriverUnlock(driver);
+ return ret;
+}
+
+static int
+qemuDomainGetBlockIoTune(virDomainPtr dom,
+ const char *disk,
+ virTypedParameterPtr params,
+ int *nparams,
+ unsigned int flags)
+{
+ struct qemud_driver *driver = dom->conn->privateData;
+ virDomainObjPtr vm = NULL;
+ qemuDomainObjPrivatePtr priv;
+ virDomainDefPtr persistentDef = NULL;
+ virDomainBlockIoTuneInfo reply;
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ const char *device = NULL;
+ int ret = -1;
+ int i;
+ bool isActive;
+
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+ VIR_DOMAIN_AFFECT_CONFIG |
+ VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+ /* We don't return strings, and thus trivially support this flag. */
+ flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
+
+ qemuDriverLock(driver);
+ virUUIDFormat(dom->uuid, uuidstr);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ if (!vm) {
+ qemuReportError(VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+
+ device = qemuDiskPathToAlias(vm, disk);
+
+ if (!device) {
+ goto cleanup;
+ }
+
+ if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
+ goto cleanup;
+
+ isActive = virDomainObjIsActive(vm);
+
+ if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
+ if (isActive)
+ flags = VIR_DOMAIN_AFFECT_LIVE;
+ else
+ flags = VIR_DOMAIN_AFFECT_CONFIG;
+ }
+
+ if ((flags & VIR_DOMAIN_AFFECT_LIVE) && (flags & VIR_DOMAIN_AFFECT_CONFIG)) {
+ qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("Cannot query with --live and --config together"));
+ goto endjob;
+ }
+
+ if (!isActive && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain is not running"));
+ goto endjob;
+ }
+
+ if ((*nparams) == 0) {
+ /* Current number of parameters supported by QEMU Block I/O Throttling */
+ *nparams = QEMU_NB_BLKIOTHROTTLE_PARAM;
+ ret = 0;
+ goto endjob;
+ }
+
+ if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+ priv = vm->privateData;
+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ ret = qemuMonitorGetBlockIoThrottle(priv->mon, device, &reply, 0);
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+ }
+
+ if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+ if (!vm->persistent) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain is transient"));
+ goto endjob;
+ }
+ if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
+ goto endjob;
+
+ sa_assert(persistentDef);
+ int idx = virDomainDiskIndexByName(vm->def, disk, true);
+ if (idx < 0)
+ goto endjob;
+ reply.total_bytes_sec = persistentDef->disks[idx]->blkdeviotune.total_bytes_sec;
+ reply.read_bytes_sec = persistentDef->disks[idx]->blkdeviotune.read_bytes_sec;
+ reply.write_bytes_sec = persistentDef->disks[idx]->blkdeviotune.write_bytes_sec;
+ reply.total_iops_sec = persistentDef->disks[idx]->blkdeviotune.total_iops_sec;
+ reply.read_iops_sec = persistentDef->disks[idx]->blkdeviotune.read_iops_sec;
+ reply.write_iops_sec = persistentDef->disks[idx]->blkdeviotune.write_iops_sec;
+ ret = 0;
+ }
+
+ if ((ret != 0) && ((*nparams) < QEMU_NB_BLKIOTHROTTLE_PARAM)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("Cannot get block I/O parameters"));
+ goto endjob;
+ }
+
+ for (i = 0; i < QEMU_NB_BLKIOTHROTTLE_PARAM; i++) {
+ virTypedParameterPtr param = ¶ms[i];
+ param->value.ul = 0;
+ param->type = VIR_TYPED_PARAM_ULLONG;
+
+ switch(i) {
+ case 0:
+ if (virStrcpyStatic(param->field,
+ VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC) == NULL) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Field name '%s' too long"),
+ VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC);
+ goto endjob;
+ }
+ param->value.ul = reply.total_bytes_sec;
+ break;
+
+ case 1:
+ if (virStrcpyStatic(param->field,
+ VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC) == NULL) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Field name '%s' too long"),
+ VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC);
+ goto endjob;
+ }
+ param->value.ul = reply.read_bytes_sec;
+ break;
+
+ case 2:
+ if (virStrcpyStatic(param->field,
+ VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC) == NULL) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Field name '%s' too long"),
+ VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC);
+ goto endjob;
+ }
+ param->value.ul = reply.write_bytes_sec;
+ break;
+
+ case 3:
+ if (virStrcpyStatic(param->field,
+ VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC) == NULL) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Field name '%s' too long"),
+ VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC);
+ goto endjob;
+ }
+ param->value.ul = reply.total_iops_sec;
+ break;
+
+ case 4:
+ if (virStrcpyStatic(param->field,
+ VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC) == NULL) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Field name '%s' too long"),
+ VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC);
+ goto endjob;
+ }
+ param->value.ul = reply.read_iops_sec;
+ break;
+
+ case 5:
+ if (virStrcpyStatic(param->field,
+ VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC) == NULL) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Field name '%s' too long"),
+ VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC);
+ goto endjob;
+ }
+ param->value.ul = reply.write_iops_sec;
+ break;
+ default:
+ break;
+ }
+ }
+ ret = 0;
+
+endjob:
+ if (qemuDomainObjEndJob(driver, vm) == 0)
+ vm = NULL;
+
+cleanup:
+ VIR_FREE(device);
+ if (vm)
+ virDomainObjUnlock(vm);
+ qemuDriverUnlock(driver);
+ return ret;
+}
static virDriver qemuDriver = {
.no = VIR_DRV_QEMU,
@@ -10919,6 +11259,8 @@ static virDriver qemuDriver = {
.domainGetBlockJobInfo = qemuDomainGetBlockJobInfo, /* 0.9.4 */
.domainBlockJobSetSpeed = qemuDomainBlockJobSetSpeed, /* 0.9.4 */
.domainBlockPull = qemuDomainBlockPull, /* 0.9.4 */
+ .domainSetBlockIoTune = qemuDomainSetBlockIoTune, /* 0.9.8 */
+ .domainGetBlockIoTune = qemuDomainGetBlockIoTune, /* 0.9.8 */
};
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 73e5ea9..c0b711f 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2567,6 +2567,43 @@ int qemuMonitorBlockJob(qemuMonitorPtr mon,
return ret;
}
+int qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoTuneInfoPtr info,
+ unsigned int flags)
+{
+ int ret;
+
+ VIR_DEBUG("mon=%p, device=%p, info=%p, flags=%x",
+ mon, device, info, flags);
+
+ if (mon->json) {
+ ret = qemuMonitorJSONSetBlockIoThrottle(mon, device, info, flags);
+ } else {
+ ret = qemuMonitorTextSetBlockIoThrottle(mon, device, info, flags);
+ }
+ return ret;
+}
+
+int qemuMonitorGetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoTuneInfoPtr reply,
+ unsigned int flags)
+{
+ int ret;
+
+ VIR_DEBUG("mon=%p, device=%p, reply=%p, flags=%x",
+ mon, device, reply, flags);
+
+ if (mon->json) {
+ ret = qemuMonitorJSONGetBlockIoThrottle(mon, device, reply, flags);
+ } else {
+ ret = qemuMonitorTextGetBlockIoThrottle(mon, device, reply, flags);
+ }
+ return ret;
+}
+
+
int qemuMonitorVMStatusToPausedReason(const char *status)
{
int st;
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 883e0aa..48c6db0 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -521,6 +521,28 @@ int qemuMonitorOpenGraphics(qemuMonitorPtr mon,
const char *fdname,
bool skipauth);
+
+typedef struct _virDomainBlockIoTuneInfo virDomainBlockIoTuneInfo;
+struct _virDomainBlockIoTuneInfo {
+ unsigned long long total_bytes_sec;
+ unsigned long long read_bytes_sec;
+ unsigned long long write_bytes_sec;
+ unsigned long long total_iops_sec;
+ unsigned long long read_iops_sec;
+ unsigned long long write_iops_sec;
+};
+typedef virDomainBlockIoTuneInfo *virDomainBlockIoTuneInfoPtr;
+
+int qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoTuneInfoPtr info,
+ unsigned int flags);
+
+int qemuMonitorGetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoTuneInfoPtr reply,
+ unsigned int flags);
+
/**
* When running two dd process and using <> redirection, we need a
* shell that will not truncate files. These two strings serve that
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 56a62db..925031e 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -3276,3 +3276,189 @@ int qemuMonitorJSONOpenGraphics(qemuMonitorPtr mon,
virJSONValueFree(reply);
return ret;
}
+
+
+static int
+qemuMonitorJSONBlockIoThrottleInfo(virJSONValuePtr result,
+ const char *device,
+ virDomainBlockIoTuneInfoPtr reply)
+{
+ virJSONValuePtr io_throttle;
+ int ret = -1;
+ int i;
+ int found = 0;
+
+ io_throttle = virJSONValueObjectGet(result, "return");
+
+ if (!io_throttle || io_throttle->type != VIR_JSON_TYPE_ARRAY) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _(" block_io_throttle reply was missing device list "));
+ goto cleanup;
+ }
+
+ for (i = 0; i < virJSONValueArraySize(io_throttle); i++) {
+ virJSONValuePtr temp_dev = virJSONValueArrayGet(io_throttle, i);
+ virJSONValuePtr inserted;
+ const char *current_dev;
+
+ if (!temp_dev || temp_dev->type != VIR_JSON_TYPE_OBJECT) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("block io throttle device entry was not in expected format"));
+ goto cleanup;
+ }
+
+ if ((current_dev = virJSONValueObjectGetString(temp_dev, "device")) == NULL) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("block io throttle device entry was not in expected format"));
+ goto cleanup;
+ }
+
+ if(STRPREFIX(current_dev, QEMU_DRIVE_HOST_PREFIX))
+ current_dev += strlen(QEMU_DRIVE_HOST_PREFIX);
+
+ if (STREQ(current_dev, device))
+ continue;
+
+ found = 1;
+ if ((inserted = virJSONValueObjectGet(temp_dev, "inserted")) == NULL ||
+ inserted->type != VIR_JSON_TYPE_OBJECT) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("block io throttle inserted entry was not in expected format"));
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(inserted, "bps", &reply->total_bytes_sec) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s"), "total_bytes_sec");
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(inserted, "bps_rd", &reply->read_bytes_sec) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s"), "read_bytes_sec");
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(inserted, "bps_wr", &reply->write_bytes_sec) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s"), "write_bytes_sec");
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(inserted, "iops", &reply->total_iops_sec) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s"), "total_iops_sec");
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(inserted, "iops_rd", &reply->read_iops_sec) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s"), "read_iops_sec");
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(inserted, "iops_wr", &reply->write_iops_sec) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s"), "write_iops_sec");
+ goto cleanup;
+ }
+ break;
+ }
+
+ if (!found) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot found info for device '%s'"),
+ device);
+ goto cleanup;
+ }
+ ret = 0;
+
+cleanup:
+ return ret;
+}
+
+int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoTuneInfoPtr info,
+ unsigned int flags)
+{
+ int ret = -1;
+ virJSONValuePtr cmd = NULL;
+ virJSONValuePtr result = NULL;
+
+ if (flags) {
+ cmd = qemuMonitorJSONMakeCommand("block_set_io_throttle",
+ "s:device", device,
+ "U:bps", info->total_bytes_sec,
+ "U:bps_rd", info->read_bytes_sec,
+ "U:bps_wr", info->write_bytes_sec,
+ "U:iops", info->total_iops_sec,
+ "U:iops_rd", info->read_iops_sec,
+ "U:iops_wr", info->write_iops_sec,
+ NULL);
+ }
+
+ if (!cmd)
+ return -1;
+
+ ret = qemuMonitorJSONCommand(mon, cmd, &result);
+
+ if (ret == 0 && virJSONValueObjectHasKey(result, "error")) {
+ if (qemuMonitorJSONHasError(result, "DeviceNotActive"))
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ _("No active operation on device: %s"), device);
+ else if (qemuMonitorJSONHasError(result, "NotSupported"))
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ _("Operation is not supported for device: %s"), device);
+ else
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unexpected error"));
+ ret = -1;
+ }
+
+ virJSONValueFree(cmd);
+ virJSONValueFree(result);
+ return ret;
+}
+
+int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoTuneInfoPtr reply,
+ unsigned int flags)
+{
+ int ret = -1;
+ virJSONValuePtr cmd = NULL;
+ virJSONValuePtr result = NULL;
+
+ if (!flags) {
+ cmd = qemuMonitorJSONMakeCommand("query-block",
+ NULL);
+ }
+
+ if (!cmd) {
+ return -1;
+ }
+
+ ret = qemuMonitorJSONCommand(mon, cmd, &result);
+
+ if (ret == 0 && virJSONValueObjectHasKey(result, "error")) {
+ if (qemuMonitorJSONHasError(result, "DeviceNotActive"))
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ _("No active operation on device: %s"), device);
+ else if (qemuMonitorJSONHasError(result, "NotSupported"))
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ _("Operation is not supported for device: %s"), device);
+ else
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unexpected error"));
+ ret = -1;
+ }
+
+ if (ret == 0 && !flags)
+ ret = qemuMonitorJSONBlockIoThrottleInfo(result, device, reply);
+
+ virJSONValueFree(cmd);
+ virJSONValueFree(result);
+ return ret;
+}
+
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index f10d7d2..bf12dc5 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -255,4 +255,14 @@ int qemuMonitorJSONOpenGraphics(qemuMonitorPtr mon,
const char *fdname,
bool skipauth);
+int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoTuneInfoPtr info,
+ unsigned int flags);
+
+int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoTuneInfoPtr reply,
+ unsigned int flags);
+
#endif /* QEMU_MONITOR_JSON_H */
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index 5de4d24..0ccc111 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -3429,3 +3429,168 @@ cleanup:
VIR_FREE(cmd);
return ret;
}
+
+
+int qemuMonitorTextSetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoTuneInfoPtr info,
+ unsigned int flags)
+{
+ char *cmd = NULL;
+ char *result = NULL;
+ int ret = 0;
+ const char *cmd_name = NULL;
+
+ /* For the not specified fields, 0 by default */
+ if (flags) {
+ cmd_name = "block_set_io_throttle";
+ ret = virAsprintf(&cmd, "%s %s %llu %llu %llu %llu %llu %llu", cmd_name,
+ device, info->total_bytes_sec, info->read_bytes_sec,
+ info->write_bytes_sec, info->total_iops_sec,
+ info->read_iops_sec, info->write_iops_sec);
+ }
+
+ if (ret < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if (qemuMonitorHMPCommand(mon, cmd, &result) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("cannot run monitor command"));
+ ret = -1;
+ goto cleanup;
+ }
+
+ if (qemuMonitorTextCommandNotFound(cmd_name, result)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ _("Command '%s' is not found"), cmd_name);
+ ret = -1;
+ goto cleanup;
+ }
+
+cleanup:
+ VIR_FREE(cmd);
+ VIR_FREE(result);
+ return ret;
+}
+
+static int qemuMonitorTextParseBlockIoThrottle(const char *result,
+ const char *device,
+ virDomainBlockIoTuneInfoPtr reply)
+{
+ char *dummy = NULL;
+ int ret = -1;
+ const char *p, *eol;
+ int devnamelen = strlen(device);
+
+ p = result;
+
+ while (*p) {
+ if (STRPREFIX(p, QEMU_DRIVE_HOST_PREFIX))
+ p += strlen(QEMU_DRIVE_HOST_PREFIX);
+
+ if (STREQLEN(p, device, devnamelen) &&
+ p[devnamelen] == ':' && p[devnamelen+1] == ' ') {
+
+ eol = strchr(p, '\n');
+ if (!eol)
+ eol = p + strlen(p);
+
+ p += devnamelen + 2; /*Skip to first label. */
+
+ while (*p) {
+ if (STRPREFIX(p, "bps=")) {
+ p += strlen("bps=");
+ if (virStrToLong_ull(p, &dummy, 10, &reply->total_bytes_sec) == -1)
+ VIR_DEBUG("error reading total_bytes_sec: %s", p);
+ } else if (STRPREFIX(p, "bps_rd=")) {
+ p += strlen("bps_rd=");
+ if (virStrToLong_ull(p, &dummy, 10, &reply->read_bytes_sec) == -1)
+ VIR_DEBUG("error reading read_bytes_sec: %s", p);
+ } else if (STRPREFIX(p, "bps_wr=")) {
+ p += strlen("bps_wr=");
+ if (virStrToLong_ull(p, &dummy, 10, &reply->write_bytes_sec) == -1)
+ VIR_DEBUG("error reading write_bytes_sec: %s", p);
+ } else if (STRPREFIX(p, "iops=")) {
+ p += strlen("iops=");
+ if (virStrToLong_ull(p, &dummy, 10, &reply->total_iops_sec) == -1)
+ VIR_DEBUG("error reading total_iops_sec: %s", p);
+ } else if (STRPREFIX(p, "iops_rd=")) {
+ p += strlen("iops_rd=");
+ if (virStrToLong_ull(p, &dummy, 10, &reply->read_iops_sec) == -1)
+ VIR_DEBUG("error reading read_iops_sec: %s", p);
+ } else if (STRPREFIX(p, "iops_wr=")) {
+ p += strlen("iops_wr=");
+ if (virStrToLong_ull(p, &dummy, 10, &reply->write_iops_sec) == -1)
+ VIR_DEBUG("error reading write_iops_sec: %s", p);
+ } else {
+ VIR_DEBUG(" unknown block info %s", p);
+ }
+
+ /* Skip to next label. */
+ p = strchr (p, ' ');
+ if (!p || p >= eol)
+ break;
+ p++;
+ }
+ ret = 0;
+ goto cleanup;
+ }
+
+ /* Skip to next line. */
+ p = strchr (p, '\n');
+ if (!p)
+ break;
+ p++;
+ }
+
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("No info for device '%s'"), device);
+
+cleanup:
+ return ret;
+}
+
+int qemuMonitorTextGetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoTuneInfoPtr reply,
+ unsigned int flags)
+{
+ char *cmd = NULL;
+ char *result = NULL;
+ int ret = 0;
+ const char *cmd_name = NULL;
+
+ if (flags) {
+ cmd_name = "info block";
+ ret = virAsprintf(&cmd, "%s", cmd_name);
+ }
+
+ if (ret < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if (qemuMonitorHMPCommand(mon, cmd, &result) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("cannot run monitor command"));
+ ret = -1;
+ goto cleanup;
+ }
+
+ if (qemuMonitorTextCommandNotFound(cmd_name, result)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ _("Command '%s' is not found"), cmd_name);
+ ret = -1;
+ goto cleanup;
+ }
+
+ ret = qemuMonitorTextParseBlockIoThrottle(result, device, reply);
+
+cleanup:
+ VIR_FREE(cmd);
+ VIR_FREE(result);
+ return ret;
+}
+
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index f32fce0..1c47d39 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -248,4 +248,14 @@ int qemuMonitorTextOpenGraphics(qemuMonitorPtr mon,
const char *fdname,
bool skipauth);
+int qemuMonitorTextSetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoTuneInfoPtr info,
+ unsigned int flags);
+
+int qemuMonitorTextGetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoTuneInfoPtr reply,
+ unsigned int flags);
+
#endif /* QEMU_MONITOR_TEXT_H */
--
1.7.1
12 years, 12 months
[libvirt] [RFC PATCH 0/5] Support online resizing of block devices.
by Osier Yang
This patch series introduce new API "virDomainBlockResize" to expose
qemu monitor command "block_size", which is for resizing the a block
device while the domain is running.
The prototype for the new API is:
int
virDomainBlockResize (virDomainPtr dom,
const char *path,
unsigned long long size,
unsigned int flags)
* "@path" is the absolute path of the block device, which can be
extraced from domain xml.
* The units for "@size" is kilobytes, which might be not quite properly.
(qemu HMP uses Megabytes as the default units, QMP uses Bytes as the
default units, so it means we need to divice "@size" by 1024 for HMP,
and multiply "@size" by 1024 for QMP. On the other hand, we need to
check the overflowing). Any ideas on this is welcomed.
* "@flags" is unused currently.
[PATCH 1/5] block_resize: Define the new API
[PATCH 2/5] block_resize: Wire up the remote protocol
[PATCH 3/5] block_resize: Implement qemu monitor functions
[PATCH 4/5] block_resize: Implement qemu driver method
[PATCH 5/5] block_resize: Expose the new API to virsh
12 years, 12 months
[libvirt] [libvirt-glib 1/2] Add some information about Apple OSs
by Zeeshan Ali (Khattak)
From: "Zeeshan Ali (Khattak)" <zeeshanak(a)gnome.org>
Based on a patch from Mateusz Kaplon <mateusz.kaplon(a)gmail.com>.
---
data/oses/macos.xml | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 94 insertions(+), 0 deletions(-)
create mode 100644 data/oses/macos.xml
diff --git a/data/oses/macos.xml b/data/oses/macos.xml
new file mode 100644
index 0000000..84aaa58
--- /dev/null
+++ b/data/oses/macos.xml
@@ -0,0 +1,94 @@
+<libosinfo version="0.0.1">
+
+ <os id="http://apple.com/macosx/10.0">
+ <short-id>macosx100</short-id>
+ <name>MacOS X Cheetah</name>
+ <version>10.0</version>
+ <vendor>Apple Inc.</vendor>
+ <family>MacOS</family>
+ </os>
+
+ <os id="http://apple.com/macosx/10.1">
+ <short-id>macosx101</short-id>
+ <name>MacOS X Puma</name>
+ <version>10.1</version>
+ <vendor>Apple Inc.</vendor>
+ <family>MacOS</family>
+ <upgrades id="http://apple.com/macosx/10.0" />
+ </os>
+
+ <os id="http://apple.com/macosx/10.2">
+ <short-id>macosx102</short-id>
+ <name>MacOS X Jaghuar</name>
+ <version>10.2</version>
+ <vendor>Apple Inc.</vendor>
+ <family>MacOS</family>
+ <upgrades id="http://apple.com/macosx/10.1" />
+ </os>
+
+ <os id="http://apple.com/macosx/10.3">
+ <short-id>macosx103</short-id>
+ <name>MacOS X Panther</name>
+ <version>10.3</version>
+ <vendor>Apple Inc.</vendor>
+ <family>MacOS</family>
+ <upgrades id="http://apple.com/macosx/10.2" />
+ </os>
+
+ <os id="http://apple.com/macosx/10.4">
+ <short-id>macosx104</short-id>
+ <name>MacOS X Tiger</name>
+ <version>10.4</version>
+ <vendor>Apple Inc.</vendor>
+ <family>MacOS</family>
+ <upgrades id="http://apple.com/macosx/10.3" />
+ </os>
+
+ <os id="http://apple.com/macosx/10.5">
+ <short-id>macosx105</short-id>
+ <name>MacOS X Leopard</name>
+ <version>10.5</version>
+ <vendor>Apple Inc.</vendor>
+ <family>MacOS</family>
+ <upgrades id="http://apple.com/macosx/10.4" />
+ </os>
+
+ <os id="http://apple.com/macosx/10.6">
+ <short-id>macosx106</short-id>
+ <name>MacOS X Snow Leopard</name>
+ <version>10.6</version>
+ <vendor>Apple Inc.</vendor>
+ <family>MacOS</family>
+ <upgrades id="http://apple.com/macosx/10.5" />
+
+ <resources arch="all">
+ <minimal>
+ <n-cpus>2</n-cpus>
+ <cpu>1600000000</cpu>
+ <ram>2147483648</ram>
+ <storage>7516192768</storage>
+ </minimal>
+ </resources>
+
+ </os>
+
+ <os id="http://apple.com/macosx/10.7">
+ <short-id>macosx107</short-id>
+ <name>MacOS X Lion</name>
+ <version>10.7</version>
+ <vendor>Apple Inc.</vendor>
+ <family>MacOS</family>
+ <upgrades id="http://apple.com/macosx/10.6" />
+
+ <resources arch="all">
+ <minimal>
+ <n-cpus>2</n-cpus>
+ <cpu>1600000000</cpu>
+ <ram>2147483648</ram>
+ <storage>7516192768</storage>
+ </minimal>
+ </resources>
+
+ </os>
+
+</libosinfo>
--
1.7.7.3
12 years, 12 months
[libvirt] [PATCH libvirt-glib 0/5] Updates to streams APIs
by Daniel P. Berrange
This patch series expands the streams APIs to allow practical use
of non-blocking bi-directional streams. It also formally documents
the required coding style conventions for libvirt-glib before we
get too much more code that is out of the ordinary.
12 years, 12 months