[libvirt] [PATCH] qemu: plug memory leak
by ajia@redhat.com
From: Alex Jia <ajia(a)redhat.com>
Deteted by valgrind:
==18462== 1,100 bytes in 1 blocks are definitely lost in loss record 183 of 184
==18462== at 0x4A05FDE: malloc (vg_replace_malloc.c:236)
==18462== by 0x4A06167: realloc (vg_replace_malloc.c:525)
==18462== by 0x4AADBB: virReallocN (memory.c:161)
==18462== by 0x4A975E: virBufferGrow (buf.c:117)
==18462== by 0x4A9D92: virBufferVasprintf (buf.c:290)
==18462== by 0x4A9EF7: virBufferAsprintf (buf.c:263)
==18462== by 0x429488: qemuBuildControllerDevStr (qemu_command.c:1993)
==18462== by 0x42C4B6: qemuBuildCommandLine (qemu_command.c:3803)
==18462== by 0x41A604: testCompareXMLToArgvHelper (qemuxml2argvtest.c:124)
==18462== by 0x41BB81: virtTestRun (testutils.c:141)
==18462== by 0x416DFF: mymain (qemuxml2argvtest.c:369)
==18462== by 0x41B277: virtTestMain (testutils.c:696)
==18462==
==18462== LEAK SUMMARY:
==18462== definitely lost: 1,100 bytes in 1 blocks
==18462== indirectly lost: 0 bytes in 0 blocks
* src/qemu/qemu_command.c (qemuBuildCommandLine): Clean up on success.
Signed-off-by: Alex Jia <ajia(a)redhat.com>
---
src/qemu/qemu_command.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 0c5bfab..9c435de 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3804,6 +3804,7 @@ qemuBuildCommandLine(virConnectPtr conn,
goto error;
virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
}
} else if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
def->controllers[i]->model == -1 &&
--
1.7.1
13 years, 1 month
[libvirt] [PATCH] qemu: avoid leaking uninit data from hotplug to dumpxml
by Eric Blake
Detected by Coverity. The fix in 2c27dfa didn't catch all bad
instances of memcpy(). Thankfully, on further analysis, all of
the problematic uses are only triggered by old qemu that lacks
-device.
* src/qemu/qemu_hotplug.c (qemuDomainAttachPciDiskDevice)
(qemuDomainAttachNetDevice, qemuDomainAttachHostPciDevice): Init
all fields since monitor only populates some of them.
---
src/qemu/qemu_hotplug.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 037f4aa..06b21c3 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -246,7 +246,7 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver,
}
}
} else {
- virDomainDevicePCIAddress guestAddr;
+ virDomainDevicePCIAddress guestAddr = disk->info.addr.pci;
ret = qemuMonitorAddPCIDisk(priv->mon,
disk->src,
type,
@@ -775,6 +775,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
goto try_remove;
}
} else {
+ guestAddr = net->info.addr.pci;
if (qemuMonitorAddPCINetwork(priv->mon, nicstr,
&guestAddr) < 0) {
qemuDomainObjExitMonitorWithDriver(driver, vm);
@@ -929,7 +930,7 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver,
configfd, configfd_name);
qemuDomainObjExitMonitorWithDriver(driver, vm);
} else {
- virDomainDevicePCIAddress guestAddr;
+ virDomainDevicePCIAddress guestAddr = hostdev->info.addr.pci;
qemuDomainObjEnterMonitorWithDriver(driver, vm);
ret = qemuMonitorAddPCIHostDevice(priv->mon,
--
1.7.4.4
13 years, 1 month
[libvirt] [RFC PATCH 0/8 v2] Summary on block IO throttle
by Lei Li
Changes since V1
- Implement the support to get the block io throttling for
a device as read only connection - QMP/HMP.
- Split virDomainBlockIoThrottle into two separate functions
virDomainSetBlockIoThrottle - Set block I/O limits for a device
- Requires a connection in 'write' mode.
- Limits (info) structure passed as an input parameter
virDomainGetBlockIoThrottle - Get the current block I/O limits for a device
- Works on a read-only connection.
- Current limits are written to the output parameter (reply).
- And Other fixups suggested by Adam Litke, Daniel P. Berrange.
- For dynamically allocate the blkiothrottle struct, I will fix
it when implement --current --live --config options support.
Today libvirt supports the cgroups blkio-controller, which handles
proportional shares and throughput/iops limits on host block devices.
blkio-controller does not support network file systems (NFS) or other
QEMU remote block drivers (curl, Ceph/rbd, sheepdog) since they are
not host block devices. QEMU I/O throttling works with all types of
drive and can be applied independently to each drive attached to
a guest and supports throughput/iops limits.
To help add QEMU I/O throttling support to libvirt, we plan to complete
it with add new API virDomainBlockIoThrottle(), new command 'blkiothrottle'
and Python bindings.
Notes: we are sending this series out now(even though they are not completed
yet.)because we want to start the review process. #1)#2) features were implemented
by Zhi Yong Wu:
1) Enable the blkio throttling in xml when guest is starting up.
Add blkio throttling in xml as follows:
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/var/lib/libvirt/images/kvm-one.img'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
<iotune bps='n'.../>
</disk>
2) Enable blkio throttling setting at guest running time.
virsh blkiothrottle <domain> <device> [--bps<number>] [--bps_rd<number>] \
[--bps_wr<number>] [--iops<number>] [--iops_rd<number>] [--iops_wr<number>]
3) The support to get the current block i/o throttling for a device - HMP/QMP.
virsh blkiothrottle <domain> <device>
bps:
bps_rd:
bps_wr:
iops:
iops_rd:
iops_wr:
And I will address feedback and work on the missing features in few days includes:
4) Python binding support for setting blkio throttling.
5) --current --live --config options support to unify the libvirt API.
daemon/remote.c | 85 +++++++++++++++++
include/libvirt/libvirt.h.in | 25 +++++
python/generator.py | 2 +
python/libvirt-override-api.xml | 16 ++++
python/libvirt-override.c | 43 +++++++++
src/conf/domain_conf.c | 77 ++++++++++++++++
src/conf/domain_conf.h | 11 +++
src/driver.h | 18 ++++
src/libvirt.c | 120 ++++++++++++++++++++++++
src/libvirt_public.syms | 2 +
src/qemu/qemu_command.c | 35 +++++++
src/qemu/qemu_driver.c | 108 ++++++++++++++++++++++
src/qemu/qemu_monitor.c | 36 ++++++++
src/qemu/qemu_monitor.h | 10 ++
src/qemu/qemu_monitor_json.c | 191 +++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 10 ++
src/qemu/qemu_monitor_text.c | 88 ++++++++++++++++++
src/qemu/qemu_monitor_text.h | 10 ++
src/remote/remote_driver.c | 81 +++++++++++++++++
src/remote/remote_protocol.x | 39 ++++++++-
src/remote_protocol-structs | 34 +++++++
src/util/xml.h | 3 +
tools/virsh.c | 100 ++++++++++++++++++++
tools/virsh.pod | 13 +++
24 files changed, 1156 insertions(+), 1 deletions(-)
--
Lei
13 years, 1 month
Re: [libvirt] [PATCH 0/7] Update systemtap probing
by Smith Brian
Hi,
I got similar mistake with you ,so I reconfigured and had dtrace
installed. But can't successfully recompile dtraced-libvirt with every
possible mean.
./autogen --with-pic --enable-shared=yes --with-dtrace
make
Then I got error below:
*** Warning: Linking the shared library libvirt.la against the non-libtool
*** objects probes.o is not portable!
/usr/bin/ld: probes.o: relocation R_X86_64_32 against `.rodata' can not be
used when making a shared object; recompile with -fPIC
probes.o: could not read symbols: Bad value
-fPIC flag added but nothing changed.BTW,I'm on 64bit system.Do you have
any idea about the reconfiguration?
Pls let me know if anyone has good advice.Thx!
13 years, 1 month
[libvirt] [PATCH v3] pci address conflict when virtio disk with drive type
by Xu He Jie
When using the xml as below:
------------------------------------------------------
<devices>
<emulator>/home/soulxu/data/work-code/qemu-kvm/x86_64-softmmu/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/home/soulxu/data/VM/images/linux.img'/>
<target dev='vda' bus='virtio'/>
<address type='drive' controller='0' bus='0' unit='0'/>
</disk>
<input type='mouse' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes'/>
<video>
<model type='cirrus' vram='9216' heads='1'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</memballoon>
</devices>
------------------------------------------------------
Then can't startup qemu, the error message as below:
virsh # start test-vm
error: Failed to start domain test-vm
error: internal error process exited while connecting to monitor: qemu-system-x86_64: -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3: PCI: slot 3 function 0 not available for virtio-balloon-pci, in use by virtio-blk-pci
qemu-system-x86_64: -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3: Device 'virtio-balloon-pci' could not be initialized
So adding check for bus type and address type. Only the address of pci type support by virtio bus.
Signed-off-by: Xu He Jie <xuhj(a)linux.vnet.ibm.com>
---
src/qemu/qemu_command.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 30c0be6..7c4bc0a 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1321,13 +1321,17 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
/* Disks (VirtIO only for now */
for (i = 0; i < def->ndisks ; i++) {
- if (def->disks[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
- continue;
-
/* Only VirtIO disks use PCI addrs */
if (def->disks[i]->bus != VIR_DOMAIN_DISK_BUS_VIRTIO)
continue;
+ if ((def->disks[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
+ (def->disks[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("virtio only supports device address type 'PCI' "));
+ goto error;
+ }
+
if (qemuDomainPCIAddressSetNextAddr(addrs, &def->disks[i]->info) < 0)
goto error;
}
--
1.7.4.1
13 years, 1 month
[libvirt] [PATCH 7/8] Enable the blkiothrottle command in virsh
by Lei Li
Signed-off-by: Zhi Yong Wu <wuzhy(a)linux.vnet.ibm.com>
Signed-off-by: Lei Li <lilei(a)linux.vnet.ibm.com>
---
tools/virsh.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
tools/virsh.pod | 13 +++++++
2 files changed, 112 insertions(+), 0 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 72344f0..de86c40 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -6023,6 +6023,104 @@ cmdBlockJob(vshControl *ctl, const vshCmd *cmd)
return true;
}
+/*
+ * "blkiothrottle" command
+ */
+static const vshCmdInfo info_blkiothrottle[] = {
+ {"help", N_("Set or display a block disk I/O throttle setting.")},
+ {"desc", N_("Set or display a block disk I/O throttle setting.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_blkiothrottle[] = {
+ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+ {"device", VSH_OT_DATA, VSH_OFLAG_REQ, N_("block device")},
+ {"bps", VSH_OT_INT, VSH_OFLAG_NONE, N_("total throughput limits in bytes/s")},
+ {"bps_rd", VSH_OT_INT, VSH_OFLAG_NONE, N_("read throughput limits in bytes/s")},
+ {"bps_wr", VSH_OT_INT, VSH_OFLAG_NONE, N_("write throughput limits in bytes/s")},
+ {"iops", VSH_OT_INT, VSH_OFLAG_NONE, N_("total operation limits in numbers/s")},
+ {"iops_rd", VSH_OT_INT, VSH_OFLAG_NONE, N_("read operation limits in numbers/s")},
+ {"iops_wr", VSH_OT_INT, VSH_OFLAG_NONE, N_("write operation limits in numbers/s")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdBlkIoThrottle(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom = NULL;
+ const char *name, *disk;
+ virDomainBlockIoThrottleInfo info;
+ virDomainBlockIoThrottleInfo reply;
+ unsigned int flags = 0;
+ int ret = -1;
+
+ memset(&info, 0, sizeof(info));
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ goto out;
+
+ if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ goto out;
+
+ if (vshCommandOptString(cmd, "device", &disk) < 0)
+ goto out;
+
+ if (vshCommandOptULongLong(cmd, "bps", &info.bps) < 0) {
+ info.bps = 0;
+ }
+
+ if (vshCommandOptULongLong(cmd, "bps_rd", &info.bps_rd) < 0) {
+ info.bps_rd = 0;
+ }
+
+ if (vshCommandOptULongLong(cmd, "bps_wr", &info.bps_wr) < 0) {
+ info.bps_wr = 0;
+ }
+
+ if (vshCommandOptULongLong(cmd, "iops", &info.iops) < 0) {
+ info.iops = 0;
+ }
+
+ if (vshCommandOptULongLong(cmd, "iops_rd", &info.iops_rd) < 0) {
+ info.iops_wr = 0;
+ }
+
+ if (vshCommandOptULongLong(cmd, "iops_wr", &info.iops_wr) < 0) {
+ info.bps_wr = 0;
+ }
+
+ if ((info.bps == 0) && (info.bps_rd == 0) && (info.bps_wr == 0)
+ && (info.iops == 0) && (info.iops_rd == 0) && (info.iops_wr == 0)) {
+
+ ret = virDomainGetBlockIoThrottle(dom, disk, &reply, flags);
+
+ if (ret != 0)
+ goto out;
+
+ vshPrint(ctl, "%-15s %llu\n", _("bps:"), reply.bps);
+ vshPrint(ctl, "%-15s %llu\n", _("bps_rd:"), reply.bps_rd);
+ vshPrint(ctl, "%-15s %llu\n", _("bps_wr:"), reply.bps_wr);
+ vshPrint(ctl, "%-15s %llu\n", _("iops:"), reply.iops);
+ vshPrint(ctl, "%-15s %llu\n", _("iops_rd:"), reply.iops_rd);
+ vshPrint(ctl, "%-15s %llu\n", _("iops_wr:"), reply.iops_wr);
+
+ virDomainFree(dom);
+ return true;
+ } else {
+ flags = 1;
+
+ ret = virDomainSetBlockIoThrottle(dom, disk, &info, flags);
+
+ if (ret == 0) {
+ virDomainFree(dom);
+ return true;
+ }
+ }
+
+out:
+ virDomainFree(dom);
+ return false;
+}
/*
* "net-autostart" command
@@ -14017,6 +14115,7 @@ static const vshCmdDef domManagementCmds[] = {
{"blkiotune", cmdBlkiotune, opts_blkiotune, info_blkiotune, 0},
{"blockpull", cmdBlockPull, opts_block_pull, info_block_pull, 0},
{"blockjob", cmdBlockJob, opts_block_job, info_block_job, 0},
+ {"blkiothrottle", cmdBlkIoThrottle, opts_blkiothrottle, info_blkiothrottle, 0},
#ifndef WIN32
{"console", cmdConsole, opts_console, info_console, 0},
#endif
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 775d302..61ec613 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -572,6 +572,19 @@ operation can be checked with B<blockjob>.
I<path> specifies fully-qualified path of the disk.
I<bandwidth> specifies copying bandwidth limit in Mbps.
+=item B<blkiothrottle> I<domain> I<device> [[I<--bps> B<bps>] | [[I<--bps_rd> B<bps_rd>] [I<--bps_wr> B<bps_wr>]] [[I<--iops> B<iops>] | [[I<--iops_rd> B<iops_rd>] [I<--iops_wr> B<iops_wr>]]
+
+Set or display the block disk io limits settting.
+I<path> specifies block disk name.
+I<--bps> specifies total throughput limit in bytes/s.
+I<--bps_rd> specifies read throughput limit in bytes/s.
+I<--bps_wr> specifies write throughput limit in bytes/s.
+I<--iops> specifies total operation limit in numbers/s.
+I<--iops_rd> specifies read operation limit in numbers/s.
+I<--iops_wr> specifies write operation limit in numbers/s.
+
+If no limit is specified, it will query current I/O limits setting.
+
=item B<blockjob> I<domain> I<path> [I<--abort>] [I<--info>] [I<bandwidth>]
Manage active block operations.
--
1.7.1
13 years, 1 month
[libvirt] [PATCH 6/8] Implement Get Block IO Throttle for qemu driver
by Lei Li
Implement the support of get block io throttle for qemu driver.
Signed-off-by: Zhi Yong Wu <wuzhy(a)linux.vnet.ibm.com>
Signed-off-by: Lei Li <lilei(a)linux.vnet.ibm.com>
---
src/qemu/qemu_driver.c | 55 ++++++++++++++++
src/qemu/qemu_monitor.c | 18 +++++
src/qemu/qemu_monitor.h | 5 ++
src/qemu/qemu_monitor_json.c | 145 ++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 5 ++
src/qemu/qemu_monitor_text.c | 117 ++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_text.h | 5 ++
7 files changed, 350 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b41a7d3..6be6301 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -10712,6 +10712,60 @@ cleanup:
return ret;
}
+static int
+qemuDomainGetBlockIoThrottle(virDomainPtr dom,
+ const char *disk,
+ virDomainBlockIoThrottleInfoPtr reply,
+ unsigned int flags)
+{
+ struct qemud_driver *driver = dom->conn->privateData;
+ virDomainObjPtr vm = NULL;
+ qemuDomainObjPrivatePtr priv;
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ const char *device = NULL;
+ int ret = -1;
+
+ 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;
+ }
+
+ if (!virDomainObjIsActive(vm)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ goto cleanup;
+ }
+ device = qemuDiskPathToAlias(vm, disk);
+
+ if (!device) {
+ goto cleanup;
+ }
+
+ if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
+ goto cleanup;
+
+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ priv = vm->privateData;
+ ret = qemuMonitorGetBlockIoThrottle(priv->mon, device, reply, flags);
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+
+ if (qemuDomainObjEndJob(driver, vm) == 0) {
+ vm = NULL;
+ goto cleanup;
+ }
+
+cleanup:
+ VIR_FREE(device);
+ if (vm)
+ virDomainObjUnlock(vm);
+ qemuDriverUnlock(driver);
+ return ret;
+}
+
static virDriver qemuDriver = {
.no = VIR_DRV_QEMU,
.name = "QEMU",
@@ -10855,6 +10909,7 @@ static virDriver qemuDriver = {
.domainBlockJobSetSpeed = qemuDomainBlockJobSetSpeed, /* 0.9.4 */
.domainBlockPull = qemuDomainBlockPull, /* 0.9.4 */
.domainSetBlockIoThrottle = qemuDomainSetBlockIoThrottle, /* 0.9.8 */
+ .domainGetBlockIoThrottle = qemuDomainGetBlockIoThrottle, /* 0.9.8 */
};
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index b061631..7a23fd8 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2560,6 +2560,24 @@ int qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
return ret;
}
+int qemuMonitorGetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoThrottleInfoPtr 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 1269430..c172b2b 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -520,6 +520,11 @@ int qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
virDomainBlockIoThrottleInfoPtr info,
unsigned int flags);
+int qemuMonitorGetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoThrottleInfoPtr 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 2f93830..32410e3 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -3290,3 +3290,148 @@ int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
return ret;
}
+static int
+qemuMonitorJSONBlockIoThrottleInfo(virJSONValuePtr result,
+ const char *device,
+ virDomainBlockIoThrottleInfoPtr 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->bps) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s"),
+ "bps");
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(inserted, "bps_rd", &reply->bps_rd) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s"),
+ "bps_rd");
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(inserted, "bps_wr", &reply->bps_wr) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s"),
+ "bps_wr");
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(inserted, "iops", &reply->iops) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s"),
+ "iops");
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(inserted, "iops_rd", &reply->iops_rd) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s"),
+ "iops_rd");
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(inserted, "iops_wr", &reply->iops_wr) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s"),
+ "iops_wr");
+ 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 qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoThrottleInfoPtr 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 36cae79..9562908 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -255,4 +255,9 @@ int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
virDomainBlockIoThrottleInfoPtr info,
unsigned int flags);
+int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoThrottleInfoPtr 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 13fdf55..496e926 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -3433,3 +3433,120 @@ cleanup:
return ret;
}
+static int qemuMonitorTextParseBlockIoThrottle(const char *result,
+ const char *device,
+ virDomainBlockIoThrottleInfoPtr reply)
+{
+ char *dummy = NULL;
+ int ret = -1;
+ const char *p, *eol;
+ int devnamelen = strlen(device);
+ int tmp;
+
+ 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->bps) == -1)
+ VIR_DEBUG("error reading bps: %s", p);
+ } else if (STRPREFIX(p, "bps_rd=")) {
+ p += strlen("bps_rd=");
+ if (virStrToLong_ull(p, &dummy, 10, &reply->bps_rd) == -1)
+ VIR_DEBUG("error reading bps_rd: %s", p);
+ } else if (STRPREFIX(p, "bps_wr=")) {
+ p += strlen("bps_wr=");
+ if (virStrToLong_ull(p, &dummy, 10, &reply->bps_wr) == -1)
+ VIR_DEBUG("error reading bps_wr: %s", p);
+ } else if (STRPREFIX(p, "iops=")) {
+ p += strlen("iops=");
+ if (virStrToLong_ull(p, &dummy, 10, &reply->iops) == -1)
+ VIR_DEBUG("error reading iops: %s", p);
+ } else if (STRPREFIX(p, "iops_rd=")) {
+ p += strlen("iops_rd=");
+ if (virStrToLong_ull(p, &dummy, 10, &reply->iops_rd) == -1)
+ VIR_DEBUG("error reading iops_rd: %s", p);
+ } else if (STRPREFIX(p, "iops_wr=")) {
+ p += strlen("iops_wr=");
+ if (virStrToLong_ull(p, &dummy, 10, &reply->iops_wr) == -1)
+ VIR_DEBUG("error reading iops_wr: %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,
+ virDomainBlockIoThrottleInfoPtr reply,
+ unsigned int flags)
+{
+ char *cmd = NULL;
+ char *result = NULL;
+ int ret = 0;
+
+ if (!flags) {
+ ret = virAsprintf(&cmd, "info block");
+ }
+
+ 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 (strstr(result, "\ninfo ")) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s",
+ _("info block not supported by this qemu"));
+ 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 d64fc55..ded5807 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -248,4 +248,9 @@ int qemuMonitorTextSetBlockIoThrottle(qemuMonitorPtr mon,
virDomainBlockIoThrottleInfoPtr info,
unsigned int flags);
+int qemuMonitorTextGetBlockIoThrottle(qemuMonitorPtr mon,
+ const char *device,
+ virDomainBlockIoThrottleInfoPtr reply,
+ unsigned int flags);
+
#endif /* QEMU_MONITOR_TEXT_H */
--
1.7.1
13 years, 1 month
[libvirt] [PATCH 1/8] Add new API virDomainSetBlockIoThrottle
by Lei Li
This patch add new pulic API virDomainSetBlockIoThrottle to src/libvirt.c
enable iotune setting for a device in domain XML.
Signed-off-by: Zhi Yong Wu <wuzhy(a)linux.vnet.ibm.com>
Signed-off-by: Lei Li <lilei(a)linux.vnet.ibm.com>
---
include/libvirt/libvirt.h.in | 17 +++++++++
src/conf/domain_conf.c | 76 ++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 11 ++++++
src/driver.h | 11 ++++++
src/libvirt.c | 62 ++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 1 +
src/util/xml.h | 2 +
7 files changed, 180 insertions(+), 0 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 7102bce..ff2926e 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1575,6 +1575,23 @@ int virDomainBlockJobSetSpeed(virDomainPtr dom, const char *path,
int virDomainBlockPull(virDomainPtr dom, const char *path,
unsigned long bandwidth, unsigned int flags);
+typedef struct _virDomainBlockIoThrottleInfo virDomainBlockIoThrottleInfo;
+struct _virDomainBlockIoThrottleInfo {
+ unsigned long long bps;
+ unsigned long long bps_rd;
+ unsigned long long bps_wr;
+ unsigned long long iops;
+ unsigned long long iops_rd;
+ unsigned long long iops_wr;
+};
+typedef virDomainBlockIoThrottleInfo *virDomainBlockIoThrottleInfoPtr;
+
+int
+virDomainSetBlockIoThrottle(virDomainPtr dom,
+ const char *disk,
+ virDomainBlockIoThrottleInfoPtr info,
+ unsigned int flags);
+
/*
* NUMA support
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7f9c542..8f1c65f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2444,6 +2444,41 @@ virDomainDiskDefParseXML(virCapsPtr caps,
iotag = virXMLPropString(cur, "io");
ioeventfd = virXMLPropString(cur, "ioeventfd");
event_idx = virXMLPropString(cur, "event_idx");
+ } else if (xmlStrEqual(cur->name, BAD_CAST "iotune")) {
+ char *io_throttle = NULL;
+ io_throttle = virXMLPropString(cur, "bps");
+ if (io_throttle) {
+ def->blkiothrottle.bps = strtoull(io_throttle, NULL, 10);
+ VIR_FREE(io_throttle);
+ }
+
+ io_throttle = virXMLPropString(cur, "bps_rd");
+ if (io_throttle) {
+ def->blkiothrottle.bps_rd = strtoull(io_throttle, NULL, 10);
+ VIR_FREE(io_throttle);
+ }
+
+ io_throttle = virXMLPropString(cur, "bps_wr");
+ if (io_throttle) {
+ def->blkiothrottle.bps_wr = strtoull(io_throttle, NULL, 10);
+ VIR_FREE(io_throttle);
+ }
+ io_throttle = virXMLPropString(cur, "iops");
+ if (io_throttle) {
+ def->blkiothrottle.iops = strtoull(io_throttle, NULL, 10);
+ VIR_FREE(io_throttle);
+ }
+
+ io_throttle = virXMLPropString(cur, "iops_rd");
+ if (io_throttle) {
+ def->blkiothrottle.iops_rd = strtoull(io_throttle, NULL, 10);
+ VIR_FREE(io_throttle);
+ }
+
+ io_throttle = virXMLPropString(cur, "iops_wr");
+ if (io_throttle) {
+ def->blkiothrottle.iops_wr = strtoull(io_throttle, NULL, 10);
+ }
} else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
def->readonly = 1;
} else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) {
@@ -9317,6 +9352,47 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " <target dev='%s' bus='%s'/>\n",
def->dst, bus);
+ /*disk I/O throttling*/
+ if (def->blkiothrottle.bps
+ || def->blkiothrottle.bps_rd
+ || def->blkiothrottle.bps_wr
+ || def->blkiothrottle.iops
+ || def->blkiothrottle.iops_rd
+ || def->blkiothrottle.iops_wr) {
+ virBufferAsprintf(buf, " <iotune");
+ if (def->blkiothrottle.bps) {
+ virBufferAsprintf(buf, " bps='%llu'",
+ def->blkiothrottle.bps);
+ }
+
+ if (def->blkiothrottle.bps_rd) {
+ virBufferAsprintf(buf, " bps_rd='%llu'",
+ def->blkiothrottle.bps_rd);
+ }
+
+ if (def->blkiothrottle.bps_wr) {
+ virBufferAsprintf(buf, " bps_wr='%llu'",
+ def->blkiothrottle.bps_wr);
+ }
+
+ if (def->blkiothrottle.iops) {
+ virBufferAsprintf(buf, " iops='%llu'",
+ def->blkiothrottle.iops);
+ }
+
+ if (def->blkiothrottle.iops_rd) {
+ virBufferAsprintf(buf, " iops_rd='%llu'",
+ def->blkiothrottle.iops_rd);
+ }
+
+ if (def->blkiothrottle.iops_wr) {
+ virBufferAsprintf(buf, " iops_wr='%llu'",
+ def->blkiothrottle.iops_wr);
+ }
+
+ virBufferAsprintf(buf, "/>\n");
+ }
+
if (def->bootIndex)
virBufferAsprintf(buf, " <boot order='%d'/>\n", def->bootIndex);
if (def->readonly)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 0b4d2c2..55c7493 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -292,6 +292,17 @@ struct _virDomainDiskDef {
virDomainDiskHostDefPtr hosts;
char *driverName;
char *driverType;
+
+ /*disk I/O throttling*/
+ struct {
+ unsigned long long bps;
+ unsigned long long bps_rd;
+ unsigned long long bps_wr;
+ unsigned long long iops;
+ unsigned long long iops_rd;
+ unsigned long long iops_wr;
+ } blkiothrottle;
+
char *serial;
int cachemode;
int error_policy; /* enum virDomainDiskErrorPolicy */
diff --git a/src/driver.h b/src/driver.h
index b899d0e..ffa71c8 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -735,6 +735,16 @@ typedef int
(*virDrvDomainBlockPull)(virDomainPtr dom, const char *path,
unsigned long bandwidth, unsigned int flags);
+/*
+ * Block I/O throttling support
+ */
+
+typedef int
+ (*virDrvDomainSetBlockIoThrottle)(virDomainPtr dom,
+ const char *disk,
+ virDomainBlockIoThrottleInfoPtr info,
+ unsigned int flags);
+
/**
* _virDriver:
@@ -893,6 +903,7 @@ struct _virDriver {
virDrvDomainGetBlockJobInfo domainGetBlockJobInfo;
virDrvDomainBlockJobSetSpeed domainBlockJobSetSpeed;
virDrvDomainBlockPull domainBlockPull;
+ virDrvDomainSetBlockIoThrottle domainSetBlockIoThrottle;
};
typedef int
diff --git a/src/libvirt.c b/src/libvirt.c
index a6bcee6..dfc74fb 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -16964,3 +16964,65 @@ error:
virDispatchError(dom->conn);
return -1;
}
+
+/**
+ * virDomainSetBlockIoThrottle:
+ * @dom: pointer to domain object
+ * @disk: Fully-qualified disk name
+ * @info: specify block I/O limits in bytes
+ * @flags: indicate if it set or display block I/O limits info
+ *
+ * This function is mainly to enable Block I/O throttling function in libvirt.
+ * It is used to change the block I/O throttling setting for specified domain.
+ *
+ * Returns 0 if the operation has started, -1 on failure.
+ */
+int virDomainSetBlockIoThrottle(virDomainPtr dom,
+ const char *disk,
+ virDomainBlockIoThrottleInfoPtr info,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(dom, "disk=%p, info=%p, flags=%x",
+ disk, info, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN (dom)) {
+ virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+ conn = dom->conn;
+
+ if (dom->conn->flags & VIR_CONNECT_RO) {
+ virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ goto error;
+ }
+
+ if (!disk) {
+ virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ goto error;
+ }
+
+ if (!info) {
+ virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ goto error;
+ }
+
+ if (conn->driver->domainSetBlockIoThrottle) {
+ int ret;
+ ret = conn->driver->domainSetBlockIoThrottle(dom, disk, info, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibDomainError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(dom->conn);
+ return -1;
+}
+
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 9762fc4..ce29978 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -495,6 +495,7 @@ LIBVIRT_0.9.7 {
virDomainSnapshotGetParent;
virDomainSnapshotListChildrenNames;
virDomainSnapshotNumChildren;
+ virDomainSetBlockIoThrottle;
} LIBVIRT_0.9.5;
# .... define new API here using predicted next version number ....
diff --git a/src/util/xml.h b/src/util/xml.h
index d30e066..cca3ea0 100644
--- a/src/util/xml.h
+++ b/src/util/xml.h
@@ -50,6 +50,8 @@ xmlNodePtr virXPathNode(const char *xpath,
int virXPathNodeSet(const char *xpath,
xmlXPathContextPtr ctxt,
xmlNodePtr **list);
+int virXMLStringToULongLong (const char *stringval,
+ unsigned long long *value);
char * virXMLPropString(xmlNodePtr node,
const char *name);
--
1.7.1
13 years, 1 month
Re: [libvirt] [PATCH 0/7] Update systemtap probing
by lvroyce
I believe enable systemtap will be very helpful for debugging.But I
encountered belowing error when enable systemtap support:
*emantic error: probe point mismatch at position 0 (alternatives: __nfs
__scheduler __signal __tcpmib __vm _linuxmib _signal _sunrpc _syscall
_vfs begin begin(number) end end(number) error error(number) generic
ioblock ioblock_trace ioscheduler ioscheduler_trace ipmib irq_handler
kernel kprobe kprocess linuxmib module(string) nd_syscall netdev never
nfs nfsd perf process process(number) process(string) procfs
procfs(string) scheduler scsi signal socket softirq stap staprun sunrpc
syscall tcp tcpmib timer tty udp vfs vm workqueue): identifier 'libvirt'
at :130:7 while resolving probe point libvirt.event_poll.run
source: probe libvirt.event_poll.run {
^
Pass 2: analysis failed. Try again with another '--vp 01' option.
*Here's my environment:
* Ubuntu 11.04 amd64
configured --with-dtrace --enable-shared=no --with-pic(fPIC flag
also tried)
dtrace installed and compile probe with dtrace -64*
Would somebody pls give me some advice with this systemtap issue?
Thanks a lot!
13 years, 1 month