[libvirt] [PATCH v2] libxl: add p2p migration
by Joao Martins
Introduce support for VIR_MIGRATE_PEER2PEER in libxl driver
for supporting migration in Openstack. Most of the changes
occur at the source and no modifications at the receiver.
In P2P mode there is only the Perform phase so we must handle
the connection with the destination and actually perform the
migration. libxlDomainPerformP2P implements the connection to
the destination and let libxlDoMigrateP2P implements the actual
migration logic with virConnectPtr. In this function we do
the migration steps in the destination similar to
virDomainMigrateVersion3Full. We appropriately save the last
error reported in each of the phases to provide proper
reporting. We don't yet support VIR_MIGRATE_TUNNELED and
we always use V3 with extensible params, making the
implementation simpler.
It is worth noting that the receiver didn't have any changes,
and because it's still the v3 sequence thus it is possible to
migrate from a P2P to non-P2P host.
Signed-off-by: Joao Martins <joao.m.martins(a)oracle.com>
---
Changes since v1:
- Move Begin step to libxlDoMigrateP2P to have all 4 steps
together.
- Remove if before VIR_FREE(dom_xml)
---
src/libxl/libxl_driver.c | 13 ++-
src/libxl/libxl_migration.c | 220 ++++++++++++++++++++++++++++++++++++++++++++
src/libxl/libxl_migration.h | 11 +++
3 files changed, 241 insertions(+), 3 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index fcdcbdb..da98265 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -4713,6 +4713,7 @@ libxlConnectSupportsFeature(virConnectPtr conn, int feature)
switch (feature) {
case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
case VIR_DRV_FEATURE_MIGRATION_PARAMS:
+ case VIR_DRV_FEATURE_MIGRATION_P2P:
return 1;
default:
return 0;
@@ -5039,9 +5040,15 @@ libxlDomainMigratePerform3Params(virDomainPtr dom,
if (virDomainMigratePerform3ParamsEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
- if (libxlDomainMigrationPerform(driver, vm, dom_xml, dconnuri,
- uri, dname, flags) < 0)
- goto cleanup;
+ if (flags & VIR_MIGRATE_PEER2PEER) {
+ if (libxlDomainMigrationPerformP2P(driver, vm, dom->conn, dom_xml,
+ dconnuri, uri, dname, flags) < 0)
+ goto cleanup;
+ } else {
+ if (libxlDomainMigrationPerform(driver, vm, dom_xml, dconnuri,
+ uri, dname, flags) < 0)
+ goto cleanup;
+ }
ret = 0;
diff --git a/src/libxl/libxl_migration.c b/src/libxl/libxl_migration.c
index 0d23e5f..a1c7b55 100644
--- a/src/libxl/libxl_migration.c
+++ b/src/libxl/libxl_migration.c
@@ -42,6 +42,7 @@
#include "libxl_conf.h"
#include "libxl_migration.h"
#include "locking/domain_lock.h"
+#include "virtypedparam.h"
#define VIR_FROM_THIS VIR_FROM_LIBXL
@@ -456,6 +457,225 @@ libxlDomainMigrationPrepare(virConnectPtr dconn,
return ret;
}
+/* This function is a simplification of virDomainMigrateVersion3Full
+ * excluding tunnel support and restricting it to migration v3
+ * with params since it was the first to be introduced in libxl.
+ */
+static int
+libxlDoMigrateP2P(libxlDriverPrivatePtr driver,
+ virDomainObjPtr vm,
+ virConnectPtr sconn,
+ const char *xmlin,
+ virConnectPtr dconn,
+ const char *dconnuri ATTRIBUTE_UNUSED,
+ const char *dname,
+ const char *uri,
+ unsigned int flags)
+{
+ virDomainPtr ddomain = NULL;
+ virTypedParameterPtr params = NULL;
+ int nparams = 0;
+ int maxparams = 0;
+ char *uri_out = NULL;
+ char *dom_xml = NULL;
+ unsigned long destflags;
+ bool cancelled = true;
+ virErrorPtr orig_err = NULL;
+ int ret = -1;
+
+ dom_xml = libxlDomainMigrationBegin(sconn, vm, xmlin);
+ if (!dom_xml)
+ goto cleanup;
+
+ if (virTypedParamsAddString(¶ms, &nparams, &maxparams,
+ VIR_MIGRATE_PARAM_DEST_XML, dom_xml) < 0)
+ goto cleanup;
+
+ if (dname &&
+ virTypedParamsAddString(¶ms, &nparams, &maxparams,
+ VIR_MIGRATE_PARAM_DEST_NAME, dname) < 0)
+ goto cleanup;
+
+ if (uri &&
+ virTypedParamsAddString(¶ms, &nparams, &maxparams,
+ VIR_MIGRATE_PARAM_URI, uri) < 0)
+ goto cleanup;
+
+ /* We don't require the destination to have P2P support
+ * as it looks to be normal migration from the receiver perpective.
+ */
+ destflags = flags & ~(VIR_MIGRATE_PEER2PEER);
+
+ VIR_DEBUG("Prepare3");
+ virObjectUnlock(vm);
+ ret = dconn->driver->domainMigratePrepare3Params
+ (dconn, params, nparams, NULL, 0, NULL, NULL, &uri_out, destflags);
+ virObjectLock(vm);
+
+ if (ret == -1)
+ goto cleanup;
+
+ if (uri_out) {
+ if (virTypedParamsReplaceString(¶ms, &nparams,
+ VIR_MIGRATE_PARAM_URI, uri_out) < 0) {
+ orig_err = virSaveLastError();
+ goto finish;
+ }
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("domainMigratePrepare3 did not set uri"));
+ goto finish;
+ }
+
+ VIR_DEBUG("Perform3 uri=%s", NULLSTR(uri_out));
+ ret = libxlDomainMigrationPerform(driver, vm, NULL, NULL,
+ uri_out, NULL, flags);
+
+ if (ret < 0)
+ orig_err = virSaveLastError();
+
+ cancelled = (ret < 0);
+
+ finish:
+ VIR_DEBUG("Finish3 ret=%d", ret);
+ if (virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_DEST_NAME, NULL) <= 0 &&
+ virTypedParamsReplaceString(¶ms, &nparams,
+ VIR_MIGRATE_PARAM_DEST_NAME,
+ vm->def->name) < 0) {
+ ddomain = NULL;
+ } else {
+ virObjectUnlock(vm);
+ ddomain = dconn->driver->domainMigrateFinish3Params
+ (dconn, params, nparams, NULL, 0, NULL, NULL,
+ destflags, cancelled);
+ virObjectLock(vm);
+ }
+
+ cancelled = (ddomain == NULL);
+
+ /* If Finish3Params set an error, and we don't have an earlier
+ * one we need to preserve it in case confirm3 overwrites
+ */
+ if (!orig_err)
+ orig_err = virSaveLastError();
+
+ VIR_DEBUG("Confirm3 cancelled=%d vm=%p", cancelled, vm);
+ ret = libxlDomainMigrationConfirm(driver, vm, flags, cancelled);
+
+ if (ret < 0)
+ VIR_WARN("Guest %s probably left in 'paused' state on source",
+ vm->def->name);
+
+ cleanup:
+ if (ddomain) {
+ virObjectUnref(ddomain);
+ ret = 0;
+ } else {
+ ret = -1;
+ }
+
+ if (orig_err) {
+ virSetError(orig_err);
+ virFreeError(orig_err);
+ }
+
+ VIR_FREE(dom_xml);
+ VIR_FREE(uri_out);
+ virTypedParamsFree(params, nparams);
+ return ret;
+}
+
+static int virConnectCredType[] = {
+ VIR_CRED_AUTHNAME,
+ VIR_CRED_PASSPHRASE,
+};
+
+static virConnectAuth virConnectAuthConfig = {
+ .credtype = virConnectCredType,
+ .ncredtype = ARRAY_CARDINALITY(virConnectCredType),
+};
+
+static void
+libxlMigrationConnectionClosed(virConnectPtr conn,
+ int reason,
+ void *opaque)
+{
+ virDomainObjPtr vm = opaque;
+
+ VIR_DEBUG("conn=%p, reason=%d, vm=%s", conn, reason, vm->def->name);
+ virDomainObjBroadcast(vm);
+}
+
+/* On P2P mode there is only the Perform3 phase and we need to handle
+ * the connection with the destination libvirtd and perform the migration.
+ * Here we first tackle the first part of it, and libxlDoMigrationP2P handles
+ * the migration process with an established virConnectPtr to the destination.
+ */
+int
+libxlDomainMigrationPerformP2P(libxlDriverPrivatePtr driver,
+ virDomainObjPtr vm,
+ virConnectPtr sconn,
+ const char *xmlin,
+ const char *dconnuri,
+ const char *uri_str ATTRIBUTE_UNUSED,
+ const char *dname,
+ unsigned int flags)
+{
+ int ret = -1;
+ int keepAliveInterval = 5;
+ int keepAliveCount = 5;
+ bool useParams;
+ virConnectPtr dconn = NULL;
+ virErrorPtr orig_err = NULL;
+
+ virObjectUnlock(vm);
+ dconn = virConnectOpenAuth(dconnuri, &virConnectAuthConfig, 0);
+ virObjectLock(vm);
+
+ if (dconn == NULL) {
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("Failed to connect to remote libvirt URI %s: %s"),
+ dconnuri, virGetLastErrorMessage());
+ return ret;
+ }
+
+ if (virConnectSetKeepAlive(dconn, keepAliveInterval,
+ keepAliveCount) < 0)
+ goto cleanup;
+
+ if (virConnectRegisterCloseCallback(dconn, libxlMigrationConnectionClosed,
+ vm, NULL) < 0) {
+ goto cleanup;
+ }
+
+ virObjectUnlock(vm);
+ useParams = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn,
+ VIR_DRV_FEATURE_MIGRATION_PARAMS);
+ virObjectLock(vm);
+
+ if (!useParams) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("Destination libvirt does not support migration with extensible parameters"));
+ goto cleanup;
+ }
+
+ ret = libxlDoMigrateP2P(driver, vm, sconn, xmlin, dconn, dconnuri,
+ dname, uri_str, flags);
+
+ cleanup:
+ orig_err = virSaveLastError();
+ virObjectUnlock(vm);
+ virConnectUnregisterCloseCallback(dconn, libxlMigrationConnectionClosed);
+ virObjectUnref(dconn);
+ virObjectLock(vm);
+ if (orig_err) {
+ virSetError(orig_err);
+ virFreeError(orig_err);
+ }
+ return ret;
+}
+
int
libxlDomainMigrationPerform(libxlDriverPrivatePtr driver,
virDomainObjPtr vm,
diff --git a/src/libxl/libxl_migration.h b/src/libxl/libxl_migration.h
index 20b45d8..0f83bb4 100644
--- a/src/libxl/libxl_migration.h
+++ b/src/libxl/libxl_migration.h
@@ -28,6 +28,7 @@
# define LIBXL_MIGRATION_FLAGS \
(VIR_MIGRATE_LIVE | \
+ VIR_MIGRATE_PEER2PEER | \
VIR_MIGRATE_UNDEFINE_SOURCE | \
VIR_MIGRATE_PAUSED)
@@ -56,6 +57,16 @@ libxlDomainMigrationPrepare(virConnectPtr dconn,
unsigned int flags);
int
+libxlDomainMigrationPerformP2P(libxlDriverPrivatePtr driver,
+ virDomainObjPtr vm,
+ virConnectPtr sconn,
+ const char *dom_xml,
+ const char *dconnuri,
+ const char *uri_str,
+ const char *dname,
+ unsigned int flags);
+
+int
libxlDomainMigrationPerform(libxlDriverPrivatePtr driver,
virDomainObjPtr vm,
const char *dom_xml,
--
2.1.4
9 years, 4 months
[libvirt] [PATCH v2 0/5] Add read error ignore to storage backend vol info APIs
by John Ferlan
v1 took a simplistic approach:
http://www.redhat.com/archives/libvir-list/2015-October/msg00919.html
but not specific enough according to the review. So adding some extra
complexity of checking for specific errors and flag bits to "ignore" the
error similar to the catch-all openflags VIR_STORAGE_VOL_OPEN_NOERROR for
all the virStorageBackendUpdateVol{Info|TargetInfo|TargetInfoFD} API's
which are used to get the volume capacity, allocation, etc. data.
Along the way an inavertent bug was found and fixed in patch 3 in
virStorageBackendUpdateVolTargetInfo where an error could have been
reported, but not propagated back to the user since 'ret' would have
been 0 after the virStorageBackendUpdateVolTargetInfoFD call.
John Ferlan (5):
storage: Add readflags for backend error processing
storage: Add comments for backend APIs
storage: Handle readflags errors
storage: Add debug message
storage: Ignore block devices that fail format detection
src/storage/storage_backend.c | 151 +++++++++++++++++++++++++++-------
src/storage/storage_backend.h | 20 ++++-
src/storage/storage_backend_disk.c | 5 +-
src/storage/storage_backend_fs.c | 8 +-
src/storage/storage_backend_gluster.c | 2 +-
src/storage/storage_backend_logical.c | 2 +-
src/storage/storage_backend_mpath.c | 2 +-
src/storage/storage_backend_scsi.c | 6 +-
8 files changed, 153 insertions(+), 43 deletions(-)
--
2.5.0
9 years, 4 months
[libvirt] [PATCH LIBVIRT v1 0/2] Support maxvcpus (AKA >1 vcpu on Xen/ARM)
by Ian Campbell
libvirt currently clamps the maximum number of vcpus to MAX_VIRT_CPUS
== XEN_LEGACY_MAX_VCPUS, which on ARM is 1 (because all guests are expected
to support vcpu info placement).
Even on x86 this limitation is a hold over from an older xm interface where
the maximum number of vcpus was expressed as a bitmap and so limited to the
number of bits in an unsigned long (for which XEN_LEGACY_MAX_VCPUS is a
convenient proxy), which doesn't apply to xl on x86 which uses a bitmap
data type to express larger bitmaps.
To do this it was necessary to add a new value to xenConfigVersionEnum
corresponding to this new version.
I've tested with tests/x?configtest (including new test case) on x86 and on
ARM with xlconfigtest and via domxml-from-native.
As you might infer from some of the changlogs I feel a bit like I am
abusing xendConfigVersion somewhat here (given that xl != xend, and that
real xend never went passed xend_config_version) but its use is quite
widespread in the common xl/xm support code in libvirt so a great deal of
refactoring/renaming would otherwise seem to be required. I'm open to other
ideas or suggestions though.
Ian.
9 years, 4 months
[libvirt] libvirt-php 0.5.1 - missing arginfo
by Remi Collet
Hi,
arginfo are very important in PHP extensions, useful for users
(documentation), and various tools rely on them (through reflection).
Attached patch add some.
Tell me if ok, and I will continue to add more.
Remi.
9 years, 4 months
[libvirt] [PATCH v2 0/2] libxl: implement virDomainInterfaceStats
by Joao Martins
Hey,
This patch series implements virDomainInterfaceStats
but based on "ConsoleCallback" as opposed of doing it in libxlDomainStart.
The series is divided as following: Patch 1 renames console callback to
something more generic and Patch 2 implements virDomainInterfaceStats also
taking the previous review (v3 statistics) comments.
Changes since v1:
- Improve error reporting in case interface is not known
- Use libxl_device_nic_list as opposed to libxl_domain_config
Regards,
Joao
Joao Martins (2):
libxl: rename libxlConsoleCallback
libxl: implement virDomainInterfaceStats
src/libxl/libxl_domain.c | 33 ++++++++++++++++++++++++++++--
src/libxl/libxl_driver.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 83 insertions(+), 2 deletions(-)
--
2.1.4
9 years, 4 months
[libvirt] [PATCH] network: selectively disable -Wcast-align in virNetDevParseDadStatus
by Ian Campbell
Commit 0f7436ca54c9 "network: wait for DAD to finish for bridge IPv6 addresses"
results in:
CC util/libvirt_util_la-virnetdevmacvlan.lo
util/virnetdev.c: In function 'virNetDevParseDadStatus':
util/virnetdev.c:1319:188: error: cast increases required alignment of target type [-Werror=cast-align]
util/virnetdev.c:1332:41: error: cast increases required alignment of target type [-Werror=cast-align]
util/virnetdev.c:1334:92: error: cast increases required alignment of target type [-Werror=cast-align]
cc1: all warnings being treated as errors
on at least ARM platforms.
The three macros involved (NLMSG_NEXT, IFA_RTA and RTA_NEXT) all appear to
correctly take care of alignment, therefore suppress Wcast-align around their
uses.
Signed-off-by: Ian Campbell <ian.campbell(a)citrix.com>
Cc: Maxim Perevedentsev <mperevedentsev(a)virtuozzo.com>
Cc: Laine Stump <laine(a)laine.org>
Cc: Dario Faggioli <dario.faggioli(a)citrix.com>
Cc: Jim Fehlig <jfehlig(a)suse.com>
---
src/util/virnetdev.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index ade9afa..0bc809e 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -1316,7 +1316,10 @@ virNetDevParseDadStatus(struct nlmsghdr *nlh, int len,
struct rtattr *rtattr_ptr;
size_t i;
struct in6_addr *addr;
+
+ VIR_WARNINGS_NO_CAST_ALIGN
for (; NLMSG_OK(nlh, len); nlh = NLMSG_NEXT(nlh, len)) {
+ VIR_WARNINGS_RESET
if (NLMSG_PAYLOAD(nlh, 0) < sizeof(struct ifaddrmsg)) {
/* Message without payload is the last one. */
break;
@@ -1329,9 +1332,11 @@ virNetDevParseDadStatus(struct nlmsghdr *nlh, int len,
}
ifaddrmsg_len = IFA_PAYLOAD(nlh);
+ VIR_WARNINGS_NO_CAST_ALIGN
rtattr_ptr = (struct rtattr *) IFA_RTA(ifaddrmsg_ptr);
for (; RTA_OK(rtattr_ptr, ifaddrmsg_len);
rtattr_ptr = RTA_NEXT(rtattr_ptr, ifaddrmsg_len)) {
+ VIR_WARNINGS_RESET
if (RTA_PAYLOAD(rtattr_ptr) != sizeof(struct in6_addr)) {
/* No address: ignore. */
continue;
--
2.1.4
9 years, 4 months
[libvirt] [PATCH 0/8] Make loading domains with invalid XML possible
by Martin Kletzander
The RFC version [1] was ACKed, but I have found out that we could then
cause inconsistency by calling virDomainCreateXML() or Restore() calls
etc. This series is basically the same apart from the fact that it is
rebased on current master and then one simple diff [2] is added to
PATCH 5/8.
[1] https://www.redhat.com/archives/libvir-list/2015-September/msg00698.html
[2] diff to the previous version:
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 16f26acf4839..c8291be2b7b5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2875,6 +2875,14 @@ virDomainObjListAddLocked(virDomainObjListPtr doms,
}
}
+ if (vm->def->parseError) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("domain '%s' was not loaded due to an XML error "
+ "(%s), please redefine it"),
+ vm->def->name, vm->def->parseError);
+ virDomainObjEndAPI(&vm);
+ }
+
virDomainObjAssignDef(vm,
def,
!!(flags & VIR_DOMAIN_OBJ_LIST_ADD_LIVE),
--
Martin Kletzander (8):
conf, virsh: Add new domain shutoff reason
qemu: Few whitespace cleanups
conf: Extract name-parsing into its own function
conf: Extract UUID parsing into its own function
conf: Optionally keep domains with invalid XML, but don't allow
starting them
qemu: Don't lookup invalid domains unless specified otherwise
qemu: Prepare basic APIs to handle invalid defs
qemu: Load domains with invalid XML on start
include/libvirt/libvirt-domain.h | 2 +
src/bhyve/bhyve_driver.c | 2 +
src/conf/domain_conf.c | 191 +++++++++++++++++++++++++++++++++------
src/conf/domain_conf.h | 5 +
src/libxl/libxl_driver.c | 3 +
src/lxc/lxc_driver.c | 3 +
src/qemu/qemu_driver.c | 64 ++++++++++---
src/uml/uml_driver.c | 2 +
tools/virsh-domain-monitor.c | 3 +-
9 files changed, 234 insertions(+), 41 deletions(-)
--
2.6.3
9 years, 4 months
[libvirt] [PATCH] tools: fix output of list with state-shutoff
by Wei Jiangang
Due to the default of flags is VIR_CONNECT_LIST_DOMAINS_ACTIVE,
It doesn't show the domains that have been shutdown when we use
'virsh list' with only --state-shutoff.
Signed-off-by: Wei Jiangang <weijg.fnst(a)cn.fujitsu.com>
---
tools/virsh-domain-monitor.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index d4e500b..7b30c4c 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -1873,7 +1873,8 @@ cmdList(vshControl *ctl, const vshCmd *cmd)
unsigned int flags = VIR_CONNECT_LIST_DOMAINS_ACTIVE;
/* construct filter flags */
- if (vshCommandOptBool(cmd, "inactive"))
+ if (vshCommandOptBool(cmd, "inactive") ||
+ vshCommandOptBool(cmd, "state-shutoff"))
flags = VIR_CONNECT_LIST_DOMAINS_INACTIVE;
if (vshCommandOptBool(cmd, "all"))
--
1.9.3
9 years, 4 months
[libvirt] [PATCH 0/8] Add perf and Intel CMT feature support
by Qiaowei Ren
The series mainly adds Intel CMT feature support into libvirt. CMT is
new introduced PQos (Platform Qos) feature to monitor the usage of
cache by applications running on the platform.
Currently CMT patches has been merged into Linux kernel mainline.
The CMT implementation in Linux kernel is based on perf mechanism and
there is no support for perf in libvirt, and so this series firstly
add perf support into libvirt, including two public API and a set of
util interfaces. And based on these APIs and interfaces, thie series
implements CMT perf event support.
TODO:
1. This series relys on keeping an open file descriptor for the guest.
We should add one patch to call sys_perf_event_open again iff libvirtd
is restarted.
Qiaowei Ren (8):
perf: add new public APIs for perf event
perf: define internal driver API for perf event
perf: implement the public APIs for perf event
perf: implement the remote protocol for perf event
perf: implement a set of util functions for perf event
qemu_driver: add support to perf event
virsh: extend domstats command
virsh: implement new command to support perf
daemon/remote.c | 60 +++++++++++
include/libvirt/libvirt-domain.h | 19 ++++
include/libvirt/virterror.h | 2 +
src/Makefile.am | 1 +
src/driver-hypervisor.h | 12 +++
src/libvirt-domain.c | 106 +++++++++++++++++++
src/libvirt_private.syms | 8 ++
src/libvirt_public.syms | 6 ++
src/qemu/qemu_domain.h | 3 +
src/qemu/qemu_driver.c | 181 +++++++++++++++++++++++++++++++
src/qemu/qemu_process.c | 6 ++
src/remote/remote_driver.c | 49 +++++++++
src/remote/remote_protocol.x | 32 +++++-
src/remote_protocol-structs | 20 ++++
src/util/virerror.c | 2 +
src/util/virperf.c | 222 +++++++++++++++++++++++++++++++++++++++
src/util/virperf.h | 60 +++++++++++
tools/virsh-domain-monitor.c | 7 ++
tools/virsh-domain.c | 139 ++++++++++++++++++++++++
tools/virsh.pod | 15 ++-
20 files changed, 947 insertions(+), 3 deletions(-)
create mode 100644 src/util/virperf.c
create mode 100644 src/util/virperf.h
--
1.9.1
9 years, 4 months